11

I am converting an old cmd command to Powershell, and currently use:

START "My Title" Path/To/ConsoleApp.exe

This works as expected to launch ConsoleApp with My Title as it's window title. This has been replaced with Start-Process which works correctly, but does not provide a mechanism to change the title.

Is there another way to do this without resorting to using the cmd command?

Joey
  • 344,408
  • 85
  • 689
  • 683
Ben Laan
  • 2,607
  • 3
  • 29
  • 30
  • Did any of the solutions worked for you? For my non-gui applications it is not working as WaitForInputIdle fails to work (see error in answers comments below). – gdelfino Nov 18 '14 at 16:55

4 Answers4

11

There is a small quirk when changing the text of the process' main window: if you try to change the text straight after you have started the process, it may fail due to one of many possible reasons (e.g. the handle to the control which displays the text does not exist at the time of the function call). So the solution is to use the WaitForInputIdle() method before trying to change the text:

Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;

public static class Win32Api
{
    [DllImport("User32.dll", EntryPoint = "SetWindowText")]
    public static extern int SetWindowText(IntPtr hWnd, string text);
}
"@

$process = Start-Process -FilePath "notepad.exe" -PassThru
$process.WaitForInputIdle()
[Win32Api]::SetWindowText($process.MainWindowHandle, "My Custom Text")

Be aware that the application itself can still change the window text after you have made your own change.

George Howarth
  • 2,767
  • 20
  • 18
  • 2
    This doesn't work for me, at least not for `CMD.EXE` as the process in question (as specified by the OP). `WaitForInputIdle()` raises an `InvalidOperationException` for non-GUI apps and `MainWindowHandle` is `0` for non-GUI apps. – Christian.K Aug 27 '12 at 10:17
  • Unfortunately, this is not working for me. I need to run a non-gui application and I get this error: Exception calling "WaitForInputIdle" with "0" argument(s): "WaitForInputIdle failed. This could be because the process does not have a graphical interface." – gdelfino Nov 18 '14 at 15:16
5

I tried this with cmd.exe and it worked well.

Add-Type -Type @"
using System;
using System.Runtime.InteropServices;
namespace WT {
   public class Temp {
      [DllImport("user32.dll")]
      public static extern bool SetWindowText(IntPtr hWnd, string lpString); 
   }
}
"@

$cmd = Start-Process cmd -PassThru
[wt.temp]::SetWindowText($cmd.MainWindowHandle, 'some text')
stej
  • 28,745
  • 11
  • 71
  • 104
  • In my script the line "[wt.temp]::SetWindowText($cmd.MainWindowHandle, 'some text')" sometimes returns True, and sometimas False, but it never sets the title of my non-GUI application. – gdelfino Nov 18 '14 at 15:25
  • It is now working! I don't really know what changed. Maybe I just needed to restart my powershell. Thank you for providing this code. – gdelfino Nov 19 '14 at 08:54
  • 2
    This solution is working not always working for me. I have added a delay (Start-Sleep -s 5) before trying to set the window title and now seems to work more reliably. – gdelfino Nov 19 '14 at 10:01
3

If you want to spawn a process with powershell with a custom title try:

$StartInfo = new-object System.Diagnostics.ProcessStartInfo
$StartInfo.FileName = "$pshome\powershell.exe"
$StartInfo.Arguments = "-NoExit -Command `$Host.UI.RawUI.WindowTitle=`'Your Title Here`'"
[System.Diagnostics.Process]::Start($StartInfo)

Note the backtick characters that escape the string for the title, they are vital!

Lou O.
  • 599
  • 4
  • 17
1

$host.UI.RawUI.WindowTitle = "new title"

As already been said by George, anything/anyone can set it back (like custom prompt functions for example).

Shay Levy
  • 121,444
  • 32
  • 184
  • 206