AppActivate在Powershell中工作不一致

时间:2016-02-28 05:42:43

标签: powershell

我有以下两个行代码,它们将相应的窗口放到前面,这将帮助我自动截取屏幕截图。但问题在于,有时它会像魅力一样,有时则不然。当我说它不起作用时,我并不是说它失败了任何错误信息或警告。什么都没发生。只是代码运行,窗口没有出现在前面。

我想知道此代码段是否有任何隐藏的先决条件才能成功运行?在我运行此代码之前,有问题的窗口是否应该处于任何状态才能使该窗口显示出来?

以下是代码:

[void][System.Reflection.Assembly]::LoadWithPartialName("'Microsoft.VisualBasic")
[Microsoft.VisualBasic.Interaction]::AppActivate("R")

6 个答案:

答案 0 :(得分:2)

我以前在使用Title-overload时遇到了麻烦。此外,Windows标题中的单个更改将中断AppActivate(string Title)

使用ProcessID - 重载会更好吗?实施例

$excelpid = (Get-Process excel).ID
[Microsoft.VisualBasic.Interaction]::AppActivate($excelpid)

如果您正在使用COM应用程序,则需要根据MainWindowHandle获取流程,如下所示:

[void][System.Reflection.Assembly]::LoadWithPartialName("'Microsoft.VisualBasic")

#start excel
$excel = New-Object -ComObject excel.application

#make excel visible
$excel.Visible = $true

#get pid from windows handle
$excelpid = (Get-Process | Where-Object { $_.MainWindowHandle -eq $excel.Hwnd }).Id

#Activate window
[Microsoft.VisualBasic.Interaction]::AppActivate($excelpid)

答案 1 :(得分:0)

可能的是,一旦powershell切换控制到所需的程序,程序就会取回控制权...尝试循环激活,直到你截取屏幕截图...

答案 2 :(得分:0)

我只是多次迭代AppActivate。我知道这不是很好的解决方案。但它对我有用。

示例代码。

for ($i = 1; $i -lt 5; $i++)
{
    [Microsoft.VisualBasic.Interaction]::AppActivate("R")
}

答案 3 :(得分:0)

$ IEtitles =获取进程iexplore |?{$ _。MainWindowTitle} |选择-exp MainWindowTitle

foreach($ IEtitles中的$ IEtitle) {

    Add-Type -AssemblyName Microsoft.VisualBasic
    [Microsoft.VisualBasic.Interaction]::AppActivate("$IEtitle") | Out-Null

}

答案 4 :(得分:0)

使用AppActivate带出窗口标题有时确实确实很奇怪:没有异常发生,并且检查前景窗口句柄(使用Win32 API:GetForegroundWindow)也是准确的,除了窗口仍然不显示。 为确保在所有操作完成之前窗口确实显示,这里是使用AppActivate的替代方法。我尝试使用win32 API:“ ShowWindowAsync”和“ SetForegroundWindow”一起使用,并检查返回值以确保。它比AppActivate更加一致。

(P.S。ShowWindowAsync:“设置窗口的显示状态,而无需等待操作完成。”,根据Microsoft online docs)。 代码示例:假设窗口标题“ R”已经存在。

Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class SFW {
     [DllImport("user32.dll")]
     [return: MarshalAs(UnmanagedType.Bool)]
     public static extern bool SetForegroundWindow(IntPtr hWnd);
     [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
     public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
    }
"@
$Target_Title="R"
$hwnd =(Get-Process | Where-Object { $_.MainWindowTitle -eq $Target_Title } ).MainWindowHandle
Do
{
try
{
$r1=[SFW]::ShowWindowAsync($hwnd, 3)
$r2=[SFW]::SetForegroundWindow($hwnd) 
}
catch
{
    Write-Host "Error activating! Press any key to exit!"
    cmd /c pause | out-null
    exit
    }
    }while(($r1 -or $r2) -eq $false)

答案 5 :(得分:0)

$PROCESS = 'WINWORD'
$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate((Get-Process $PROCESS).ID)

打开Microsoft Word进行测试。