2011-01-14 24 views
4

免責事項:これはプログラムの要件の一部ですので、悪い意味はありません。あなたが1つを見つけた場合は、誤用を指摘してください。私はC++の初心者です。ERROR_INVALID_HANDLE on TerminateProcess(VS C++)

基本的に、私はWindowsでOutlook.exeをC++で再起動しようとしています。

これはOutlookを再起動するために使用したコードです。

#include <TlHelp32.h> 
void RestartOutlook() { 
    PROCESSENTRY32 Pc = { sizeof(PROCESSENTRY32) }; 
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0); 

    MODULEENTRY32 Mo = {sizeof (MODULEENTRY32) }; 

    if(Process32First(hSnapshot, &Pc)){ 
     do{ 
      if(!_stricmp(Pc.szExeFile, "outlook.exe")) { 
       DWORD pid = Pc.th32ProcessID; 

       HANDLE hModuleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); 

       //kill outlook 
       HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid); 
       DWORD fdwExit = 0; 
       GetExitCodeProcess(process, &fdwExit); 
       TerminateProcess(process, fdwExit); 

       char * path; 
       if (Module32First(hModuleSnapshot, &Mo)) { 
        path = Mo.szExePath; 

        STARTUPINFO si; 
        PROCESS_INFORMATION pi; 
        ZeroMemory(&si, sizeof(si)); 
        si.cb = sizeof (si); 
        CreateProcess(path, NULL, NULL, NULL, false, NORMAL_PRIORITY_CLASS, 
         NULL, NULL, &si, &pi); 
       } 


      } 
     }while(Process32Next(hSnapshot, &Pc)); 
    } 
} 

面白い部分は、このコードはWindows 7で完璧に機能します.Windows XP(SP3)では、私は重複したOutlookを取得します。 GetLastErrorは私に6: ERROR_INVALID_HANDLEを与えます。私は何時間もの研究の後、本当に無知です。

とにかく、C++は私のフィールドではありません。私はウェブ:)

そして、上記のコードは以下のソースの混合物である:

1:http://www.istorya.net/forums/programming/107435-how-can-i-kill-a-process-using-c.html

2:http://code.activestate.com/recipes/576362-list-system-process-and-process-information-on-win/

環境:Windows 7の、WindowsのXP、VS2010、Outlook 2003、Outlook 2007、Outlook 2010

+0

これは、なぜ私が見通しを再開すべきかに関するいくつかの質問をもたらすかもしれないことを知っています。これは、いくつかの変更を加えた後にOutlookが新しいレジストリ値を使用するように強制する必要があるためです。もちろん、このメソッドが実行される前に複数の確認が求められます。それとも何か別の選択肢がありますか? –

答えて

4

犯人が見つかりました。その理由は、この行にある

HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid); 

http://msdn.microsoft.com/en-us/library/ms684880(v=vs.85).aspxによると、PROCESS_ALL_ACCESSは、Windows XP/NTシステム、またはそれ以上の詳細については、大きすぎる:

増加PROCESS_ALL_ACCESSフラグのサイズWindows Server 2008およびWindows Vistaの場合Windows Server 2008およびWindows Vista用にコンパイルされたアプリケーションがWindows Server 2003またはWindows XP/2000で実行されている場合、PROCESS_ALL_ACCESSフラグが大きすぎます。このフラグを指定する関数はERROR_ACCESS_DENIEDで失敗します。この問題を回避するには、操作に必要なアクセス権の最小限のセットを指定します。

私は間違いなくXPでこのプログラムをコンパイルしている間に、このプログラムをコンパイルしています。

だからソリューションは、

HANDLE process = OpenProcess(PROCESS_TERMINATE, TRUE, pid); 

が完了され、PROCESS_ALL_ACCESSPROCESS_TERMINATEに変更されました!迅速な回答のため

おかげ@DReJ :)

1

あなたの問題は多分GetExitCodeProcessであなたが状況STILL_ACTIVEを取得し、その後、あなたは私が考えて、適切ではありません。この状態でプロセスを終了、コードファースト

DWORD fdwExit = 0; 
GetExitCodeProcess(process, &fdwExit); 
TerminateProcess(process, fdwExit); 

のこの作品に関連します。コードからGetExitCodeProcessを削除し、代わりにTerminateProcess(process, 0);を試してください。

+0

いいえ、私は試しました、できません。私は 'TerminateProcess(process、0);を実行しますが、Windows XPでは' 6'を返します。 Windows 7は問題ありません。 –

+0

Fyi、Windows 7では 'GetExitCodeProcess'は' 259'を、Windows XPでは 'GetExitCodeProcess'は' 0'を返します –

+0

OpenProcessに問題があるか、それとも早いですか? – DReJ

2

私はあなたがOutlookを再起動することを得るが、見通しの上のTerminateProcessを呼び出すには、最初の場所で悪いアイデアのように思えます。データファイルを書き込む途中であればどうでしょうか?

もっと良い方法は、Outlookに属しているすべてのトップレベルウィンドウを見つけて、それらにWM_CLOSEを送信し、プロセスが終了するまで待つことです。 (あなたは最初の場所でこれを行っていても、ユーザーが何かの真ん中にいないことを前提としていますが、「あなたは確かですか?」というメッセージを開いたユーザーに対処しなければならないかもしれません。 )

さらに良い方法は、Outlookの自動化インターフェイスを使用して、明示的にシャットダウンするように指示することです。

+0

こんにちは。しかし実際、このコードはC++でコード化されているプロジェクトの一部に属しています。その後、exeはAdobe Airの主なアプリケーションから実際に呼び出されます。したがって、実際には、ユーザー確認 –

+0

OHの後にこのアクションを開始し、 'WM_CLOSE'のリマインダーに感謝します。ユーザーがメモ帳を終了したときのようなものですか?保存されていない作品がある場合、ユーザーは警告を受け取りますか?はい、私はこの感謝を見ていきます! –