Reputation: 167
With a powershell code I try to change the position of a window (is works correctly) and put this windows "Always on top".
Please find below my code:
Import-Module C:/install/WASP/wasp.dll
for($i=1; $i -le 300000; $i++)
{
$allWindow = Select-Window MyCheck*
if($allWindow)
{
foreach ($currentWindow in $allWindow)
{
$positionWindow = WindowPosition $currentWindow
foreach ($currentPosition in $positionWindow)
{
#if we find the correct windows
if ( $currentWindow.title -match "\([0-9]*\)#" )
{
#write-host "@@##@@"$currentWindow.title",(@@#@@)"$currentPosition.x",(@@#@@)"$currentPosition.y",(@@#@@)"$currentPosition.width",(@@#@@)"$currentPosition.height",(@@#@@)"$currentWindow.title",(@@#@@)"$currentWindow.IsActive
$id = $currentWindow.title.Substring($currentWindow.title.IndexOf("(")+1, $currentWindow.title.IndexOf(")")-$currentWindow.title.IndexOf("(")-1)
$allHUDWindow = Select-Window * | where {$_.Title -match "\($id\).*.txt"}
#If we find the second window, we have to superimpose $currentHUDWindow to $currentWindow
if($allHUDWindow)
{
foreach ($currentHUDWindow in $allHUDWindow)
{
#I need to set $currentHUDWindow "Always on top"
Set-WindowActive $currentHUDWindow
Set-WindowPosition -X ($currentPosition.x-10) -Y ($currentPosition.y-30) -WIDTH ($currentPosition.width+20) -HEIGHT ($currentPosition.height+30) -Window $currentHUDWindow
}
}
}
}
}
}
}
Currenlty, I call "Set-WindowActive $currentHUDWindow" but I need to apply also this kind of function :
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
I try to added this function to my code and called SetForegroundWindow($currentHUDWindow). But I encountered an error.
Could you please help me ?
I need to put the window $currentHUDWindow on top !
Thanks
Upvotes: 6
Views: 21970
Reputation: 254
If you are looking to circumvent this, the linked post has a method for getting around it, but it's written in C#.
I have translated that code from C# over to PowerShell, and I even expanded the C++ enums to PowerShell, and linked where you can find them at:
function ShowWindow( $hwnd ){
$constants = @{
ShowWindowCommands = @{ #from https://pinvoke.net/default.aspx/Enums/ShowWindowCommands.html
Hide = 0; #completely hides the window
Normal = 1; #if min/max'd, restores to original size and position
ShowMinimized = 2; #activates and minimizes window
Maximize = 3; #activates and maximizes window
ShowMaximized = 3; #activates and maximizes window
ShowNoActivate = 4; #shows a window in its most recent size and position without activating it
Show = 5; #activates the window and displays it in its current size and position
Minimize = 6; #minimizes and activates the next top-level window
ShowMinNoActive = 7; #minimizes and activates no windows"
ShowNA = 8; #shows a window in its current size and position without activating it
Restore = 9; #activates and displays window. if min/max'd, restores to original size and position
ShowDefault = 10; #sets the window to its default show state
ForceMinimize = 11; #Windows 2000/XP-only feature. minimize window even if thread is hung
};
WindowLongParam = { #from https://www.pinvoke.net/default.aspx/Constants/GWL%20-%20GetWindowLong.html
SetWndProc = -4; #sets new address for procedure (can't be changed unless the window belongs to the same thread)
SetHndInst = -6; #sets a new application instance handle
SetHndParent = -8 #unsepecified
SetId = -12 #sets a new identifier of the child window
SetStyle = -16 #sets a new window style
SetExtStyle = -20 #sets a new extended window style
SetUserData = -21 #sets the user data associated with the window
#there's a few more of these that are positive for the dialog box procedure
};
WindowsStyles = {
#see https://learn.microsoft.com/en-us/windows/win32/winmsg/window-styles
# and
# http://pinvoke.net/default.aspx/Constants.Window%20styles
# for more... (there's a lot)
Minimize = 0x20000000; #hexadecimal of 536870912
}
}
$sigs = '[DllImport("user32.dll", EntryPoint="GetWindowLong")]
public static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("User32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr hWnd, int lpdwProcessId);
[DllImport("user32.dll")]
public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("user32.dll", SetLastError=true)]
public static extern bool BringWindowToTop(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();'
$type = Add-Type -MemberDefinition $sigs -Name WindowAPI5 -IgnoreWarnings -PassThru
$type::ShowWindow( $hwnd, $constants.ShowWindowCommands.Minimize )
$type::ShowWindow( $hwnd, $constants.ShowWindowCommands.Restore )
[int] $currentlyFocusedWindowProcessId = $type::GetWindowThreadProcessId($type::GetForegroundWindow(), 0)
[int] $appThread = [System.AppDomain]::GetCurrentThreadId()
if( $currentlyFocusedWindowProcessId -ne $appThread ){
$type::AttachThreadInput( $currentlyFocusedWindowProcessId, $appThread, $true )
$type::BringWindowToTop( $hwnd )
$type::ShowWindow( $hwnd, $constants.ShowWindowCommands.Show )
$type::AttachThreadInput( $currentlyFocusedWindowProcessId, $appThread, $false )
} else {
$type::BringWindowToTop( $hwnd )
$type::ShowWindow( $hwnd, $constants.ShowWindowCommands.Show )
}
}
If you notice, I did not use variables or the function. I found the calls from the C# code to be useless in PowerShell, but decided to leave the defs for them in case someone wants to use them.
Upvotes: 1
Reputation: 60928
This is how P/invoke and use SetForegroundWindow
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);
}
"@
$h = (get-process NOTEPAD).MainWindowHandle # just one notepad must be opened!
[SFW]::SetForegroundWindow($h)
Upvotes: 20