Friday Fun: New-PSWindow

When I work in a command prompt, I’m used to start a new window by just typing ‘start’.
Unfortunately, it doesn’t work in a Powershell prompt as start is defined as the alias of the Start-Process cmdlet.

Get-Alias -Name Start

I was about to use the suggested one-liners that you can find on the following page:
http://stackoverflow.com/questions/15667322/how-to-open-powershell-console-window-from-powershell

Invoke-Item C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe            
# or            
start-process powershell

..But it doesn’t meet my needs perfectly.

I wrote for fun the following function that has also some limitations:

  • It’s unable to take in account the MTA (multithreaded apartment) mode vs. STA (single-threaded apartment. It always launches in STA and issues a warning if your parent window was in MTA.
  • It doesn’t use the console file and modules that were previously used that start the parent shell
  • It doesn’t use the arguments that were previously used that start the parent shell
  • Idem for the version of Powershell, the working directory, …

But it has the following advantages:

  • It takes into account whether it’s the ISE or the console, whether it’s a 32bit or a 64bit process
  • It keeps the default colors
  • It’s run under the same account and privileges

In other words, it just starts a new window as if you clicked on its shortcut in the start menu.

#Requires -Version 2.0
Function New-PSWindow {
[cmdletBinding()]
Param()
    Begin {
        
        # Is it a 32bit process
        $is32Bit = ([IntPtr]::size -eq 4)
        
        # Is it the ISE
        $isISE = (Get-Process -id $PID).ProcessName -match '_ise$'

        Switch -Regex ([Environment]::OSVersion.Version) {
        "^6\.1" {
            # Windows 7
            $FilePath = 'C:\Programdata\Microsoft\Windows\Start Menu\Programs\Accessories\Windows PowerShell';
            break;
        }
        "^6\.(2|3)" {
            # Windows 8 and 8.1
            $FilePath = 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\System Tools'
            break;
        }
            default {
                $FilePath = $false
            }
        } # end of switch
    }
    Process {
        if ($FilePath) {
            # Define a string based on architecture
            if ($is32Bit) {
                $32BitPathStr = ' (x86)'
            } else {
                $32BitPathStr = [string]::Empty
            }
            # Define a string based on the type of host
            if ($isISE) {
                $ISEPathStr = ' ISE'
            } else {
                $ISEPathStr = [string]::Empty
            }

            try {
                # Launch the appropriate shortcut
                $nshl = Join-Path -Path (Resolve-Path -Path $FilePath -ErrorAction Stop) -ChildPath ("Windows Powershell",$ISEPathStr,$32BitPathStr,".lnk" -join "")
                if ($host.Runspace.ApartmentState -ne 'STA') {
                    Write-Warning -Message "The new PS Window is not opened in MTA mode but in STA mode"
                }
                Invoke-Item -Path $nshl -ErrorAction Stop
            } catch {
                Write-Warning -Message "Failed to launch new PS Windows because $($_.Exception.Message)"
            }
        } else {
            $Msg = "Invalid OS: runs only on Windows 7/8/8.1 or 2008R2/2012/2012R2"
            throw (New-Object System.Exception -ArgumentList $Msg)

        }
    }
} # end of function

I propose nps as alias for this function:

Set-Alias -Name nps -Value New-PSWindow

Have fun 😎

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.