- ベストアンサー
Active Basicで他のアプリケーションを終了させる方法
- Active Basic4.23.00を使用しています。他のアプリケーションを終了させる方法について質問です。
- FindWindow関数についてお聞きしたいです。lpClassNameの指定やlpWindowNameにNULLを指定する場合のハンドル取得について教えてください。
- コードに誤りがある場合は指摘お願いします。TerminateProcessでエラーが発生する場合の対処方法も教えてください。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
API宣言を Declare Function EnumProcesses Lib "psapi.dll" _ (lpidProcess As DWord,cb As DWord ,ByRef cbNeeded As DWord) As Integer といった具合に cbNeededを ByRefの参照渡しにしてください たぶんここが値渡しになっているので EnumProcess側でデータを書き込もうとしてエラーになっているのでしょう
その他の回答 (5)
- redfox63
- ベストアンサー率71% (1325/1856)
Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT) Dim nRet As Integer Dim err As Long Dim code As DWord nRet = EnumProcesses(ProcessID,Len(ProcessID),ProcessSize) If nRet=0 Then Error("EnumProcesses") End If ProcessNum = ProcessSize / SizeOf( DWord ) End Sub といった具合でしょう GetProcessModulesは ActiveBasicから直接呼び出すのは無理なようです 関数の呼び出し規約が違っているようで C/C++でActiveBasic用のラッパーを作らないといけないようです EnumProcessesではアクセス違反などは確認できておりません どこまで実行できているのかを確認しましょう debugステートメントを挿入して F2キーでデバッグ実行 ブレークポイントで止まったら デバッガの ステップアウトなどで1行ごとに実行してみましょう
お礼
>>EnumProcessesではアクセス違反などは確認できておりません >>debugステートメントを挿入して F2キーでデバッグ実行 やってみましたが、 nRet = EnumProcesses(ProcessID,Len(ProcessID),ProcessSize) でアクセス違反が起こります。 コンピュータの再起動、プロジェクトの作成のやり直しなどをやってみましたが、アクセス違反が直りません。 これは、コンピュータが可笑しいのでしょうか
- redfox63
- ベストアンサー率71% (1325/1856)
ごめんなさい EnumProcessesの第2引数は配列の大きさなので Lenで求めたバイト長でよかったですね EnumProcesses( ProcessID, Len( ProcessID ), ProcessSize ) といった具合でした
お礼
ご回答ありがとうございます。 試してみたのですが、アクセス違反が取れません。 訂正をお願いします。 Declare Function EnumProcesses Lib "psapi.dll"(lpidProcess As DWord,cb As DWord ,cbNeeded As DWord) As Integer Dim ProcessID[1024] As DWord 'プロセスの配列 Dim ProcessNum As DWord 'プロセスの個数 Dim ProcessSize As DWord 'プロセスのサイズ '----------------------------------------------------------------------------- ' ここから下は、イベントプロシージャを記述するための領域になります。 Sub MainWnd_Destroy() Vul_DestroyObjects() PostQuitMessage(0) End Sub Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT) Dim nRet As Integer Dim err As Long Dim code As DWord EnumProcesses(ProcessID,Len(ProcessID),ProcessSize) If nRet=0 Then Error("EnumProcesses") End If End Sub Sub Error(ErrorWord As BytePtr) Dim length As Long Dim w As BytePtr length=lstrlen(ErrorWord) length=length+lstrlen("でエラーが発生しました") w=malloc(length+1) w=lstrcat(ErrorWord,"でエラーが発生しました") MessageBox(hMainWnd,w,"Error",MB_OK or MB_ICONHAND) ExitProcess(0) End Sub スレッド(&H284)でアクセス違反がありました(EPI=&H76BA3B23)。
- redfox63
- ベストアンサー率71% (1325/1856)
SizeOfではなく LenとSizeOfを使って配列の個数を求めます Len(ProcessID)で 配列ProcessIDのバイト長を取得します SizeOf(DWord)で 配列要素1つのバイト長を求めます これの商を求めれば個数が求まります Len(ProcessID)/SizeOf(DWord) といった具合です EnumProcesses(ProcessID, Len(ProcessID)/SizeOf(DWord), ProcessSize) といった具合です 第3引数に『&』は不要です お示しのページの例は Cなので 変数のアドレスを渡すのに&演算子を使います ActiveBasicでは アドレス渡しは関数宣言時の 引数に ByRefを記述すればいいのです また 返り値は HWND型ではなく Integer(本来はBOOL)なのでhWndで受けるのではなく Dim nRet As Integer nRet = EnumProcesses(ProcessID, Len(ProcessID)/SizeOf(DWord), ProcessSize) などとするか 直接 if EnumProcesses(ProcessID, Len(ProcessID)/SizeOf(DWord), ProcessSize) then などと判断に使ったりします
- redfox63
- ベストアンサー率71% (1325/1856)
BOOLは Integerで代用可能ですよ declare EnumProcessModules Lib "psapi" _ (hProcess as HANDLE, lphModule() as HANDLE ,cb as DWord ByRef lpcbNeeded as DWord) as Integer といった具合です
お礼
ご回答ありがとうございます。 とりあえず、IDを取得しようと Declare Function EnumProcesses Lib "psapi.dll"(lpidProcess As DWord,cb As DWord ,cbNeeded As DWord) As Integer を定義しましたが、上手くIDが返ってきません。 いろいろ、探し、 http://nienie.com/~masapico/api_EnumProcesses.html を参考にプログラムを書いてみましたが、『無効』だといわれます。 'グローバル Dim ProcessID[1024] As DWord 'プロセスの配列 Dim ProcessNum As DWord 'プロセスの個数 Dim ProcessSize As DWord 'プロセスのサイズ 'ウインドウクリエイト hWnd=EnumProcesses(ProcessID,SizeOf(ProcessID),&ProcessSize) ↑SizeOfに『ProcessID』を入れると無効といわれ、(これが正しい使い方だと思ったので)『DWord』と入れるとアクセス違反が起こり、SizeOfを消すと、アクセス違反が起きます。 どのように扱えばいいのでしょうか。
- redfox63
- ベストアンサー率71% (1325/1856)
ProcessハンドルとWindowハンドルを混同して使っているのが問題なのでしょう ProcessハンドルはEnumProcessesなどでプロセスIDを取得して このIDを使ってOpenProcessで取得します 使い終わったら CloseHandleでプロセスハンドルは閉じましょう プロセスハンドルには関連付けされたモジュールを取得するためには EnumProcessModulesをつかってモジュールハンドルを取得して このハンドルからGetModuleBaseNameをつかってEXEやDLLの名前を取得します これらのAPI関数はActiveBasicで準備されていないようですので Declareステートメントで新規に宣言しないといけないでしょう テストでEnumProcessesを作ってみたのですがEnumProcessModulesでどうしてもモジュールハンドルが取得できませんでした EnumProcessesで起動しているプロセスIDは取得でき その数もタスクマネージャの値に合致していました FindWindowで取得できるのはWindowハンドルです このアプリを閉じたいのでしたら WM_CLOSEメッセージを SendMessageで送るほうがいいでしょう FindWindowのlpClassNameはアプリケーション側でWindowsに対して 自分のウィンドウはこの名前で登録します といった手続きがあります これは、アプリごとに任意に行いますので メモ帳のようなアプリが "WebBrowser"というクラス名に登録してもいいことになっています Exeのベース名(sample.exeなら『sample』)で登録される場合が多いですが...
お礼
ご回答ありがとうございます。 EnumProcessesやEnumProcessModulesを定義しようと探してみましたが、 BOOL EnumProcessModules(HANDLE hProcess,HMODULE * lphModule,DWORD cb LPDWORD lpcbNeeded) のように、DLLではなく『BOOL』と言うものを使っていますよね。 ABではBOOL型を受け付けてくれません。 どのように定義すればいいのでしょうか。 ご教授いただければ嬉しいです
お礼
何とかできました! 此処までのお付き合い、ありがとうございました