こんにちは、いつもお世話になっております。
現在、単純にexeファイル名でプロセスが上がっているかどうか?を確認する
コンソールプログラムを作っています(開発環境Windows XP + VS.NET 2008
Developer)。
WMIをつかって取得する方法を検討し、以下のようなソースにしたのですが、
Windows XPでは動作するのですが、Windows 2000だとExecQueryで失敗します。
ライブラリに記載されているエラーコードのどれにも当てはまらず(-1073741819)、
切り分けができずに困っている状況です。
何か原因として考えられるものなどがありましたらご指摘いただけると幸いです。
以下ソースを記載しますので、よろしくお願いいたします。
#include<windows.h>
#include<windowsx.h>
#include <comutil.h>
#include<Wbemidl.h>
//ライブラリのインポート
#pragma comment(lib, "comsuppw.lib")
#pragma comment(lib, "wbemuuid.lib")
//グローバル変数の定義
//グローバル関数の定義
int CheckProcessExists(WCHAR *ExeName);
//main関数
int main(int argc, char *argv[] )
{
int l_ReturnValue;
BSTR l_ExeName = NULL;
//引数を取得(オプション引数がない場合は何もしない、多すぎても最初の一つしかみない)
if(argc < 2)
{
return -99;
}
else
{
l_ExeName = _com_util::ConvertStringToBSTR(argv[1]);
}
//COM初期化
if(FAILED(CoInitializeEx(0, COINIT_MULTITHREADED)))
{
l_ReturnValue = -1;
}
else
{
//COMのセキュリティレベルを設定
if(FAILED(CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL)))
{
l_ReturnValue = -2;
}
else
{
/* if(CheckProcessExists(l_ExeName))
{
l_ReturnValue = 0;
}
else
{
l_ReturnValue = 1;
}
*/
l_ReturnValue = CheckProcessExists(l_ExeName);
}
//COMを閉じる
CoUninitialize();
}
SysFreeString(l_ExeName);
switch(l_ReturnValue)
{
case 0:
printf("正常終了:指定されたプロセスが見つかりました。\n\n");
break;
case 1:
printf("正常終了:指定されたプロセスは見つかりませんでした。\n\n");
break;
case -1:
printf("エラー:COMの初期化に失敗しました。\n\n");
break;
case -2:
printf("エラー:COMのセキュリティレベルの設定に失敗しました。\n\n");
break;
case -10:
printf("エラー:WMI呼び出し用のバッファ確保に失敗しました。\n\n");
break;
case -20:
printf("エラー:WMIロケータの取得に失敗しました。\n\n");
break;
case -21:
printf("エラー:WMIの接続に失敗しました。\n\n");
break;
case -22:
printf("エラー:WMIのセキュリティレベルの取得に失敗しました。\n\n");
break;
case -23:
printf("エラー:WMIから情報を取得できませんでした。\n\n");
break;
default:
printf("エラー:不明なエラーです\n\n");
break;
}
return l_ReturnValue;
}
int CheckProcessExists(WCHAR *ExeName)
{
IWbemLocator *l_pLoc = NULL; //IWbemLocator インターフェイス
IWbemServices *l_pSvc = NULL; //IWbemServices インターフェイス
IEnumWbemClassObject *l_pEnumerator = NULL; //IEnumWbemClassObject インターフェイス
IWbemClassObject *l_pclsObj = NULL; //IWbemClassObject インターフェイス
ULONG l_uReturn; //ULONG型の関数の戻り値を格納
ULONG l_cntProcess; //プロセス数を格納
WCHAR *l_WQLString = NULL; //WQL文字列
int l_lenWQLString; //↑の長さ
//WQL文字列の格納
l_lenWQLString = lstrlen(L"SELECT * FROM WIN32_Process WHERE Caption = ''") + lstrlen(ExeName);
l_WQLString = new WCHAR[l_lenWQLString + 1];
if(l_WQLString == NULL)
{
return -10;
}
wsprintf(l_WQLString, L"SELECT * FROM WIN32_Process WHERE Caption = '%s'", ExeName);
//WMI初期ロケータの取得
if(FAILED(CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&l_pLoc)))
{
if(l_WQLString != NULL)
{
delete[] l_WQLString;
l_WQLString = NULL;
}
return -20;
}
//コンピュータのWMIに接続
if(FAILED(l_pLoc->ConnectServer(L"ROOT\\CIMV2", NULL, NULL, 0, NULL, 0, 0, &l_pSvc)))
{
if(l_WQLString != NULL)
{
delete[] l_WQLString;
l_WQLString = NULL;
}
if(l_pLoc != NULL)
{
l_pLoc->Release();
l_pLoc = NULL;
}
return -21;
}
//WMIセキュリティレベル設定
if(FAILED(CoSetProxyBlanket(l_pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE)))
{
if(l_WQLString != NULL)
{
delete[] l_WQLString;
l_WQLString = NULL;
}
if(l_pSvc != NULL)
{
l_pSvc->Release();
l_pSvc = NULL;
}
if(l_pLoc != NULL)
{
l_pLoc->Release();
l_pLoc = NULL;
}
return -22;
}
//WMIの要求
if(FAILED(l_pSvc->ExecQuery(L"WQL", l_WQLString, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &l_pEnumerator)))
{
if(l_WQLString != NULL)
{
delete[] l_WQLString;
l_WQLString = NULL;
}
if(l_pSvc != NULL)
{
l_pSvc->Release();
l_pSvc = NULL;
}
if(l_pLoc != NULL)
{
l_pLoc->Release();
l_pLoc = NULL;
}
return -23;
}
if(l_WQLString != NULL)
{
delete[] l_WQLString;
l_WQLString = NULL;
}
l_cntProcess = 0;
while(l_pEnumerator)
{
l_pEnumerator->Next(WBEM_INFINITE, 1, &l_pclsObj, &l_uReturn);
if(0 == l_uReturn)
{
if(l_pclsObj != NULL)
{
l_pclsObj->Release();
l_pclsObj = NULL;
}
break;
}
if(l_pclsObj != NULL)
{
l_pclsObj->Release();
l_pclsObj = NULL;
}
l_cntProcess++;
}
if(l_cntProcess > 0)
{
return 0;
}
return 1;
}
Win2000の問題として・・・
http://support.microsoft.com/kb/306497/ja
http://support.microsoft.com/kb/300038/ja
こういうものがありました。
エラーコードが同じなので・・・
Win2000のサービスパックは何でしょう?
それによっては、解決の方法に至るかも・・・です。
以上。
オショウさん
いつもありがとうございます。
Windows 2000のSPは・・・残念ながら4なんですT_T
なんなんでしょうね・・・
同じことをVBScriptで実行させると問題ないのが悔しいです(ユーザ側に置く
為、ソースの見えるVBScriptではなく、exeで作りたくて作成しているのです)
私もあのエラーコードを調べてみたのですが「-1073741819」は「STATUS_ACCESS_VIOLATION 」
だとか・・・
もう少し調べてみます。
であれば・・・
WMIでのアクセスで、やり取りする際に使用する変数は、VARIANT宣言
したもので行いますが、掲載されたコードには、使っておられません
よネ?!
インターネットで検索した際のいろいろな掲載されているコードを
参考に、VARIANT宣言した変数で受け渡すよう修正してみては?
以上。参考まで
解決したっぽいです。
【修正前】
//コンピュータのWMIに接続
if(FAILED(l_pLoc->ConnectServer(L"ROOT\\CIMV2", NULL, NULL, 0, NULL, 0, 0, &l_pSvc)))
{
・・・・
//WMIの要求
if(FAILED(l_pSvc->ExecQuery(L"WQL", l_WQLString, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &l_pEnumerator)))
{
・・・
【修正後】
//コンピュータのWMIに接続
if(FAILED(l_pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &l_pSvc)))
{
・・・・
//WMIの要求
if(FAILED(l_pSvc->ExecQuery(_bstr_t(L"WQL"), _bstr_t(l_WQLString), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &l_pEnumerator)))
{
・・・
と、WCHAR型でそのまま突っ込んでいたものを_bstr_t()でちゃんと変換してい
なかった?のがいけなかったみたいです。
お騒がせしました^^;
ツイート | ![]() |