C#:关闭Excel窗体关闭事件 [英] C# : Closing a windows form on excel closing event

查看:442
本文介绍了C#:关闭Excel窗体关闭事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的情况是我正在开发一个启动Microsoft Office Excel应用程序的实例的C#应用​​程序。

我更改了一些Form的功能,以便实例化的Excel应用程序被杀死当我的表单被关闭时,从内存中清理。



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

解决方案

尝试这样做,所以我不知道它是否可以工作,但你可以尝试以下这些行:

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

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

foreach(进程中的var进程)
{
if(process.Handle.ToInt32()== excel.Hwnd)
excelProcess = process;
}

excelProcess.Exited + = new EventHandler(excelProcess_Exited);

更新



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

  Microsoft.Office.Interop.Excel.Application xlsApp; 
进程xlsProcess;
定时器定时器

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

foreach(Process.GetProcesses()中的var p)//获取相关的Excel进程。
{
if(p.MainWindowHandle == new IntPtr(xlsApp.Hwnd))
{
xlsProcess = p;
break;
}
}

如果(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 )
{
//清理以确保后台Excel进程已终止。
xlsApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlsApp);
xlsApp = null;
}

如果(xlsProcess.HasExited)
{
//事件不会触发,但是一旦进程终止,属性才会被设置
this.timer.Dispose();
this.Close();
}
}

使用Excel应用程序时的问题是即使如果用户关闭它的主窗口,该进程将继续在后台运行。为了完全释放它,你必须调用 Application.Quit ,但是你应该只有当你检测到关闭窗口的用户时才这样做,这正是你正在解决的问题...你有一个循环引用:D



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



所以我可以看到唯一的解决方案是轮询Excel的主窗口是可见的。一旦没有,这可能意味着用户关闭了主窗口,并且应该终止Excel应用程序(如果有一些场景,其中Excel的主窗口的可见性可能是假的,而不是当用户想要终止进程时,这个解决方案不是有效)。从那里开始很简单。


My situation is that I'm developing a C# application which is launching an instance of a Microsoft Office Excel Application.
I change some of the Form's functions so that the instantiated Excel Application is being killed and cleaned up from memory when my Form's being closed.

What I want to do is to perform the opposite. I'd like my instance of Excel to close my windows Form when it's being exited.

解决方案

Ok, I haven't even tried this so I'm not sure if it will work, but you could try something along these lines:

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

Try the following code (its not pretty):

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();
    }
}

The problem when working with an Excel Application is that even if the user closes it's main window, the process will keep on running in the background. In order to release it completely you have to call Application.Quit but you should only do that when you detect the user closing the window which is exactly the problem you are trying to solve...you have a circular reference here :D

Latching to the relevant System.Diagnostics.Process doesn't seem to work either, as the Exited event never gets fired (not even if you terminate the background process from the task manager). My guess is that this event is fired only with processes launched through process = Process.Start(...).

So the only solution I can see is polling if Excel`s main window is visible. Once it is not, that probably means the user closed the main window and the Excel application should be terminated (if there is some scenario where Excel's main window's visibility can be false other than when the user wants to terminate the process then this solution is not valid). From there it is pretty straightforward.

这篇关于C#:关闭Excel窗体关闭事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆