I have a powershell script that opens a program called CNCScreenE, saves a screenshot of this window, and then closes down the application.
it worked perfectly the first few times I ran it.
after those few times, now every time the program gets called, instead of opening in the foreground, it opens behind whatever else is already open (visual studio code in this case). the screenshot still gets saved, but the image contains whatever was in the foreground, which is visual studio code in this case.
I have tried various scripts to bring the window to the foreground that are all basically slight variations on the same thing without much success. they usually just cause the window to flash in the taskbar.
I have found some suggestions that its not always possible to bring windows to the foreground without first fulfilling certain criteria, such as last input must be from a program in the foreground, or you can minimize the window first and then it can be brought to the foreground.
My problem is that I am not very experienced at working with windows api's through powershell. I understand that add-type is compiling the c# code and then allowing powershell to access the api, but I know almost nothing about c# and this is my first time using add-type.
#open screen viewer app
Start-Process -FilePath 'C:\Program Files (x86)\CNCScreenE\cncscrne.exe' -ArgumentList 'C:\Users\mcnc\Documents\programming\p900_program\p900' -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)
I also tried this script which looks very well written, but it gives me a series of erros every time I try to run it.
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}
the errors it produces are all basically the same as below but refer to a variety of characters:
Add-Type : c:\Users\mcnc\AppData\Local\Temp\oegsfdcr\oegsfdcr.0.cs(1) : Unexpected
character '€'
c:\Users\mcnc\AppData\Local\Temp\oegsfdcr\oegsfdcr.0.cs(1) : >>> â€memberDefinition @â€
c:\Users\mcnc\AppData\Local\Temp\oegsfdcr\oegsfdcr.0.cs(2) : [DllImport(user32.dll)]
At C:\Users\mcnc\Documents\programming\p900_program\powershell
screenshot\show-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
I think it has to do with the odd looking quotation marks but when I replace them with regular quotes, it gives these errors which don't make much sense to me
At C:\Users\mcnc\Documents\programming\p900_program\powershell
screenshot\show-process.ps1:50 char:5
+ [DllImport("user32.dll")]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
Unexpected attribute 'DllImport'.
At C:\Users\mcnc\Documents\programming\p900_program\powershell
screenshot\show-process.ps1:51 char:5
+ public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdSh ...
+ ~~~~~~
Unexpected token 'public' in expression or statement.
At C:\Users\mcnc\Documents\programming\p900_program\powershell
screenshot\show-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
Well, I tried to do it via c#, and found that SetForegroundWindow will not work. Searching workaround I got this one
So working C# part code will look like:
Just call BringToFront method from your PowerShell. And you can also remove this part: