如何使用Powershell将焦点放在模式对话框上?

时间:2018-10-24 23:22:26

标签: powershell modal-dialog

我找到了一个脚本here(请参见下文),该脚本使我可以从Powershell中选择一个主窗口,然后添加一些按键。但是,当脚本选择主窗口而不是对话框时,我想按一下以使其消失。是否有某种方法可以选择对话框,或者使用按键将其选中?

Function SendKey{
    [CMDLetBinding()]
    Param(
        [String]
        [Parameter(Mandatory=$True,ValueFromPipelineByPropertyName=$True,Position=1)]
        $WindowTitle,

        [String[]]
        [Parameter(Mandatory=$True,ValueFromPipelineByPropertyName=$True,Position=2)]
        $Key
    )
    Begin{ 
        $ErrorActionPreference = 'SilentlyContinue'
        $Dlls = @' 
    [DllImport("user32.dll")] 
    public static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll")] 
    public static extern bool SetForegroundWindow(IntPtr hWnd); 
'@

    $WindowControl = Add-Type -MemberDefinition $Dlls -Name "Win32WindowControl" -namespace Win32Functions -passThru
    }
    Process{
        $WindowHandle = Get-Process | Where-Object { $_.MainWindowTitle -Match $WindowTitle } | Select-Object -ExpandProperty MainWindowHandle

        If($WindowHandle){
            $WindowControl::SetForegroundWindow($WindowHandle)

            Sleep 1

            $FocusHandle = $WindowControl::GetForegroundWindow()
            If($FocusHandle -eq $WindowHandle){
                ForEach($Press in $Key){
                    [System.Windows.Forms.SendKeys]::SendWait("$Press")
                }
            }
        }
    }
}   

1 个答案:

答案 0 :(得分:1)

您的代码:

  • 有一个附带的问题:$ErrorActionPreference = 'SilentlyContinue'程序集从未加载到您的代码中,[System.Windows.Forms.SendKeys]::SendWait("$Press")抑制了后续错误,因此System.Windows.Forms悄然失败({{1} }

  • 有一个基本问题:将Add-Type -AssemblyName System.Windows.Forms与进程的窗口一起使用确实会在该主窗口上设置焦点,即使打开了模式对话框也是如此-结果,击键可能无济于事。

最简单的解决方案是改用SetForegroundWindow()类型的静态.AppActivate()方法:

  • [Microsoft.VisualBasic.Interaction]会正确激活属于目标应用程序的最前面的任何窗口-如果您按Alt键制表到应用程序,则会激活该窗口。例如,这可能是主窗口或打开的模式对话框。
.AppActivate()

要测试代码:

  • 在PowerShell窗口中,点源提供上述函数(在您的会话中定义)。

  • 打开一个NotePad实例(运行Function SendKey { [CmdletBinding()] Param( [String] [Parameter(Mandatory = $True, Position = 1)] $WindowTitle, [String[]] [Parameter(Mandatory = $True, Position = 2)] $Key ) Begin { # Load the required assemblies. Add-Type -AssemblyName System.Windows.Forms, Microsoft.VisualBasic } Process { # Find the process with the main window title of interest. $procId = (Get-Process | Where-Object { $_.MainWindowTitle -Match $WindowTitle }).Id If ($procId) { # Target application's process found. # Activate it by its process ID. [Microsoft.VisualBasic.Interaction]::AppActivate($procId) # Send the keystrokes. ForEach ($Press in $Key) { [System.Windows.Forms.SendKeys]::SendWait($Press) } } } } )。

  • 切换到新实例,并使文件打开对话框可见( Ctrl + O )。

  • 切换回您的PowerShell窗口并运行notepad

应该激活记事本,关闭文件打开对话框,并在主窗口(文档)中键入SendKey Notepad '{ESC}o'

如果没有打开任何对话框,则o应该无效,{ESC}也应该出现在主窗口中。

注意事项:击键将发送到目标窗口/目标窗口的打开对话框中恰好具有键盘焦点的任何控件。

因此,如果您知道在发送按键时将打开哪个特定的窗口/对话框,则可以首先发送其他按键来激活所需的特定控件。

例如,如果您希望打开文件打开对话框,则可以先发送o(相当于 Alt + N ),以确保{{1 }}文本框具有输入焦点。 例如,发送文件名%nFile name: