|
|
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
|
|
2014/9/27(Sat) 23:53:11|NO.65284
|
|
2014/9/28(Sun) 01:11:58|NO.65285
プロセス名というのはつまり実行ファイル名です。
ウィンドウハンドルからプロセスIDやプロセスのハンドルを調べて
そこからファイル場所を特定することができます。
|
|
2014/9/28(Sun) 10:22:41|NO.65289
いろいろ探し回って書いてみたけどうまくできない・・・
さっぱりわからん!
ということでもうちょっと(ちょっとじゃないかも)受け付けます!
|
|
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」を消して検索してください。)
| |
|
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
|
|
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アプリケーションなら正常にファイル名が取得できることがわかります。
| |
|
2014/9/28(Sun) 16:10:08|NO.65309
あ゛〜っ! ↑の書き込み、 人物名 間違ってました。ごめんなさい。
「ctas」さんではなく、「cats」さんです。失礼しました。
|
|
2014/9/28(Sun) 16:20:55|NO.65310
>FunnyMakerさん
なるほど、確かに64bitのものは取得できませんね。
全く気づきませんでした。
となるとFunnyMakerさんの挙げられた方法が確実でベストなのでしょう。
私自身ツールはよく作るので今後ファイルパスを取得するときのための参考にさせていただきます。
|
|
2014/9/28(Sun) 20:51:23|NO.65322
ありがとうございます。
ところが、1番の問題にぶつかりました。
アクティブウィンドウのプロセスを取得できません・・・
つまり、「カーソルの下のウィンドウ」を「アクティブになっているウィンドウ」
に変えたいのに・・・
ちょっとしたものが簡単な分、複雑なものは余計に大変になりますね。
|
|
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
| |
|
2014/9/30(Tue) 22:41:44|NO.65370
>VISTA以降ならQueryFullProcessImageNameが使えます
情報ありがとうございます。こんな便利な関数があるとは知りませんでした。
こちらでも試してみたところ、(Windows7)
ファイルパスが正しく取得できました。
WinXPのサポートが切れていることを考えると、今後プロセス名取得はこの関数で片付けてしまうのも選択肢ですね。
|
|
2014/10/4(Sat) 11:46:30|NO.65411
返信遅くなってすいません。
無事、プロセス名を表示させることができました。
ありがとうございました!
|
|