为什么这将运行在32位,但不是64位? (x86与编译器选项中的x64)

问题描述:

我使用以下代码遍历并在其标题栏中找到包含特定字符串的窗口。我有两个包含这些相同信息的项目,但由于某些原因 - 它在定位到x64时有效,但FindWindowLike始终在x86上返回0。我需要这个在x86中运行。为什么这将运行在32位,但不是64位? (x86与编译器选项中的x64)

我正在开发Windows 7 x64上的这个,但它需要在我的机器以及XPx32上运行。我无法捉摸就是为什么它编译/运行在64位,但不是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 

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

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 s到GetWindowTextGetClassName。尝试StringBuilder

+1

“不应该”几乎不够强,这是非常错误的。访问pinvoke.net以获得更好的声明。 – 2010-01-18 09:14:40

+0

好吧,这不是那么糟糕。如果你创建了一定长度的字符串并确保它没有被执行,那么你应该没问题。 – wj32 2010-01-18 09:30:48

另一条建议是将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。我更喜欢使用反射器,并且确切地看,框架如何处理它。