HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2014
0927
チャーくんアクティブウィンドウのプロセス名13解決


チャーくん

リンク

2014/9/27(Sat) 19:49:03|NO.65277

アクティブウィンドウのタイトルは取得できますが
プロセス名はできないのでしょうか?



この記事に返信する


ななし

リンク

2014/9/27(Sat) 23:22:51|NO.65283

プロセス名は分かりませんがプロセスIDならGetWindowThreadProcessIdで取得できます。


#include "user32.as" sdim buf, 300 pid = 0 GetForeGroundWindow hWindow = stat GetWindowText hWindow, varptr(buf), 299 GetWindowThreadProcessId hWindow, varptr(pid) threadid = stat mes buf mes "pid = " + pid mes "threadid = " + threadid



nepisat

リンク

2014/9/27(Sat) 23:53:11|NO.65284

違うかもしれませんが
http://blog.goo.ne.jp/hiro239415/e/8146d7c0f10246f455b25a2b6e3728f1
こういうのがあるらしいですよ。
作者は私ではないので...



cats

リンク

2014/9/28(Sun) 01:11:58|NO.65285

プロセス名というのはつまり実行ファイル名です。
ウィンドウハンドルからプロセスIDやプロセスのハンドルを調べて
そこからファイル場所を特定することができます。



チャーくん

リンク

2014/9/28(Sun) 10:22:41|NO.65289

いろいろ探し回って書いてみたけどうまくできない・・・
さっぱりわからん!
ということでもうちょっと(ちょっとじゃないかも)受け付けます!



FunnyMaker

リンク

2014/9/28(Sun) 12:20:28|NO.65302

1週間ほど前、ちょうど私も同じことをしてました。(もうソフトは完成しちゃったんですが。)
意外とあっさりいけます。

「EnumProcessModules」を使うとだめなんですよね〜。
この関数、呼び出し側が32bitアプリケーションだと、64bitアプリケーションのモジュールパスを取得できないんです。

だから代わりに「GetProcessImageFileNameA」を使います。
ただしこれはパスの先頭を論理ドライブ名ではなくデバイス名で返してくるので、HSPでexistとかするときのために
こちら側で論理ドライブ名に変換してやらなくてはなりません。
そのために利用可能な論理ドライブを列挙する処理が必要になります。

こんな感じになります。ちょっと遊び要素を加えてます。
(フォアグラウンドウィンドウだけだと、エディタからF5実行したときにそれ自身のパスになって面白みがないので。)


#uselib "User32.dll" #cfunc GetForegroundWindow "GetForegroundWindow" #cfunc WindowFromPoint "WindowFromPoint" int,int #cfunc GetAncestor "GetAncestor" int,int #define GA_ROOT 2 *InitInternalModules ;モジュールの初期化 init@InternalModule_1 *mkwnds screen 0,800,100,8 title "死神の目" sysfont 17 *main ;< 利用可能な論理ドライブを列挙 > bmp_AvailableDrvs = 0 : LDNL = "" : DNL = "" GetLogicalDrivesList bmp_AvailableDrvs, LDNL, DNL hwnd_ForeGround = GetForegroundWindow() ;フォアグラウンドウィンドウのハンドルを取得 ;< そのハンドルからモジュールファイルパスのリストのうち最上位の項目(=通常、これが実行ファイル名である。)を取得 > sdim mfpath_Foreground,260 GetFirstModuleFilePathFromHwnd mfpath_Foreground, hwnd_Foreground, LDNL, DNL sdim mfpath_aimed,260 repeat hwnd_aimed = GetAncestor(WindowFromPoint(ginfo_mx,ginfo_my), GA_ROOT) ;マウスカーソル直下のウィンドウのルートウィンドウのハンドルを取得 GetFirstModuleFilePathFromHwnd mfpath_aimed, hwnd_aimed, LDNL, DNL redraw 0 color : boxf color 255,255,255 pos 0,0 : mes "The path of the process which made the foreground window is ↓\n\n "+mfpath_Foreground+"\n\n" mes "The path of the process which made the window under the mouse cursor is ↓\n\n "+mfpath_aimed+"" redraw 1 await 100 loop #module InternalModule_1 ;ウィンドウハンドルからそれに関連するモジュールファイルパスのリストのうち最上位の項目を取得する。 ; ; ; [書式] ; ; GetFirstModuleFilePathFromHwnd mfpath, hwnd_, LDNL, DNL ; ; mfpath : 取得したファイルパスを格納するための変数。事前に260バイト確保せよ。 ; hwnd_ : ターゲットのウィンドウハンドル ; LDNL : GetLogicalDrivesList 命令で取得できる「LogicalDriveNameList」と同じ作りのデータ ; DNL : 〃「DeviceNameList」〃 ; ; [実行後のstatの値] ; ; (0,1) = (成功,失敗) #uselib "user32.dll" #cfunc IsWindow "IsWindow" int #cfunc GetWindowThreadProcessId "GetWindowThreadProcessId" int, var #uselib "psapi.dll" #func GetProcessImageFileNameA "GetProcessImageFileNameA" int, var,int #uselib "Kernel32.dll" #cfunc OpenProcess "OpenProcess" int,int,int #define PROCESS_ALL_ACCESS 2035711 #func CloseHandle "CloseHandle" int #deffunc local init ;モジュール初期化 PID_tgt = 0 return #deffunc GetFirstModuleFilePathFromHwnd var mfname, int hwnd_, array LDNL, array DNL if IsWindow(hwnd_) = 0 : return 1 ThreadID_tgt = GetWindowThreadProcessId(hwnd_,PID_tgt) ;ターゲットウィンドウを作成したスレッドのIDを取得。同時にプロセスIDも取得 hProcess_tgt = OpenProcess(PROCESS_ALL_ACCESS, 1, PID_tgt) ;そのプロセスのハンドルを開く GetProcessImageFileNameA hProcess_tgt, mfname, 260 ;そのプロセスに関連するモジュールファイルパスのリストのうち最上位の項目を取得(通常、これが実行ファイル名である。) CloseHandle hProcess_tgt ;プロセスハンドルを閉じる(必ず!) mDDI_CnvDevName2LogicalDrvName mfname, LDNL, DNL ;デバイス名を論理ドライブ名に変換 return 0 #global ;▼-------------------- 拙作モジュール「mod_DiskDriveInfo」より引用 --------------------▼ #module mDDI_10 ;利用可能なドライブの列挙 ; ; [書式] ; ; GetLogicalDrivesList bmp, LogicalDriveNameList, DeviceNameList ; ; bmp : 利用可能な論理ドライブのビットマップを格納する変数。Aドライブが使用可能なら最下位ビットが1、そうでないなら0、Bドライブが使用可能ならビット1が1、そうでないなら0 ・・・ 以下同様。 ; LogicalDriveNameList : 論理ドライブ名のリストを格納する26要素文字列型配列。1要素64バイトで確保される。Aドライブが利用可能なら要素0に"A:"が格納される。B,C,...,Zまで同様。 ; DeviceNameList : 論理ドライブ名に対応するデバイス名のリストを格納する26要素文字列型配列。1要素260バイトで確保される。 ; ; [命令実行後のstatの値] ; ; 検出された利用可能なドライブの個数 #uselib "kernel32.dll" #cfunc GetLogicalDrives "GetLogicalDrives" #func QueryDosDeviceA "QueryDosDeviceA" sptr,var,int #deffunc GetLogicalDrivesList var bmp, array LDNL, array DNL cnt_AvailableDrives = 0 sdim LDNL,64,26 sdim DNL,260,26 sdim buf,64 bmp = GetLogicalDrives() repeat 26 if bmp & 1<<cnt { poke buf,0,65+cnt LDNL(cnt) = ""+buf+":" QueryDosDeviceA LDNL(cnt), DNL(cnt), 260 cnt_AvailableDrives ++ } loop return cnt_AvailableDrives #global #module mDDI_11 ;デバイス名を論理ドライブ名に変換 ; ; [書式] ; ; mDDI_CnvDevName2LogicalDrvName Target, LogicalDriveNameList, DeviceNameList ; ; Target : 置き換えたい文字列が入っている変数 ; LogicalDriveNameList : GetLogicalDrivesList 命令で扱うものと同じ ; DeviceNameList : 〃 ; ; [実行後のstatの値] ; ; (0,1) = (成功,失敗) #deffunc mDDI_CnvDevName2LogicalDrvName var TGT, array LDNL, array DNL RC = 1 repeat 26 if instr(TGT,0,DNL(cnt)) = 0 { a = strlen(TGT) b = strlen(DNL.cnt) TGT = LDNL(cnt) + strmid(TGT,b,a-b) RC = 0 break } loop return RC #global ;▲-------------------- 拙作モジュール「mod_DiskDriveInfo」より引用 --------------------▲

案の定、Win32APIのお祭りになりました。
各関数の仕事はMSDNとかで見てください。(最後に「A」がついているやつは「A」を消して検索してください。)



cats

リンク

2014/9/28(Sun) 15:07:58|NO.65306

kernel32さんとpspaiさんを使うと簡単にできますよ。

#module #uselib "user32.dll" #cfunc GetWindowLong "GetWindowLongA" sptr, sptr #cfunc GetWindowThreadProcessID "GetWindowThreadProcessId" sptr, sptr #uselib "kernel32.dll" #cfunc OpenProcess "OpenProcess" sptr, sptr, sptr #func CloseHandle "CloseHandle" sptr #uselib "psapi.dll" #func GetModuleFileNameEx "GetModuleFileNameExA" sptr, sptr, sptr, sptr #deffunc GetProcessName int _hwnd_, var pName dim ret sdim pName, 256 sdim FilePath, 1024 hMod = GetWindowLong(_hwnd_, 0xFFFFFFFA) thID = GetWindowThreadProcessId(_hwnd_, varptr(PId)) hProcess = OpenProcess(0x001F0FFF, 1, PId) if hProcess != 0 { GetModuleFileNameEx hProcess, hMod, varptr(FilePath), 1024 len = stat if len = 0 : ret = -1 } else { ret = -1 } CloseHandle hProcess pName = getpath(FilePath, 8) return ret #global sdim pName, 256 GetProcessName hwnd , pName mes pName stop



FunnyMaker

リンク

2014/9/28(Sun) 15:35:48|NO.65307

>kernel32さんとpspaiさんを使うと簡単にできますよ。

えっ!そんな方法があったとは!..と、期待して実行してみましたが、
提示してくださった方法ではうまくいかないみたいです...。
少なくとも私の環境では(Win 7 64bit)。

HSPは32bitアプリケーションですので、64bitアプリケーションのウィンドウをターゲットにしたとき、
HSP側から呼ばれた「GetModuleFileNameEx」は失敗していると思います。
(HSPが64bit対応になればいいんですが。)

↓はctasさんのコードに一部変更を加えたものです。


#module #uselib "user32.dll" #cfunc GetWindowLong "GetWindowLongA" sptr, sptr #cfunc GetWindowThreadProcessID "GetWindowThreadProcessId" sptr, sptr #uselib "kernel32.dll" #cfunc OpenProcess "OpenProcess" sptr, sptr, sptr #func CloseHandle "CloseHandle" sptr #uselib "psapi.dll" #func GetModuleFileNameEx "GetModuleFileNameExA" sptr, sptr, sptr, sptr #deffunc GetProcessName int _hwnd_, var pName dim ret sdim pName, 256 sdim FilePath, 1024 hMod = GetWindowLong(_hwnd_, 0xFFFFFFFA) thID = GetWindowThreadProcessId(_hwnd_, varptr(PId)) hProcess = OpenProcess(0x001F0FFF, 1, PId) if hProcess != 0 { GetModuleFileNameEx hProcess, hMod, varptr(FilePath), 1024 len = stat if len = 0 : ret = -1 } else { ret = -1 } CloseHandle hProcess pName = getpath(FilePath, 8) return ret #global #uselib "user32.dll" #cfunc WindowFromPoint "WindowFromPoint" int,int #cfunc GetAncestor "GetAncestor" int,int #define GA_ROOT 2 sdim pName, 256 repeat GetProcessName GetAncestor(WindowFromPoint(ginfo_mx,ginfo_my),GA_ROOT) , pName redraw 0 color : boxf color 255,255,255 pos 0,0 : mes pName redraw 1 await 100 loop stop

このコードを実行し、64bitアプリケーションを起動してそのウィンドウを狙ってみてください。
(例えば メモ帳 や コマンドプロンプト等)
実行ファイル名を正常に取得できないことが分かります。
ターゲットが32bitアプリケーションなら正常にファイル名が取得できることがわかります。



FunnyMaker

リンク

2014/9/28(Sun) 16:10:08|NO.65309

あ゛〜っ! ↑の書き込み、 人物名 間違ってました。ごめんなさい。
「ctas」さんではなく、「cats」さんです。失礼しました。



cats

リンク

2014/9/28(Sun) 16:20:55|NO.65310

>FunnyMakerさん
なるほど、確かに64bitのものは取得できませんね。
全く気づきませんでした。
となるとFunnyMakerさんの挙げられた方法が確実でベストなのでしょう。
私自身ツールはよく作るので今後ファイルパスを取得するときのための参考にさせていただきます。



チャーくん

リンク

2014/9/28(Sun) 20:51:23|NO.65322

ありがとうございます。
ところが、1番の問題にぶつかりました。
アクティブウィンドウのプロセスを取得できません・・・
つまり、「カーソルの下のウィンドウ」を「アクティブになっているウィンドウ」
に変えたいのに・・・
ちょっとしたものが簡単な分、複雑なものは余計に大変になりますね。



pol

リンク

2014/9/28(Sun) 21:16:57|NO.65323

>HSP側から呼ばれた「GetModuleFileNameEx」は失敗していると思います。
VISTA以降ならQueryFullProcessImageNameが使えます。
>アクティブウィンドウのプロセスを取得できません・・・
こういうことかな。

#module #uselib "user32.dll" #cfunc GetWindowLong "GetWindowLongA" sptr, sptr #cfunc GetWindowThreadProcessID "GetWindowThreadProcessId" sptr, sptr #uselib "kernel32.dll" #cfunc OpenProcess "OpenProcess" sptr, sptr, sptr #func CloseHandle "CloseHandle" sptr #func QueryFullProcessImageName "QueryFullProcessImageNameA" sptr,sptr,sptr,sptr #uselib "psapi.dll" #func GetModuleFileNameEx "GetModuleFileNameExA" sptr, sptr, sptr, sptr #deffunc GetProcessName int _hwnd_, var pName dim ret sdim pName, 256 sdim FilePath, 1024 hMod = GetWindowLong(_hwnd_, 0xFFFFFFFA) thID = GetWindowThreadProcessId(_hwnd_, varptr(PId)) hProcess = OpenProcess(0x001F0FFF, 1, PId) if hProcess != 0 { size=1024 QueryFullProcessImageName hProcess,0, varptr(FilePath), varptr(size) len = stat if len = 0 : ret = -1 } else { ret = -2 } CloseHandle hProcess pName = FilePath if ret:pname=""+ret return ret #global #uselib "user32.dll" #cfunc WindowFromPoint "WindowFromPoint" int,int #cfunc GetAncestor "GetAncestor" int,int #cfunc GetForegroundWindow "GetForegroundWindow" #define GA_ROOT 2 sdim pName, 256 repeat GetProcessName GetForegroundWindow() , pName redraw 0 color : boxf color 255,255,255 pos 0,0 : mes pName redraw 1 await 100 loop stop



FunnyMaker

リンク

2014/9/30(Tue) 22:41:44|NO.65370

>VISTA以降ならQueryFullProcessImageNameが使えます

情報ありがとうございます。こんな便利な関数があるとは知りませんでした。
こちらでも試してみたところ、(Windows7)
ファイルパスが正しく取得できました。

WinXPのサポートが切れていることを考えると、今後プロセス名取得はこの関数で片付けてしまうのも選択肢ですね。



チャーくん

リンク

2014/10/4(Sat) 11:46:30|NO.65411

返信遅くなってすいません。
無事、プロセス名を表示させることができました。
ありがとうございました!



ONION software Copyright 1997-2023(c) All rights reserved.