从MS-Word ApplicationClass获取PID?

考虑以下代码:

using Microsoft.Office.Interop.Word; ApplicationClass _application = new ApplicationClass(); 

我可以从_application启动的Winword.exe进程中获取PID吗?

我需要PID因为文件损坏,我只是不能退出ApplicationClass,即使使用这段代码:

 _application.Quit(ref saveFile, ref missing, ref missing); System.Runtime.InteropServices.Marshal.ReleaseComObject(_application); GC.Collect(); GC.WaitForPendingFinalizers(); 

我无法搜索winword.exe进程并将其杀死,因为我会有几个,而且我不知道要杀哪个。 如果我可以为每个ApplicationClass获取一个PID,我可以杀死正确的winword.exe进程,这会给我带来麻烦。

这是怎么做的。

 //Set the AppId string AppId = ""+DateTime.Now.Ticks(); //A random title //Create an identity for the app this.oWordApp = new Microsoft.Office.Interop.Word.ApplicationClass(); this.oWordApp.Application.Caption = AppId; this.oWordApp.Application.Visible = true; ///Get the pid by for word application this.WordPid = StaticMethods.GetProcessIdByWindowTitle(AppId); while ( StaticMethods.GetProcessIdByWindowTitle(AppId) == Int32.MaxValue) //Loop till u get { Thread.Sleep(5); } this.WordPid = StaticMethods.GetProcessIdByWindowTitle(AppId); ///You canh hide the application afterward this.oWordApp.Application.Visible = false; string this.oWordApp = new Microsoft.Office.Interop.Word.ApplicationClass(); this.oWordApp.Application.Caption = AppId; this.oWordApp.Application.Visible = true; ///Get the pid by this.WordPid = StaticMethods.GetProcessIdByWindowTitle(AppId); while ( StaticMethods.GetProcessIdByWindowTitle(AppId) == Int32.MaxValue) { Thread.Sleep(5); } this.WordPid = StaticMethods.GetProcessIdByWindowTitle(AppId); this.oWordApp.Application.Visible = false; //You Can hide the application now ///  /// Returns the name of that process given by that title ///  /// Int32MaxValue returned if it cant be found. ///  public static int GetProcessIdByWindowTitle(string AppId) { Process[] P_CESSES = Process.GetProcesses(); for (int p_count = 0; p_count < P_CESSES.Length; p_count++) { if (P_CESSES[p_count].MainWindowTitle.Equals(AppId)) { return P_CESSES[p_count].Id; } } return Int32.MaxValue; } 

Word文件中可能存在一些错误。 因此,当您使用Word.ApplicationClass.Documents.Open()方法打开文件时,将显示一个对话框,该过程将挂起。

请改用Word.ApplicationClass.Documents.OpenNoRepairDialog() 。 我发现它解决了这个问题。

获得它的通常方法是将Word的标题更改为独特的内容并跳过顶级窗口列表,直到找到它(EnumWindows)。

http://www.codekeep.net/snippets/7835116d-b254-466e-ae66-666e4fa3ea5e.aspx

 ///Return Type: DWORD->unsigned int ///hWnd: HWND->HWND__* ///lpdwProcessId: LPDWORD->DWORD* [System.Runtime.InteropServices.DllImportAttribute( "user32.dll", EntryPoint = "GetWindowThreadProcessId" )] public static extern int GetWindowThreadProcessId ( [System.Runtime.InteropServices.InAttribute()] System.IntPtr hWnd, out int lpdwProcessId ); private int _ExcelPID = 0; Process _ExcelProcess; private Application _ExcelApp = new ApplicationClass(); GetWindowThreadProcessId( new IntPtr(_ExcelApp.Hwnd), out _ExcelPID ); _ExcelProcess = System.Diagnostics.Process.GetProcessById( _ExcelPID ); ... _ExcelProcess.Kill(); 

不,遗憾的是,没有办法将ApplicationClass的实例与正在运行的Word进程相关联。

为什么你需要杀死Word的实例? 难道你不能要求它关闭所有文件然后停止使用该实例吗? 如果删除对该类的所有引用, GC最终将启动并关闭COM服务器。

在启动应用程序之前,列出所有正在运行的Word进程,启动应用程序,然后再次列出正在运行的Word进程。 在第二个列表中找到但在第一个列表中找不到的过程是正确的:

 var oPL1 = from proc in Process.GetProcessesByName("WINWORD") select proc.Id; var app = new Word.Application(); var oPL2 = from proc in Process.GetProcessesByName("WINWORD") select proc.Id; var pid = (from p in oPL2 where !oPL1.Contains(p) select p).ToList()[0]; 

该方法有明显的时间问题,但它是我发现的唯一一个在大多数情况下可靠运行的方法。