2012-01-18 2 views
0

내 상황은 Microsoft Office Excel 응용 프로그램의 인스턴스를 시작하는 C# 응용 프로그램을 개발하고 있습니다.
폼의 일부 기능이 변경되어 인스턴스가 닫히면 인스턴스화 된 Excel 응용 프로그램이 종료되고 메모리에서 정리됩니다.C# : 닫는 이벤트를 Excel에서 닫는 창 양식

내가 원하는 것은 그 반대입니다. Excel의 내 인스턴스가 종료 될 때 내 Windows Form을 닫으려고합니다.

+0

Excel 프로세스가 종료되면 폴링 프로세스가 실행되고 종료됩니다. – CodingBarfield

+1

Visual Studio 2008 또는 2010을 사용하는 경우 양식을 완전히 건너 뛰고 Excel 추가 기능을 만들 수 있습니다. - http://msdn.microsoft.com/en-us/library/cc668205.aspx – JMK

+0

내 신청서의 요점. 나는 이렇게 할 필요가있다. 내가 모르는 것은 C#의 인스턴스화 된 응용 프로그램이 종료 될 때 내 C# 응용 프로그램을 닫을 청취자를 설정하는 방법입니다 ... – Jsncrdnl

답변

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

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 응용 프로그램을 사용하여 작업 할 때의 문제점은 사용자가 기본 창을 닫더라도 pr ocess는 백그라운드에서 계속 실행됩니다. 완전히 공개하려면 Application.Quit으로 전화해야하지만 해결해야 할 문제가있는 창을 닫은 사용자를 감지 할 때만해야합니다. 여기에서 순환 참조가 있습니다. D

관련 에 대한 래치는 Exited 이벤트가 실행되지 않으므로 (작업 관리자의 백그라운드 프로세스를 종료하더라도) 작동하지 않는 것으로 보입니다. 내 생각 엔이 이벤트는 process = Process.Start(...)을 통해 시작된 프로세스에서만 해고됩니다.

Excel의 기본 창이 표시되는 경우 볼 수있는 유일한 해결책은 폴링입니다. 일단 그렇지 않다면 아마 사용자가 메인 윈도우를 닫고 엑셀 어플리케이션이 종료되어야한다는 것을 의미합니다 (엑셀의 메인 윈도우의 가시성이 사용자가 프로세스를 종료하기를 원할 때가 아닌 다른 시나리오가 있다면이 솔루션은 그렇지 않습니다) 유효한). 거기에서 그것은 꽤 간단합니다.

+0

나는 당신과 동의합니다. 유일한 문제는 내가이 작업을 수행하는 데 필요한 관리자 권한을 가지고 있지 않다는 것입니다.'process.Handle.ToInt32()'관리자 권한이 필요없이 할 수있는 방법이 없습니까 ?? – Jsncrdnl

+0

@ Kuroicloud666 : 업데이트를 확인하십시오. 그 예쁜 아니지만 그것은 작동하는 것. – InBetween

2

이것은 동일한 시나리오에서 수행 한 작업입니다.

는 I 앱 폐쇄 방법

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

를 호출됩니다.

희망이이 나는 시작 Visio가 종료 또는 충돌을 잡으려고했던 것입니다, 당신의 첫 번째 시도는 일 것

+0

"크로스 스레드 작업이 유효하지 않습니다 : 컨트롤 'Form1'이 (가) 만들어진 스레드가 아닌 다른 스레드에서 액세스했습니다."라는 폼을 직접 닫은 후 대리인을 추가했습니다. 예외가 발생했습니다. –

+0

솔루션에 문제가있는 것은 "Microsoft.Office.Interop.Excel.Application"이 아니기 때문에 내 응용 프로그램과 시작된 프로세스 사이의 상호 작용을 사용할 수는 없지만 간단한 프로세스입니다. 나는이 시점에서 그것에 대한 어떠한 통제도하지 않는다 ... – Jsncrdnl

0

가 바로 프로세스 이벤트의 모금을 enavle 필요가 있습니다.

    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); 
관련 문제