我的情况是,我正在开发一个C#应用程序,该应用程序正在启动Microsoft Office Excel应用程序的实例
我更改了Form的一些函数,这样当我的Form关闭时,实例化的Excel应用程序就会被杀死并从内存中清除。
我想做的是反其道而行之。我希望我的Excel实例在退出时关闭我的windows窗体。
好吧,我甚至还没有尝试过,所以我不确定它是否有效,但你可以尝试一下:
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);
更新
尝试以下代码(它不漂亮):
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应用程序时的问题是,即使用户关闭了它的主窗口,该进程也将继续在后台运行。为了完全释放它,你必须调用Application.Quit
,但只有当你检测到用户正在关闭窗口时才应该这样做,这正是你试图解决的问题。。。这里有一个循环参考:D
锁定到相关的System.Diagnostics.Process
似乎也不起作用,因为Exited
事件永远不会被触发(即使您从任务管理器终止后台进程也不会)。我的猜测是,只有通过process = Process.Start(...)
启动的进程才会触发此事件。
因此,我能看到的唯一解决方案是轮询Excel的主窗口是否可见。一旦不是,这可能意味着用户关闭了主窗口,Excel应用程序应该终止(如果在某些情况下,Excel的主窗口的可见性可能是错误的,而不是当用户想要终止流程时,则此解决方案无效)。从那以后,一切都很简单。
这是我对相同场景所做的。
我在类中创建了一个流程
System.Diagnostics.Process myProcess = new System.Diagnostics.Process();
然后委托关闭应用程序的方法
delegate void KillProcess();
KillProcess aKillProcess;
将委托设置为应用程序关闭方法
aKillProcess = CloseApp;
下面的代码写在按钮点击事件中这将打开excel。在这里订阅进程的退出事件
myProcess.StartInfo = new System.Diagnostics.ProcessStartInfo (@"D:SomeExcel.xlsx");
myProcess.Start();
myProcess.EnableRaisingEvents = true;
myProcess.Exited += new EventHandler(ProcessKilled);
单击excel的关闭按钮,这种方法将被称为
private void ProcessKilled(object sender, EventArgs e)
{
if (this.InvokeRequired)
this.Invoke(aKillProcess);
else
this.Close();
}
void CloseApp()
{
this.Close();
}
这将关闭应用程序。
希望这能帮助
您的第一次尝试会成功,只需要为流程引发事件,这就是我为捕捉启动的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);