How to find a desktop window (by window name) in Windows 8.1 Update 2 OS, using the Win32 API FindWindow() in PowerShell environment?

后端 未结 4 989
鱼传尺愫
鱼传尺愫 2021-01-19 05:53

I don\'t remember having any problem finding a window in older Windows OS\'s, but, I\'m not succeeding in Windows 8.1 Update 2 OS, using PowerShell v4.0.

相关标签:
4条回答
  • 2021-01-19 06:33

    The following code works fine for me, thanks to @zyq's advice

    [System.Windows.Forms.MessageBox]::Show('Test', 'PowerShell Dialog', 
            [Windows.Forms.MessageBoxButtons]::OK, 
            [Windows.Forms.MessageBoxIcon]::Information, 
            [Windows.Forms.MessageBoxDefaultButton]::Button1,
            [Windows.Forms.MessageBoxOptions]::ServiceNotification
            )
    
    $Win32API = Add-Type -Name Funcs -Namespace Win32 -PassThru -MemberDefinition @'
        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    
        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindow(string lpClassName, IntPtr lpWindowName);
    
        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindow(IntPtr lpClassName, string lpWindowName);
    '@
    
    $Win32API::FindWindow('#32770',       'PowerShell Dialog')
    $Win32API::FindWindow([IntPtr]::Zero, 'PowerShell Dialog')
    $Win32API::FindWindow('#32770',       [IntPtr]::Zero)
    $Win32API::FindWindow('Notepad',      [IntPtr]::Zero)
    
    0 讨论(0)
  • 2021-01-19 06:36

    I had a look at the C# implementation for this issue, and found 2 WNDCLASS structures: WNDCLASS_D AND WNDCLASS_I. The former is the traditional structure that uses strings as types, following the Win32 API. But the latter, uses IntPtr.Zero values for those WNDCLASS structure that take null string values. For this reason, specifying null string values will result in noting found because a null string value is not implicitly convertible to IntPtr.Zero.

    0 讨论(0)
  • 2021-01-19 06:37

    First : not an answer but to help other people working on it, if you use the good class, for example here I code CalcFrame wich is the real class of the main window of calc.exe it works.

    $fw::FindWindow("CalcFrame", $wname) # returns the right value for me if calc.exe is started.
    

    Second : The following works for me ; accordind to Microsoft documentation the first parameter should be null, but accordin to PInvoke site you must pass IntPtr.Zero as the first parameter.

    $sig = @"
      [DllImport("user32.dll", CharSet = CharSet.Unicode)]
      public static extern IntPtr FindWindow(IntPtr sClassName, String sAppName);
    
      [DllImport("kernel32.dll")]
      public static extern uint GetLastError();
    "@
    
    $fw = Add-Type -Namespace Win32 -Name Funcs -MemberDefinition $sig -PassThru
    $wname='Calculatrice' # any existing window name
    
    $fw::FindWindow([IntPtr]::Zero, $wname ) # returns the Window Handle
    $a = $fw::GetLastError()
    $a
    
    0 讨论(0)
  • 2021-01-19 06:52

    It seems that the method doesn't fail if, and only if, the ClassName is also specified (cannot be null) like in this example:

    $sig=@'
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    '@    
    
    $w32 = Add-Type -Namespace Win32 -Name Funcs -MemberDefinition $sig -PassThru
    $w32::FindWindow('ConsoleWindowClass', 'Windows PowerShell') # Windows PowerShell Console
    

    If the ClassName is null, then the JPBlanc's method works correctly, which specifies a different signature for the method.

    0 讨论(0)
提交回复
热议问题