19

When I locally log in to a Server 2012 Core installation, every time I have to type powershell to get to a PowerShell command line instead of plain ol' cmd.

Assuming that I will never remove the PowerShell Windows Feature, how can I configure the server to just get me straight into a PowerShell prompt instead of cmd?

vcsjones
  • 712
  • 1
  • 8
  • 21

3 Answers3

9

Simply add your powershell command line as a new value to the "AvailableShells" regkey to have it as a machine-wide setting:

reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AlternateShells\AvailableShells" /v "90000" /t REG_SZ /d "%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\Powershell.exe"

Reference: http://andrewmorgan.ie/2012/03/30/changing-the-default-shell-of-windows-server-8-core/

Edit: note that the default registry permissions for the "AvailableShells" key will not allow for the change. You will have to change the permissions beforehand (e.g. manually through "regedit") to allow your account (or the "Administrators" group) to perform this change.

the-wabbit
  • 40,319
  • 13
  • 105
  • 169
  • 2
    That looks promising, but it doesn't appear that the Administrators group has write access to that `AvailableShells` key, only TrustedInstaller does. I can't change permissions without taking ownership of the key. Do you think taking ownership of a system key will present any problems? Here are the ACLs of my registry: https://gist.github.com/vcsjones/4dca25f94bfb1cfd5857 – vcsjones May 23 '13 at 20:19
  • OK, well I decided to snapshot the VM and try anyway, it appears to work. The only other thing is the value should be 90000, not 9000. If the value is too low then cmd kicks in first. – vcsjones May 23 '13 at 20:25
  • @vcsjones it should not present any problems as long as you let TrustedInstaller keep FullControl over the key. To be on the safe side, you could just reset the ownership back to TrustedInstaller after you're done. Oh and thank you for the correction of the number - indeed I have mistyped it in my `reg add` example. – the-wabbit May 23 '13 at 23:04
  • 2
    Or deploy this via a Group Policy for added automation win and circumvent the need to modify any permissions ;) – Ashley Jun 04 '13 at 23:49
  • I just tried this again, does not work. Access Denied. -1 – Peter Hahndorf Oct 25 '13 at 12:55
  • Or `reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AlternateShells\AvailableShells" /v "90000" /t REG_SZ /d "%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\Powershell.exe -noexit -command """cd $env:userprofile""""` – Andrew Savinykh Dec 04 '18 at 11:13
4

So here is my solution to this question.

  • I didn't want to mess around with changing the permissions of the AvailableShells path.
  • I wanted a simple Group Policy that could be safely applied to all systems on the domain.
  • Detecting if you have Server Core via WMI is different between 2008R2 and 2012, so I didn't want to use that.
  • I want avoid scripts as much as possible and just use policies and preferences.

My solution like many you will find in a search is to change the HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell value to Powershell. I have used item level targeting to modify this value only on systems without explorer.exe. AFAIK, this is one of the simplest tests to sort Server Core systems from Systems with a standard desktop.

The command line I use (powershell.exe -noexit -Command "Set-Location ${Env:USERPROFILE} ;start sconfig ; start runonce.exe /AlternativeShellStartup") will start powershell, fire off the runone tasks, sets my current directory, and starts sconfig in another Window.

Set Default Powershell on Server Core

Zoredache
  • 128,755
  • 40
  • 271
  • 413
2

The command in syneticon-dj's answer does not work, because a normal elevated administrator does not have write access to the key. The comments mention that you need to change the permissions. But this involves a lot of clicking in regedit.exe and does not work for scripted installations.

I use the following PowerShell script:

 $definition = @"
 using System;
 using System.Runtime.InteropServices;
 namespace Win32Api
 {
    public class NtDll
    {
       [DllImport("ntdll.dll", EntryPoint="RtlAdjustPrivilege")]
       public static extern int RtlAdjustPrivilege(ulong Privilege, bool Enable, bool CurrentThread, ref bool Enabled);
    }
 }
 "@

 Add-Type -TypeDefinition $definition -PassThru  | out-null

 $bEnabled = $false

 # Enable SeTakeOwnershipPrivilege
 $res = [Win32Api.NtDll]::RtlAdjustPrivilege(9, $true, $false, [ref]$bEnabled)

 $key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AlternateShells\AvailableShells", [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,[System.Security.AccessControl.RegistryRights]::takeownership)
 $acl = $key.GetAccessControl()
 $acl.SetOwner([System.Security.Principal.NTAccount]"Administrators")
 $key.SetAccessControl($acl)

 $rule = New-Object System.Security.AccessControl.RegistryAccessRule ("BUILTIN\Administrators","FullControl","Allow")
 $acl.SetAccessRule($rule)
 $key.SetAccessControl($acl)

 New-ItemProperty -path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AlternateShells\AvailableShells" -name 90000 -value "%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\Powershell.exe" -propertyType String

it first changes the permissions on the key and then sets PowerShell as the shell.

Notice this may only work on an English OS, as it refers to the 'Administrators' group.

Peter Hahndorf
  • 13,763
  • 3
  • 37
  • 58