2012-01-18 22 views
0

私の状況は、Microsoft Office Excelアプリケーションのインスタンスを起動しているC#アプリケーションを開発しているということです。
フォームの一部の機能を変更して、フォームが閉じられているときにインスタンス化されたExcelアプリケーションが強制終了され、メモリからクリーンアップされるようにします。C#:Excelの終了イベントでWindowsフォームを閉じる

私がしたいことは、反対を実行することです。私はExcelの私のインスタンスが終了するときに私のウィンドウフォームを閉じるにしたいと思います。

+0

実行中のプロセスをポーリングして、Excelプロセスが終了すると終了しますか? – CodingBarfield

+1

Visual Studio 2008または2010を使用している場合、フォームを完全にバイパスしてExcel Addinを作成することができます - http://msdn.microsoft.com/en-us/library/cc668205.aspx – JMK

+0

私のアプリケーションのポイント。私はこのようにする必要があります。私が知らないのは、C#のインスタンス化されたアプリケーションが終了しているときにC#アプリケーションを閉じることになるリスナーを設定する方法です。 – Jsncrdnl

答えて

1

[OK]を、私はそうであっても、これを試していない私はそれが動作するかどうかわからないんだけど、あなたはこれらの線に沿って何かを試みることができる:

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アプリケーションで作業するときの問題は、ユーザーがメインウィンドウを閉じても、 ocessはバックグラウンドで実行し続けます。完全に解放するためには、Application.Quitに電話をしなければなりませんが、あなたが解決しようとしている問題であるウィンドウを閉じているユーザーを検出したときにのみ行うべきです...ここで循環参照があります:D

関連するSystem.Diagnostics.Processへのラッチは、Exitedイベントが発生しないため、(タスクマネージャからバックグラウンドプロセスを終了しても)動作しないため、どちらも機能していないようです。私の推測では、このイベントは、process = Process.Start(...)によって起動されたプロセスでのみ発生するということです。

私が見ることができる唯一の解決策は、Excelのメインウィンドウが表示されている場合にポーリングすることです。それがないと、ユーザーがメインウィンドウを閉じ、Excelアプリケーションを終了する必要があることを意味します(Excelのメインウィンドウの可視性は、ユーザーがプロセスを終了するとき以外は間違っている場合があります有効)。そこからはかなり簡単です。

+0

私はあなたに同意します。唯一の問題は、私がこのアクションを実行するために必要な起動時に管理者権限を持っていないということです。 'process.Handle.ToInt32()'管理者権限を必要とせずにこれを行う方法はありませんか? – Jsncrdnl

+0

@ Kuroicloud666:アップデートを確認してください。それはかなりではありませんが、うまくいくようです。 – InBetween

2

これは私が同じシナリオで行ったことです。

私は、アプリを閉じる方法

aKillProcess = CloseApp; 

これにデリゲートを設定するアプリ

delegate void KillProcess(); 
KillProcess aKillProcess; 

を閉じメソッドへの委譲次にクラス内

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

をプロセスを作成しました下のコードはボタンのクリックイベントの内部に書き込まれます これはexセル。ここではエクセルの閉じるボタンをクリックすると、プロセス

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

の終了しましたイベントをサブスクライブし、この方法は、このアプリを閉じます

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

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

呼び出されます。

希望これは

+0

フォームを直接閉じるときにデリゲートを追加しました。「クロススレッド操作が有効ではありません:Control 'Form1」が作成されたスレッド以外のスレッドからアクセスされました。例外がスローされました。 –

+0

あなたのソリューションの問題点は、起動された「Microsoft.Office.Interop.Excel.Application」ではなく単純なプロセスであるため、アプリケーションと起動されたプロセスとのやりとりを使用できなくなることです。私はこの時点でそれについて何もコントロールしていません... – Jsncrdnl

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