15

考虑这段代码:

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 进程,这让我很难退出。

4

9 回答 9

10

这是如何做到的。

//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;
}
于 2011-07-01T09:42:29.533 回答
3

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

改为使用Word.ApplicationClass.Documents.OpenNoRepairDialog()。我发现它解决了问题。

于 2010-08-03T14:32:34.967 回答
2

获取它的常用方法是将 Word 的标题更改为独特的名称,然后在顶层窗口列表中跳转,直到找到它 (EnumWindows)。

于 2009-05-02T15:10:18.933 回答
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();
于 2009-09-08T07:25:44.347 回答
2

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

在此处输入图像描述

在此处输入图像描述

通过这段代码,我们不需要使用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();
            }
        }
    }
于 2020-03-18T19:12:14.693 回答
2

在我们的街道上迎来了假期!“Word”从我这里喝了多少血……

获取 PID 的方法有哪些:

  1. 获取进程列表,运行 WORD,获取进程列表,其中将是所需的进程。缺点如果多线程,那就是大问题了!!!
  2. 通过安装一个唯一的窗口名称。“Bing”先生给Guid带来了一个好主意。缺点是Windows操作系统的一个特性,如果进程生成的窗口没有显示属性,进程就会失去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)
        {
        }
    }
}
于 2020-07-31T04:56:31.953 回答
1

不,很遗憾,无法将 ApplicationClass 的实例与 Word 的运行进程相关联。

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

于 2009-05-02T14:42:11.903 回答
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];

该方法有明显的时间问题,但它是我发现的唯一一种在大多数情况下都能可靠工作的方法。

于 2014-02-07T09:41:37.203 回答
1
    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;
        }
    }
于 2019-04-22T10:13:48.563 回答