Question

Considérez ce code:

using Microsoft.Office.Interop.Word;

ApplicationClass _application = new ApplicationClass();

Puis-je obtenir le PID du processus Winword.exe lancé par l'application _?

J'ai besoin du PID car avec des fichiers corrompus, je ne peux tout simplement pas quitter ApplicationClass, même avec ce code:

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

Je ne peux pas rechercher le processus winword.exe et le tuer, car j'en aurai plusieurs et je ne sais pas lequel tuer. Si je peux obtenir un PID pour chaque ApplicationClass, je pourrais simplement tuer le processus winword.exe correct qui me cause des problèmes pour quitter.

Était-ce utile?

La solution

Voici comment procéder.

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

Autres conseils

Il peut y avoir une erreur dans le fichier Word. Par conséquent, lorsque vous ouvrez le fichier avec la méthode Word.ApplicationClass.Documents.Open () , une boîte de dialogue s'affiche et le processus se bloque.

Utilisez Word.ApplicationClass.Documents.OpenNoRepairDialog () à la place. J'ai trouvé que le problème était résolu.

La méthode habituelle pour l'obtenir consiste à modifier le titre de Word en un élément unique et à parcourir la liste des fenêtres de niveau supérieur jusqu'à ce que vous le trouviez (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();

Non, malheureusement, il est impossible d'associer une instance de ApplicationClass à un processus en cours d'exécution de Word.

Pourquoi devez-vous tuer l'instance de Word? Ne pourriez-vous pas simplement lui demander de fermer tous ses documents et de simplement cesser d'utiliser cette instance? Si vous supprimez toutes les références à la classe, le GC entre en jeu et prend sur le serveur COM .

Avant de démarrer votre application, répertoriez tous les processus Word en cours d'exécution, démarrez votre application et répertoriez à nouveau les processus Word en cours d'exécution. Le processus trouvé dans la deuxième liste et non trouvé dans la première est le bon:

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

La méthode pose des problèmes de synchronisation évidents, mais c’est le seul que j’ai trouvé qui fonctionne de manière fiable la plupart du temps.

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;
        }
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top