by kb2021 » 2021年10月31日(日) 00:57
自分のソフトから他のアプリのlistviewの値を取得したいのですがうまくいきません。
手順としては、
目的のウィンドウを見つける。
そこから目的のlistviewを見つける
プロセスIDを取得
プロセスハンドルを取得
VirtualAllocEXでlistviewの値取得用の共有メモリAを確保
構造体LVITEMを設定、共有メモリAのアドレス等を設定する。
VirtualAllocEXでLVITEMのサイズの共有メモリBを確保
共有メモリBに先ほど設定した構造体LVITEMをWriteProcessMemoryにてコピーする。
SendMessage(hWnd,LVM_GETITEMTEXT,ほしい行,共有メモリB)をする。
ReadProcessMemoryで、通常のメモリに共有メモリAからデータを移す。
順次解放する。
手順は良いと思うのですが、取得したいアプリからはできませんでした。
自分で作成した、Listviewを持つ別アプリを作成し、それからは取得できました。
どちらも、64bitOS上の32bitで動く(?)アプリです。
何か原因があればご指摘願いたく思います。
コードと結果を置いておきます。
どうもSendMessageで取得長さ0で返ってきます。
独学なので、表現の名前など間違いもあるとは存じますがご了承ください。
windows10 64bit版
ActiveBasic ver4.24
-------結果---------
Count 2
GetWindowThreadProcessId>5096
プロセスID pid>4268
hProcess->396 processMemoryA->&h2A40000<-
pszText -> &h2A40000
WriteProcessMemoryB->1 > 40
SendMessage > answer Read length->0
ReadProcessMemory->1 > 2550/2550
VirtualFreeEX processMemoryA >1
VirtualFreeEX LVITEMMemoryB>1
text>
--------------------
コード: 全て選択
Declare Function EnumWindows Lib "user32" (lpEnumFunc As DWord, lParam As DWord) As Long
Declare Function ReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (hProcess as HANDLE , lpBaseAddress As VoidPtr, lpBuffer As VoidPtr, nSize As SIZE_T, lpNumberOfBytesWritten As DWordPtr) As BOOL
Declare Function WriteProcessMemory Lib "kernel32" Alias "WriteProcessMemory" (hProcess as HANDLE , lpBaseAddress As VoidPtr, lpBuffer As VoidPtr, nSize As SIZE_T, lpNumberOfBytesWritten As DWordPtr) As BOOL
Declare Function VirtualAllocEX Lib "kernel32" Alias "VirtualAllocEx" (hProcess as HANDLE , lpAddress As VoidPtr, dwSize As SIZE_T, flAllocationType As DWord, flProtect As DWord) As VoidPtr
Declare Function VirtualFreeEX Lib "kernel32" Alias "VirtualFreeEx" (hProcess as HANDLE , lpAddress As VoidPtr , dwSize As SIZE_T , dwFreeType As DWord) As BOOL
Function Get_LVM_GetItemTextEEXX(hWnd As HWND, y As Long, x As Long ) as BytePtr
Dim text as BytePtr
'プロセスIDを取得
Dim pid As DWord 'プロセスID
Dim hProcess As HANDLE 'プロセスハンドル
Dim processMemoryA as VoidPtr
Dim LVITEMMemoryB as VoidPtr
Dim textlengthA as long '取得文字列の長さ
Dim LVITEMlengthB as long '構造体の長さ
Dim lvi As LVITEM
Dim count as DWord
ADText(GetDlgItem(hMainWnd,EditBox1) , "Count " +Str$(ListView_GetItemCount( hWnd )) +ex"\r\n")
text = 0
pid = 0
hProcess = 0
processMemoryA = 0
textlengthA = 0
'指定されたプロセスの仮想アドレス空間内のメモリ領域の状態を予約
ADText(GetDlgItem(hMainWnd,EditBox1) , ex"GetWindowThreadProcessId>"+Str$(GetWindowThreadProcessId( hWnd ,VarPtr(pid)))+ex"\r\n") 'プロセスIDを取得
hProcess=OpenProcess( PROCESS_VM_OPERATION + PROCESS_VM_READ + PROCESS_VM_WRITE, FALSE, pid) 'プロセスハンドルを取得
ADText(GetDlgItem(hMainWnd,EditBox1) , ex"プロセスID pid>"+Str$(pid)+ex"\r\n")
'メモリを確保
processMemoryA = VirtualAllocEX( hProcess , NULL , MaxPath , MEM_COMMIT + MEM_RESERVE , PAGE_READWRITE) '共有メモリAを確保
ADText(GetDlgItem(hMainWnd,EditBox1) , "hProcess->" + Str$(hProcess as Long)+" processMemoryA->&h"+Hex$(processMemoryA as Long)+ex"<-\r\n") '確認
lvi.mask =LVIF_TEXT
lvi.iItem =y
lvi.iSubItem =x
lvi.cchTextMax =MaxPath
lvi.pszText =processMemoryA '共有メモリAを設定
ADText(GetDlgItem(hMainWnd,EditBox1) , "pszText -> &h" + Hex$(lvi.pszText ) + ex"\r\n" ) '確認
LVITEMlengthB = SizeOf(LVITEM)
LVITEMMemoryB = VirtualAllocEX( hProcess , NULL , LVITEMlengthB , MEM_COMMIT + MEM_RESERVE , PAGE_READWRITE) '共有メモリBを確保
'共有メモリBに構造体をコピー
ADText(GetDlgItem(hMainWnd,EditBox1) , "WriteProcessMemoryB->" + Str$(WriteProcessMemory(hProcess , LVITEMMemoryB , VarPtr(lvi) , LVITEMlengthB , VarPtr(count) )) + " > "+ Str$(count) +ex"\r\n" )
textlengthA = SendMessage(hWnd,LVM_GETITEMTEXT,y,LVITEMMemoryB) 'listviewに指示
ADText(GetDlgItem(hMainWnd,EditBox1) , "SendMessage > answer Read length->" + Str$(textlengthA) +ex"\r\n" ) '確認
text=calloc( MaxPath+1 ) '通常メモリを確保
'共有メモリから通常メモリに回収
ADText(GetDlgItem(hMainWnd,EditBox1) , "ReadProcessMemory->" + Str$(ReadProcessMemory(hProcess, processMemoryA , text , MaxPath , VarPtr(count) ) ) + " > "+ Str$(count) + "/" + Str$(MaxPath) +ex"\r\n" )
'解放
ADText(GetDlgItem(hMainWnd,EditBox1) , ex"VirtualFreeEX processMemoryA >"+Str$(VirtualFreeEX(hProcess , processMemoryA , 0 , MEM_RELEASE)) +ex"\r\n")
ADText(GetDlgItem(hMainWnd,EditBox1) , ex"VirtualFreeEX LVITEMMemoryB>"+Str$(VirtualFreeEX(hProcess , LVITEMMemoryB , 0 , MEM_RELEASE)) +ex"\r\n")
LVITEMMemoryB=0
processMemoryA=0
'プロセスハンドルを閉じる
CloseHandle(hProcess)
hProcess=0
ADText(GetDlgItem(hMainWnd,EditBox1) , ex"text>"+MakeStr(text) +ex"\r\n")
Get_LVM_GetItemTextEEXX = text
End function
自分のソフトから他のアプリのlistviewの値を取得したいのですがうまくいきません。
手順としては、
目的のウィンドウを見つける。
そこから目的のlistviewを見つける
プロセスIDを取得
プロセスハンドルを取得
VirtualAllocEXでlistviewの値取得用の共有メモリAを確保
構造体LVITEMを設定、共有メモリAのアドレス等を設定する。
VirtualAllocEXでLVITEMのサイズの共有メモリBを確保
共有メモリBに先ほど設定した構造体LVITEMをWriteProcessMemoryにてコピーする。
SendMessage(hWnd,LVM_GETITEMTEXT,ほしい行,共有メモリB)をする。
ReadProcessMemoryで、通常のメモリに共有メモリAからデータを移す。
順次解放する。
手順は良いと思うのですが、取得したいアプリからはできませんでした。
自分で作成した、Listviewを持つ別アプリを作成し、それからは取得できました。
どちらも、64bitOS上の32bitで動く(?)アプリです。
何か原因があればご指摘願いたく思います。
コードと結果を置いておきます。
どうもSendMessageで取得長さ0で返ってきます。
独学なので、表現の名前など間違いもあるとは存じますがご了承ください。
windows10 64bit版
ActiveBasic ver4.24
-------結果---------
Count 2
GetWindowThreadProcessId>5096
プロセスID pid>4268
hProcess->396 processMemoryA->&h2A40000<-
pszText -> &h2A40000
WriteProcessMemoryB->1 > 40
SendMessage > answer Read length->0
ReadProcessMemory->1 > 2550/2550
VirtualFreeEX processMemoryA >1
VirtualFreeEX LVITEMMemoryB>1
text>
--------------------
[code]
Declare Function EnumWindows Lib "user32" (lpEnumFunc As DWord, lParam As DWord) As Long
Declare Function ReadProcessMemory Lib "kernel32" Alias "ReadProcessMemory" (hProcess as HANDLE , lpBaseAddress As VoidPtr, lpBuffer As VoidPtr, nSize As SIZE_T, lpNumberOfBytesWritten As DWordPtr) As BOOL
Declare Function WriteProcessMemory Lib "kernel32" Alias "WriteProcessMemory" (hProcess as HANDLE , lpBaseAddress As VoidPtr, lpBuffer As VoidPtr, nSize As SIZE_T, lpNumberOfBytesWritten As DWordPtr) As BOOL
Declare Function VirtualAllocEX Lib "kernel32" Alias "VirtualAllocEx" (hProcess as HANDLE , lpAddress As VoidPtr, dwSize As SIZE_T, flAllocationType As DWord, flProtect As DWord) As VoidPtr
Declare Function VirtualFreeEX Lib "kernel32" Alias "VirtualFreeEx" (hProcess as HANDLE , lpAddress As VoidPtr , dwSize As SIZE_T , dwFreeType As DWord) As BOOL
Function Get_LVM_GetItemTextEEXX(hWnd As HWND, y As Long, x As Long ) as BytePtr
Dim text as BytePtr
'プロセスIDを取得
Dim pid As DWord 'プロセスID
Dim hProcess As HANDLE 'プロセスハンドル
Dim processMemoryA as VoidPtr
Dim LVITEMMemoryB as VoidPtr
Dim textlengthA as long '取得文字列の長さ
Dim LVITEMlengthB as long '構造体の長さ
Dim lvi As LVITEM
Dim count as DWord
ADText(GetDlgItem(hMainWnd,EditBox1) , "Count " +Str$(ListView_GetItemCount( hWnd )) +ex"\r\n")
text = 0
pid = 0
hProcess = 0
processMemoryA = 0
textlengthA = 0
'指定されたプロセスの仮想アドレス空間内のメモリ領域の状態を予約
ADText(GetDlgItem(hMainWnd,EditBox1) , ex"GetWindowThreadProcessId>"+Str$(GetWindowThreadProcessId( hWnd ,VarPtr(pid)))+ex"\r\n") 'プロセスIDを取得
hProcess=OpenProcess( PROCESS_VM_OPERATION + PROCESS_VM_READ + PROCESS_VM_WRITE, FALSE, pid) 'プロセスハンドルを取得
ADText(GetDlgItem(hMainWnd,EditBox1) , ex"プロセスID pid>"+Str$(pid)+ex"\r\n")
'メモリを確保
processMemoryA = VirtualAllocEX( hProcess , NULL , MaxPath , MEM_COMMIT + MEM_RESERVE , PAGE_READWRITE) '共有メモリAを確保
ADText(GetDlgItem(hMainWnd,EditBox1) , "hProcess->" + Str$(hProcess as Long)+" processMemoryA->&h"+Hex$(processMemoryA as Long)+ex"<-\r\n") '確認
lvi.mask =LVIF_TEXT
lvi.iItem =y
lvi.iSubItem =x
lvi.cchTextMax =MaxPath
lvi.pszText =processMemoryA '共有メモリAを設定
ADText(GetDlgItem(hMainWnd,EditBox1) , "pszText -> &h" + Hex$(lvi.pszText ) + ex"\r\n" ) '確認
LVITEMlengthB = SizeOf(LVITEM)
LVITEMMemoryB = VirtualAllocEX( hProcess , NULL , LVITEMlengthB , MEM_COMMIT + MEM_RESERVE , PAGE_READWRITE) '共有メモリBを確保
'共有メモリBに構造体をコピー
ADText(GetDlgItem(hMainWnd,EditBox1) , "WriteProcessMemoryB->" + Str$(WriteProcessMemory(hProcess , LVITEMMemoryB , VarPtr(lvi) , LVITEMlengthB , VarPtr(count) )) + " > "+ Str$(count) +ex"\r\n" )
textlengthA = SendMessage(hWnd,LVM_GETITEMTEXT,y,LVITEMMemoryB) 'listviewに指示
ADText(GetDlgItem(hMainWnd,EditBox1) , "SendMessage > answer Read length->" + Str$(textlengthA) +ex"\r\n" ) '確認
text=calloc( MaxPath+1 ) '通常メモリを確保
'共有メモリから通常メモリに回収
ADText(GetDlgItem(hMainWnd,EditBox1) , "ReadProcessMemory->" + Str$(ReadProcessMemory(hProcess, processMemoryA , text , MaxPath , VarPtr(count) ) ) + " > "+ Str$(count) + "/" + Str$(MaxPath) +ex"\r\n" )
'解放
ADText(GetDlgItem(hMainWnd,EditBox1) , ex"VirtualFreeEX processMemoryA >"+Str$(VirtualFreeEX(hProcess , processMemoryA , 0 , MEM_RELEASE)) +ex"\r\n")
ADText(GetDlgItem(hMainWnd,EditBox1) , ex"VirtualFreeEX LVITEMMemoryB>"+Str$(VirtualFreeEX(hProcess , LVITEMMemoryB , 0 , MEM_RELEASE)) +ex"\r\n")
LVITEMMemoryB=0
processMemoryA=0
'プロセスハンドルを閉じる
CloseHandle(hProcess)
hProcess=0
ADText(GetDlgItem(hMainWnd,EditBox1) , ex"text>"+MakeStr(text) +ex"\r\n")
Get_LVM_GetItemTextEEXX = text
End function
[/code]