可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Consider this code:
using Microsoft.Office.Interop.Word;
ApplicationClass _application = new ApplicationClass();
Can I get the PID from the Winword.exe process that was launched by the _application?
I need the PID because with corrupted files, I just can't quit the ApplicationClass, even using this code:
_application.Quit(ref saveFile, ref missing, ref missing);
System.Runtime.InteropServices.Marshal.ReleaseComObject(_application);
GC.Collect();
GC.WaitForPendingFinalizers();
I can't search for the winword.exe process and kill it, because I will have several, and I don't know which one to kill. If I can get a PID for each ApplicationClass, I could just kill the correct winword.exe process that is giving me troubles to quit.
回答1:
Here is how to do it.
//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;
}
回答2:
There may be some error in the Word file. As a result, when you open the file with the method Word.ApplicationClass.Documents.Open()
, there will be a dialog shown and the process will hang.
Use Word.ApplicationClass.Documents.OpenNoRepairDialog()
instead. I found it fixed the problem.
回答3:
The usual way to get it is to change Word's title to something unique and hop through the top-level window list until you find it (EnumWindows).
回答4:
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();
回答5:
No, unfortunately there is no way to associate an instance of ApplicationClass with a running process of Word.
Why do you need to kill the instance of Word? Couldn't you just ask it to close all of its documents and then simply stop using that instance? If you remove all references to the class eventually the GC will kick in and take down the COM server.
回答6:
Before you start your application, list all running Word processes, start your application, and list running Word processes again. The process found in the second list and not found in the first one is the right one:
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];
The method has obvious timing issues, but it is the only one I've found which works reliably most of the time.
回答7:
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;
}
}