C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト


■95885 / )  Re[2]: 他のプロセスのリストビューの内容を取得する
□投稿者/ 波留男 (3回)-(2020/10/07(Wed) 11:54:19)
魔界の仮面弁士 さんへ
早速の返答大変ありがとうございます。
しかしかなりハードルが高いです。ただあきらめる訳にはいきませんので、よろしくお願いいたします。

> No95760 のように UIAutomation で拾えないでしょうか (未確認)
> https://yizm.work/winactor/uiautomation_combobox_listview/
>
私には、難しくてちょっと手が出ませんでした。

> 相手のプロセスが管理者実行されていて、
> こちらのプロセスはそうではない…という状態にはなっていませんか?

フリーの画像位置情報取得ツールのリストビューの内容を取得したいのですが、管理者実行では
無いと思います

>
> 自身のアプリは、x86 / AnyCPU32bitPreferred / AnyCPU / x64 いずれでも良いのですか?
>
> 64bit プロセスから 64bit プロセスの ListView を読み取ろうとしているのか
> 64bit プロセスから 32bit プロセスの ListView を読み取ろうとしているのか
> 32bit プロセスから 64bit プロセスの ListView を読み取ろうとしているのか
> 32bit プロセスから 32bit プロセスの ListView を読み取ろうとしているのか
>
1プロセスにおける32ビットと64ビットの混在のことでしょうか?
ネットには以下
ネィティブアプリケーションの場合、プラットフォームの異なるExeとDllは共存できません。
・x64のExeと x64のDLL ⇒動作する
・x86のExeと x86のDLL ⇒動作する
・x64のExeと x86のDLL ⇒動作しない
・x86のExeと x64のDLL ⇒動作しない
とありました。最近は、64OSが主流なので、他のプロセスが32,64であっても動作してもらえると
助かります。どちらかに絞るなら 画像位置情報取得ツールに順じ64でしょうか。

結果ですが、
1) intRc = WriteProcessMemory(hProc, lpShared1, li, Marshal.SizeOf(li), lWritten) '書込み
2) intRc = SendMessageW(hWnd, LVM_GETITEMW, 0, li) '取得依頼
3) intRc = ReadProcessMemory(hProc, lpShared2, strBuffer(0), TEXT_SIZE, 0) '読込
1)intRc の値が1でうまくいってないと思います
2)画像位置情報取得ツールが終了しまいました。何らかの影響を与えた点では、一歩前進です
1)の実行結果が、ポイントとは思いますが、私には、難しくてまた助言して頂けると助かります。
以下の抜粋ですが変更後コードを掲載いたします

'----------------------
' ウィンドウメッセージ
'----------------------

' 魔界の仮面弁士さんより
Private Declare Unicode Function SendMessageW Lib "user32" _
(hWnd As IntPtr, wMsg As Integer, wParam As IntPtr, ByRef lvi As LV_ITEMW) As IntPtr
#Const NTDDI_WINXP = &H5010000&
#Const NTDDI_VISTA = &H6000000&
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
Private Structure LV_ITEMW
Public mask As UInteger
Public iItem As Integer
Public iSubItem As Integer
Public state As UInteger
Public stateMask As UInteger
<MarshalAs(UnmanagedType.LPTStr)> Public lpszText As String
Public cchTextMax As Integer
Public iImage As Integer
Public lParam As IntPtr
#If NTDDI_VERSION >= NTDDI_WINXP Then
  Public iIndent As Integer
  Public iGroupId As Integer
  Public cColumns As UInteger
#End If
#If NTDDI_VERSION >= NTDDI_VISTA Then
  Public puColumns As IntPtr
  Public piColFmt As IntPtr
  Public iGroup As Integer
#End If
End Structure



'------------------------------------
' システム関数
'------------------------------------
   'APIは省略 

'------------------------------------
'リストビュー定義
'------------------------------------

Public Const WC_LISTVIEW As String = "SysListView32"

Private Const LVM_FIRST As Integer = &H1000
Private Const LVM_GETTITEMCOUNT As Integer = (LVM_FIRST + 4) 'アイテムの数を取得
'Private Const LVM_GETITEMW As Integer = &H1005        'アイテムの属性を取得 従来の文
Private Const LVM_GETITEMA As Integer = &H1000 + 5      ' 魔界の仮面弁士さんより変更
Private Const LVM_GETITEMW As Integer = &H1000 + 75      ' 魔界の仮面弁士さんより変更
Private Const LVM_GETHEADER As Integer = &H101F 'ヘッダコントロールを取得
Private Const LVM_GETITEMTEXTA As Decimal = (LVM_FIRST + 45)
Private Const HDM_GETITEMCOUNT As Integer = &H1200
Private Const LVIF_TEXT As Integer = &H1
Private Const LVIF_IMAGE As Integer = &H2
Private Const LVIF_PARAM As Integer = &H4
Private Const LVIF_STATE As Integer = &H8


<StructLayout(LayoutKind.Sequential)> Structure LV_TEXT 'データエリア
Dim sItemText As Byte
End Structure



'------------------------------------
' キーボード
'------------------------------------
'Public Const VK_ESCAPE As Integer = &H1B 'Escape
Public Declare Function GetAsyncKeyState Lib "user32.dll" (ByVal vKey As Integer) As Integer


'-------------------------------
' リストビューボックス文字列取得
'-------------------------------

Public Function MyGetListViewItem(ByRef hWnd As Integer) As String

Dim i, p, k As Integer
Dim Dt As String

Dim pid, tid As Integer 'プロセスID,スレッドID
Dim hProc As Integer 'プロセスハンドル
Dim intRc As Integer

Dim hWndHeader As Integer 'リストビューヘッダのハンドル
Dim nCountRow, nCountCol As Integer '行列数

'----------------------
' 共有メモリアドレス
'----------------------
Dim lpShared1 As Long 'パラメータエリア
Dim lpShared2 As Integer 'データエリア
Dim lWritten As Integer = 0 '書込済バイト数

'----------------------
' リストビューパラメータ
'----------------------
Dim li As New LV_ITEMW 'パラメータ
Const TEXT_SIZE As Integer = 80
Dim strBuffer(TEXT_SIZE) As Byte

MyGetListViewItem = ""

'リストビューの項目(行)数取得
nCountRow = SendMessage(hWnd, LVM_GETTITEMCOUNT, 0, 0)
If nCountRow = 0 Then Exit Function

'リストビューの列数取得
hWndHeader = SendMessage(hWnd, LVM_GETHEADER, 0, 0)
nCountCol = SendMessage(hWndHeader, HDM_GETITEMCOUNT, 0, 0)
If (nCountCol = 0) Then Exit Function

'プロセスIDとスレッドID取得
tid = GetWindowThreadProcessId(hWnd, pid)

'共有メモリ確保
lpShared1 = GetSharedMem(pid, Marshal.SizeOf(li), hProc)
lpShared2 = GetSharedMem(pid, TEXT_SIZE, hProc)

Dt = ""


For i = 0 To nCountRow - 1 '行数分ループ
For k = 0 To nCountCol - 1 '列数分ループ

'メッセージパラメータセット
li.iItem = i '行インデックス
li.iSubItem = k '列インデックス

li.mask = LVIF_STATE '文字情報取得
li.lpszText = lpShared2 '文字格納アドレス
li.cchTextMax = TEXT_SIZE '文字数最大値

intRc = WriteProcessMemory(hProc, lpShared1, li, Marshal.SizeOf(li), lWritten) '書込み
intRc = SendMessageW(hWnd, LVM_GETITEMW, 0, li)          '取得依頼  SendMessageWに変更
intRc = ReadProcessMemory(hProc, lpShared2, strBuffer(0), TEXT_SIZE, 0) '読込


Dim tmp As String
tmp = System.Text.Encoding.Default.GetString(strBuffer)
p = InStr(tmp, vbNullChar) - 1 '文字数
If p > 0 Then Dt = Dt & Left(tmp, p)
Dt &= vbTab 'タブ追加

Next k
Dt &= vbCrLf '改行追加

Next i

'共有メモリ開放
FreeSharedMem(hProc, lpShared1, Marshal.SizeOf(li))
FreeSharedMem(hProc, lpShared2, TEXT_SIZE)

MyGetListViewItem = Dt

End Function

返信 編集キー/


管理者用

- Child Tree -