Application.Quit()方法无法清除进程

我已经看过很多关于这个post从Google搜索中返回的post,但是他们中提到的解决方案都没有为我清楚。 所以,我以为我会尝试自己。

在这段代码之后:

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

我可以发出ppt.Quit(); 命令和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()将无法工作。 关于打开演示文稿的东西,即使我然后关闭它,也会阻止Quit()工作,它会出现。

任何人都有任何关于如何让应用程序退出正确的想法?

以下KB Aritcle可能会帮助您解决问题的根源。 http://support.microsoft.com/kb/317109

您可能需要明确调用ppt实例上的System.Runtime.InteropServices.Marshal.ReleaseComObject 。

powerPoint.Presentations.Open(..)

请注意Presentations对象的使用。 COM使用基于引用计数的手动内存管理,每个COM接口都有一个AddRef()和一个Release()方法。 获取对象时,AddRef调用是自动的。 完成后,您必须调用Release()方法。 在此处使用Presentations对象添加对Presentations对象的引用。 这反过来又添加了对内部应用程序对象的引用。

这与.NET框架中的内存管理非常不兼容。 它是自动的,垃圾收集器负责处理它。 对于COM对象也是如此,interop包装器有一个终结器,当它看到COM对象上没有留下.NET引用时,它会减少引用计数。

也许你会看到它的发展方向:在发布所有对象引用之前,PowerPoint无法退出。 在垃圾收集器运行并且终结器线程完成之前,这是不可能发生的。 您对Quit()方法的调用不会使垃圾收集器运行。 只有GC.Collect()+ GC.WaitForPendingFinalizers可以做到这一点。

您也可以采用手动方法。 它需要Marshal.ReleaseComObject()。 这样做很难做到,请注意,您没有对代码中任何位置存储的Presentations对象的引用。 您必须完全重写代码以跟踪这些引用,以便可以在它们上调用ReleaseComObject()。

我不能推荐这个。 如果你真的想要PowerPoint退出,那么更好的方法是确保所有引用都为null并调用GC.Collect()和GC.WFPF。 我也不能推荐这个。 它最终会退出。 别担心。

替代你的问题。 在完成工作后找到该流程然后将其删除。

码:

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

命名空间: System.Diagnostics

我在工作中面临同样的问题……你尝试下面的代码它正在工作

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

试试下面的内容。

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

您可能也必须以这种方式使用它

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

因为,请参阅此页面的最后一点http://code.msdn.microsoft.com/office/CSAutomatePowerPoint-b312d416

如果您有多个PowerPoint实例打开,您可以使用这些内容 – 这是我发现关闭PowerPoint应用程序时最简单的方法,当要求退出时,这些应用程序无法清除。

这就是我最终杀死/关闭PowerPoint(由已打开的文档路径指定)的方式

 ///  /// Close open PowerPoint document ///  /// Path to document /// Save changes to document 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")); } } 

File Util类,为您提供当前锁定文档的进程列表。

 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); ///  /// Find out what process(es) have a lock on the specified file. ///  /// Path of the file. /// Processes locking the file /// 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) /// ///  static public List WhoIsLocking(string path) { uint handle; string key = Guid.NewGuid().ToString(); List processes = new List(); 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((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; } }