2010-07-07 3 views
9

Google 검색에서 많은 게시물을 보았습니다.하지만 여기에 언급 된 솔루션 중 어느 것도 나를 위해이 내용을 정리하지 않았습니다. 그래서 나는 나 자신을 시험 할 줄 알았다. 코드 블록 후Application.Quit() 메소드가 프로세스를 지우지 못했습니다.

: I)을합니다 (ppt.Quit을 실행할 수

PowerPoint.Application powerPoint = new Microsoft.Office.Interop.PowerPoint.Application(); 
powerPoint.Visible = Office.MsoTriState.msoTrue; 
Microsoft.Office.Interop.PowerPoint.Presentation ppt = null;enter code here 

; 명령 및 Powerpoint가 닫히고 실행중인 프로세스가 남아 있지 않습니다. 이 코드 뒤에 내가 할 경우

그러나이 : ​​

ppt = powerPoint.Presentations.Open(localCopyOfPPT, 
            Microsoft.Office.Core.MsoTriState.msoCTrue, 
            Microsoft.Office.Core.MsoTriState.msoTriStateMixed, 
            Microsoft.Office.Core.MsoTriState.msoTrue); 
ppt.Close(); 
powerPoint.Quit(); 

는 다음,()는 작동하지 않습니다 종료합니다. 프레젠테이션을 열 때 프레젠테이션을 닫아도 Quit()이 작동하지 않는 경우 프레젠테이션이 나타납니다.

아무도 내가 correctlY 종료하는 방법을 응용 프로그램을 얻을 수있는 방법에 대한 생각이 있습니까?

+0

"종료()가 작동하지 않음"보다 실패 모드에 대한 자세한 정보를 제공하면 도움이됩니다. –

+0

죄송합니다. Quit() 메서드를 사용하려는 내 의도는 응용 프로그램이 실행중인 Powerpoint 프로세스를 벗어나는 것을 방지하는 것입니다. Quit()은 Powerpoint를 계속 실행 중이다. 오류는 아니지만 프로세스를 종료하지는 않습니다. – Henry

답변

6

다음 KB 아 트리클은 문제의 근본 원인을 찾는 데 도움이 될 수 있습니다. http://support.microsoft.com/kb/317109

ppt 인스턴스에 System.Runtime.InteropServices.Marshal.ReleaseComObject을 명시 적으로 호출해야 할 수도 있습니다.

+0

ReleaseComObject를 실행하는 것이 티켓이었던 것 같습니다. 나는 Presentations 객체를 선언하고 그 객체와 ppt 객체 모두에서 ReleaseComObject 메소드를 실행해야만했다. 일단 두 개체를 릴리스하면 Application.Quit()가 작동하고 Powerpoint.exe 프로세스가 실행되지 않고 남아 있습니다. 이 코드로 상속 된 문제를 해결하고 오랫동안 저에게 잔소리 해 왔습니다. 도움을 많이 주셔서 감사합니다. – Henry

3

powerPoint.Presentations.Open (..) 프리젠 테이션의 사용을 반대

참고. COM은 참조 카운팅을 기반으로하는 수동 메모리 관리를 사용하며 모든 COM 인터페이스에는 AddRef() 및 Release() 메서드가 있습니다. AddRef 호출은 개체를 가져올 때 자동으로 수행됩니다. 작업이 끝나면 Release() 메소드를 호출해야합니다. 여기서 Presentations 객체를 사용하면 Presentations 객체에 대한 참조가 추가됩니다. 내부 애플리케이션 객체에 대한 참조가 차례로 추가됩니다.

.NET Framework에서 메모리 관리와 호환되지 않습니다. 자동으로 가비지 컬렉터가 처리합니다. interop 래퍼는 COM 개체에 대해서도 마찬가지이며, COM 개체에 .NET 참조가 남아 있지 않을 때 참조 카운트를 감소시킵니다.

아마도 이것이 어디로가는 지 알 수 있습니다. PowerPoint는 모든 개체 참조가 해제 될 때까지 종료 할 수 없습니다. 가비지 수집기가 실행되고 종료 자 스레드가 완료 될 때까지는 발생할 수 없습니다. Quit() 메서드를 호출하면 이 아닌 가비지 수집기가 실행됩니다. GC.Collect() + GC.WaitForPendingFinalizers 만 가능합니다.

또한 수동 방식을 사용할 수도 있습니다. Marshal.ReleaseComObject()가 필요합니다. 이렇게하는 것은 어렵습니다. 코드의 아무 곳에 나 저장된 Presentations 개체에 대한 참조가 없습니다. 이 참조를 추적 할 수 있도록 코드를 완전히 다시 작성해야 ReleaseComObject()를 호출 할 수 있습니다.

나는 이것을 추천 할 수 없다. 정말로 이라면 PowerPoint를 종료하고 더 좋은 방법은 모든 참조가 null인지 확인하고 GC.Collect() 및 GC.WFPF를 호출하는 것입니다. 나는 이것을 추천 할 수도 없다. 결국 그만 둘 것이다. 그것에 대해 걱정하지 마십시오.

2

나는 내 작품에 동일한 문제에 직면 ... 당신은 당신의 문제에 대한

PowerPoint.Application powerPoint = new Microsoft.Office.Interop.PowerPoint.Application(); 
    //powerPoint.Visible = Office.MsoTriState.msoTrue; 
    Microsoft.Office.Interop.PowerPoint.Presentation ppt = null; 

    try 
    { 
     ppt = powerPoint.Presentations.Open(localCopyOfPPT, 
              Microsoft.Office.Core.MsoTriState.msoCTrue, 
              Microsoft.Office.Core.MsoTriState.msoTriStateMixed, 
              Microsoft.Office.Core.MsoTriState.msoFalse); 
    ppt.Close(); 
    Marshal.FinalReleaseComObject(ppt); 
    }catch(){}finally 
    { 
     powerPoint.Quit(); 
     Marshal.FinalReleaseComObject(powerPoint); 
     GC.Collect(); 
    } 
3

대안을 일하고 코드 아래에보십시오.작업이 완료되면 프로세스를 찾은 다음 죽이십시오.

코드 :

Process[] processes = Process.GetProcessesByName("powerpnt"); 
for (int i = 0; i < processes.Count(); i++) 
{ 
    processes[i].Kill(); 
} 

네임 스페이스 : System.Diagnostics 네임은

+3

왜 Process.GetProcessesByName ("POWERPNT")'가 아닌가? –

+1

이 내 문제를 해결, 감사합니다, –

1

의 마지막 지점을 볼 수 있기 때문에이 방법으로도

GC.Collect(); 
GC.WaitForPendingFinalizers(); 

GC.Collect(); 
GC.WaitForPendingFinalizers(); 

을 이것을 사용 할 수 있습니다 이 줄을 따라 -이 질문은 PowerPoint 응용 프로그램을 닫을 때 가장 쉬운 방법으로 종료하라는 메시지가 나타나면 지우지 않습니다.

이 내가

/// <summary> 
    /// Close open PowerPoint document 
    /// </summary> 
    /// <param name="path">Path to document</param> 
    /// <param name="saveChanges">Save changes to document</param> 
    public void PowerPointCloseOpenDocument(String path, Boolean saveChanges = true) 
    { 
     ppApp = getPowerPointApp(path); 
     PowerPoint.Presentation pp = null; 

     if (!String.IsNullOrEmpty(path)) 
     { 
      foreach (PowerPoint.Presentation p in ppApp.Presentations) 
      { 
       if (p.FullName.Equals(path, StringComparison.CurrentCultureIgnoreCase)) 
       { 
        try 
        { 
         pp = p; 
        } 
        catch (Exception) 
        { } 
        break; 
       } 
      } 
     } 
     if(saveChanges) 
     { 
      if(pp!=null) 
      { 
       pp.Save(); 
      } 
     } 
     if(pp!= null) 
     { 
      Marshal.FinalReleaseComObject(pp); 
     } 
     if(null != ppApp) 
     { 
      Marshal.FinalReleaseComObject(ppApp); 
     } 
     var procs = FileUtil.WhoIsLocking(path); 
     if(procs!= null) 
     { 
      foreach(var proc in procs) 
      { 
       proc.Kill(); 
      } 
     } 
     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 

     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 
    } 

private PowerPoint.Application getPowerPointApp(String path = "") 
    { 
     try 
     { 
      PowerPoint.Application ppapp = null; 
      try 
      { 
       if (!String.IsNullOrEmpty(path)) 
       { 
        ppapp = ((PowerPoint.Presentation)System.Runtime.InteropServices.Marshal.BindToMoniker(path)).Application; 
       } 
      } 
      catch (Exception) { } 
      if (ppapp == null) 
      { 
       try 
       { 
        ppapp = (PowerPoint.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("PowerPoint.Application"); 
       } 
       catch (Exception) 
       { 
        ppapp = new PowerPoint.Application(); 
        ppapp.Visible = Microsoft.Office.Core.MsoTriState.msoTrue; 
       } 
      } 
      if (ppapp != null) 
      { 
       ppapp.DisplayAlerts = Microsoft.Office.Interop.PowerPoint.PpAlertLevel.ppAlertsNone; 
      } 
      try { ppapp.Activate(); } 
      catch (Exception) { } 
      return ppapp; 
     } 
     catch (Exception) 
     { 
      return (PowerPoint.Application)Activator.CreateInstance(Type.GetTypeFromProgID("PowerPoint.Application")); 
     } 
    } 

현재 문서를 잠금 프로세스의 목록을 제공하는 파일 백분율 클래스 (오픈 된 문서 경로 지정) 파워 포인트를 닫는/살인을 끝낼 방법이다.

static public class FileUtil 
{ 
    [StructLayout(LayoutKind.Sequential)] 
    struct RM_UNIQUE_PROCESS 
    { 
     public int dwProcessId; 
     public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime; 
    } 

    const int RmRebootReasonNone = 0; 
    const int CCH_RM_MAX_APP_NAME = 255; 
    const int CCH_RM_MAX_SVC_NAME = 63; 

    enum RM_APP_TYPE 
    { 
     RmUnknownApp = 0, 
     RmMainWindow = 1, 
     RmOtherWindow = 2, 
     RmService = 3, 
     RmExplorer = 4, 
     RmConsole = 5, 
     RmCritical = 1000 
    } 

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
    struct RM_PROCESS_INFO 
    { 
     public RM_UNIQUE_PROCESS Process; 

     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_APP_NAME + 1)] 
     public string strAppName; 

     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)] 
     public string strServiceShortName; 

     public RM_APP_TYPE ApplicationType; 
     public uint AppStatus; 
     public uint TSSessionId; 
     [MarshalAs(UnmanagedType.Bool)] 
     public bool bRestartable; 
    } 

    [DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)] 
    static extern int RmRegisterResources(uint pSessionHandle, 
              UInt32 nFiles, 
              string[] rgsFilenames, 
              UInt32 nApplications, 
              [In] RM_UNIQUE_PROCESS[] rgApplications, 
              UInt32 nServices, 
              string[] rgsServiceNames); 

    [DllImport("rstrtmgr.dll", CharSet = CharSet.Auto)] 
    static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, string strSessionKey); 

    [DllImport("rstrtmgr.dll")] 
    static extern int RmEndSession(uint pSessionHandle); 

    [DllImport("rstrtmgr.dll")] 
    static extern int RmGetList(uint dwSessionHandle, 
           out uint pnProcInfoNeeded, 
           ref uint pnProcInfo, 
           [In, Out] RM_PROCESS_INFO[] rgAffectedApps, 
           ref uint lpdwRebootReasons); 

    /// <summary> 
    /// Find out what process(es) have a lock on the specified file. 
    /// </summary> 
    /// <param name="path">Path of the file.</param> 
    /// <returns>Processes locking the file</returns> 
    /// <remarks>See also: 
    /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa373661(v=vs.85).aspx 
    /// http://wyupdate.googlecode.com/svn-history/r401/trunk/frmFilesInUse.cs (no copyright in code at time of viewing) 
    /// 
    /// </remarks> 
    static public List<Process> WhoIsLocking(string path) 
    { 
     uint handle; 
     string key = Guid.NewGuid().ToString(); 
     List<Process> processes = new List<Process>(); 

     int res = RmStartSession(out handle, 0, key); 
     if (res != 0) throw new Exception("Could not begin restart session. Unable to determine file locker."); 

     try 
     { 
      const int ERROR_MORE_DATA = 234; 
      uint pnProcInfoNeeded = 0, 
       pnProcInfo = 0, 
       lpdwRebootReasons = RmRebootReasonNone; 

      string[] resources = new string[] { path }; // Just checking on one resource. 

      res = RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null); 

      if (res != 0) throw new Exception("Could not register resource."); 

      //Note: there's a race condition here -- the first call to RmGetList() returns 
      //  the total number of process. However, when we call RmGetList() again to get 
      //  the actual processes this number may have increased. 
      res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons); 

      if (res == ERROR_MORE_DATA) 
      { 
       // Create an array to store the process results 
       RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded]; 
       pnProcInfo = pnProcInfoNeeded; 

       // Get the list 
       res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons); 
       if (res == 0) 
       { 
        processes = new List<Process>((int)pnProcInfo); 

        // Enumerate all of the results and add them to the 
        // list to be returned 
        for (int i = 0; i < pnProcInfo; i++) 
        { 
         try 
         { 
          processes.Add(Process.GetProcessById(processInfo[i].Process.dwProcessId)); 
         } 
         // catch the error -- in case the process is no longer running 
         catch (ArgumentException) { } 
        } 
       } 
       else throw new Exception("Could not list processes locking resource."); 
      } 
      else if (res != 0) throw new Exception("Could not list processes locking resource. Failed to get size of result."); 
     } 
     finally 
     { 
      RmEndSession(handle); 
     } 

     return processes; 
    }  
} 
관련 문제