Obtener PID de MS-Word ApplicationClass?

Considera este código:

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

¿Puedo obtener el PID del proceso Winword.exe que inició la aplicación _application?

Necesito el PID porque con archivos corruptos, simplemente no puedo salir de ApplicationClass, incluso usando este código:

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

No puedo buscar el proceso winword.exe y matarlo, porque tendré varios, y no sé cuál matar. Si puedo obtener un PID para cada ApplicationClass, podría matar el proceso correcto de winword.exe que me está dando problemas para abandonarlo.

Aquí es cómo hacerlo.

 //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; } 

Puede haber algún error en el archivo de Word. Como resultado, cuando abre el archivo con el método Word.ApplicationClass.Documents.Open() , se mostrará un diálogo y el proceso se bloqueará.

Use Word.ApplicationClass.Documents.OpenNoRepairDialog() lugar. Encontré que arregló el problema.

La forma habitual de conseguirlo es cambiar el título de Word a algo único y saltar a través de la lista de ventanas de nivel superior hasta que lo encuentre (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(); 

No, lamentablemente no hay forma de asociar una instancia de ApplicationClass con un proceso en ejecución de Word.

¿Por qué necesitas matar la instancia de Word? ¿No podría simplemente pedirle que cierre todos sus documentos y luego simplemente dejar de usar esa instancia? Si elimina todas las referencias a la clase, eventualmente el GC entrará en acción y desactivará el servidor COM .

Antes de iniciar su aplicación, enumere todos los procesos de Word en ejecución, inicie su aplicación y vuelva a enumerar los procesos de Word en ejecución. El proceso que se encuentra en la segunda lista y no se encuentra en el primero es el correcto:

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

El método tiene problemas de sincronización obvios, pero es el único que he encontrado que funciona confiablemente la mayor parte del tiempo.