Почему это будет работать в 32-битной, а не 64-битной?(x86 против x64 в настройках компилятора) - PullRequest
1 голос
/ 18 января 2010

Я использую следующий код для перебора и поиска окон, содержащих конкретные строки в заголовках. У меня есть два проекта, содержащие эту идентичную информацию, но по какой-то причине - она ​​работает, когда нацелена на x64, но FindWindowLike всегда возвращает 0 на x86. Мне нужно это для запуска в x86.

Я разрабатываю это на Windows 7 x64, но оно должно работать на моей машине, а также на XPx32. Я не могу понять, почему он компилируется / работает на x64, но не на x32 (учитывая, что я нацеливаюсь на пользователя 32 .dll)

А вот и код:

    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
    End Function

    <DllImport("user32.dll", EntryPoint:="FindWindow", SetLastError:=True, CharSet:=CharSet.Auto)> Private Shared Function FindWindowByClass(ByVal lpClassName As String, ByVal zero As IntPtr) As IntPtr
    End Function

    <DllImport("user32.dll", EntryPoint:="FindWindow", SetLastError:=True, CharSet:=CharSet.Auto)> Private Shared Function FindWindowByCaption(ByVal zero As IntPtr, ByVal lpWindowName As String) As IntPtr
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True)> Public Shared Function IsWindow(ByVal hWnd As IntPtr) As Boolean
    End Function

    Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As IntPtr) As IntPtr
    Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal hdc As IntPtr) As IntPtr
    Public Declare Function GetDesktopWindow Lib "user32" () As Long
    Public Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
    Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
    Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
    Public Const GW_HWNDFIRST = 0
    Public Const GW_HWNDLAST = 1
    Public Const GW_HWNDNEXT = 2
    Public Const GW_HWNDPREV = 3
    Public Const GW_OWNER = 4
    Public Const GW_CHILD = 5
    Public listWindows As New List(Of String)

Private Function FindWindows() As Long
        Dim hWndStart As Long = 0
        Dim WindowText As String = "*message*"
        Dim Classname As String = "*"
        Dim hwnd As Long
        Dim sWindowText As String
        Dim sClassname As String
        Dim r As Long

        'Hold the level of recursion and
        'hold the number of matching windows
        Static level As Integer

        'Initialize if necessary. This is only executed 
        'when level = 0 and hWndStart = 0, normally 
        'only on the first call to the routine.
        If level = 0 Then
            If hWndStart = 0 Then hWndStart = GetDesktopWindow()
        End If

        'Increase recursion counter      
        level = level + 1

        'Get first child window
        hwnd = GetWindow(hWndStart, GW_CHILD)

        Do Until hwnd = 0

            'Search children by recursion
            Call FindWindows()

            'Get the window text and class name
            sWindowText = Space$(255)
            r = GetWindowText(hwnd, sWindowText, 255)
            sWindowText = Microsoft.VisualBasic.Left(sWindowText, r)
            sClassname = Space$(255)
            r = GetClassName(hwnd, sClassname, 255)
            sClassname = Microsoft.VisualBasic.Left(sClassname, r)

            'Check if window found matches the search parameters
            If (sWindowText Like WindowText) And (sClassname Like Classname) Then
                If listWindows.Contains(hwnd & "||||" & sClassname & "||||" & sWindowText) = False Then
                    listWindows.Add(hwnd & "||||" & sClassname & "||||" & sWindowText)
                End If
                FindWindows = hwnd

                'uncommenting the next line causes the routine to
                'only return the first matching window.
                'Exit Do

            End If

            'Get next child window
            hwnd = GetWindow(hwnd, GW_HWNDNEXT)

        Loop

        'Reduce the recursion counter
        level = level - 1
End Function

Ответы [ 2 ]

3 голосов
/ 18 января 2010

Ваши определения функций неверны. В C LONG имеет ширину 32 бита, но в C # и VB.NET long имеет ширину 64 бита как в 32-разрядных, так и в 64-разрядных системах Кроме того, параметры вашего дескриптора окна должны быть IntPtr с.

Private Declare Function GetDC Lib "user32.dll" (ByVal hwnd As IntPtr) As IntPtr
Private Declare Function ReleaseDC Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal hdc As IntPtr) As IntPtr
Private Declare Function GetDesktopWindow Lib "user32" () As IntPtr
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As IntPtr, ByVal wCmd As Integer) As IntPtr
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As IntPtr, ByVal lpString As String, ByVal cch As Integer) As Integer
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As IntPtr, ByVal lpClassName As String, ByVal nMaxCount As Integer) As Integer

Обратите внимание, что вы не должны передавать String с GetWindowText и GetClassName. Попробуйте StringBuilder.

1 голос
/ 18 января 2010

Еще один совет - свернуть вызовы, предназначенные для 32- и 64-битных систем.Вот пример для GetWindowLong:

Public Shared Function GetWindowLong(ByVal hWnd As HandleRef, ByVal nIndex As Integer) As IntPtr
    If (IntPtr.Size = 4) Then
        Return NativeMethods.GetWindowLong32(hWnd, nIndex)
    End If
    Return NativeMethods.GetWindowLongPtr64(hWnd, nIndex)
End Function

Как говорит nobugz, вы можете взглянуть на pinvoke.net.Я предпочитаю использовать отражатель и вижу, как именно его обрабатывает фреймворк.

...