【问题标题】:Why will this run in 32bit, but not 64bit? (x86 vs x64 in compiler options)为什么这会在 32 位上运行,而不是 64 位? (编译器选项中的 x86 与 x64)
【发布时间】:2010-01-18 08:22:51
【问题描述】:

我正在使用以下代码来遍历并在其标题栏中查找包含特定字符串的窗口。我有两个项目包含相同的信息,但出于某种原因 - 它在针对 x64 时有效,但 FindWindowLike 在 x86 上总是返回 0。我需要它在 x86 中运行。

我正在 Windows 7 x64 上开发它,但它需要在我的机器和 XPx32 上运行。我无法理解的是为什么它在 x64 而不是 x32 上编译/运行(考虑到我的目标是 user32.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

【问题讨论】:

    标签: vb.net 64-bit 32-bit 32bit-64bit


    【解决方案1】:

    您的函数定义错误。在 C 中,LONG 是 32 位宽,但在 C# 和 VB.NET 中,long 在 32 位和 64 位系统上都是 64 位宽。另外,你的窗口句柄参数应该是IntPtrs。

    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
    

    请注意,您不应将Strings 传递给GetWindowTextGetClassName。试试StringBuilder

    【讨论】:

    • “不应该”还不够强大,这是大错特错。访问 pinvoke.net 以获得更好的声明。
    • 嗯,还不错。如果你创建了一个特定长度的字符串并确保它没有被实习,那么你应该没问题。
    【解决方案2】:

    另一条建议是结束针对 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。我更喜欢使用反射器,看看框架是如何处理它的。

    【讨论】:

      猜你喜欢
      • 2014-06-27
      • 2013-07-03
      • 2012-08-30
      • 1970-01-01
      • 2015-06-29
      • 2013-10-20
      • 2015-04-03
      • 2017-10-24
      相关资源
      最近更新 更多