DOBON.NET DOBON.NETプログラミング掲示板過去ログ

デスクトップからアイコンテキストが返ってこない

環境/言語:[vb.net 2005 express windows7 64bit]
分類:[.NET]

XP 32bitでは動く以下のコードが7 64bitでは値が返ってきません
原因は何でしょう

hWnd = WindowFromPoint(HovPnt.X, HovPnt.Y)
TId = GetWindowThreadProcessId(CType(hWnd, IntPtr), PId)

hProc = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, PId)

lpShared1 = VirtualAllocEx(hProc, IntPtr.Zero, Marshal.SizeOf(LVI), MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
lpShared2 = VirtualAllocEx(hProc, IntPtr.Zero, TEXT_SIZE, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)

LVI = New LV_ITEM
LVI.iItem = DskTopIcnIdx
LVI.iSubItem = 0
LVI.mask = LVIF_TEXT
LVI.lpszText = CType(_lpShared2, IntPtr)
LVI.cchTextMax = TEXT_SIZE

rslt = WriteProcessMemory(hProc, lpShared1, LVI, Marshal.SizeOf(LVI), lWritten)
rslt = SendMessage(CType(hWnd, IntPtr), LVM_GETITEMW, IntPtr.Zero, lpShared1)
rslt = ReadProcessMemory(hProc, lpShared2, strBuffer(0), TEXT_SIZE, 0)

iconText = System.Text.Encoding.Default.GetString(strBuffer) '<==コレ

VirtualFreeEx(hProc, lpShared1, Marshal.SizeOf(LVI), MEM_RELEASE)
VirtualFreeEx(hProc, lpShared2, TEXT_SIZE, MEM_RELEASE)
■No32230に返信(/400さんの記事)
> XP 32bitでは動く以下のコードが7 64bitでは値が返ってきません
処理対象のアプリは何ですか?
相手が 32bit アプリか 64bit アプリかに応じて、
とるべき処理が異なってくるかと思います。

下記が参考になるかもしれません。
http://www.inasoft.org/webhelp/lv2csv/chapter5.html
レスありがとうございます

> 処理対象のアプリは何ですか?
> 相手が 32bit アプリか 64bit アプリかに応じて、
> とるべき処理が異なってくるかと思います。

デスクトップです(ポイントしたアイコンのテキストを取得してました)

> 下記が参考になるかもしれません。
> http://www.inasoft.org/webhelp/lv2csv/chapter5.html

32bitから64bitへのアクセスは無理ってことですね
了解しました
解決済み!
■No32232に返信(/400さんの記事)
> デスクトップです(ポイントしたアイコンのテキストを取得してました)

であれば、IAccessible インターフェイスの方が手っ取り早いかも。


Imports System.Runtime.InteropServices
Public Class Form1

    'Accessibility.dll を参照設定しておくこと
    <DllImport("oleacc")> _
    Private Shared Function AccessibleObjectFromPoint _
        (ByVal xScreen As Integer, _
         ByVal yScreen As Integer, _
         ByRef ppvObject As Accessibility.IAccessible, _
         ByRef pvarChild As Object) As Integer
    End Function

    Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
        'マウス座標
        Dim pos As Point = Cursor.Position

        Dim acc As Accessibility.IAccessible = Nothing
        Dim child As Object = Nothing
        AccessibleObjectFromPoint(pos.X, pos.Y, acc, child)

        Label1.Text = ""
        Label2.Text = ""
        Try
            Label1.Text = acc.accName(child)
            Dim l, t, w, h As Integer
            acc.accLocation(l, t, w, h, child)
            Label2.Text = (New Rectangle(l, t, w, h)).ToString()
        Catch ex As Exception
        End Try
    End Sub
End Class



> 32bitから64bitへのアクセスは無理ってことですね

Express は、特に何もしなければ AnyCPU ビルドだと聞いていますので、
その環境では 64bit 版アプリとして動作しているかと思います。

なお、32bit アプリから 64bit プロセスにアクセスする場合には、
Very Large Memory 系 API (VirtualAllocVlm 等)が存在する
らしいですが、試してみたことはありません。
重ねてのレスありがとうございます

> であれば、IAccessible インターフェイスの方が手っ取り早いかも。

なる程テキストだけならこっちのが楽ですね
まあ後出しになってしまいますけどテキストだけだとカレントユーザーと
オールユーザーがダブる可能性も含めてサブアイテムのタイムスタンプも
取得して識別してました
(ショートカットもありますし)
直接フルパスが取れれば一番楽だったんですけど調べても「難しいです」しか
情報が無いという…(笑

> Express は、特に何もしなければ AnyCPU ビルドだと聞いていますので、
> その環境では 64bit 版アプリとして動作しているかと思います。

他のライブラリアクセスしてる都合でX86ビルドです
重ね重ねありがとうございました
解決済み!
■No32234に返信(/400さんの記事)
> 直接フルパスが取れれば一番楽だったんですけど調べても「難しいです」しか
> 情報が無いという…(笑

パスを列挙するだけなら:

Imports System.Runtime.InteropServices
Public Class Form1
    Private tbl As DataTable
    Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
        tbl = New DataTable()
        tbl.Columns.Add("Name")
        tbl.Columns.Add("Path")
        tbl.Columns.Add("Modified", GetType(Date))
        tbl.Columns.Add("Link", GetType(Boolean))
        tbl.Columns.Add("Target")

        DataGridView1.DataSource = tbl

        Dim sh As SHDocVw.ShellWindows = GetObject("new:9BA05972-F6A8-11CF-A442-00A0C90A8F39")
        Dim o As Object = sh.Item(Type.Missing)
        Dim sfvd As Shell32.IShellFolderViewDual = o.Document
        Dim sd As Shell32.Shell = sfvd.Application
        Dim f As Shell32.Folder3 = sfvd.Folder
        Dim fis As Shell32.FolderItems3 = f.Items()
        For i As Integer = 0 To fis.Count - 1
            Dim fi As Shell32.FolderItem2 = fis.Item(CObj(i))
            Dim row As DataRow = tbl.NewRow()
            row!Name = fi.Name
            row!Path = fi.Path
            If fi.IsLink Then
                row!Link = True
                Dim lnk As Shell32.ShellLinkObject = Nothing
                Try
                    lnk = fi.GetLink
                    row!Target = lnk.Path
                Catch ex As Exception
                    row.RowError = ex.Message
                Finally
                    If Not lnk Is Nothing Then
                        Marshal.ReleaseComObject(lnk)
                    End If
                    lnk = Nothing
                End Try
            Else
                row!Link = False
                row!Target = DBNull.Value
            End If
            row!Modified = fi.ModifyDate
            tbl.Rows.Add(row)

            Marshal.ReleaseComObject(fi)
        Next
        Marshal.ReleaseComObject(fis)
        Marshal.ReleaseComObject(f)
        Marshal.ReleaseComObject(sd)
        Marshal.ReleaseComObject(sfvd)
        Marshal.ReleaseComObject(o)
        Marshal.ReleaseComObject(sh)
    End Sub
End Class


SHDocVw や Shell32 を参照設定しない場合は、
As SHDocVw.何某 や As Shell32.何某 を
As Object に置き換えてみてください。

DOBON.NET | プログラミング道 | プログラミング掲示板