在windows 10中将窗口移到前台拒绝工作



我有一个powershell脚本,它打开一个名为cncscreen的程序,保存该窗口的屏幕截图,然后关闭该应用程序。

前几次运行的很好。

在那几次之后,现在每次程序被调用时,它不是在前台打开,而是在其他已经打开的(在这种情况下是visual studio代码)后面打开。截图仍然会被保存,但图像包含了前景中的内容,在本例中是visual studio代码。

我试过各种脚本把窗口带到前台,基本上都是同一件事的轻微变化,没有太大的成功。它们通常只会使窗口在任务栏中闪烁。

我发现了一些建议,如果不首先满足某些条件,则不可能总是将窗口带到前台,例如最后输入必须来自前台的程序,或者您可以先最小化窗口,然后将其带到前台。

我的问题是,我不是很有经验的工作与windows api的通过powershell。我知道add-type是编译c#代码,然后允许powershell访问api,但我对c#几乎一无所知,这是我第一次使用add-type。

#open screen viewer app
Start-Process  -FilePath 'C:Program Files (x86)CNCScreenEcncscrne.exe' -ArgumentList 'C:UsersmcncDocumentsprogrammingp900_programp900' -Passthru
start-sleep -seconds 1
#Get PID for p900 screen viewer
$Screen_viewer = (Get-Process -Name 'CNCScrnE').MainWindowHandle
#bring program to the foreground
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);
}
"@
#call class SFW with Function SetForegroundWindow to bring screen viewer to the front
[SFW]::SetForegroundWindow($Screen_viewer)

我也试过这个脚本,看起来写得很好,但它给了我一系列的错误,每次我试图运行它。

Function Set-WindowStyle 
{
param
(
[Parameter()]
[ValidateSet('FORCEMINIMIZE', 'HIDE', 'MAXIMIZE', 'MINIMIZE', 'RESTORE', 
'SHOW', 'SHOWDEFAULT', 'SHOWMAXIMIZED', 'SHOWMINIMIZED', 
'SHOWMINNOACTIVE', 'SHOWNA', 'SHOWNOACTIVATE', 'SHOWNORMAL')]
$Style = 'SHOW',
[Parameter()]
$MainWindowHandle = (Get-Process -Id $pid).MainWindowHandle
)
$WindowStates = @{
FORCEMINIMIZE = 11; HIDE = 0
MAXIMIZE = 3; MINIMIZE = 6
RESTORE = 9; SHOW = 5
SHOWDEFAULT = 10; SHOWMAXIMIZED = 3
SHOWMINIMIZED = 2; SHOWMINNOACTIVE = 7
SHOWNA = 8; SHOWNOACTIVATE = 4
SHOWNORMAL = 1
}
Write-Verbose ("Set Window Style {1} on handle {0}" -f $MainWindowHandle, $($WindowStates[$style]))
$Win32ShowWindowAsync = Add-Type –memberDefinition @” 
[DllImport("user32.dll")] 
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
“@ -name “Win32ShowWindowAsync” -namespace Win32Functions –passThru
$Win32ShowWindowAsync::ShowWindowAsync($MainWindowHandle, $WindowStates[$Style]) | Out-Null
}
# Usage
# Minimize a running process window
Get-Process -Name Taskmgr | %{Set-WindowStyle MINIMIZE $PSItem.MainWindowHandle}
Get-Process -Name notepad | %{Set-WindowStyle MINIMIZE $PSItem.MainWindowHandle}
# Restore a running process window - the last window called will be topmost
Get-Process -Name Taskmgr | %{Set-WindowStyle RESTORE $PSItem.MainWindowHandle}
Get-Process -Name notepad | %{Set-WindowStyle RESTORE $PSItem.MainWindowHandle}

它产生的错误基本上都与下面相同,但涉及不同的字符:

Add-Type : c:UsersmcncAppDataLocalTempoegsfdcroegsfdcr.0.cs(1) : Unexpected 
character '€'
c:UsersmcncAppDataLocalTempoegsfdcroegsfdcr.0.cs(1) : >>> â€memberDefinition @†
c:UsersmcncAppDataLocalTempoegsfdcroegsfdcr.0.cs(2) :     [DllImport(user32.dll)]  
At C:UsersmcncDocumentsprogrammingp900_programpowershell 
screenshotshow-process.ps1:49 char:29
+     $Win32ShowWindowAsync = Add-Type –memberDefinition @â€
+                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : InvalidData: (Microsoft.Power...peCompilerError:AddTypeComp 
ilerError) [Add-Type], Exception
+ FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeComm 
and

我认为这与奇怪的引号有关,但是当我用常规引号替换它们时,它会给出这些对我来说没有多大意义的错误

At C:UsersmcncDocumentsprogrammingp900_programpowershell 
screenshotshow-process.ps1:50 char:5
+     [DllImport("user32.dll")]
+     ~~~~~~~~~~~~~~~~~~~~~~~~~
Unexpected attribute 'DllImport'.
At C:UsersmcncDocumentsprogrammingp900_programpowershell 
screenshotshow-process.ps1:51 char:5
+     public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdSh ...
+     ~~~~~~
Unexpected token 'public' in expression or statement.
At C:UsersmcncDocumentsprogrammingp900_programpowershell 
screenshotshow-process.ps1:52 char:11
+ "@ -name "Win32ShowWindowAsync" -namespace Win32Functions –passThru
+           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unexpected token 'Win32ShowWindowAsync" -namespace Win32Functions –passThru' in    
expression or statement.
+ CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedAttribute

我的最佳猜测是您应该只更改外部引号,如下所示:

$Win32ShowWindowAsync = Add-Type –memberDefinition @" 
[DllImport("user32.dll")] 
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
"@ -name "Win32ShowWindowAsync" -namespace Win32Functions –passThru

@"one_answers"@包围多行被称为这里字符串。在这里字符串中不应该加上引号

嗯,我试着通过c#来做,发现SetForegroundWindow不起作用。我找到了这个

所以c#部分代码看起来像:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
public class SFW
{
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool ShowWindowAsync(HandleRef hWnd, int nCmdShow);
public const int SW_RESTORE = 9;
public static void BringToFront()
{
Process[] processes = Process.GetProcessesByName("CNCScrnE");
foreach (Process p in processes)
{
IntPtr windowHandle = p.MainWindowHandle;
ShowWindowAsync(new HandleRef(null, windowHandle), SW_RESTORE);
SetForegroundWindow(windowHandle);
}
}
}

从你的PowerShell调用BringToFront方法。你也可以删除这部分:

#Get PID for p900 screen viewer
$Screen_viewer = (Get-Process -Name 'CNCScrnE').MainWindowHandle

和往常一样,我在发帖寻求帮助后发现了一些有用的东西。

还有,我想我可能已经有了一个可行的解决方案,但我没有意识到,因为我正在逐步完成这个程序。我记得看到程序闪到前台,然后立即转到vsc后面,我想这是因为我刚刚按下了降级按钮。如果我只是让它运行而不按任何按钮,它可能会工作。

无论如何,这是我发现的像魅力一样工作的代码

Function Set-WindowState {
<#
.LINK
https://gist.github.com/Nora-Ballard/11240204
#>
[CmdletBinding(DefaultParameterSetName = 'InputObject')]
param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)]
[Object[]] $InputObject,
[Parameter(Position = 1)]
[ValidateSet('FORCEMINIMIZE', 'HIDE', 'MAXIMIZE', 'MINIMIZE', 'RESTORE',
'SHOW', 'SHOWDEFAULT', 'SHOWMAXIMIZED', 'SHOWMINIMIZED',
'SHOWMINNOACTIVE', 'SHOWNA', 'SHOWNOACTIVATE', 'SHOWNORMAL')]
[string] $State = 'SHOW'
)
Begin {
$WindowStates = @{
'FORCEMINIMIZE'     = 11
'HIDE'              = 0
'MAXIMIZE'          = 3
'MINIMIZE'          = 6
'RESTORE'           = 9
'SHOW'              = 5
'SHOWDEFAULT'       = 10
'SHOWMAXIMIZED'     = 3
'SHOWMINIMIZED'     = 2
'SHOWMINNOACTIVE'   = 7
'SHOWNA'            = 8
'SHOWNOACTIVATE'    = 4
'SHOWNORMAL'        = 1
}
$Win32ShowWindowAsync = Add-Type -MemberDefinition @'
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
'@ -Name "Win32ShowWindowAsync" -Namespace Win32Functions -PassThru
if (!$global:MainWindowHandles) {
$global:MainWindowHandles = @{ }
}
}
Process {
foreach ($process in $InputObject) {
if ($process.MainWindowHandle -eq 0) {
if ($global:MainWindowHandles.ContainsKey($process.Id)) {
$handle = $global:MainWindowHandles[$process.Id]
} else {
Write-Error "Main Window handle is '0'"
continue
}
} else {
$handle = $process.MainWindowHandle
$global:MainWindowHandles[$process.Id] = $handle
}
$Win32ShowWindowAsync::ShowWindowAsync($handle, $WindowStates[$State]) | Out-Null
Write-Verbose ("Set Window State '{1} on '{0}'" -f $MainWindowHandle, $State)
}
}
}
Get-Process -Name CNCScrnE | Set-WindowState -State Minimize
Get-Process -Name CNCScrnE | Set-WindowState -State Restore

这里是我找到它的地方给它应得的荣誉

https://gist.github.com/lalibi/3762289efc5805f8cfcf

我也认为你确实需要最小化它(或以其他方式改变它的状态)在把它带到前台之前,否则窗口只允许你激活窗口,而不是把它带到前台。

最新更新