| title | CMD and PowerShell in Azure Windows VMs |
|---|---|
| description | How to use CMD and PowerShell commands within SAC in Azure Windows VMs |
| services | virtual-machines |
| documentationcenter | |
| author | JarrettRenshaw |
| manager | dcscontentpm |
| tags | azure-resource-manager |
| ms.service | azure-virtual-machines |
| ms.collection | windows |
| ms.tgt_pltfrm | vm-windows |
| ms.workload | infrastructure-services |
| ms.date | 10/16/2025 |
| ms.author | jarrettr |
| ms.custom | sap:Cannot connect to my VM |
Applies to: ✔️ Windows VMs
This article provides example commands to perform common tasks in scenarios in which you have to use the Special Administration Console (SAC) to access your Windows virtual machine (VM). For example, you might have to use SAC to troubleshoot RDP connection failures.
SAC is included in all versions of Windows since Windows Server 2003. By default, however, it's disabled. SAC relies on the sacdrv.sys kernel driver, the Special Administration Console Helper service (sacsvr), and the sacsess.exe process. For more information, see Emergency Management Services Tools and Settings.
SAC enables you to connect through a serial port to the running OS. When you open a Command Prompt window in SAC, sacsess.exe starts cmd.exe within your running OS. In Task Manager, you can see that if, at the same time, you also connect through RDP to your VM, you're now connected to SAC through the serial console feature. The CMD window that you access through SAC is the same as the cmd.exe window that you use when you connect through RDP. All the same commands and tools are available, including the ability to start PowerShell from that CMD instance. The major difference between SAC and the Windows Recovery Environment (WinRE) is that SAC lets you manage your running OS, but WinRE starts up into a different, minimal OS. Although Azure VMs don't support the ability to access WinRE, they can be managed through SAC.
Because SAC is limited to an 80x24 pixel screen buffer that has no scroll back capability, add | more to commands to display the output one page at a time. Use <spacebar> to see the next page, or <enter> to see the next line.
The paste shortcut for the serial console window is SHIFT+INSERT.
Because of SAC's limited screen buffer, it might be easier to manage longer commands by copying them from a local text editor to SAC.
To view and edit Windows registry settings by using CMD, follow these steps:
-
Verify that RDP is enabled. Run the following commands:
reg query "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections
reg query "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v fDenyTSConnections
Note: The second key (under \Policies) exists only if the relevant Group Policy setting is configured.
-
Enable RDP by running the following commands:
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0
reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services" /v fDenyTSConnections /t REG_DWORD /d 0
Note: The second key (under \Policies) is necessary only if the relevant Group Policy setting is configured. The value is rewritten at next Group Policy refresh if it's configured in Group Policy.
To manage Windows services by using CMD, follow these steps:
-
View the service state:
sc query termservice -
View the service logon account:
sc qc termservice -
Set the service logon account:
sc config termservice obj= "NT Authority\NetworkService"Note: A space is required after the equal sign.
-
Set service start type:
sc config termservice start= demandNote: A space is required after the equal sign. Possible start values include:
boot,system,auto,demand,disabled, anddelayed-auto. -
Set service dependencies:
sc config termservice depend= RPCSSNote: A space is required after the equal sign.
-
Start service by running either of the following commands:
net start termservicesc start termservice -
Stop the service by running either of the following commands:
net stop termservicesc stop termservice
To manage networking features using CMD, follow these steps:
-
Show the network shell (netsh) properties:
netsh interface show interface -
Show IP properties:
netsh interface ip show config -
Show IPSec configuration:
netsh nap client show configuration -
Enable the network shell interface:
netsh interface set interface name="<interface name>" admin=enabled -
Set the netsh interface to use DHCP:
netsh interface ip set address name="<interface name>" source=dhcp
For more information about netsh, see Network shell (netsh).
Azure VMs should always be configured in the guest OS to use DHCP to get an IP address. The Azure static IP setting still uses DHCP to give the static IP to the VM.
ping 8.8.8.8
Install the telnet client
dism /online /Enable-Feature /FeatureName:TelnetClient
Test connectivity
telnet bing.com 80
To remove the telnet client
dism /online /Disable-Feature /FeatureName:TelnetClient
When limited to methods available in Windows by default, PowerShell can be a better approach for testing port connectivity. See the following PowerShell section for examples.
nslookup bing.com
netsh advfirewall firewall show rule name="Remote Desktop - User Mode (TCP-In)"
netsh advfirewall set allprofiles state off
You can use this command when you troubleshoot to temporarily rule out Windows Firewall. Firewall will be enabled at the next restart or when you enable it by using the command in the next section. Don't stop the Windows Firewall service (MPSSVC) or Base Filtering Engine (BFE) service as a method to rule out the Windows Firewall. Stopping MPSSVC or BFE causes all connectivity to be blocked.
netsh advfirewall set allprofiles state on
net user /add <username> <password>
net localgroup Administrators <username> /add
net user <username> | find /i "active"
Azure VMs that are created from a generalized image have the local administrator account renamed to the name that's specified during VM provisioning. Usually, the name isn't Administrator.
net user <username> /active:yes
net user <username>
Example lines of interest from a local admin account:
Account active Yes
Account expires Never
Password expires Never
Workstations allowed All
Logon hours allowed All
Local Group Memberships *Administrators
net localgroup
wevtutil qe system /c:10 /f:text /q:"Event[System[Level=2]]" | more
Change /c:10 to the desired number of events to return, or move it to return all events matching the filter.
wevtutil qe system /c:1 /f:text /q:"Event[System[EventID=11]]" | more
wevtutil qe system /c:1 /f:text /q:"Event[System[Provider[@Name='Microsoft-Windows-Hyper-V-Netvsc'] and EventID=11]]" | more
wevtutil qe system /c:1 /f:text /q:"Event[System[Provider[@Name='Microsoft-Windows-Hyper-V-Netvsc'] and EventID=11 and TimeCreated[timediff(@SystemTime) <= 86400000]]]"
Use 604800000 to look back seven days instead of 24 hours.
wevtutil qe security /c:1 /f:text /q:"Event[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID=4624 and TimeCreated[timediff(@SystemTime) <= 604800000]] and EventData[Data[@Name='TargetUserName']='<username>']]" | more
wmic product get Name,InstallDate | sort /r | more
The sort /r command sorts results in descending order by install date, making it easier to identify recently installed applications. Use <spacebar> to advance to the next page of output, or <enter> to advance one line.
wmic path win32_product where name="<name>" call uninstall
Replace <name> with the name that's returned in the previous command for the application that you want to remove.
wmic datafile where "drive='C:' and path='\\windows\\system32\\drivers\\' and filename like 'netvsc%'" get version /format:list
This example returns the file version of the virtual network adapter driver, which is netvsc.sys, netvsc63.sys, or netvsc60.sys depending on the Windows version.
sfc /scannow
See also Repair a Windows Image.
dism /online /cleanup-image /scanhealth
See also Repair a Windows Image.
icacls %programdata%\Microsoft\Crypto\RSA\MachineKeys /t /c > %temp%\MachineKeys_permissions_before.txt
icacls %programdata%\Microsoft\Crypto\RSA\MachineKeys /save %temp%\MachineKeys_permissions_before.aclfile /t
icacls %programdata%\Microsoft\Crypto\RSA /save %temp%\MachineKeys_permissions_before.aclfile /t
When using /restore, specify the parent folder of the one used in
/save. For example, use \RSA if you previously saved permissions for \MachineKeys.
takeown /f %programdata%\Microsoft\Crypto\RSA\MachineKeys /a /r
icacls C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys /t /c /grant "BUILTIN\Administrators:(F)"
This command cleans up device entries for hardware that no longer exists on the system:
%windir%\System32\RUNDLL32.exe %windir%\System32\pnpclean.dll,RunDLL_PnpClean /Devices /Maxclean
gpupdate /force /wait:-1
ver
or
wmic os get caption,version,buildnumber /format:list
or
systeminfo find /i "os name"
systeminfo | findstr /i /r "os.*version.*build"
systeminfo | find /i "original"
or
wmic os get installdate
systeminfo | find /i "system boot time"
systeminfo | find /i "time zone"
or
wmic timezone get caption,standardname /format:list
shutdown /r /t 0
Adding /f forces running applications to close without warning users.
bcdedit /enum | find /i "safeboot"
To run PowerShell in SAC, after you reach a CMD prompt, type:
powershell <enter>
Caution
Remove the PSReadLine module from the PowerShell session before running any other PowerShell commands. There's a known issue where extra characters may be introduced in text pasted from the clipboard if PSReadLine is running in a PowerShell session in SAC.
First check if PSReadLine is loaded. It's loaded by default on Windows Server 2016, Windows 10, and later versions of Windows. It would only be present on earlier Windows versions if it's manually installed.
If this command returns to a prompt with no output, then the module wasn't loaded and you can continue using the PowerShell session in SAC as normal.
get-module psreadline
If the previous command returns the PSReadLine module version, run the following command to unload it. This command doesn't delete or uninstall the module. It only unloads it from the current PowerShell session.
remove-module psreadline
If PSReadLine is loaded, it may introduce extra characters when you paste text. To avoid this, unload the module by using remove-module psreadline.
get-itemproperty -path 'hklm:\system\curRentcontrolset\control\terminal server' -name 'fdenytsconNections'
get-itemproperty -path 'hklm:\software\policies\microsoft\windows nt\terminal services' -name 'fdenytsconNections'
The second key under \Policies exists only if the relevant Group Policy setting is configured.
set-itemproperty -path 'hklm:\system\curRentcontrolset\control\terminal server' -name 'fdenytsconNections' 0 -type dword
set-itemproperty -path 'hklm:\software\policies\microsoft\windows nt\terminal services' -name 'fdenytsconNections' 0 -type dword
The second key (under \Policies) would be needed only if the relevant group policy setting was configured. The value will be rewritten at next group policy refresh if it's configured in group policy.
get-wmiobject win32_service -filter "name='termservice'" | format-list Name,DisplayName,State,StartMode,StartName,PathName,ServiceType,Status,ExitCode,ServiceSpecificExitCode,ProcessId
Get-Service can be used but doesn't include the service logon account. Get-WmiObject win32-service does.
(get-wmiobject win32_service -filter "name='termservice'").Change($null,$null,$null,$null,$null,$false,'NT Authority\NetworkService')
When using a service account other than NT AUTHORITY\LocalService, NT AUTHORITY\NetworkService, or LocalSystem, specify the account password as the last (eighth) argument after the account name.
set-service termservice -startuptype Manual
Set-service accepts Automatic, Manual, or Disabled for startup type.
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\TermService' -Name DependOnService -Value @('RPCSS','TermDD')
start-service termservice
stop-service termservice
get-netadapter | where {$_.ifdesc.startswith('Microsoft Hyper-V Network Adapter')} | format-list status,name,ifdesc,macadDresS,driverversion,MediaConNectState,MediaDuplexState
or
get-wmiobject win32_networkadapter -filter "servicename='netvsc'" | format-list netenabled,name,macaddress
Get-NetAdapter is available in 2012 and later versions, for 2008 R2, use Get-WmiObject.
get-wmiobject Win32_NetworkAdapterConfiguration -filter "ServiceName='netvsc'" | format-list DNSHostName,IPAddress,DHCPEnabled,IPSubnet,DefaultIPGateway,MACAddress,DHCPServer,DNSServerSearchOrder
get-netadapter | where {$_.ifdesc.startswith('Microsoft Hyper-V Network Adapter')} | enable-netadapter
or
(get-wmiobject win32_networkadapter -filter "servicename='netvsc'").enable()
Get-NetAdapter is available in 2012 and later versions, for 2008 R2, use Get-WmiObject.
get-netadapter | where {$_.ifdesc.startswith('Microsoft Hyper-V Network Adapter')} | Set-NetIPInterface -DHCP Enabled
(get-wmiobject Win32_NetworkAdapterConfiguration -filter "ServiceName='netvsc'").EnableDHCP()
Get-NetAdapter is available in 2012 and later versions. For 2008 R2, use Get-WmiObject. Azure VMs should always be configured in the guest OS to use DHCP to obtain an IP address. The Azure static IP setting still uses DHCP to give the IP to the VM.
test-netconnection
Note
The Write-Progress cmdlet might not work by using this command. As a mitigation, you can run $ProgressPreference = "SilentlyContinue" in PowerShell to disable the progress bar.
Or
get-wmiobject Win32_PingStatus -Filter 'Address="8.8.8.8"' | format-table -autosize IPV4Address,ReplySize,ResponseTime
Test-Netconnection without any parameters, try to ping internetbeacon.msedge.net. It's available in 2012 and later versions. For 2008 R2, use Get-WmiObject, as in the second example.
test-netconnection -ComputerName bing.com -Port 80
Or
(new-object Net.Sockets.TcpClient).BeginConnect('bing.com','80',$null,$null).AsyncWaitHandle.WaitOne(300)
Test-NetConnection is available in 2012 and later versions. For 2008 R2, use Net.Sockets.TcpClient.
resolve-dnsname bing.com
Or
[System.Net.Dns]::GetHostAddresses('bing.com')
Resolve-DnsName is available in 2012 and later versions. For 2008 R2, use System.Net.DNS.
get-netfirewallrule -name RemoteDesktop-UserMode-In-TCP
get-netfirewallportfilter | where {$_.localport -eq 3389} | foreach {Get-NetFirewallRule -Name $_.InstanceId} | format-list Name,Enabled,Profile,Direction,Action
Or
(new-object -ComObject hnetcfg.fwpolicy2).rules | where {$_.localports -eq 3389 -and $_.direction -eq 1} | format-table Name,Enabled
Get-NetFirewallPortFilter is available in 2012 and later versions. For 2008 R2, use the hnetcfg.fwpolicy2 COM object.
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
Set-NetFirewallProfile is available in 2012 and later versions. For 2008 R2, use netsh advfirewall as referenced in the CMD section earlier in this article.
new-localuser <name>
(get-localuser | where {$_.SID -like "S-1-5-21-*-500"}).Enabled
Or
(get-wmiobject Win32_UserAccount -Namespace "root\cimv2" -Filter "SID like 'S-1-5-%-500'").Disabled
Get-LocalUser is available in 2012 and later versions. For 2008 R2, use Get-WmiObject. This example shows the built-in local administrator account. This account always has SID S-1-5-21-*-500. Azure VMs that are created from a generalized image have the local administrator account renamed to the name that's specified during VM provisioning. Usually, the name isn't Administrator.
add-localgroupmember -group Administrators -member <username>
get-localuser | where {$_.SID -like "S-1-5-21-*-500"} | enable-localuser
This example enables the built-in local administrator account. This account always has SID S-1-5-21-*-500. Azure VMs that are created from a generalized image have the local administrator account renamed to the name specified during VM provisioning. Usually, the name isn't Administrator.
get-localuser | where {$_.SID -like "S-1-5-21-*-500"} | format-list *
Or
get-wmiobject Win32_UserAccount -Namespace "root\cimv2" -Filter "SID like 'S-1-5-%-500'" | format-list Name,Disabled,Status,Lockout,Description,SID
Get-LocalUser is available in 2012 and later versions. For 2008 R2, use Get-WmiObject. This example shows the built-in local administrator account. This account always has SID S-1-5-21-*-500.
(get-localgroup).name | sort (get-wmiobject win32_group).Name | sort
Get-LocalUser is available in 2012 and later versions. For 2008 R2, use Get-WmiObject.
get-winevent -logname system -maxevents 1 -filterxpath "*[System[Level=2]]" | more
Change /c:10 to the desired number of events to return, or remove it to return all matching events.
get-winevent -logname system -maxevents 1 -filterxpath "*[System[EventID=11]]" | more
get-winevent -logname system -maxevents 1 -filterxpath "*[System[Provider[@Name='Microsoft-Windows-Hyper-V-Netvsc'] and EventID=11]]" | more
get-winevent -logname system -maxevents 1 -filterxpath "*[System[Provider[@Name='Microsoft-Windows-Hyper-V-Netvsc'] and EventID=11 and TimeCreated[timediff(@SystemTime) <= 86400000]]]"
Use 604800000 to look back seven days instead of 24 hours. |
get-winevent -logname system -maxevents 1 -filterxpath "*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID=4624 and TimeCreated[timediff(@SystemTime) <= 604800000]] and EventData[Data[@Name='TargetUserName']='<username>']]" | more
get-wmiobject win32_product | select installdate,name | sort installdate -descending | more
(get-wmiobject win32_product -filter "Name='<name>'").Uninstall()
(get-childitem $env:windir\system32\drivers\netvsc*.sys).VersionInfo.FileVersion
This example returns the file version of the virtual NIC driver, which is named netvsc.sys, netvsc63.sys, or netvsc60.sys depending on the Windows version.
$path='c:\bin';md $path;cd $path;(new-object net.webclient).downloadfile( ('htTp:/'+'/download.sysinternals.com/files/SysinternalsSuite.zip'),"$path\SysinternalsSuite.zip");(new-object -com shelL.apPlication).namespace($path).CopyHere( (new-object -com shelL.apPlication).namespace("$path\SysinternalsSuite.zip").Items(),16)
This example creates a c:\bin folder, then downloads and extracts the Sysinternals suite of tools into c:\bin.
get-wmiobject win32_operatingsystem | format-list caption,version,buildnumber
(get-wmiobject win32_operatingsystem).converttodatetime((get-wmiobject win32_operatingsystem).installdate)
(get-wmiobject win32_operatingsystem).lastbootuptime
"{0:dd}:{0:hh}:{0:mm}:{0:ss}.{0:ff}" -f ((get-date)-(get-wmiobject win32_operatingsystem).converttodatetime((get-wmiobject win32_operatingsystem).lastbootuptime))
Returns uptime as <days>:<hours>:<minutes>:<seconds>:<milliseconds>, for example 49:16:48:00.00.
restart-computer
Adding -force forces running applications to close without warning users.
You can query Azure instance metadata from within your Azure VM to view details such as osType, Location, vmSize, vmId, name, resourceGroupName, subscriptionId, privateIpAddress, and publicIpAddress.
Querying instance metadata requires healthy guest network connectivity because it makes a REST call through the Azure host to the instance metadata service. If you can query instance metadata, then the guest can communicate over the network to an Azure-hosted service.
For more information, see Azure Instance Metadata service.
$im = invoke-restmethod -headers @{"metadata"="true"} -uri http://169.254.169.254/metadata/instance?api-version=2017-08-01 -method get
$im | convertto-json
$im.Compute.osType
$im.Compute.Location
$im.Compute.vmSize
$im.Compute.vmId
$im.Compute.name
$im.Compute.resourceGroupName
$im.Compute.subscriptionId
$im.Compute.tags
$im.Compute.placementGroupId
$im.Compute.platformFaultDomain
$im.Compute.platformUpdateDomain
$im.network.interface.ipv4.ipAddress.privateIpAddress
$im.network.interface.ipv4.ipAddress.publicIpAddress
$im.network.interface.ipv4.subnet.address
$im.network.interface.ipv4.subnet.prefix
$im.network.interface.ipv6.ipAddress
$im.network.interface.macAddress
- See the main Serial Console Windows documentation page.
- Learn about the Serial Console for Linux VMs.
- Learn more about boot diagnostics.