Besides configuration through the GUI, Windows Server 2012 can be configured with a variety of command line tools:
- netsh for the IP address, default gateway and DNS server
- netdom renamecomputer for the hostname
- netdom join for joining the server to a domain
Of course, Microsoft now recommends the use of Powershell so I wanted to configure a fresh install of Windows Server 2012 using this tool.
When it came to enabling the Remote Desktop or setting Windows Firewall rules, the process was rather complex and seemed to confirm the idea in some cases, the GUI is the better tool. For example, setting time and date, not to mention the time zone, on a single server, is achieved much more efficiently by entering control timedate.cpl and adjusting settings in the resulting window. Likewise for regional settings, in which case we can use control intl.cpl.
Given the new interface, to which I am slowly adjusting however, I find it is often just as easy to type commands such as those above, rather than clicking multiple times to reach the appropriate icon in the Control Panel.
Otherwise, I've used Powershell as illustrated in the paragraphs that follow to configure...
- IP address (IPv4 and IPv6)
- Hostname
- Domain join
- Remote Powershell
- Remote Desktop (RDP)
- Firewall setting adjustments for Remote Desktop
IP address and related settings (default gateway, DNS servers)
Note: I've sometimes analyzed in some detail certain aspects of the addressing process. If you are most interested in the cmdlets themselves, please concentrate on the commands in bold and notably in red.
First, I want to see the name of the network adapter (or "network card") and the general status quo of the IP information.
As we can see below, using the Powershell cmdlets in question, the name of the first (and most often only) network adapter is "Ethernet" (rather than "Local Area Connection" as in previous versions of Windows).
Even before manual configuration of IP settings (assuming we do not use DHCP - less likely on a server), some IP addresses, notably IPv6, have been assigned automatically. We also have an IPv4 and IPv6 loopback address, respectively 127.0.0.1 and ::1
Since the output of some of the commands can be quite lengthy, I've used the format-list cmdlet to limit the output to values that I find most useful.
PS C:\> Get-NetAdapter | fl name,interfacedescription,macaddress,linkspeed
name : Ethernet
interfacedescription : Intel(R) 82574L Gigabit Network Connection
MacAddress : 00-0C-29-06-55-CE
LinkSpeed : 1 Gbps
PS C:\> Get-NetIPAddress | fl ipaddress,interfacealias,addressfamily,addressstate
ipaddress : fe80::1fe:23d7:24dc:1847%12
interfacealias : Ethernet
AddressFamily : IPv6
AddressState : Preferred
ipaddress : fd00::de17:18f7:578f:48ca
interfacealias : Ethernet
AddressFamily : IPv6
AddressState : Preferred
ipaddress : fe80::5efe:169.254.24.71%19
interfacealias : Local Area Connection* 11
AddressFamily : IPv6
AddressState : Deprecated
ipaddress : ::1
interfacealias : Loopback Pseudo-Interface 1
AddressFamily : IPv6
AddressState : Preferred
ipaddress : 169.254.24.71
interfacealias : Ethernet
AddressFamily : IPv4
AddressState : Preferred
ipaddress : 127.0.0.1
interfacealias : Loopback Pseudo-Interface 1
AddressFamily : IPv4
AddressState : Preferred
IPCONFIG is still useful - and less verbose:
PS C:\> ipconfig
Windows IP Configuration
Ethernet adapter Ethernet:
Connection-specific DNS Suffix . :
IPv6 Address. . . . . . . . . . . : fd00::de17:18f7:578f:48ca
Link-local IPv6 Address . . . . . : fe80::1fe:23d7:24dc:1847%12
Autoconfiguration IPv4 Address. . : 169.254.24.71
Subnet Mask . . . . . . . . . . . : 255.255.0.0
Default Gateway . . . . . . . . . :
Tunnel adapter Local Area Connection* 11:
Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :
Now we will configure an IPv4 address - this is roughly the equivalent of the netsh int ipv4 set address command. The command is at least as long to type as the parameters must be indicated, unlike netsh with which we can simply enter 10.1.1.12 255.0.0.0 10.1.1.2 at the end (using the same values as below).
PS C:\> New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress 10.1.1.12 -PrefixLength 8 -DefaultGateway 10.1.1.2
IPAddress : 10.1.1.12
InterfaceIndex : 12
InterfaceAlias : Ethernet
AddressFamily : IPv4
Type : Unicast
PrefixLength : 8
PrefixOrigin : Manual
SuffixOrigin : Manual
AddressState : Tentative
...
IPAddress : 10.1.1.12
InterfaceIndex : 12
InterfaceAlias : Ethernet
AddressFamily : IPv4
Type : Unicast
PrefixLength : 8
PrefixOrigin : Manual
SuffixOrigin : Manual
AddressState : Invalid
...
PS C:\> Get-NetIPAddress | where { $_.IPAddress -eq "10.1.1.12" } | fl
IPAddress : 10.1.1.12
InterfaceIndex : 12
InterfaceAlias : Ethernet
AddressFamily : IPv4
Type : Unicast
PrefixLength : 8
PrefixOrigin : Manual
SuffixOrigin : Manual
AddressState : Preferred
...
Note that the state of the address changes. In the output that displayed automatically after the execution of the New-NetIPAddress, it is first "Tentative" and then (for some reason?) "Invalid" but finally "Preferred" - after verification with the cmdlet Get-NetIPAddress.
Here we configure the DNS server:
PS C:\> Set-DnsClientServerAddress "Ethernet" -ServerAddresses 10.1.1.10
So what's changed? Now, instead of the 169.254.24.71 address, we have "10.1.1.12".
PS C:\> Get-NetIPAddress | fl ipaddress,interfacealias,addressfamily,addressstate
[snip]
ipaddress : ::1
interfacealias : Loopback Pseudo-Interface 1
AddressFamily : IPv6
AddressState : Preferred
ipaddress : 10.1.1.12
interfacealias : Ethernet
AddressFamily : IPv4
AddressState : Preferred
ipaddress : 127.0.0.1
interfacealias : Loopback Pseudo-Interface 1
AddressFamily : IPv4
AddressState : Preferred
Now we'll configure an IPv6 address. Unlike the IPv4 address, that replaced the APIPA address (169.254.x.x), the manually assigned IPv6 address can coexist with the IPv6 link local address (and others).
PS C:\> New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress fd00::12
IPAddress : fd00::12
InterfaceIndex : 12
InterfaceAlias : Ethernet
AddressFamily : IPv6
Type : Unicast
PrefixLength : 128
PrefixOrigin : Manual
SuffixOrigin : Manual
AddressState : Tentative
ValidLifetime : Infinite ([TimeSpan]::MaxValue)
PreferredLifetime : Infinite ([TimeSpan]::MaxValue)
SkipAsSource : False
PolicyStore : ActiveStore
IPAddress : fd00::12
InterfaceIndex : 12
InterfaceAlias : Ethernet
AddressFamily : IPv6
Type : Unicast
PrefixLength : 128
PrefixOrigin : Manual
SuffixOrigin : Manual
AddressState : Invalid
ValidLifetime : Infinite ([TimeSpan]::MaxValue)
PreferredLifetime : Infinite ([TimeSpan]::MaxValue)
SkipAsSource : False
PolicyStore : PersistentStore
Once again, as for the IPv4 address, the status of the address goes from "Tentative" to "Invalid" to "Preferred" (see below).
PS C:\> Get-NetIPAddress | where { $_.IPAddress -eq "fd00::12" } | fl
IPAddress : fd00::12
InterfaceIndex : 12
InterfaceAlias : Ethernet
AddressFamily : IPv6
Type : Unicast
PrefixLength : 128
PrefixOrigin : Manual
SuffixOrigin : Manual
AddressState : Preferred
ValidLifetime : Infinite ([TimeSpan]::MaxValue)
PreferredLifetime : Infinite ([TimeSpan]::MaxValue)
SkipAsSource : False
PolicyStore : ActiveStore
We can use the following commands to verify the status of our network adapters:
PS C:\> ipconfig /all
Windows IP Configuration
Host Name . . . . . . . . . . . . : WIN-6CSB0KQ27BN
Primary Dns Suffix . . . . . . . :
Node Type . . . . . . . . . . . . : Hybrid
IP Routing Enabled. . . . . . . . : No
WINS Proxy Enabled. . . . . . . . : No
Ethernet adapter Ethernet:
Connection-specific DNS Suffix . :
Description . . . . . . . . . . . : Intel(R) 82574L Gigabit Network Connection
Physical Address. . . . . . . . . : 00-0C-29-06-55-CE
DHCP Enabled. . . . . . . . . . . : No
Autoconfiguration Enabled . . . . : Yes
IPv6 Address. . . . . . . . . . . : fd00::12(Preferred)
IPv6 Address. . . . . . . . . . . : fd00::f0a7:570b:489b:a320(Preferred)
Lease Obtained. . . . . . . . . . : Wednesday, November 6, 2015 8:16:55 PM
Lease Expires . . . . . . . . . . : Thursday, November 21, 2015 6:58:10 AM
Link-local IPv6 Address . . . . . : fe80::1fe:23d7:24dc:1847%12(Preferred)
IPv4 Address. . . . . . . . . . . : 10.1.1.12(Preferred)
Subnet Mask . . . . . . . . . . . : 255.0.0.0
Default Gateway . . . . . . . . . : 10.1.1.2
DHCPv6 IAID . . . . . . . . . . . : 251661353
DHCPv6 Client DUID. . . . . . . . : 00-01-00-01-1A-0C-C5-57-00-0C-29-06-55-CE
DNS Servers . . . . . . . . . . . : 10.1.1.10
NetBIOS over Tcpip. . . . . . . . : Enabled
PS C:\> Get-NetIPAddress | fl IPAddress,SuffixOrigin,AddresState
IPAddress : fe80::1fe:23d7:24dc:1847%12
SuffixOrigin : Link
IPAddress : fd00::7f64:7932:81f9:dc56
SuffixOrigin : Dhcp
IPAddress : fd00::12
SuffixOrigin : Manual
IPAddress : fe80::5efe:10.1.1.12%13
SuffixOrigin : Link
IPAddress : ::1
SuffixOrigin : WellKnown
IPAddress : 10.1.1.12
SuffixOrigin : Manual
IPAddress : 127.0.0.1
SuffixOrigin : WellKnown
PS C:\> Get-DnsClientServerAddress | fl interfacealias,ServerAddresses
interfacealias : Ethernet
ServerAddresses : {10.1.1.10}
interfacealias : Ethernet
ServerAddresses : {fd00::10}
[snip]
Hostname
The netdom renamecomputer command requires the designation of the current name of the computer. After experimenting with the first option below, I discovered that Powershell allows us to rename the computer without indicating the current name.
In either case, the cmdlet is Rename-Computer.
Option 1
PS C:\> $oldname = hostname
PS C:\> $oldname
WIN-6CSB0KQ27BN
PS C:\> Rename-Computer -NewName SVR-00X -ComputerName $oldname
WARNING: The changes will take effect after you restart the computer WIN-6CSB0KQ27BN.
PS C:\> Restart-Computer
Option 2
PS C:\>Rename-Computer -NewName SVR-004 -force -restart
Note: There are parameters that allow us to perform the operation using specific credentials, local or domain:
-DomainCredential
-LocalCredential
Otherwise, the credentials of the user performing the operation are used by default.
The -force parameter eliminates the confirmation prompt.
The -restart parameter restarts the computer automatically.
Join computer to domain
Note: the command assumes that the computer account and organizational unit in question have already been created in Active Directory.
Creation of OU:
PS C:\> New-ADOrganizationalUnit "Servers"
By default, the OU is created at the domain root. If that is where we want to create the OU, no further parameters are necessary.
Creation of computer account for server:
PS C:\> New-ADComputer SVR-004 -Path "OU=Servers,DC=machlinkit,DC=biz"
Joining server to domain:
PS C:\> Add-Computer -DomainName machlinkit.biz -restart
Note: if logged on with credentials that allow joining a computer to the domain, it is not necessary to enter them.
Enable Remote Powershell
In fact, there is not much to do here.
On Windows 2012, remote access via PowerShell is enabled by default.
In this case, we want to be able to execute Powershell commands on member server SVR-004 from domain controller DC-001.
We can run the following command on previous operating systems, Windows 2008 R2 in particular, or use it to enable PS remoting on a machine where it was disabled:
PS C:\> Enable-PSRemoting -force
WinRM is already set up to receive requests on this computer.
WinRM is already set up for remote management on this computer.
PS C:\>
Since the function is already enabled, we have the output shown above.
Note: if necessary, we would run this command on SVR-004 - the target computer.
------------------------------------------------------------------------------------------
Note: the -force parameter eliminates the rather verbose confirmation that we would otherwise see. I'll post that output here since it does describe what the command accomplishes:
PS C:\> Enable-PSRemoting
WinRM Quick Configuration
Running command "Set-WSManQuickConfig" to enable remote management of this computer by using the Windows Remote Management (WinRM) service.
This includes:
1. Starting or restarting (if already started) the WinRM service
2. Setting the WinRM service startup type to Automatic
3. Creating a listener to accept requests on any IP address
4. Enabling Windows Firewall inbound rule exceptions for WS-Management traffic (for http only).
Do you want to continue?
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): A
WinRM is already set up to receive requests on this computer.
WinRM has been updated for remote management.
Configured LocalAccountTokenFilterPolicy to grant administrative rights remotely to local users.
Confirm
Are you sure you want to perform this action?
Performing operation "Set-PSSessionConfiguration" on Target "Name: microsoft.powershell SDDL:
O:NSG:BAD:P(A;;GA;;;BA)(A;;GA;;;RM)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD). This will allow selected users to remotely run Windows PowerShell commands on this computer".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): A
---------------------------------------------------------------------------------------------------------
From DC-001 we can first test the WinRM service on SVR-004: is it running? responding to requests?
PS C:\> Test-WsMan SVR-004
wsmid : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentity.xsd
ProtocolVersion : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
ProductVendor : Microsoft Corporation
ProductVersion : OS: 0.0.0 SP: 0.0 Stack: 3.0
To verify (one step further), I'll stop and later start the WinRM service.
Right now it is on.
PS C:\> Get-Service WinRM | fl
Name : WinRM
DisplayName : Windows Remote Management (WS-Management)
Status : Running
DependentServices : {}
[snip]
PS C:\> Stop-Service WinRM
We try Test-WsMan again... this time, failure:
PS C:\> Test-Wsman SVR-004
test-wsman : <f:WSManFault xmlns:f="http://schemas.microsoft.com/wbem/wsman/1/wsmanfault" Code="2150859046" Machine="DC-001.machlinkit.biz"><f:Message>WinRM cannot complete the operation. Verify that the specified computer name is valid, that the computer is accessible over the network, and that a firewall exception for the WinRM service is enabled and allows access from this computer. By default, the WinRM firewall exception for public profiles limits access to remote computers within the same local subnet. </f:Message></f:WSManFault>
If I enable the WinRM on SVR-004 (with Start-Service), the test succeeds once again.
Now I'll start a remote Powershell session on SVR-004 from DC-001 and execute some basic file system commands.
PS C:\> Enter-PSSession -ComputerName SVR-004
[snip]
[SVR-004]: PS C:\>
[SVR-004]: PS C:\> gci
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 7/26/2012 3:44 AM PerfLogs
d-r-- 11/6/2015 8:14 PM Program Files
d---- 7/26/2012 4:04 AM Program Files (x86)
d---- 11/13/2015 4:50 PM TeamDocuments
d-r-- 11/13/2015 5:12 PM Users
d---- 11/6/2015 10:45 PM Windows
[SVR-004]: PS C:\> sl .\TeamDocuments
[SVR-004]: PS C:\TeamDocuments> New-Item -Name NewFile1.txt -Type File
[snip]
We can also execute I single command on the remote computer using the Invoke-Command cmdlet as shown below. First we need to exit from the current session.
[SVR-004]: PS C:\TeamDocuments> Exit
PS C:\>
PS C:\> Invoke-Command SVR-004 -ScriptBlock {gci C:\TeamDocuments}
Directory: C:\TeamDocuments
Mode LastWriteTime Length Name PSComputerName
---- ------------- ------ ---- --------------
-a--- 11/13/2015 5:13 PM 0 NewFile.txt SVR-004
-a--- 11/13/2015 5:13 PM 0 NewFile1.txt SVR-004
Note that in both cases, I am able to omit the parameter -ComputerName because it is a positional parameter and do not need to use the -Credential parameter because I am using a domain administrator account that has complete access to both machines.
Note (once again) that "Windows Remote Management" is enabled by default in Windows 2012. It was not necessary for me to adjust firewall settings.
Enable Remote Desktop
This is where I find Powershell to be most lacking. There is not a simple cmdlet that performs the two necessary operations that must be accomplished to enable remote desktop:
1. Enable Remote Desktop itself
2. Configure Windows Firewall in consequence.
In my opinion, the simplest - or least complicated way - to achieve this is to manipulate the registry settings that govern Remote Desktop with the Set-ItemProperty cmdlet and then the firewall rules with the Enable-NetFirewallRule cmdlet. As I proceeded by trial and error, until I found the commands that seemed most appropriate (to me), I'll place the "best" cmdlets (in my opinion) in bold red font, the others in simple bold.
I found an alternate method that uses WMI to manipulate the Remote Desktop setting as well. I will post this alternative at the end (of this already very long post).
***
The parameter that governs Remote Desktop is "fDenyTSConnections" and can be found in the Windows registry in the location below. I will limit the output with the format-list cmdlet.
PS C:\> Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' -Name fDenyTSConnections | fl fDenyTSConnections
fDenyTSConnections : 1
Since the parameters are apparently both positional (meaning they can be omitted), we can abbreviate as follows:
PS C:\> Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' fDenyTSConnections | fl fDenyTSConnections
fDenyTSConnections : 1
The value "1" indicates that Terminal Connections (or Remote Desktop connections) are indeed denied. We will need to change this.
We also need to manage user authentication (enable it or not). It is more secure (thus generally preferable) to enable it. However, older versions of Windows (XP,2003) may not be able to connect this way.
PS C:\> Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' UserAuthentication | fl UserAuthentication
UserAuthentication : 1
So, Remote Desktop is disabled and User Authentication is enabled. The latter, of course, has no effect, since the former is not enabled.
Now let's look at the status of the Windows Firewall, concerning Remote Desktop access.
PS C:\> Get-NetFirewallRule | where {$_.Name -like "*Desktop*"} | fl Name,Enabled,Profile,Direction
Name : RemoteDesktop-UserMode-In-TCP
Enabled : False
Profile : Public
Direction : Inbound
Name : RemoteDesktop-UserMode-In-UDP
Enabled : False
Profile : Public
Direction : Inbound
This only applies to the Public profile which has no effect on the Domain (or Private) profile which interests me.
Let's try this:
PS C:\> Get-NetFirewallRule -DisplayGroup "Remote Desktop" | fl Name,Enabled,Profile,Direction
Name : RemoteDesktop-UserMode-In-TCP
Enabled : False
Profile : Public
Direction : Inbound
Name : RemoteDesktop-UserMode-In-UDP
Enabled : False
Profile : Public
Direction : Inbound
Name : {12954380-D013-432D-A2A1-646FC09BB918}
Enabled : False
Profile : Domain, Private
Direction : Inbound
Name : {9CD18D97-6B13-4463-BA5E-A2794D7237E9}
Enabled : False
Profile : Domain, Private
Direction : Inbound
For some reason, in the Powershell output, the name of the firewall rule is a long GUID. I'll deal with that in a moment...
Enable Remote Desktop
OK, that is the status quo. Now let's enable remote desktop with this cmdlet:
PS C:\> Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' fDenyTSConnections -value 0
This is the result:
PS C:\> Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server' fDenyTSConnections | fl fDenyTSConnections
fDenyTSConnections : 0
User Authentication is at "1" (enabled) already and we will leave it as that because all clients likely to connect to the Windows 2012 servers are running Windows Vista / Server 2008 or above.
Enable Windows Firewall rules
I found - but am not satisfied - with the following command since it enables Remote Desktop in the Public profile. Although one could argue that it does not matter if we are behind a perimeter firewall anyway.
PS C:\> Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
PS C:\> Get-NetFirewallRule -DisplayGroup "Remote Desktop" | fl Name,Enabled,Profile,Direction
Name : RemoteDesktop-UserMode-In-TCP
Enabled : True
Profile : Public
Direction : Inbound
Name : RemoteDesktop-UserMode-In-UDP
Enabled : True
Profile : Public
Direction : Inbound
Name : {12954380-D013-432D-A2A1-646FC09BB918}
Enabled : True
Profile : Domain, Private
Direction : Inbound
Although more complex, the command that follows (in bold red) provides exactly what I prefer.
I first test to see what rules the following cmdlet will produce...
PS C:\> Get-NetFirewallRule | where {$_.DisplayGroup -eq "Remote Desktop" -and $_.Profile -match "Domain"} | fl Name,DisplayGroup,Profile,Enabled
Name : {12954380-D013-432D-A2A1-646FC09BB918}
DisplayGroup : Remote Desktop
Profile : Domain, Private
Enabled : False
Name : {9CD18D97-6B13-4463-BA5E-A2794D7237E9}
DisplayGroup : Remote Desktop
Profile : Domain, Private
Enabled : False
And then pipeline the result to the Enable-NetFirewallRule cmdlet. This allows Remote Desktop access. I will refrain from lengthening this post any longer by posting the result.
PS C:\> Get-NetFirewallRule | where {$_.DisplayGroup -eq "Remote Desktop" -and $_.Profile -match "Domain"} | Enable-NetFirewallRule
To open the Remote Desktop tool from the command line, we can simply type (and then presse Enter):
mstsc.exe
And then provide necessary credentials.
***
Alternate method of enabling Remote Desktop using the Get-WMIObject cmdlet with the SetAllowTsConnections method:
PS C:\> (Get-WmiObject -Class "Win32_TerminalServiceSetting" -NameSpace root\cimv2\terminalservices).AllowTsConnections
0
PS C:\> (Get-WmiObject -Class "Win32_TerminalServiceSetting" -NameSpace root\cimv2\terminalservices).SetAllowTsConnections(1)
[snip]
Here we have allowed TsConnections by setting the value to "1".
The result:
PS C:\> (Get-WmiObject -Class "Win32_TerminalServiceSetting" -NameSpace root\cimv2\terminalservices).AllowTsConnections
1
--------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------
In conclusion...
This was a useful though time-consuming adventure with Powershell but if you have the "Full" install of Windows Server 2012, as opposed to the Server Core install, and want to configure (among others) Remote Desktop, just use the GUI.
Thank you for reading the article about Windows Server 2012 - basic configuration with PowerShell on the blog NEW TECH If you want to disseminate this article on please list the link as the source, and if this article was helpful please bookmark this page in your web browser by pressing Ctrl + D on your keyboard keys.