【问题标题】:C# : Closing a windows form on excel closing eventC#:在 excel 关闭事件中关闭窗体
【发布时间】:2012-01-18 09:48:19
【问题描述】:

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

我想做的是反其道而行之。我希望我的 Excel 实例在退出时关闭我的 Windows 窗体。

【问题讨论】:

  • 轮询正在运行的进程并在 Excel 进程结束时直接退出?
  • 如果您使用 Visual Studio 2008 或 2010,您可以完全绕过表单并创建一个 Excel 插件 - msdn.microsoft.com/en-us/library/cc668205.aspx
  • 我知道这不是我申请的重点。我需要这样做。我不知道的是如何设置一个监听器,当退出 C# 的实例化应用程序时,它将关闭我的 C# 应用程序......

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


【解决方案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 的主窗口的可见性可能是假的,而不是当用户想要终止进程时,那么这个解决方案不是有效的)。从那里开始非常简单。

【讨论】:

  • 我同意你的看法。唯一的问题是我在启动时没有管理员权限来执行此操作process.Handle.ToInt32() 没有任何方法可以在不需要管理员权限的情况下执行此操作吗??
  • @Kuroicloud666:检查更新。它不漂亮,但它似乎工作。
【解决方案2】:

这是我为相同场景所做的。

我在类中创建了一个进程

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

然后是关闭应用程序的方法的委托

delegate void KillProcess();
KillProcess aKillProcess;

将代理设置为应用关闭方法

aKillProcess = CloseApp;

下面的代码写在按钮点击事件中 这将打开 Excel。这里订阅进程的Exited事件

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

这将关闭应用程序。

希望对你有帮助

【讨论】:

  • 我已经添加了委托,因为在直接关闭表单时,“跨线程操作无效:控件'Form1'从创建它的线程之外的线程访问。”抛出异常。
  • 您的解决方案的问题似乎是我将无法在我的应用程序和启动的进程之间使用交互,因为它不是启动的“Microsoft.Office.Interop.Excel.Application”而是一个简单的过程。在这一点上我没有任何控制...
【解决方案3】:

您的第一次尝试会奏效,只需要为进程启动事件,这就是我为捕获已启动的 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);

【讨论】:

    猜你喜欢
    • 2015-07-30
    • 2016-04-06
    • 1970-01-01
    • 2018-01-11
    • 1970-01-01
    • 2011-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多