Shell Launcher

Shell Launcher is an interesting item in that Microsoft allows developers to create their own shells for Windows. The documentation on doing this for Windows 10 is somewhat incomplete at this time, but one can expect it follows similar guidelines as Windows Embedded, which is documented on MSDN and TechNet. This is also how we can specify Windows 10 to launch Citrix or VMWare launchers for thin clients. Interestingly enough, in build 1511, this was known as Embedded Shell Launcher and in newer builds as Custom Shell Launcher.

Typically, these need to know which users you want the custom shell for. This is only available to control via PowerShell at this time and is documented at https://docs.microsoft.com/en-us/windows-hardware/customize/enterprise/shell-launcher.

The concept here is that you want standard or kiosk accounts to log in using the custom shell but administrator accounts need not use it so they can perform administrative tasks if necessary.

For example, to make an internet browsing kiosk, you'd make a script to execute Internet Explorer to serve as our launch command:

start-process -wait -WindowStyle Maximized -FilePath 'c:\program files\internet explorer\iexplore.exe' -ArgumentList 'https://insider.windows.com/' 

Then you'd implement a PowerShell script to set this as the Custom Shell Launcher:

NET USER kiosk "P@ssw0rd" /ADD

$COMPUTER = "localhost"
$NAMESPACE = "root\standardcimv2\embedded"

# Create a handle to the class instance so we can call the static methods.
$ShellLauncherClass = [wmiclass]"\\$COMPUTER\${NAMESPACE}:WESL_UserSetting"


# This well-known security identifier (SID) corresponds to the BUILTIN\Administrators group.
$Admins_SID = "S-1-5-32-544"

# Create a function to retrieve the SID for a user account on a machine.
function Get-UsernameSID($AccountName) {
$NTUserObject = New-Object System.Security.Principal.NTAccount($AccountName)
$NTUserSID = $NTUserObject.Translate([System.Security.Principal.SecurityIdentifier])
return $NTUserSID.Value
}

# Get the SID for a user account named "Cashier". Rename "Cashier" to an existing account on your system to test this script.
$Cashier_SID = Get-UsernameSID("kiosk")

# Define actions to take when the shell program exits.
$restart_shell = 0
$restart_device = 1
$shutdown_device = 2

# Examples

# Set the command prompt as the default shell, and restart the device if it's closed.
#$ShellLauncherClass.SetDefaultShell("explorer.exe", $restart_device)

# Set Internet Explorer as the shell for "Cashier", and restart the machine if it's closed.

$ShellLauncherClass.SetCustomShell($Cashier_SID, "powershell -executionpolicy bypass -windowstyle hidden -file c:\Windows\LaunchIE.ps1", ($null), ($null), $restart_shell)

# Set Explorer as the shell for administrators.
$ShellLauncherClass.SetCustomShell($Admins_SID, "explorer.exe")

# View all the custom shells defined.
"`nCurrent settings for custom shells:"
Get-WmiObject -namespace $NAMESPACE -computer $COMPUTER -class WESL_UserSetting | Select Sid, Shell, DefaultAction

# Enable Shell Launcher
$ShellLauncherClass.SetEnabled($TRUE)

$ShellLauncherClass.RemoveCustomShell($Admins_SID)