2009-05-02 36 views
13

xem xét mã này:Nhận PID từ MS-Word ApplicationClass?

using Microsoft.Office.Interop.Word; 

ApplicationClass _application = new ApplicationClass(); 

Tôi có thể có được từ quá trình PID Winword.exe đã được đưa ra bởi các _application?

Tôi cần PID vì với các tập tin bị lỗi, tôi chỉ có thể không bỏ ApplicationClass, thậm chí sử dụng mã này:

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

tôi không thể tìm kiếm cho quá trình winword.exe và giết nó, bởi vì Tôi sẽ có một số, và tôi không biết cái nào để giết. Nếu tôi có thể nhận được một PID cho mỗi ApplicationClass, tôi chỉ có thể giết chết quá trình winword.exe chính xác đó là cho tôi khó khăn để bỏ thuốc lá.

Trả lời

5

Đây là cách thực hiện.

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

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

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

this.WordPid = StaticMethods.GetProcessIdByWindowTitle(AppId); 


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

string this.oWordApp = new Microsoft.Office.Interop.Word.ApplicationClass(); 
this.oWordApp.Application.Caption = AppId; 
this.oWordApp.Application.Visible = true; 
///Get the pid by 
this.WordPid = StaticMethods.GetProcessIdByWindowTitle(AppId); 

while (StaticMethods.GetProcessIdByWindowTitle(AppId) == Int32.MaxValue) 
{ 
    Thread.Sleep(5); 
} 

this.WordPid = StaticMethods.GetProcessIdByWindowTitle(AppId); 

this.oWordApp.Application.Visible = false; //You Can hide the application now 

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

@Mmyikka bạn có thể đăng lớp 'StaticMethods' không? – BrunoLM

+3

Tôi đã thử điều này nhưng tất cả các quá trình từ của tôi MainWindowTitle trống và thiết lập chú thích cho một chuỗi dường như không có hiệu ứng, tôi có thiếu cái gì không? – Arvand

1

Không, thật không may là không có cách nào để liên kết một cá thể của ApplicationClass với một tiến trình đang chạy của Word.

Tại sao bạn cần phải giết phiên bản Word? Bạn không thể yêu cầu nó đóng tất cả các tài liệu của nó và sau đó chỉ đơn giản là ngừng sử dụng trường hợp đó? Nếu bạn xóa tất cả các tham chiếu đến lớp cuối cùng thì GC sẽ khởi động và gỡ xuống máy chủ COM.

+3

Tôi không thể đóng tài liệu vì tài liệu chưa được mở. Tài liệu bị hỏng nên hộp thoại cửa sổ xuất hiện chờ đợi sự can thiệp của con người. Tuy nhiên, tôi sử dụng mã trong một dịch vụ, và tôi mở hàng ngàn tài liệu từ, và sự can thiệp của con người là không thể. Tôi điều tra thêm một chút và Excel ApplicationClass có Hwnd. Với: [DllImport ("user32.dll")] static extern int GetWindowThreadProcessId (int hWnd, out int lpdwProcessId); Tôi có thể lấy PID. Nhưng từ ApplicationClass không có một Hwnd ... Thật là một sự xấu hổ ... – Ricardo

2

Cách thông thường để làm cho nó là thay đổi tiêu đề của Word thành một cái gì đó độc đáo và nhảy qua danh sách cửa sổ cấp cao nhất cho đến khi bạn tìm thấy nó (EnumWindows).

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(); 
+0

Chỉ excel.ApplicationClass lớp tài sản Hwnd, không phải là class.ApplicationClass lớp mà câu hỏi là về. –

2

Có thể có một số lỗi trong file Word. Do đó, khi bạn mở tệp bằng phương thức Word.ApplicationClass.Documents.Open(), sẽ có một hộp thoại được hiển thị và quá trình sẽ treo.

Sử dụng Word.ApplicationClass.Documents.OpenNoRepairDialog() để thay thế. Tôi thấy nó đã khắc phục được sự cố.

1

Trước khi bạn khởi động ứng dụng, liệt kê tất cả các tiến trình đang chạy, khởi động ứng dụng và danh sách chạy lại quy trình Word. Quá trình tìm thấy trong danh sách thứ hai và không tìm thấy trong một đầu tiên là một trong những quyền:

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

Phương pháp này có vấn đề về thời gian rõ ràng, nhưng nó là người duy nhất tôi đã tìm thấy trong đó hoạt động đáng tin cậy hầu hết thời gian .

+0

điều này không thể là câu trả lời, bởi vì không có đảm bảo rằng chỉ có ứng dụng của bạn đang mở các quy trình winword! – Arvand

Các vấn đề liên quan