C#:关闭excel结束事件的窗体

时间:2012-01-18 09:48:19

标签: c# excel event-handling add-in

我的情况是我正在开发一个C#应用程序,它正在启动一个Microsoft Office Excel应用程序的实例 我更改了Form的一些功能,以便在我的表单关闭时,实例化的Excel应用程序被杀死并从内存中清除。

我想要做的就是执行相反的操作。我希望我的Excel实例能够在退出时关闭我的窗体。

3 个答案:

答案 0 :(得分:2)

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

我在班级

中创建了一个流程
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();
}

这将关闭应用程序。

希望这有帮助

答案 1 :(得分: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);

<强>更新

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

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的主窗口的可见性可能是假的,除非用户想要终止该过程,那么此解决方案不是有效)。从那里它非常简单。

答案 2 :(得分:0)

你的第一次尝试是有效的,只需要为这个过程启动事件,这就是我为了启动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);