7

I currently open my PowerShell script through a .bat file. The script has a GUI. I tried to put this in my script but it hid the GUI as well and also kept looping because I wanted my GUI to continuously loop:

powershell.exe -WindowStyle Hidden -file c:\script.ps1

How do we run a script without Command Promp, but also not hide the gui? And is that the same if we run the script using a .bat file? Thank you!

DrixlRey
  • 205
  • 3
  • 4
  • 13
  • 2
    Put it in a shortcut instead of in a batch file. Right click a blank spot on desktop or in a folder window, New, Shortcut, paste your line in, Next, name it, Finish. –  Nov 15 '16 at 19:47
  • 1
    Thanks Noodles, this worked! I did this `%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -NoProfile -file "\\location\folder1\script.ps1"` – DrixlRey Dec 14 '16 at 22:58

6 Answers6

22

If you want to hide the Console behind the GUI I've had success with the following native functions:

# .Net methods for hiding/showing the console in the background
Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();

[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'

function Show-Console
{
    $consolePtr = [Console.Window]::GetConsoleWindow()

    # Hide = 0,
    # ShowNormal = 1,
    # ShowMinimized = 2,
    # ShowMaximized = 3,
    # Maximize = 3,
    # ShowNormalNoActivate = 4,
    # Show = 5,
    # Minimize = 6,
    # ShowMinNoActivate = 7,
    # ShowNoActivate = 8,
    # Restore = 9,
    # ShowDefault = 10,
    # ForceMinimized = 11

    [Console.Window]::ShowWindow($consolePtr, 4)
}

function Hide-Console
{
    $consolePtr = [Console.Window]::GetConsoleWindow()
    #0 hide
    [Console.Window]::ShowWindow($consolePtr, 0)
}

Once the above functions have been added to your Form, simply call the Hide-Console function in your Form_Load event:

$OnFormLoad = 
{
    Hide-Console
}

If you need to show the Console, perhaps for debugging, you can easily show the console again by calling the Show-Console function:

$OnButtonClick = 
{
    Show-Console
}

For more information on the numbers you can pass to ShowWindow you can check out the ShowWindow documentation on MSDN here

Update based on comment

Thanks for this code. I tried to use it in my script, but where exactly am I suppose to put Hide-Console? My form load looks like this $objForm.Add_Shown({$objForm.Activate()}) [void] $objForm.ShowDialog()

To hide the console with this code, all you need to do is call Hide-Console. Since you already have code in the Shown event ($objForm.Add_Shown) we can simply add another line to call the command:

Change this:

$objForm.Add_Shown({$objForm.Activate()})

To this:

$objForm.Add_Shown({
    $objForm.Activate()
    Hide-Console
})

When your form is Shown the console will be hidden (You can still call Show-Console if you want to see it later).

Bluecakes
  • 2,069
  • 17
  • 23
  • Thanks for this code. I tried to use it in my script, but where exactly am I suppose to put Hide-Console? My form load looks like this `$objForm.Add_Shown({$objForm.Activate()}) [void] $objForm.ShowDialog()` – DrixlRey Dec 07 '16 at 15:57
  • I've updated my answer to include an example of how you can call the `Hide-Console` command inside the `Shown` event block. If this answer has helped you please click the tick to accept the answer to help others find the same answer. – Bluecakes Dec 07 '16 at 21:53
5

If you run PowerShell from a shortcut with the window set to minimized, it will briefly flash a cmd icon in the taskbar but you barely notice it. Yet, it will start your PowerShell GUI without having a console window behind it.

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -windowstyle Hidden -file "C:\path\whatever.ps1"

If you want to start a second GUI console window from whatever.ps1 without it stopping the processing on whatever.ps1 you need to use start-process. However, start-process with -WindowStyle hidden prevents the GUI from showing up. Removing -WindowStyle shows a command window behind your GUI. However, if you start-process with cmd.exe /k, it does work.

$argumentlist = "/c powershell.exe -file `"c:\path\whatever2.ps1`" -param1 `"paramstring`""
Start-Process cmd.exe -WindowStyle Hidden -ArgumentList $argumentlist

As a bonus, if you start whatever2.ps1 with a param() statement, you can pass named, required arguments. Just be sure it's the very first thing in the ps1 file, before assemblies even.

param (
  [Parameter(Mandatory=$true)]
  [string]$var1
)
$argumentlist = "/c powershell.exe -file `"C:\path\whatever2.ps1`" -param1 `"param1string`""
Iconiu
  • 367
  • 4
  • 5
1

In the solution proposed posted in a comment (*

Put it in a shortcut instead of in a batch file. Right click a blank spot on desktop or in a folder window, New, Shortcut, paste your line in, Next, name it, Finish

*.) to hide definitely the Command Prompt, I set, in the properties of the shortcut Run=minimized in General.

0

Simplified the function for show hide a bit

function Show-Console
{
    param ([Switch]$Show,[Switch]$Hide)
    if (-not ("Console.Window" -as [type])) { 

        Add-Type -Name Window -Namespace Console -MemberDefinition '
        [DllImport("Kernel32.dll")]
        public static extern IntPtr GetConsoleWindow();

        [DllImport("user32.dll")]
        public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
        '
    }

    if ($Show)
    {
        $consolePtr = [Console.Window]::GetConsoleWindow()

        # Hide = 0,
        # ShowNormal = 1,
        # ShowMinimized = 2,
        # ShowMaximized = 3,
        # Maximize = 3,
        # ShowNormalNoActivate = 4,
        # Show = 5,
        # Minimize = 6,
        # ShowMinNoActivate = 7,
        # ShowNoActivate = 8,
        # Restore = 9,
        # ShowDefault = 10,
        # ForceMinimized = 11

        $null = [Console.Window]::ShowWindow($consolePtr, 5)
    }

    if ($Hide)
    {
        $consolePtr = [Console.Window]::GetConsoleWindow()
        #0 hide
        $null = [Console.Window]::ShowWindow($consolePtr, 0)
    }
}

show-console -show

show-console -hide

Community
  • 1
  • 1
0

I had this exact same issue. I needed a Winform to display without having the console window display. By far the easiest way to do this, is open another non-hidden window that runs the Winform and then hides itself. For example:

start-process powershell.exe -windowstyle normal C:\SomePathToScript.ps1

the above script.ps1 file will act as a sort of "launcher" for your actual Winform script.

inside this "launch" script:

powershell.exe -windowstyle hidden C:\Path\To\Winform\Script.ps1

Inside the launch script, be sure to omit the "start-process" before powershell.exe. This acts as a sort of built in hiding effect. You get a momentary PowerShell window appear, then it immediately disappears.

0

Although the answer by Bluecakes is great, it can be simplified a bit. There is no need to use GetConsoleWindow() function from kernel32.dll to get the console window handler. It can be obtained through MainWindowHandle property of the Process class, while the process itself is returned by Get-Process cmdlet with the automatic $pid variable passed as an argument. Here is an example that just hides the current console window:

add-type -name user32 -namespace win32 -memberDefinition '[DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);'
[win32.user32]::showWindow((get-process -id $pid).mainWindowHandle, 0)

Note that the above will only work to hide the console before the GUI form is loaded. Otherwise the form will become process's main window and form's handle will be returned by MainWindowHandle. If you need to manipulate console window after the form is loaded and still avoid using kernel32.dll, you can save its handle in a variable at the very beginning:

add-type -name user32 -namespace win32 -memberDefinition '[DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);'
$consoleHandle = (get-process -id $pid).mainWindowHandle

# load your form or whatever ...

# hide console
[win32.user32]::showWindow($consoleHandle, 0)
# show console
[win32.user32]::showWindow($consoleHandle, 5)
Wojtek K.
  • 11
  • 3