Powershell / selenium发送键以弹出窗口

时间:2017-07-04 11:53:08

标签: c# powershell selenium

我编写了一个代码,打开一个弹出窗口,我必须选择文件路径才能上传。See link to view popup screen

现在我想让这个脚本在后台运行。但是,我使用的 Wshell命令是不可能的。

有没有办法可以替换Wshell命令?

#go to the uploadtab
#---------------------
$searchBtnIris2 = $driver.FindElementByXPath('//*[@id="menuFormHome:j_id44_body"]/ul[3]/li[4]/a')
Write-Host "Den ID van de zoekknop is $seachBtnIris2"
$searchBtnIris2.Click();

Start-Sleep -s 15


#click add button and select file to upload
#-------------------------------------------
$searchBtnIris3 = $driver.FindElementByXPath('//*[@id="uploadFormPanel:upload:flashContainer"]')
Write-Host "Den ID van de zoekknop is $seachBtnIris3"
$searchBtnIris3.Click();

Start-Sleep -s 1

$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate('title of the application window')
Sleep 1
$wshell.SendKeys('C:\Users\SVan37\Documents\test\EDI_IRIS_UPLOAD.xlsx');

$wshell.SendKeys('~')

Start-Sleep -s 1

2 个答案:

答案 0 :(得分:0)

这是一种快速而肮脏的方法。将下面的整个代码块粘贴到您的脚本中并像这样调用它:

Set-OpenFileDialogPath -Path 'C:\Users\SVan37\Documents\test\EDI_IRIS_UPLOAD.xlsx' -OwnerBinaryFileName 'chrome.exe'

<#
.SYNOPSIS
Sets the path of all open file dialogs, optionally filtered by binary file name.

.PARAMETER Path
The file path to use.

.PARAMETER OwnerBinaryFileName
The binary file name to filter by, such as chrome.exe.

.OUTPUTS
System.Boolean. True if at least one open file dialog was found and updated; false otherwise.
#>

function Set-OpenFileDialogPath
{
    Param(
        [Parameter(Mandatory = $true)]
        [string]
        $Path,

        [string]
        $OwnerBinaryFileName
    )

    # Add Win32 window functions, ignoring the exception if they've already been added
    try
    {
        $user32 = Add-Type -Name 'user32' -Namespace 'Win32' -PassThru -MemberDefinition @'
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam);
'@
    }
    catch
    {
    }

    $foundOne = $false
    $lastOpenDialogHwnd = [IntPtr]::Zero

    # Loop over all open file dialogs
    while ($true)
    {
        # Find the open file dialog
        $lastOpenDialogHwnd = $user32::FindWindowEx([IntPtr]::Zero, $lastOpenDialogHwnd, '#32770', 'Open')
        if ($lastOpenDialogHwnd -eq [IntPtr]::Zero)
        {
            break
        }

        # If a binary filter was specified and the found open file dialog doesn't belong, look for the next dialog
        if (![string]::IsNullOrEmpty($OwnerBinaryFileName))
        {
            $processId = 0
            $user32::GetWindowThreadProcessId($lastOpenDialogHwnd, [ref]$processId) | Out-Null
            $process = [Diagnostics.Process]::GetProcessById($processId -as [int])
            if ([IO.Path]::GetFileName($process.MainModule.FileName) -ine $OwnerBinaryFileName)
            {
                continue
            }
            $process.Dispose()
        }

        # Find the Open button
        $buttonHwnd = $user32::FindWindowEx($lastOpenDialogHwnd, [IntPtr]::Zero, 'Button', '&Open')

        # Find the open file dialog's file name textbox
        $comboBoxExHwnd = $user32::FindWindowEx($lastOpenDialogHwnd, [IntPtr]::Zero, 'ComboBoxEx32', $null)
        if ($comboBoxExHwnd -ne [IntPtr]::Zero -and $buttonHwnd -ne [IntPtr]::Zero)
        {
            $comboBoxHwnd = $user32::FindWindowEx($comboBoxExHwnd, [IntPtr]::Zero, 'ComboBox', $null)
            if ($comboBoxHwnd -ne [IntPtr]::Zero)
            {
                $editHwnd = $user32::FindWindowEx($comboBoxHwnd, [IntPtr]::Zero, 'Edit', $null)
                if ($editHwnd -ne [IntPtr]::Zero)
                {
                    # Set the open file dialog's file name textbox to the desired path
                    $user32::SendMessage($editHwnd, 12, [IntPtr]::Zero, $Path) | Out-Null

                    # Click "Open"
                    $user32::SendMessage($buttonHwnd, 245, [IntPtr]::Zero, [IntPtr]::Zero) | Out-Null

                    $foundOne = $true
                }
            }
        }
    }

    return $foundOne
}

(为了清楚说明其长度,上述代码是根据Unlicense license许可的,这意味着它可以免费用于任何类型的使用和修改,并且没有归属或许可证包含要求。)

备注

  • 该函数使用SendMessage而不是SendKeys,因此无论打开文件对话框是隐藏还是非活动,它都将起作用。 (事实上​​,即使您在运行时在另一个窗口中主动输入,它也会起作用。)
  • 使用chrome.exe作为OwnerBinaryFileName调用该函数会使其更新属于chrome.exe的所有打开文件对话框的文件名文本框。因此,如果chrome.exe的多个实例同时显示打开的文件对话框的可能性,您应该添加几行来检查对话框的标签名称是否拥有流程窗口与您要定位的流程窗口匹配。
  • 如果您将来需要通过PowerShell进行更多对话自动化,我建议您查看WASP (Windows Automation Snapin for PowerShell)。不幸的是,它已经托管在即将发布的CodePlex上,而且它似乎还没有出现在GitHub上,所以希望有人会在2017年12月15日之前拿到它(CodePlex&#39 ;计划完全关闭的日期)。

答案 1 :(得分:0)

#click add button and select file to upload
#-------------------------------------------
$searchBtnIris3 = $driver.FindElementByXPath('//*[@id="uploadFormPanel:upload:flashContainer"]')
Write-Host "Den ID van de zoekknop is $seachBtnIris3"
$searchBtnIris3.Click();

Start-Sleep -s 1

Set-OpenFileDialogPath -Path "C:\Users\SVan37\Documents\test\EDI_IRIS_UPLOAD.xlsx" -OwnerBinaryFileName 'chrome.exe'

Start-Sleep -s 1
<#
.SYNOPSIS
Sets the path of all open file dialogs, optionally filtered by binary file name.

.PARAMETER Path
The file path to use.

.PARAMETER OwnerBinaryFileName
The binary file name to filter by, such as chrome.exe.

.OUTPUTS
System.Boolean. True if at least one open file dialog was found and updated; false otherwise.
#>

function Set-OpenFileDialogPath
{
    Param(
        [Parameter(Mandatory = $true)]
        [string]
        $Path,

        [string]
        $OwnerBinaryFileName
    )

    # Add Win32 window functions, ignoring the exception if they've already been added
    try
    {
        $user32 = Add-Type -Name 'user32' -Namespace 'Win32' -PassThru -MemberDefinition @'
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam);
'@
    }
    catch
    {
    }

    $foundOne = $false
    $lastOpenDialogHwnd = [IntPtr]::Zero

    # Loop over all open file dialogs
    while ($true)
    {
        # Find the open file dialog
        $lastOpenDialogHwnd = $user32::FindWindowEx([IntPtr]::Zero, $lastOpenDialogHwnd, '#32770', 'Open')
        if ($lastOpenDialogHwnd -eq [IntPtr]::Zero)
        {
            break
        }

        # If a binary filter was specified and the found open file dialog doesn't belong, look for the next dialog
        if (![string]::IsNullOrEmpty($OwnerBinaryFileName))
        {
            $processId = 0
            $user32::GetWindowThreadProcessId($lastOpenDialogHwnd, [ref]$processId) | Out-Null
            $process = [Diagnostics.Process]::GetProcessById($processId -as [int])
            if ([IO.Path]::GetFileName($process.MainModule.FileName) -ine $OwnerBinaryFileName)
            {
                continue
            }
            $process.Dispose()
        }

        # Find the Open button
        $buttonHwnd = $user32::FindWindowEx($lastOpenDialogHwnd, [IntPtr]::Zero, 'Button', '&Open')

        # Find the open file dialog's file name textbox
        $comboBoxExHwnd = $user32::FindWindowEx($lastOpenDialogHwnd, [IntPtr]::Zero, 'ComboBoxEx32', $null)
        if ($comboBoxExHwnd -ne [IntPtr]::Zero -and $buttonHwnd -ne [IntPtr]::Zero)
        {
            $comboBoxHwnd = $user32::FindWindowEx($comboBoxExHwnd, [IntPtr]::Zero, 'ComboBox', $null)
            if ($comboBoxHwnd -ne [IntPtr]::Zero)
            {
                $editHwnd = $user32::FindWindowEx($comboBoxHwnd, [IntPtr]::Zero, 'Edit', $null)
                if ($editHwnd -ne [IntPtr]::Zero)
                {
                    # Set the open file dialog's file name textbox to the desired path
                    $user32::SendMessage($editHwnd, 12, [IntPtr]::Zero, $Path) | Out-Null

                    # Click "Open"
                    $user32::SendMessage($buttonHwnd, 245, [IntPtr]::Zero, [IntPtr]::Zero) | Out-Null

                    $foundOne = $true
                }
            }
        }
    }

    return $foundOne
}

Start-Sleep -s 1


#click the proceedbutton
#-------------------------
$ProcessBtnIris = $driver.FindElementByXPath('//*[@id="uploadFormPanel:processButton"]')
Write-Host "Den ID van de zoekknop is $ProcessBtnIris"
$ProcessBtnIris.Click();