2012-01-18 66 views
0

我的情况是,我正在开发一个启动Microsoft Office Excel应用程序实例的C#应用​​程序。
我更改了某些表单的函数,以便在我的表单被关闭时,实例化的Excel应用程序正在被杀死并从内存中清除。C#:关闭excel关闭事件的窗体表格

我想要做的是做相反的事情。我希望我的Excel实例在退出时关闭我的窗体窗体。

+0

调查运行进程,并简单地退出时,Excel进程结束? – CodingBarfield 2012-01-18 09:58:45

+1

如果您使用的是Visual Studio 2008或2010,则可以完全绕过表单并创建Excel Addin - http://msdn.microsoft.com/zh-cn/library/cc668205.aspx – JMK 2012-01-18 10:00:49

+0

我知道这不是我的应用程序的重点。我需要这样做。我不知道如何设置一个监听器,当C#的实例化应用程序正在退出时,它将关闭我的C#应用​​程序... – Jsncrdnl 2012-01-18 10:09:28

回答

1

好吧,我还没有试过这个,所以我不知道这是否会工作,但你可以尝试沿着这些路线的东西:

Microsoft.Office.Interop.Excel.Application excel = ...; 

System.Diagnostics.Process excelProcess = null; 
var processes = System.Diagnostics.Process.GetProcesses(); 

foreach (var process in processes) 
{ 
     if (process.Handle.ToInt32() == excel.Hwnd) 
      excelProcess = process; 
} 

excelProcess.Exited += new EventHandler(excelProcess_Exited); 

UPDATE

请尝试以下代码(它不漂亮):

Microsoft.Office.Interop.Excel.Application xlsApp; 
Process xlsProcess; 
Timer timer; 

public Form1() 
{ 
    xlsApp = new Microsoft.Office.Interop.Excel.Application(); 
    xlsApp.Visible = true; 

    foreach (var p in Process.GetProcesses()) //Get the relevant Excel process. 
    { 
     if (p.MainWindowHandle == new IntPtr(xlsApp.Hwnd)) 
     { 
      xlsProcess = p; 
      break; 
     } 
    } 

    if (xlsProcess != null) 
    { 
     timer = new Timer(); 
     timer.Interval = 500; 
     timer.Tick += new EventHandler(timer_Tick); 
     timer.Start(); 
    } 
} 

void timer_Tick(object sender, EventArgs e) 
{ 
    if (xlsApp != null && !xlsApp.Visible) 
    { 
     //Clean up to make sure the background Excel process is terminated. 
     xlsApp.Quit(); 
     System.Runtime.InteropServices.Marshal.ReleaseComObject(xlsApp); 
     xlsApp = null; 
    } 

    if (xlsProcess.HasExited) 
    { 
     //The event is not fired but the property is eventually set once the process is terminated 
     this.timer.Dispose(); 
     this.Close(); 
    } 
} 

使用Excel应用程序时的问题是,即使用户关闭它的主窗口,pr接下来将继续在后台运行。为了完全释放它,您必须致电Application.Quit,但只有在检测到用户关闭窗口时才应该这样做,这正是您正在尝试解决的问题...您在此处有一个循环参考:D

锁定到相关的System.Diagnostics.Process似乎也不起作用,因为Exited事件不会被触发(即使您从任务管理器中终止后台进程也不会)。我的猜测是,这个事件只能通过process = Process.Start(...)启动的进程触发。

所以我能看到的唯一解决方案是轮询Excel的主窗口是否可见。一旦不是这样,这可能意味着用户关闭了主窗口并且应用程序应该被终止(如果在某些情况下Excel的主窗口的可见性可能是错误的,而不是当用户想要终止该过程时,那么该解决方案不是有效)。从那里它非常简单。

+0

我同意你的意见。唯一的问题是,我没有获得管理员权限在启动时需要执行此操作'process.Handle.ToInt32()'是否有任何办法做到这一点,而不需要管理员权限? – Jsncrdnl 2012-01-18 11:05:29

+0

@ Kuroicloud666:检查更新。它不漂亮,但它似乎工作。 – InBetween 2012-01-18 12:22:49

2

这就是我为同样的场景所做的。

我创建的类

System.Diagnostics.Process myProcess = new System.Diagnostics.Process(); 

然后委托内的进程,以封闭该应用

delegate void KillProcess(); 
KillProcess aKillProcess; 

委托设置到应用程序关闭方法

aKillProcess = CloseApp; 

此方法下面的代码写在按钮点击事件中 这会打开前CEL。这里认购过程

myProcess.StartInfo = new System.Diagnostics.ProcessStartInfo (@"D:\SomeExcel.xlsx"); 
myProcess.Start(); 
myProcess.EnableRaisingEvents = true; 
myProcess.Exited += new EventHandler(ProcessKilled); 

的Exited事件在单击Excel中的关闭按钮,这个方法会被称为

private void ProcessKilled(object sender, EventArgs e) 
{ 
    if (this.InvokeRequired) 
     this.Invoke(aKillProcess); 
    else 
     this.Close(); 
} 

void CloseApp() 
{ 
    this.Close(); 
} 

这将关闭该应用程序。

希望这有助于

+0

我在直接关闭表单后添加了委托,“跨线程操作无效:控制'Form1'从其创建线程以外的线程访问。”异常被抛出。 – 2012-01-18 10:25:40

+0

您的解决方案的问题似乎是,我将无法使用我的应用程序和启动的进程之间的交互,因为它不是启动的“Microsoft.Office.Interop.Excel.Application”,而是一个简单的进程。目前我无法控制它... – Jsncrdnl 2012-01-18 11:00:53

0

你的第一次尝试会工作,只是需要enavle事件的筹措过程中,这是我做的钓推出的Visio退出或崩溃。

    foreach (var process in processes) 
        { 
         try 
         { 
          if (process.MainWindowHandle == new IntPtr(app.WindowHandle32)) 
           visioProcess = process; 
         } 
         catch 
         { 

         } 
        } 

        visioProcess.EnableRaisingEvents = true; 

        visioProcess.Exited += new EventHandler(visioProcess_Exited);