从MS-Word ApplicationClass获取PID?

时间:2009-05-02 14:28:58

标签: c# ms-word pid

考虑以下代码:

using Microsoft.Office.Interop.Word;

ApplicationClass _application = new ApplicationClass();

我可以从_application?

启动的Winword.exe进程中获取PID

我需要PID,因为文件损坏,即使使用此代码,我也无法退出ApplicationClass:

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

我无法搜索winword.exe进程并将其杀死,因为我会有几个,而且我不知道要杀哪个。如果我可以为每个ApplicationClass获取一个PID,我可能会杀死正确的winword.exe进程,这会给我带来麻烦。

9 个答案:

答案 0 :(得分:7)

以下是如何做到的。

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

答案 1 :(得分:3)

Word文件中可能存在一些错误。因此,当您使用方法Word.ApplicationClass.Documents.Open()打开文件时,将显示一个对话框,该过程将挂起。

请改用Word.ApplicationClass.Documents.OpenNoRepairDialog()。我发现它解决了这个问题。

答案 2 :(得分:2)

通常的方法是将Word的标题更改为唯一的标题,并跳过顶级窗口列表,直到找到它(EnumWindows)。

答案 3 :(得分: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();

答案 4 :(得分:2)

最后,我想出了解决用户“名称”中的“使用中文件锁定”的方法,而Word文档没有被用户打开,但是我们的程序将在后台进程中产生空白标题,我们也可以在后台杀死那些虚假的WINWORD。

enter image description here

enter image description here

通过此代码,我们无需使用 ReleaseComObject(_application),我真的不知道这是一个好主意,因为当我重新打开该文件时,第一次发布时看不到任何内容。文档至少需要关闭然后再次打开。

    public static void KillProcessBlankMainTitle(string name) // WINWORD
    {
        foreach (Process clsProcess in Process.GetProcesses())
        {

            if (Process.GetCurrentProcess().Id == clsProcess.Id)
                continue;
            if (clsProcess.ProcessName.Equals(name))
            {
                if(clsProcess.MainWindowTitle.Equals(""))
                    clsProcess.Kill();
            }
        }
    }

答案 5 :(得分:1)

不,遗憾的是,没有办法将ApplicationClass的实例与正在运行的Word进程相关联。

为什么需要杀死Word的实例?难道你不能要求它关闭所有文件然后停止使用该实例吗?如果您最终删除了对该类的所有引用,则GC将启动并取消COM服务器。

答案 6 :(得分:1)

在启动应用程序之前,列出所有正在运行的Word进程,启动应用程序,然后再次列出正在运行的Word进程。在第二个列表中找到但在第一个列表中找不到的过程是正确的:

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

该方法存在明显的时序问题,但它是我发现的唯一一个在大多数情况下可靠运行的方法。

答案 7 :(得分:1)

假期在我们的街道上! 我喝了多少血的“话语” ...

获取PID的方法是什么

  1. 获取进程列表,运行WORD,获取进程列表,其中将是所需的进程。 如果多线程的缺点,那将是一个大问题!!!
  2. 在安装过程中,窗口的唯一名称。 “冰先生”给Guid带来了一个好主意。 缺点是Windows OS的功能,如果该进程生成的窗口不具有display属性,则该进程将失去Title属性,并且该属性将为空。即,必须始终为wordApp.Visible = true。我们要么做对,做魔术,然后再做错。
  3. 您可以通过打开的文档的窗口获取Hwnd!如其中一条消息https://stackoverflow.com/a/59146157/4143902中所建议 缺点是您需要暂时创建一个不可见的文档窗口并获取Hwnd,将其关闭并继续工作。最佳选择。

示例:

// Setting up the environment
app.Visible = false;
app.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
app.AutomationSecurity = Microsoft.Office.Core.MsoAutomationSecurity.msoAutomationSecurityForceDisable;
app.ScreenUpdating = false;

// The interface is a collection of documents
Word.Documents docs = app.Documents;

// Getting the window handle
Word.Document trashDoc = docs.Add();
Word.Window wind = trashDoc.ActiveWindow;
// Converting the handle to the process id
int intProcId;
GetWindowThreadProcessId(wind.Hwnd, out intProcId);
// If we want multithreading, we store the dictionary task - >window id
lock (objWorkThreadLock)
{
    if (dictThread.ContainsKey(idTask)) dictThread[idTask] = intProcId;
}
trashDoc.Saved = true;
trashDoc.Close(Word.WdSaveOptions.wdDoNotSaveChanges, Type.Missing, Type.Missing);
if (trashDoc != null) Marshal.ReleaseComObject(trashDoc);
if (wind != null) Marshal.ReleaseComObject(trashDoc);

// Work further
Word.Document doc = null;
doc = docs.OpenNoRepairDialog( ... )

...

[DllImport("user32.dll")]
public static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);

public void Killing(int intProcId)
{
    if (intProcId != 0)
    {
        try
        {
            Process proc = Process.GetProcessById(intProcId);
            proc.Kill();
        }
        catch (Exception ex)
        {
        }
    }
}

答案 8 :(得分:0)

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