2009-05-02 21 views
13

Considerate questo codice:Ottieni PID da MS-Word ApplicationClass?

using Microsoft.Office.Interop.Word; 

ApplicationClass _application = new ApplicationClass(); 

Posso ottenere il PID dal processo Winword.exe che è stato lanciato dal _Application?

Ho bisogno il PID, perché con i file danneggiati, non riesco proprio a uscire dal ApplicationClass, anche utilizzando questo codice:

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

Non posso cercare il processo Winword.exe e uccidere, perché Ne avrò diversi e non so quale uccidere. Se riesco a ottenere un PID per ogni ApplicationClass, potrei semplicemente uccidere il processo winword.exe corretto che mi sta dando problemi per uscire.

risposta

5

Ecco come procedere.

//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 puoi pubblicare la classe 'StaticMethods'? – BrunoLM

+3

Ho provato questo, ma tutti i miei processi di parole MainWindowTitle sono vuoti e l'impostazione della didascalia su una stringa non sembra avere un effetto, mi manca qualcosa? – Arvand

1

No, sfortunatamente non è possibile associare un'istanza di ApplicationClass a un processo in esecuzione di Word.

Perché è necessario eliminare l'istanza di Word? Non potresti semplicemente chiederlo di chiudere tutti i suoi documenti e poi semplicemente smettere di usare quell'istanza? Se si rimuovono tutti i riferimenti alla classe, lo GC eseguirà il kicking e il server COM.

+3

Non riesco a chiudere il documento perché non è ancora stato aperto. Il documento è corrotto, quindi appare una finestra di dialogo in attesa di un intervento umano. Tuttavia, uso il codice in un servizio e apro migliaia di documenti di parole e un intervento umano è impossibile. Esamina un po 'di più e Excel ApplicationClass ha un Hwnd. Con: [DllImport ("user32.dll")] extern statico GetWindowThreadProcessId (int hWnd, out int lpdwProcessId); Posso ottenere il PID. Ma Word ApplicationClass non ha un Hwnd ... Che vergogna ... – Ricardo

2

Il modo normale per ottenerlo è di cambiare il titolo di Word in qualcosa di unico e saltare l'elenco delle finestre di livello superiore finché non lo trovi (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 classe excel.ApplicationClass la proprietà Hwnd, non la classe word.ApplicationClass di cui tratta la domanda. –

2

Ci può essere qualche errore nel file di Word. Di conseguenza, quando apri il file con il metodo Word.ApplicationClass.Documents.Open(), verrà visualizzata una finestra di dialogo e il processo si bloccherà.

Utilizzare invece Word.ApplicationClass.Documents.OpenNoRepairDialog(). Ho trovato risolto il problema.

1

Prima di avviare l'applicazione, elencare tutti i processi in esecuzione di Word, avviare l'applicazione ed elencare nuovamente i processi in esecuzione. Il processo trovato nel secondo elenco e non trovato nel primo è quello giusto:

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

Il metodo ha problemi di temporizzazione evidenti, ma è l'unico che ho trovato che funziona in modo affidabile la maggior parte del tempo .

+0

questa non può essere la risposta, perché non vi è alcuna garanzia che solo la vostra applicazione stia aprendo i processi di winword! – Arvand