【问题标题】:Powershell New-Object -comobject InternetExplorer.Application bring to frontPowershell New-Object -comobject InternetExplorer.Application 放在前面
【发布时间】:2014-12-24 00:26:07
【问题描述】:

我进行了搜索,但没有找到任何专门解决此问题的内容。

考虑一下代码,新的 IE 窗口可以在所有其他打开的窗口之前创建吗? VBScript 有提供intWindowStyleRun Method (Windows Script Host) 可选的。指示程序窗口外观的整数值。请注意,并非所有程序都使用此信息。

Powershell 的新 com 对象有类似的吗?

Param(
[Parameter(Mandatory=$false)]
[string]$svr,
[Parameter(Mandatory=$false)]
[string]$last,
[Parameter(Mandatory=$false)]
[string]$desc,
[Parameter(Mandatory=$false)]
[string]$date)
$ie = new-object -comobject InternetExplorer.Application
$ie.navigate("http://www.stackoverflow.com")
# Wait for the page to finish loading
 do {sleep 1} until (-not ($ie.Busy))
$doc = $ie.document
$link = $doc.getElementById("Sym_Msg").Value = "$svr"
$link = $doc.getElementById("Lname").Value = "$last"
$link = $doc.getElementById("Desc").Value = "$desc"
$link = $doc.getElementById("Date_Ent").Value = "$date"
$button = $doc.getElementById("submit1")
$ie.Visible = $true
$button.click();
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($ie) | Out-Null

【问题讨论】:

  • 你想把窗口放在所有其他窗口的顶部,还是仅仅在前台?
  • 目标是让新打开的 IE 窗口位于所有其他窗口之上。 Windows 将使任务栏中的 IE 图标闪烁,但我的目标是更加用户友好。

标签: windows internet-explorer powershell


【解决方案1】:

不幸的是,我不认为这是“新对象”的一部分。有几个 PowerShell 扩展将其实现为 cmdlet(例如 http://pscx.codeplex.com/"Set-ForegroundWindow")。

实现的方式是调用“user32.dll”。

在您的代码中,这应该可以工作:

#Load DLL
$pinvoke = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow)'   
Add-Type -MemberDefinition $pinvoke -name NativeMethods -namespace Win32

#Get WindowHandle of the COM Object
$hwnd = $ie.HWND

# Minimize window
[Win32.NativeMethods]::ShowWindowAsync($hwnd, 2)

# Restore window
[Win32.NativeMethods]::ShowWindowAsync($hwnd, 4)

--编辑在nCmdShow之后添加')

【讨论】:

  • 谢谢 Jan,最终使用了恢复方法,现在新创建的 IE 窗口出现在其他 IE 窗口的前面。奇怪的是,它仍然落后于我要从中启动 PS1 脚本的 HTA 应用程序。
  • 您可能对下面的 Nathans 变体有更好的运气。使用同一 DLL 中的 SetWindowPos 函数并将 hWndInsertAfter 设置为 -1 可能会更好。自己没有测试过。
【解决方案2】:

这对我来说非常有帮助。我需要对 Windows 窗体做同样的事情,而不是 IE,所以我需要做一些调整。我从网上借用别人的表单创建代码。

这在 SCCM 客户端执行基于脚本的安装程序时非常有效。

特别是我必须在最后添加以下内容,并调整其他一些内容:

$appContext = New-Object System.Windows.Forms.ApplicationContext 
[void][System.Windows.Forms.Application]::Run($appContext)

这是我使用的代码:

Add-Type -AssemblyName PresentationFramework, System.Drawing, System.Windows.Forms, WindowsFormsIntegration

    $objForm = New-Object System.Windows.Forms.Form 
    $objForm.Text = "Test"
    $objForm.Size = New-Object System.Drawing.Size(400,200) 
    $objForm.StartPosition = "CenterScreen"
    $objform.icon = "$StrInstDir\source\favicon.ico"

    $objForm.KeyPreview = $True
    $objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") 
        {$output = "OK";$objForm.Close()}})
    $objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape") 
        {$output = "Cancel";$objForm.Close()}})

    $OKButton = New-Object System.Windows.Forms.Button
    $OKButton.Location = New-Object System.Drawing.Size(105,120)
    $OKButton.Size = New-Object System.Drawing.Size(75,23)
    $OKButton.Text = "OK"
    $OKButton.Add_Click({$global:output="OK";$objForm.Close()})
    $objForm.Controls.Add($OKButton)

    $CancelButton = New-Object System.Windows.Forms.Button
    $CancelButton.Location = New-Object System.Drawing.Size(220,120)
    $CancelButton.Size = New-Object System.Drawing.Size(75,23)
    $CancelButton.Text = "Cancel"
    $CancelButton.Add_Click({$global:output = "Cancel";$objForm.Close()})
    $objForm.Controls.Add($CancelButton)

    $objform.Add_Closing({[System.Windows.Forms.Application]::Exit()})

    $objLabel = New-Object System.Windows.Forms.Label
    $objLabel.Location = New-Object System.Drawing.Size(60,20) 
    $objLabel.Size = New-Object System.Drawing.Size(280,200) 
    $objLabel.Text = "Test Text"
    $objForm.Controls.Add($objLabel) 


    [void] $objForm.Show()
    $objForm.Add_Shown({$objForm.Activate()})



    $signature = @"

    [DllImport("user32.dll")]  
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);  

    public static IntPtr FindWindow(string windowName){
        return FindWindow(null,windowName);
    }

    [DllImport("user32.dll")]
    public static extern bool SetWindowPos(IntPtr hWnd, 
    IntPtr hWndInsertAfter, int X,int Y, int cx, int cy, uint uFlags);

    [DllImport("user32.dll")]  
    public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 

    static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
    static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);

    const UInt32 SWP_NOSIZE = 0x0001;
    const UInt32 SWP_NOMOVE = 0x0002;

    const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;

    public static void MakeTopMost (IntPtr fHandle)
    {
        SetWindowPos(fHandle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
    }

    public static void MakeNormal (IntPtr fHandle)
    {
        SetWindowPos(fHandle, HWND_NOTOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
    }
"@
    $hWnd = $objform.handle
    $app = Add-Type -MemberDefinition $signature -Name Win32Window -Namespace ScriptFanatic.WinAPI -ReferencedAssemblies System.Windows.Forms -Using System.Windows.Forms -PassThru
    $null = $app::MakeTopMost($hWnd)
    $objform.Visible = $true

    $appContext = New-Object System.Windows.Forms.ApplicationContext 
    [void][System.Windows.Forms.Application]::Run($appContext)

【讨论】:

    【解决方案3】:

    为了将来参考,使窗口置顶的唯一方法是对 Win32 API 进行一些 P/Invoke。有趣的东西,尤其是来自 PowerShell!

    Add-Type -Namespace PInvoke -Name SWP '[DllImport("user32.dll", SetLastError=true)] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);'
    [PInvoke.SWP]::SetWindowPos($hWnd, -1, 0, 0, 0, 0, 3)
    

    此代码由this answerLee Holmes' old blog post on P/Invoke in PoShpinvoke.net/MSDN docs 拼凑而成。

    【讨论】:

    • 感谢 Nathan 的回复,创建的 IE 窗口似乎仍然出现在其他窗口后面。
    • 哦,麻烦了,我忘了包括我的警告,即 IE 在降低权限的情况下会发生一些奇怪的事情,虽然这确实可以在任何其他窗口上运行,但它在 IE 上不起作用无需关闭保护模式或其他东西。 (您也许可以在降低权限模式下运行脚本。)
    • @user4317867,我将尝试挖掘上述的解决方法,可能是通过以低完整性运行 PowerShell。
    • 有趣,当然启用了保护模式。这不是一些必须具备的功能,如果有就好了。我正在尝试清理此 HTA 以与同事共享,并希望使事情尽可能干净和简单。
    • 我也找到了这篇博文,可能会有所帮助blogs.msdn.com/b/ieinternals/archive/2011/08/03/…
    【解决方案4】:

    最后,在@Nathan Tuggy 的指导下,我发现了this page,它最终工作得很好。创建新的 IE 窗口,然后将其置于所有打开的窗口的前面。

    PowerShell 中创建新 IE ComObject 并将其置于最前面的代码摘要。

    $ie = New-Object -ComObject InternetExplorer.Application
    $ie.navigate("http://www.stackoverflow.com")
    do {sleep 1} until (-not ($ie.Busy))
    $signature = @"
    
    [DllImport("user32.dll")]  
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);  
    
    public static IntPtr FindWindow(string windowName){
        return FindWindow(null,windowName);
    }
    
    [DllImport("user32.dll")]
    public static extern bool SetWindowPos(IntPtr hWnd, 
    IntPtr hWndInsertAfter, int X,int Y, int cx, int cy, uint uFlags);
    
    [DllImport("user32.dll")]  
    public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 
    
    static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
    static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
    
    const UInt32 SWP_NOSIZE = 0x0001;
    const UInt32 SWP_NOMOVE = 0x0002;
    
    const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;
    
    public static void MakeTopMost (IntPtr fHandle)
    {
        SetWindowPos(fHandle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
    }
    
    public static void MakeNormal (IntPtr fHandle)
    {
        SetWindowPos(fHandle, HWND_NOTOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
    }
    "@
    $hWnd = $ie.HWND
    $app = Add-Type -MemberDefinition $signature -Name Win32Window -Namespace ScriptFanatic.WinAPI -ReferencedAssemblies System.Windows.Forms -Using System.Windows.Forms -PassThru
    $null = $app::MakeTopMost($hWnd)
    $ie.Visible = $true
    $button.click();
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($ie) | Out-Null
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-11
      • 1970-01-01
      • 2016-02-03
      • 2015-02-02
      相关资源
      最近更新 更多