2009-05-02 30 views
13

consideran este código:Obtener PID de MS-Word ApplicationClass?

using Microsoft.Office.Interop.Word; 

ApplicationClass _application = new ApplicationClass(); 

¿Puedo obtener el PID del proceso Winword.exe que fue lanzada por el _application?

necesito el PID porque con archivos dañados, simplemente no puedo salir de la ApplicationClass, incluso utilizando 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.

Respuesta

5

Aquí se muestra 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 

/// <summary> 
/// Returns the name of that process given by that title 
/// </summary> 
/// <param name="AppId">Int32MaxValue returned if it cant be found.</param> 
/// <returns></returns> 
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; 
} 
+2

@Mmyikka ¿puedes publicar la clase 'StaticMethods'? – BrunoLM

+3

Intenté esto pero todos mis procesos de Word MainWindowTitle están vacíos y configurar el título de una cadena no parece tener un efecto. ¿Me falta algo? – Arvand

1

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

¿Por qué necesita 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, finalmente, el GC se activará y desactivará el servidor COM.

+3

No puedo cerrar el documento porque aún no está abierto. El documento está dañado por lo que aparece un cuadro de diálogo de ventana en espera de una intervención humana. Sin embargo, uso el código en un servicio, y abro miles de documentos de Word, y la intervención humana es imposible. Investigo un poco más y Excel ApplicationClass tiene un Hwnd. Con: [DllImport ("user32.dll")] static extern int GetWindowThreadProcessId (int hWnd, out int lpdwProcessId); Puedo obtener el PID. Pero Word ApplicationClass no tiene un Hwnd ... Qué lástima ... – Ricardo

2

La forma habitual de conseguirlo es cambiar el título de Word por algo único y pasar por la lista de ventanas de nivel superior hasta encontrarlo (EnumWindows).

2

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(); 
+0

Solo la clase excel.ApplicationClass es la propiedad Hwnd, no la clase word.ApplicationClass de la que se trata la pregunta. –

2

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() en su lugar. Encontré que arregló el problema.

1

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 se encuentra en la segunda lista y no se encuentra en la primera de ellas es la correcta:

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 tiempo obvias, pero es el único que he encontrado que funciona de forma fiable la mayoría de las veces .

+0

esto no puede ser la respuesta, porque no hay garantía de que solo su aplicación está abriendo procesos winword! – Arvand