5

So while there is much advise about how to set forms topmost, i couldnt find anything that makes my console run topmost.

So my question: How do I make my console run top-most during a script?

Omglolyes
  • 156
  • 11

1 Answers1

5

This requires some .NET interop, as detailed in this blog:

Scripts From TechEd 2012… Part 1 (Keeping PowerShell Window On Top)

I've copied the relevant code below in case the linked site disappears:

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

$type = Add-Type -MemberDefinition $signature -Name SetWindowPosition -Namespace SetWindowPos -Using System.Text -PassThru

$handle = (Get-Process -id $Global:PID).MainWindowHandle
$alwaysOnTop = New-Object -TypeName System.IntPtr -ArgumentList (-1)
$type::SetWindowPos($handle, $alwaysOnTop, 0, 0, 0, 0, 0x0003)

Edit:

As described in the comments: If you're from a batch file, PowerShell runs in a child process and doesn't own the console window, so you'll have to make changes:

$signature = @'
[DllImport("kernel32.dll")] public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern bool SetWindowPos(
    IntPtr hWnd,
    IntPtr hWndInsertAfter,
    int X,
    int Y,
    int cx,
    int cy,
    uint uFlags);
'@

$type = Add-Type -MemberDefinition $signature -Name SetWindowPosition -Namespace SetWindowPos -Using System.Text -PassThru

$handle = $type::GetConsoleWindow()
$type::SetWindowPos($handle, -1, 0, 0, 0, 0, 0x0003)
Omglolyes
  • 156
  • 11
boxdog
  • 7,894
  • 2
  • 18
  • 27
  • Nice. From what I can tell, you can just pass `-1` directly as `hwndInsertAfter` (or use `[IntPtr] -1` for clarity) - no need for `New-Object`. – mklement0 Oct 24 '19 at 14:26
  • Okay this works fine in the console. But I want this to work in a script =) this gives me an error which seems to result from the `'@ @'`? I have no clue about .NET yet so sry if my analesys ist too good =) – Omglolyes Oct 24 '19 at 14:41
  • @mklement0 So I can remove the `$alwaysonTop ...` and replace `IntPtr hWndInsertAfter,` with `[IntPtr] -1`? – Omglolyes Oct 24 '19 at 14:45
  • 1
    @Omglolyes: You can replace `$type::SetWindowPos($handle, $alwaysOnTop, 0, 0, 0, 0, 0x0003)` with `$type::SetWindowPos($handle, -1, 0, 0, 0, 0, 0x0003)` – mklement0 Oct 24 '19 at 14:48
  • @Omglolyes: The closing delimiter of a here-string - `'@` in this case - must be not only on its own line, but must also be _at the very start of the line_ - not even whitespace may precede it. – mklement0 Oct 24 '19 at 14:50
  • AAAAHHH Okay so I can't even tab into my code. Fine but this somehow didn't do the trick for me. I dont get an error anymore, but even if I put this at the start of my script, it does'nt seem to do anything anymore. It also gives me a "false" instead of "true" like in the normal console. – Omglolyes Oct 24 '19 at 15:05
  • How are you executing the script? – boxdog Oct 24 '19 at 15:07
  • Well Powershell is kindof resticted at work. So I run a batchcommand: `PowerShell -ExecutionPolicy ByPass -command ". '%cd%\a.ps1'; Test;"` – Omglolyes Oct 24 '19 at 15:08
  • 2
    @boxdog, your script has [curly quotes](https://practicaltypography.com/straight-and-curly-quotes.html) that [aren't well supported](https://4sysops.com/archives/dealing-with-smart-quotes-in-powershell/) in Powershell. – Rich Moss Oct 24 '19 at 16:20
  • 1
    @Omglolyes: If you're from a batch file, PowerShell runs in a child process and doesn't own the console window, so you'll have to make changes: Add `[DllImport("kernel32.dll")] public static extern IntPtr GetConsoleWindow();` to the value of `$signature`, replace the `$handle = ...` line with `$handle = $type::GetConsoleWindow()` – mklement0 Oct 24 '19 at 19:14
  • 1
    @RichMoss: It's definitely better to avoid the non-ASCII-range quotation marks, but do note that PowerShell _itself_ fully supports them. The problem is usually one of _character encoding_ - see [this answer](https://stackoverflow.com/a/55053609/45375). – mklement0 Oct 24 '19 at 19:19
  • 1
    @RichMoss. As I said in the post, I literally copy/pasted it from a blog, so that's where the odd quotes come from. Having said that, I should have checked it, rather than just assuming it was OK. Fixed now. – boxdog Oct 24 '19 at 22:20
  • Thanks alot. This works entirely. This will save me much time and some nerves. @boxdog – Omglolyes Oct 25 '19 at 19:45