Domanda

Considera questo codice:

using Microsoft.Office.Interop.Word;

ApplicationClass _application = new ApplicationClass();

Posso ottenere il PID dal processo Winword.exe avviato da _application?

Ho bisogno del PID perché con file danneggiati, non riesco a chiudere ApplicationClass, anche usando questo codice:

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

Non riesco a cercare il processo winword.exe e ucciderlo, perché ne avrò diversi e non so quale uccidere. Se riesco a ottenere un PID per ogni ApplicationClass, potrei semplicemente terminare il corretto processo winword.exe che mi dà problemi per uscire.

È stato utile?

Soluzione

Ecco come farlo.

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

while (GetProcessIdByWindowTitle(AppId) == Int32.MaxValue) //Loop till u get
{
    Thread.Sleep(5);
}

///Get the pid by for word application
this.WordPid = GetProcessIdByWindowTitle(AppId);

///You canh hide the application afterward            
this.oWordApp.Application.Visible = false;

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

Altri suggerimenti

Potrebbe esserci un errore nel file Word. Di conseguenza, quando si apre il file con il metodo Word.ApplicationClass.Documents.Open () , viene visualizzata una finestra di dialogo e il processo si bloccherà.

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

Il solito modo per ottenerlo è cambiare il titolo di Word in qualcosa di unico e saltare l'elenco delle finestre di livello superiore fino a quando non lo trovi (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, sfortunatamente non c'è modo di associare un'istanza di ApplicationClass a un processo in esecuzione di Word.

Perché è necessario uccidere l'istanza di Word? Non potresti semplicemente chiedergli di chiudere tutti i suoi documenti e poi semplicemente smettere di usare quell'istanza? Se rimuovi tutti i riferimenti alla classe, alla fine GC prenderà il via e prenderà lungo il COM server.

Prima di avviare l'applicazione, elencare tutti i processi di Word in esecuzione, avviare l'applicazione ed elencare nuovamente i processi di Word 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 presenta ovvi problemi di temporizzazione, ma è l'unico che ho trovato che funziona in modo affidabile per la maggior parte del tempo.

enter code here  public void OpenWord(string Path, bool IsVisible)
    {

        MessageFilter.Register();
        object oMissing = Missing.Value;
        GUIDCaption = Guid.NewGuid().ToString();
        wordApp = new Microsoft.Office.Interop.Word.ApplicationClass();
        wordApp.Visible = IsVisible;
        wordApp.Caption = GUIDCaption;
        object oPath = Path;
        wordDoc = wordApp.Documents.Open(ref  oPath, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing);

    }
    /// <summary>
    /// 关闭文件
    /// </summary>
    public void CloseWord()
    {
        object oMissing = Missing.Value;
        GUIDCaption = "";
        if (null != wordDoc)
        {
            wordDoc.Close(ref oMissing, ref oMissing, ref oMissing);
        }
        if (null != wordApp)
        {
            wordApp.Quit(ref oMissing, ref oMissing, ref oMissing);
        }
        MessageFilter.Revoke();
        GC.Collect();
        KillwordProcess();

    }
    /// <summary>
    /// 结束word进程
    /// </summary>
    public void KillwordProcess()
    {
        try
        {
            Process[] myProcesses;
            //DateTime startTime;
            myProcesses = Process.GetProcessesByName("WINWORD");

            //通过进程窗口标题判断
            foreach (Process myProcess in myProcesses)
            {
                if (null != GUIDCaption && GUIDCaption.Length > 0 && myProcess.MainWindowTitle.Equals(GUIDCaption))
                {
                    myProcess.Kill();
                }
            }
            MessageFilter.Revoke();
        }
        catch (Exception e)
        {
            throw e;
        }
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top