-1

i have the following code:

Start-Process -FilePath myprogram.exe -Wait
# ... some other code to be executed AFTER the previous process has ended

What i need

I need to start the process with -wait as you can see, but i also need that that the window of that process to be always on top (or "topmost").

What i tried

I've seen this question/answer: https://stackoverflow.com/a/73319269

And i've tried what the solution suggests, like this:

$User32 = Add-Type -Debug:$False -MemberDefinition '
    [DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,int Y, int cx, int cy, uint uFlags);
' -Name "User32Functions" -namespace User32Functions -PassThru

$proc = Start-Process -FilePath myprogram.exe -Passthru

$Handle = ($proc).MainWindowHandle
[Void]$User32::SetWindowPos($Handle, -1, 0, 0, 0, 0, 0x53)

But

  • it doesn't work, the myprogram.exe window is not topmost
  • i had to remove -wait to add and utilise -passthru, so how can i detect when the execution of myprogram.exe is over?

Thank you for your help.

aetonsi
  • 208
  • 2
  • 9
  • I guess `myprogram.exe` starts a new child process. You will need to identify that child process (with e.g. the task manager) and `Get-Process` that to be able to wait for it and put it on top. – iRon Sep 19 '22 at 13:30
  • @iRon myprogram.exe _is_ the child process, started by powershell. `start-process` with `-passthru` correctly gets its handle. but if i use passthru, i can't use `-wait`, that's my problem – aetonsi Sep 19 '22 at 13:54
  • That doesn't mean that `myprogram.exe` does have a (grand) child itself. – iRon Sep 19 '22 at 14:36

1 Answers1

0

Taking cmd.exe for a Minimal, Reproducible Example:

$User32 = Add-Type -Debug:$False -MemberDefinition '
    [DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,int Y, int cx, int cy, uint uFlags);
' -Name "User32Functions" -namespace User32Functions -PassThru

Start-Process -FilePath cmd.exe
Start-Sleep 1 # wait for the process to initialize
$Proc = Get-Process cmd
$Handle = ($Proc).MainWindowHandle
[Void]$User32::SetWindowPos($Handle, -1, 0, 0, 0, 0, 0x53)
Wait-Process $Proc.id
iRon
  • 20,463
  • 10
  • 53
  • 79
  • With this code, powershell reports: `Cannot convert argument "hWnd", with value: "System.Object[]", for "SetWindowPos" to type "System.IntPtr": "Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.IntPtr"."` . If i instead get the handle via `$proc = Start-Process -FilePath cmd.exe -Passthru ; $Handle = ($proc).MainWindowHandle`, it doesn't error out. *however*, `SetWindowPos` returns *false*, it doesn't work. I tried both with cmd.exe and with an empty c# win form app – aetonsi Sep 20 '22 at 09:43
  • I also tried importing and calling `GetLastError` from kernel32.dll but it returns 0... – aetonsi Sep 20 '22 at 09:48