PowerShell: Add and Remove a Registry Key

How to Add a Registry Key

# Add New Registry Key
$regHive='REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSCRM'
$keyname='OleDbTimeout'
$value=600
Set-ItemProperty -Path $regHive -Name $keyname -value $value

# Validation
Get-ItemProperty $regHive -name $keyname

PS C:\Users\backupadmin> Get-ItemProperty $regHive -name $keyname
OleDbTimeout : 600
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSCRM
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft
PSChildName  : MSCRM
PSProvider   : Microsoft.PowerShell.Core\Registry

How to Remove a Registry Key

# Remove Registry Key
$regHive='REGISTRY::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSCRM'
$keyname='OleDbTimeout'
Remove-ItemProperty -Path $regHive -Name $keyname -value $value

How to Repair Windows Corrupted System Files

Check for Corruptions

# Check for corrupted system files
Dism /Online /Cleanup-Image /ScanHealth

[TESTWINDOWS001]: PS C:\Users\backupadmin\Documents> Dism /Online /Cleanup-Image /ScanHealth

Deployment Image Servicing and Management tool
Version: 10.0.14393.4169
Image Version: 10.0.14393.4169
[==                         5.0%                           ]
---- and a long wait ----
[==========================100.0%==========================]
No component store corruption detected.
The operation completed successfully.

Perform Repairs

# Perform repairs
Dism /Online /Cleanup-Image /RestoreHealth

[TESTWINDOWS001]: PS C:\Users\backupadmin\Documents> Dism /Online /Cleanup-Image /RestoreHealth
Deployment Image Servicing and Management tool
Version: 10.0.14393.4169
Image Version: 10.0.14393.4169
[==                         4.5%                           ]
---- and a long wait ----
[==========================100.0%==========================]
The restore operation completed successfully.
The operation completed successfully.

Legacy Commands

# Legacy corrupted system files repair
SFC /scannow

# Sample output
[TESTWINDOWS001]: PS C:\Users\backupadmin\Documents> SFC /scannow

 B e g i n n i n g   s y s t e m   s c a n .     T h i s   p r o c e s s   w i l l   t a k e   s o m e   t i m e .

 B e g i n n i n g   v e r i f i c a t i o n   p h a s e   o f   s y s t e m   s c a n .

 V e r i f i c a t i o n   0 %   c o m p l e t e . V e r i f i c a t i o n   0 %   c o m p l e t e . V e r i f i c a t i o n   1 %   c o m p l e t e . V e r i f i c
t i o n   1 %   c o m p l e t e . V e r i f i c a t i o n   1 %   c o m p l e t e . V e r i f i c a t i o n   2 %   c o m p l e t e . V e r i f i c a t i o n   2 %
c o m p l e t e . V e r i f i c a t i o n   3 %   c o m p l e t e . V e r i f i c a t i o n   3 %   c o m p l e t e . V e r i f i c a t i o n   3 %   c o m p l e t e
. V e r i f i c a t i o n   4 %   c o m p l e t e . V e r i f i c a t i o n   4 %   c o m p l e t e . V e r i f i c a t i o n   4 %   c o m p l e t e . V e r i f i c
a t i o n   5 %   c o m p l e t e . V e r i f i c a t i o n   5 %   c o m p l e t e . V e r i f i c a t i o n   6 %   c o m p l e t e . V e r i f i c a t i o n   6 %
  c o m p l e t e . V e r i f i c a t i o n   6 %   c o m p l e t e . V e r i f i c a t i o n   7 %   c o m p l e t e . V e r i f i c a t i o n   7 %   c o m p l e t
e . V e r i f i c a t i o n   7 %   c o m p l e t e . V e r i f i c a t i o n   8 %   c o m p l e t e . V e r i f i c a t i o n   8 %   c o m p l e t e . V e r i f i
c a t i o n   9 %   c o m p l e t e . V e r i f i c a t i o n   9 %   c o m p l e t e . V e r i f i c a t i o n   9 %   c o m p l e t e . V e r i f i c a t i o n   1
0 %   c o m p l e t e . V e r i f i c a t i o n   1 0 %   c o m p l e t e . V e r i f i c a t i o n   1 0 %   c o m p l e t e . V e r i f i c a t i o n   1 1 %   c o
m p l e t e . V e r i f i c a t i o n   1 1 %   c o m p l e t e . V e r i f i c a t i o n   1 2 %   c o m p l e t e . V e r i f i c a t i o n   1 2 %   c o m p l e t
e . V e r i f i c a t i o n   1 2 %   c o m p l e t e . V e r i f i c a t i o n   1 3 %   c o m p l e t e . V e r i f i c a t i o n   1 3 %   c o m p l e t e . V e r
i f i c a t i o n   1 3 %   c o m p l e t e . V e r i f i c a t i o n   1 4 %   c o m p l e t e . V e r i f i c a t i o n   1 4 %   c o m p l e t e . V e r i f i c a
t i o n   1 5 %   c o m p l e t e . V e r i f i c a t i o n   1 5 %   c o m p l e t e . V e r i f i c a t i o n   1 5 %   c o m p l e t e . V e r i f i c a t i o n
1 6 %   c o m p l e t e . V e r i f i c a t i o n   1 6 %   c o m p l e t e . V e r i f i c a t i o n   1 6 %   c o m p l e t e . V e r i f i c a t i o n   1 7 %   c
o m p l e t e . V e r i f i c a t i o n   1 7 %   c o m p l e t e . V e r i f i c a t i o n   1 8 %   c o m p l e t e . V e r i f i c a t i o n   1 8 %   c o m p l e
t e . V e r i f i c a t i o n   1 8 %   c o m p l e t e . V e r i f i c a t i o n   1 9 %   c o m p l e t e . V e r i f i c a t i o n   1 9 %   c o m p l e t e . V e
r i f i c a t i o n   2 0 %   c o m p l e t e . V e r i f i c a t i o n   2 0 %   c o m p l e t e . V e r i f i c a t i o n   2 0 %   c o m p l e t e . V e r i f i c
a t i o n   2 1 %   c o m p l e t e . V e r i f i c a t i o n   2 1 %   c o m p l e t e . V e r i f i c a t i o n   2 1 %   c o m p l e t e . V e r i f i c a t i o n
  2 2 %   c o m p l e t e . V e r i f i c a t i o n   2 2 %   c o m p l e t e . V e r i f i c a t i o n   2 3 %   c o m p l e t e . V e r i f i c a t i o n   2 3 %
c o m p l e t e . V e r i f i c a t i o n   2 3 %   c o m p l e t e . V e r i f i c a t i o n   2 4 %   c o m p l e t e . V e r i f i c a t i o n   2 4 %   c o m p l
e t e . V e r i f i c a t i o n   2 4 %   c o m p l e t e . V e r i f i c a t i o n   2 5 %   c o m p l e t e . V e r i f i c a t i o n   2 5 %   c o m p l e t e . V
e r i f i c a t i o n   2 6 %   c o m p l e t e . V e r i f i c a t i o n   2 6 %   c o m p l e t e . V e r i f i c a t i o n   2 6 %   c o m p l e t e . V e r i f i
c a t i o n   2 7 %   c o m p l e t e . V e r i f i c a t i o n   2 7 %   c o m p l e t e . V e r i f i c a t i o n   2 7 %   c o m p l e t e . V e r i f i c a t i o
n   2 8 %   c o m p l e t e . V e r i f i c a t i o n   2 8 %   c o m p l e t e . V e r i f i c a t i o n   2 9 %   c o m p l e t e . V e r i f i c a t i o n   2 9 %
  c o m p l e t e . V e r i f i c a t i o n   2 9 %   c o m p l e t e . V e r i f i c a t i o n   3 0 %   c o m p l e t e . V e r i f i c a t i o n   3 0 %   c o m p
l e t e . V e r i f i c a t i o n   3 0 %   c o m p l e t e . V e r i f i c a t i o n   3 1 %   c o m p l e t e . V e r i f i c a t i o n   3 1 %   c o m p l e t e .
V e r i f i c a t i o n   3 2 %   c o m p l e t e . V e r i f i c a t i o n   3 2 %   c o m p l e t e . V e r i f i c a t i o n   3 2 %   c o m p l e t e . V e r i f
i c a t i o n   3 3 %   c o m p l e t e . V e r i f i c a t i o n   3 3 %   c o m p l e t e . V e r i f i c a t i o n   3 3 %   c o m p l e t e . V e r i f i c a t i
o n   3 4 %   c o m p l e t e . V e r i f i c a t i o n   3 4 %   c o m p l e t e . V e r i f i c a t i o n   3 5 %   c o m p l e t e . V e r i f i c a t i o n   3 5
%   c o m p l e t e . V e r i f i c a t i o n   3 5 %   c o m p l e t e . V e r i f i c a t i o n   3 6 %   c o m p l e t e . V e r i f i c a t i o n   3 6 %   c o m
p l e t e . V e r i f i c a t i o n   3 6 %   c o m p l e t e . V e r i f i c a t i o n   3 7 %   c o m p l e t e . V e r i f i c a t i o n   3 7 %   c o m p l e t e
. V e r i f i c a t i o n   3 8 %   c o m p l e t e . V e r i f i c a t i o n   3 8 %   c o m p l e t e . V e r i f i c a t i o n   3 8 %   c o m p l e t e . V e r i
f i c a t i o n   3 9 %   c o m p l e t e . V e r i f i c a t i o n   3 9 %   c o m p l e t e . V e r i f i c a t i o n   4 0 %   c o m p l e t e . V e r i f i c a t
i o n   4 0 %   c o m p l e t e . V e r i f i c a t i o n   4 0 %   c o m p l e t e . V e r i f i c a t i o n   4 1 %   c o m p l e t e . V e r i f i c a t i o n   4
1 %   c o m p l e t e . V e r i f i c a t i o n   4 1 %   c o m p l e t e . V e r i f i c a t i o n   4 2 %   c o m p l e t e . V e r i f i c a t i o n   4 2 %   c o
m p l e t e . V e r i f i c a t i o n   4 3 %   c o m p l e t e . V e r i f i c a t i o n   4 3 %   c o m p l e t e . V e r i f i c a t i o n   4 3 %   c o m p l e t
e . V e r i f i c a t i o n   4 4 %   c o m p l e t e . V e r i f i c a t i o n   4 4 %   c o m p l e t e . V e r i f i c a t i o n   4 4 %   c o m p l e t e . V e r
i f i c a t i o n   4 5 %   c o m p l e t e . V e r i f i c a t i o n   4 5 %   c o m p l e t e . V e r i f i c a t i o n   4 6 %   c o m p l e t e . V e r i f i c a
t i o n   4 6 %   c o m p l e t e . V e r i f i c a t i o n   4 6 %   c o m p l e t e . V e r i f i c a t i o n   4 7 %   c o m p l e t e . V e r i f i c a t i o n
4 7 %   c o m p l e t e . V e r i f i c a t i o n   4 7 %   c o m p l e t e . V e r i f i c a t i o n   4 8 %   c o m p l e t e . V e r i f i c a t i o n   4 8 %   c
o m p l e t e . V e r i f i c a t i o n   4 9 %   c o m p l e t e . V e r i f i c a t i o n   4 9 %   c o m p l e t e . V e r i f i c a t i o n   4 9 %   c o m p l e
t e . V e r i f i c a t i o n   5 0 %   c o m p l e t e . V e r i f i c a t i o n   5 0 %   c o m p l e t e . V e r i f i c a t i o n   5 0 %   c o m p l e t e . V e
r i f i c a t i o n   5 1 %   c o m p l e t e . V e r i f i c a t i o n   5 1 %   c o m p l e t e . V e r i f i c a t i o n   5 2 %   c o m p l e t e . V e r i f i c
a t i o n   5 2 %   c o m p l e t e . V e r i f i c a t i o n   5 2 %   c o m p l e t e . V e r i f i c a t i o n   5 3 %   c o m p l e t e . V e r i f i c a t i o n
  5 3 %   c o m p l e t e . V e r i f i c a t i o n   5 3 %   c o m p l e t e . V e r i f i c a t i o n   5 4 %   c o m p l e t e . V e r i f i c a t i o n   5 4 %
c o m p l e t e . V e r i f i c a t i o n   5 5 %   c o m p l e t e . V e r i f i c a t i o n   5 5 %   c o m p l e t e . V e r i f i c a t i o n   5 5 %   c o m p l
e t e . V e r i f i c a t i o n   5 6 %   c o m p l e t e . V e r i f i c a t i o n   5 6 %   c o m p l e t e . V e r i f i c a t i o n   5 6 %   c o m p l e t e . V
e r i f i c a t i o n   5 7 %   c o m p l e t e . V e r i f i c a t i o n   5 7 %   c o m p l e t e . V e r i f i c a t i o n   5 8 %   c o m p l e t e . V e r i f i
c a t i o n   5 8 %   c o m p l e t e . V e r i f i c a t i o n   5 8 %   c o m p l e t e . V e r i f i c a t i o n   5 9 %   c o m p l e t e . V e r i f i c a t i o
n   5 9 %   c o m p l e t e . V e r i f i c a t i o n   6 0 %   c o m p l e t e . V e r i f i c a t i o n   6 0 %   c o m p l e t e . V e r i f i c a t i o n   6 0 %
  c o m p l e t e . V e r i f i c a t i o n   6 1 %   c o m p l e t e . V e r i f i c a t i o n   6 1 %   c o m p l e t e . V e r i f i c a t i o n   6 1 %   c o m p
l e t e . V e r i f i c a t i o n   6 2 %   c o m p l e t e . V e r i f i c a t i o n   6 2 %   c o m p l e t e . V e r i f i c a t i o n   6 3 %   c o m p l e t e .
V e r i f i c a t i o n   6 3 %   c o m p l e t e . V e r i f i c a t i o n   6 3 %   c o m p l e t e . V e r i f i c a t i o n   6 4 %   c o m p l e t e . V e r i f
i c a t i o n   6 4 %   c o m p l e t e . V e r i f i c a t i o n   6 4 %   c o m p l e t e . V e r i f i c a t i o n   6 5 %   c o m p l e t e . V e r i f i c a t i
o n   6 5 %   c o m p l e t e . V e r i f i c a t i o n   6 6 %   c o m p l e t e . V e r i f i c a t i o n   6 6 %   c o m p l e t e . V e r i f i c a t i o n   6 6
%   c o m p l e t e . V e r i f i c a t i o n   6 7 %   c o m p l e t e . V e r i f i c a t i o n   6 7 %   c o m p l e t e . V e r i f i c a t i o n   6 7 %   c o m
p l e t e . V e r i f i c a t i o n   6 8 %   c o m p l e t e . V e r i f i c a t i o n   6 8 %   c o m p l e t e . V e r i f i c a t i o n   6 9 %   c o m p l e t e
. V e r i f i c a t i o n   6 9 %   c o m p l e t e . V e r i f i c a t i o n   6 9 %   c o m p l e t e . V e r i f i c a t i o n   7 0 %   c o m p l e t e . V e r i
f i c a t i o n   7 0 %   c o m p l e t e . V e r i f i c a t i o n   7 0 %   c o m p l e t e . V e r i f i c a t i o n   7 1 %   c o m p l e t e . V e r i f i c a t
i o n   7 1 %   c o m p l e t e . V e r i f i c a t i o n   7 2 %   c o m p l e t e . V e r i f i c a t i o n   7 2 %   c o m p l e t e . V e r i f i c a t i o n   7
2 %   c o m p l e t e . V e r i f i c a t i o n   7 3 %   c o m p l e t e . V e r i f i c a t i o n   7 3 %   c o m p l e t e . V e r i f i c a t i o n   7 3 %   c o
m p l e t e . V e r i f i c a t i o n   7 4 %   c o m p l e t e . V e r i f i c a t i o n   7 4 %   c o m p l e t e . V e r i f i c a t i o n   7 5 %   c o m p l e t
e . V e r i f i c a t i o n   7 5 %   c o m p l e t e . V e r i f i c a t i o n   7 5 %   c o m p l e t e . V e r i f i c a t i o n   7 6 %   c o m p l e t e . V e r
i f i c a t i o n   7 6 %   c o m p l e t e . V e r i f i c a t i o n   7 7 %   c o m p l e t e . V e r i f i c a t i o n   7 7 %   c o m p l e t e . V e r i f i c a
t i o n   7 7 %   c o m p l e t e . V e r i f i c a t i o n   7 8 %   c o m p l e t e . V e r i f i c a t i o n   7 8 %   c o m p l e t e . V e r i f i c a t i o n
7 8 %   c o m p l e t e . V e r i f i c a t i o n   7 9 %   c o m p l e t e . V e r i f i c a t i o n   7 9 %   c o m p l e t e . V e r i f i c a t i o n   8 0 %   c
o m p l e t e . V e r i f i c a t i o n   8 0 %   c o m p l e t e . V e r i f i c a t i o n   8 0 %   c o m p l e t e . V e r i f i c a t i o n   8 1 %   c o m p l e
t e . V e r i f i c a t i o n   8 1 %   c o m p l e t e . V e r i f i c a t i o n   8 1 %   c o m p l e t e . V e r i f i c a t i o n   8 2 %   c o m p l e t e . V e
r i f i c a t i o n   8 2 %   c o m p l e t e . V e r i f i c a t i o n   8 3 %   c o m p l e t e . V e r i f i c a t i o n   8 3 %   c o m p l e t e . V e r i f i c
a t i o n   8 3 %   c o m p l e t e . V e r i f i c a t i o n   8 4 %   c o m p l e t e . V e r i f i c a t i o n   8 4 %   c o m p l e t e . V e r i f i c a t i o n
  8 4 %   c o m p l e t e . V e r i f i c a t i o n   8 5 %   c o m p l e t e . V e r i f i c a t i o n   8 5 %   c o m p l e t e . V e r i f i c a t i o n   8 6 %
c o m p l e t e . V e r i f i c a t i o n   8 6 %   c o m p l e t e . V e r i f i c a t i o n   8 6 %   c o m p l e t e . V e r i f i c a t i o n   8 7 %   c o m p l
e t e . V e r i f i c a t i o n   8 7 %   c o m p l e t e . V e r i f i c a t i o n   8 7 %   c o m p l e t e . V e r i f i c a t i o n   8 8 %   c o m p l e t e . V
e r i f i c a t i o n   8 8 %   c o m p l e t e . V e r i f i c a t i o n   8 9 %   c o m p l e t e . V e r i f i c a t i o n   8 9 %   c o m p l e t e . V e r i f i
c a t i o n   8 9 %   c o m p l e t e . V e r i f i c a t i o n   9 0 %   c o m p l e t e . V e r i f i c a t i o n   9 0 %   c o m p l e t e . V e r i f i c a t i o
n   9 0 %   c o m p l e t e . V e r i f i c a t i o n   9 1 %   c o m p l e t e . V e r i f i c a t i o n   9 1 %   c o m p l e t e . V e r i f i c a t i o n   9 2 %
  c o m p l e t e . V e r i f i c a t i o n   9 2 %   c o m p l e t e . V e r i f i c a t i o n   9 2 %   c o m p l e t e . V e r i f i c a t i o n   9 3 %   c o m p
l e t e . V e r i f i c a t i o n   9 3 %   c o m p l e t e . V e r i f i c a t i o n   9 3 %   c o m p l e t e . V e r i f i c a t i o n   9 4 %   c o m p l e t e .
V e r i f i c a t i o n   9 4 %   c o m p l e t e . V e r i f i c a t i o n   9 5 %   c o m p l e t e . V e r i f i c a t i o n   9 5 %   c o m p l e t e . V e r i f
i c a t i o n   9 5 %   c o m p l e t e . V e r i f i c a t i o n   9 6 %   c o m p l e t e . V e r i f i c a t i o n   9 6 %   c o m p l e t e . V e r i f i c a t i
o n   9 7 %   c o m p l e t e . V e r i f i c a t i o n   9 7 %   c o m p l e t e . V e r i f i c a t i o n   9 7 %   c o m p l e t e . V e r i f i c a t i o n   9 8
%   c o m p l e t e . V e r i f i c a t i o n   9 8 %   c o m p l e t e . V e r i f i c a t i o n   9 8 %   c o m p l e t e . V e r i f i c a t i o n   9 9 %   c o m
p l e t e . V e r i f i c a t i o n   9 9 %   c o m p l e t e . V e r i f i c a t i o n   1 0 0 %   c o m p l e t e .


 W i n d o w s   R e s o u r c e   P r o t e c t i o n   d i d   n o t   f i n d   a n y   i n t e g r i t y   v i o l a t i o n s .

PowerShell: Set Service Startup Mode

# setServiceStartupMode.ps1

$computernames=@(
    'TESTWINDOWS001',
    'TESTWINDOWS002'
)
$servicename='TrustedInstaller'
$startupType='Automatic'

foreach ($computername in $computernames){
    Set-Service -computername $computername -Name $servicename -StartupType $startupType
    Get-Service -computername $computername -Name $servicename|start-service
}

Get-Service -computername $computernames -Name $servicename

PowerShell: Add Windows NTFS Permissions to File or Folder

The re-usable function:

$path='C:\Windows\servicing'
$accountsToAdd='Administrators'
$permissions='Full'

function addNtfsPermissions ($path,$accountsToAdd,$permissions){
  $acl = Get-ACL $path
  $accessRule=New-Object System.Security.AccessControl.FileSystemAccessRule($accountsToAdd,$permissions,"Allow")
  $acl.AddAccessRule($accessRule)
  Set-Acl $path $acl
  Get-ACL $path
}

addNtfsPermissions $path $accountsToAdd $permissions

Example:

The following is an output of fixing an issue related to ‘TrustedInstaller will not run. Windows Module Installer service missing’ errors.

$computernames=@(
  'TESTWINDOWS1',
  'TESTWINDOWS2'
  )

$path='C:\Windows\servicing'
$accountsToAdd='Administrators'
$permissions='Full'

function addNtfsPermissions ($path,$accountsToAdd,$permissions){
  $acl = Get-ACL $path
  $accessRule=New-Object System.Security.AccessControl.FileSystemAccessRule($accountsToAdd,$permissions,"Allow")
  $acl.AddAccessRule($accessRule)
  Set-Acl $path $acl
  Get-ACL $path
}

foreach($computername in $computernames){
  invoke-command -computername $computername -scriptblock{
    param($addNtfsPermissions,$path,$accountsToAdd,$permissions)
    write-host "Invoking function on $env:computername"
    [scriptblock]::create($addNtfsPermissions).invoke($path,$accountsToAdd,$permissions)
    start-service trustedinstaller
    get-service trustedinstaller
  } -ArgumentList ${function:addNtfsPermissions},$path,$accountsToAdd,$permissions
}
[TESTWINDOWS]: PS C:\Users\kimconnect\Documents> Get-ACL $localPath|select *

PSPath                  : Microsoft.PowerShell.Core\FileSystem::C:\Windows\servicing
PSParentPath            : Microsoft.PowerShell.Core\FileSystem::C:\Windows
PSChildName             : servicing
PSDrive                 : C
PSProvider              : Microsoft.PowerShell.Core\FileSystem
CentralAccessPolicyId   :
CentralAccessPolicyName :
Path                    : Microsoft.PowerShell.Core\FileSystem::C:\Windows\servicing
Owner                   : NT SERVICE\TrustedInstaller
Group                   : NT SERVICE\TrustedInstaller
Access                  : {System.Security.AccessControl.FileSystemAccessRule,
                          System.Security.AccessControl.FileSystemAccessRule,
                          System.Security.AccessControl.FileSystemAccessRule,
                          System.Security.AccessControl.FileSystemAccessRule...}
Sddl                    : O:S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464G:S-1-5-80-956008885-34185226
                          49-1831038044-1853292631-2271478464D:PAI(A;OICIIO;GXGR;;;SY)(A;;0x1200a9;;;SY)(A;;FA;;;BA)(A;
                          OICIIO;GXGR;;;BA)(A;OICIIO;GXGR;;;BU)(A;;0x1200a9;;;BU)(A;OICIIO;GA;;;S-1-5-80-956008885-3418
                          522649-1831038044-1853292631-2271478464)(A;;FA;;;S-1-5-80-956008885-3418522649-1831038044-185
                          3292631-2271478464)(A;;0x1200a9;;;AC)(A;OICIIO;GXGR;;;AC)(A;;0x1200a9;;;S-1-15-2-2)(A;OICIIO;
                          GXGR;;;S-1-15-2-2)
AccessToString          : NT AUTHORITY\SYSTEM Allow  -1610612736
                          NT AUTHORITY\SYSTEM Allow  ReadAndExecute, Synchronize
                          BUILTIN\Administrators Allow  FullControl
                          BUILTIN\Administrators Allow  -1610612736
                          BUILTIN\Users Allow  -1610612736
                          BUILTIN\Users Allow  ReadAndExecute, Synchronize
                          NT SERVICE\TrustedInstaller Allow  268435456
                          NT SERVICE\TrustedInstaller Allow  FullControl
                          APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Allow  ReadAndExecute, Synchronize
                          APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES Allow  -1610612736
                          APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES Allow  ReadAndExecute,
                          Synchronize
                          APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES Allow  -1610612736
AuditToString           :
AccessRightType         : System.Security.AccessControl.FileSystemRights
AccessRuleType          : System.Security.AccessControl.FileSystemAccessRule
AuditRuleType           : System.Security.AccessControl.FileSystemAuditRule
AreAccessRulesProtected : True
AreAuditRulesProtected  : False
AreAccessRulesCanonical : True
AreAuditRulesCanonical  : True

[TESTWINDOWS]: PS C:\Users\kimconnect\Documents> get-service trustedinstaller
Status   Name               DisplayName
------   ----               -----------
Stopped  trustedinstaller   Windows Modules Installer

[TESTWINDOWS]: PS C:\Users\kimconnect\Documents> get-service trustedinstaller|start-service
[TESTWINDOWS]: PS C:\Users\kimconnect\Documents> get-service trustedinstaller
Status   Name               DisplayName
------   ----               -----------
Running  trustedinstaller   Windows Modules Installer

PS C:\Windows\system32> get-service -Name trustedinstaller -ComputerName $computernames|start-service

PS C:\Windows\system32> get-service -Name trustedinstaller -ComputerName $computernames|select MachineName,ServiceName,S
tartType,Status

MachineName     ServiceName      StartType  Status
-----------     -----------      ---------  ------
TESTWINDOWS0001 trustedinstaller    Manual Running
TESTWINDOWS0002 trustedinstaller    Manual Running

Search for Windows computers in a certain subnet using Active Directory

# Search for Windows computers in a certain subnet using Active Directory
$subnetQuery='10.10'
$filterString='2016'
$computers=Get-ADComputer -Filter "enabled -eq 'true' -and OperatingSystem -like '*$filterString*'"`
-Properties Name,Operatingsystem,OperatingSystemVersion,IPv4Address |
Sort-Object -Property Operatingsystem | Select-Object -Property Name,Operatingsystem,OperatingSystemVersion,IPv4Address
$results=$computers|?{$_.IPv4Address|?{[string]$_ -like "*$subnetQuery*"}}
write-host "$($results.count) computer(s) have been matched.`r`n$results"
# Sample output
Name            Operatingsystem              OperatingSystemVersion IPv4Address
----            ---------------              ---------------------- -----------
SERVER-NAME-001 Windows Server 2016 Standard 10.0 (14393)           10.10.120.9
SERVER-NAME-002 Windows Server 2016 Standard 10.0 (14393)           10.10.120.10
------ Results truncated ---------

How To Stop, Start, Restart a Windows Service Being Stuck in ‘Stopping’ Status

Convenient Function:

function restartService($serviceName){
    $waitSeconds=40
    $isValidProcess=try{[bool](get-service $serviceName -EA Stop)}catch{$false}
    if($isValidProcess){
        try{
            $process=Start-Process -FilePath powershell.exe -ArgumentList "-Command Restart-Service $serviceName" -PassThru -NoNewWindow
            $process|Wait-Process -Timeout $waitSeconds -ErrorAction Stop
            return $true
        }catch{
            write-warning $_
            $process|Stop-Process -Force
            $processId=(get-process $serviceName).Id
            if($processId){
                write-host "Program now forcefully kills PID $processId of process $serviceName"
                $null=$processId|%{taskkill /f /pid $_} # works more reliably than Stop-Process $processName -Force
                Start-Service $serviceName -ErrorAction Ignore
                $started=$(try{get-service $serviceName}catch{$false})
                if($started){
                    write-host "'serviceName' status is now $($started.Status)"
                    return $true
                }else{
                    write-warning "'serviceName' status is $($started.Status)"
                    return $false
                }
            }else{
                write-warning "Service '$serviceName' PID not found."
                return $false         
            }
        }
    }
}
 
restartService vmms
Symptom:
# Example error of Hyper-V Virtual Machine Management Service
Service 'Hyper-V Virtual Machine Management (vmms)' cannot be stopped due to the following error: Cannot stop vmms
service on computer '.'.
+ CategoryInfo : CloseError: (System.ServiceProcess.ServiceController:ServiceController) [Restart-Service], ServiceCommandException
+ FullyQualifiedErrorId : CouldNotStopService,Microsoft.PowerShell.Commands.RestartServiceCommand
+ PSComputerName : HYPERV05
Resolution:
# Kill the process id prior to attempting to start the service
$serviceName='vmms'
$processId=(get-process $serviceName).Id
$null=taskkill /f /pid $processId
Start-Service $serviceName
PS C:\Windows\system32> taskkill /f /pid $processId
SUCCESS: The process with PID 21404 has been terminated.
PS C:\Windows\system32> restart-service vmms
WARNING: Waiting for service 'Hyper-V Virtual Machine Management (vmms)' to stop...
WARNING: Waiting for service 'Hyper-V Virtual Machine Management (vmms)' to stop...
WARNING: Waiting for service 'Hyper-V Virtual Machine Management (vmms)' to stop...
WARNING: Waiting for service 'Hyper-V Virtual Machine Management (vmms)' to stop...
WARNING: Waiting for service 'Hyper-V Virtual Machine Management (vmms)' to stop...

PowerShell: Copy Active Directory User

# copyADUser.ps1
# Version 0.01

$fromUsername='mTyson'
$newUserFirstname='Bruce'
$newUserLastname='Lee'
$newPassword='SOMEPASSWORD'
$newEmailAddress='bruce.lee@kimconnect.com'
$setProxyAddress=$false

function copyADUser{
  param(
    $fromUsername,
    $newUserFirstname,
    $newUserLastname,
    $newPassword,
    $newEmailAddress,
    $setProxyAddress=$false
  )
  try{
    Import-Module activedirectory
  }catch{
    write-warning $_
    return $false
  }
  $availableUserName=.{
    $index=0
    $x=($newUserFirstname.toLower())[$index]+$newUserLastname.tolower()
    do{
      $usernameExists=try{$null=get-aduser $x;$true}catch{$false}
      if($usernameExists){
        $index+=1
        $x=(($newUserFirstname.toLower())[0..$index] -join '')+$newUserLastname.tolower()
      }else{
        return $x
      }
    }until(!$usernameExists -or $newUserFirstname.length+$newUserLastname.length -eq $x.length)
    $number=1
    $x=($newUserFirstname.toLower())[$index]+$newUserLastname.tolower()
    do{
      $y=$x+"$number"
      $usernameExists=try{$null=get-aduser $y;$true}catch{$false}
      if($usernameExists){
        $number+=1
        $y=$x+"$number"
      }else{
        return $y
      }      
    }until($number -ge 10000)
    return $null
  }
  if(!$availableUserName){
    write-warning "Unable to proceed due to username being NOT available."
    return $false
  }
  function copyGroupMemberships($fromIdentity,$toIdentity){
    $ErrorActionPreference='stop'
    try{
      Import-module activedirectory
      $groupNames=(Get-ADPrincipalGroupMembership $fromIdentity).Name
      $groupNames|%{try{Add-ADGroupMember -Identity "$_" -Members $toIdentity -ea SilentlyContinue}catch{}}
      $currentMemberships=(Get-ADPrincipalGroupMembership $toIdentity).Name
      write-host "User '$env:USERDOMAIN\$toIdentity' now has these memberships:`r`n---------------------------------`r`n$($currentMemberships|out-string)"
      return $true
    }catch{
      write-warning $_
      return $false
    }
  }

  $fullName=$newUserFirstname+' '+$newUserLastname
  $newPrinciplename=$availableUserName+'@'+$env:USERDNSDOMAIN
  $securedPass=(ConvertTo-SecureString $newPassword -AsPlainText -Force)
  write-host "Creating UserID '$availableUserName' with full name of '$fullname', and setting the password of '$newPassword'"
  try{
    $copyAttributes=Get-ADUser -Identity $fromUsername -Properties StreetAddress,City,Title,PostalCode,Office,Department,Manager
    $targetOu=.{
      $x=((Get-aduser $fromUsername).DistinguishedName -split ',')
      return $x[1..$x.length] -join ','
    }
    New-ADUser -SAMAccountName $availableUserName -Name $fullName -GivenName $newUserFirstname -Surname $newUserLastname -Instance $copyAttributes -DisplayName $fullName -UserPrincipalName $newPrincipleName -AccountPassword $securedPass -ChangePasswordAtLogon $false -Enabled $true
    Set-ADUser -Identity $availableUserName -EmailAddress $newEmailAddress
    if($setProxyAddress){
      Set-ADUser -Identity $availableUserName -Add @{proxyAddresses="SMTP:$newEmailAddress";proxyAddressesForGapps="SMTP:$newEmailAddress"}
    }

    # This error would occur if UserPrincipleName is not specified or having conflicts
    # New-ADUser : The operation failed because UPN value provided for addition/modification is not unique forest-wide
    # At line:1 char:5
    # +     New-ADUser -Name $fullName -GivenName $newUserFirstname -Surname  ...
    # +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #     + CategoryInfo          : NotSpecified: (CN=Bruce Lee...DC=kimconnect,DC=com:String) [New-ADUser], ADException
    #     + FullyQualifiedErrorId : ActiveDirectoryServer:8648,Microsoft.ActiveDirectory.Management.Commands.NewADUser

    $currentIdentity=(Get-aduser $availableUserName).DistinguishedName
    Move-ADObject -Identity $currentIdentity -TargetPath $targetOu
    copyGroupMemberships $fromUsername $availableUserName
    return $true
  }catch{
    write-warning $_
    return $false
  }
}

copyADUser $fromUsername `
  $newUserFirstname `
  $newUserLastname `
  $newPassword `
  $newEmailAddress `
  $setProxyAddress

PowerShell: Quickly Add Users into Groups on a List of Computers

$newVmNames=@(
    'SERVER0001', 
    'SERVER0002'
)
$newUsers=@(
    'domain\user1'
)
$groupNames='Administrators','Remote Desktop Users'

$newVmNames|%{
    invoke-command -computername $_ {
        param($newUsers,$groupNames)
        try{            
            $groupNames|%{
                Add-LocalGroupMember -Group $_ -Member $newUsers
                write-host "$env:computername`: Group name '$groupName' now has these users`r`n$(get-localgroupmember $groupName)"
            }
        }catch{
            write-warning $_
        }        
    } -ArgumentList $newUsers,$groupNames
}

How To Disable Startup Automatic Repair

Problem:

Sometimes, a certain virtual machine would not boot correctly when it’s being moved between Hyper-V hosts. An error such as this would result

Resolution:

Addressing the root cause of unplanned reboots is beyond the scope of this blog. The following command would ensure that those guest VMs would not load automatic repair upon abrupt shutdowns.

write-host "Disabling Automatic Startup Repair..."
$null=cmd.exe /c "bcdedit /set {default} recoveryenabled No"
$null=cmd.exe /c "bcdedit /set {default} bootstatuspolicy ignoreallfailures"
 
Note: command cannot be invoked in PowerShell directly; hence the cmd.exe call is necessary

PowerShell: How To Disable and/or Stop Windows Service

Disable and Stop Using Native Command ‘Set-Service’

# To disable service as well as stopping it, assuming that the service does not have dependencies
$serviceName='windows_exporter'
$computernames=@('SERVER02','SERVER03')
$setStatus='stopped'
$setStartup='disabled'

Set-Service -Name $serviceName -Status $setStatus -StartupType $setStartup -computername $computernames

# Possible error: this means the service cannot be disabled without disabling its upstream parent services
Set-Service : Cannot stop service 'windows_exporter (windows_exporter)' because it is dependent on other services.
At line:1 char:1
+ Set-Service -Name $serviceName -Status stopped -StartupType disabled  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.ServiceProcess.ServiceController:ServiceController) [Set-Service], ServiceCommandException
    + FullyQualifiedErrorId : ServiceIsDependentOnNoForce,Microsoft.PowerShell.Commands.SetServiceCommand

Using SC

$computernames=@('SERVER01','SERVER02')
$serviceName='windows_exporter'
$action='start' # or stop

function setService{
    param(
        $computernames=$env:computername,
        $serviceName='RemoteRegistry',
        $action='start' # or stop
    )
    $computernames|%{Start-Process "$env:WINDIR\system32\sc.exe" \\$_,start,$serviceName -NoNewWindow -Wait}
}

setService $computerNames $serviceName $action
# To simply stop or start a service using the legacy tool SC.EXE on a list of servers
$computerNames=$env:computername
$serviceName='windows_exporter'
$action='start' # or stop
$computernames|%{Start-Process "$env:WINDIR\system32\sc.exe" \\$_,$action,$serviceName -NoNewWindow -Wait}

# Note: The native stop-service Powershell command does not have a computername parameter; Hence, the native command above is used as a workaround
Stop-Service : A parameter cannot be found that matches parameter name 'computername'.
At line:1 char:14
+ stop-service -computername $computernames -name $servicename -force
+              ~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Stop-Service], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.StopServiceCommand
# Sample output
SERVICE_NAME: windows_exporter
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 3  STOP_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

Verify

PS C:\Users\administrator> get-service windows_exporter -computername $computernames|select MachineName,Name,Status

MachineName   Name              Status
-----------   ----              ------
dev01 windows_exporter Stopped
dev02  windows_exporter Stopped
dev03   windows_exporter Stopped
dev04   windows_exporter Stopped

How To Create a Virtual Machine Administrator Role in SCVMM

Update: A new write-up has been posted with screenshots here.

Virtual Machine Manager (VMM) 2019 includes a new role, ‘VM administrator.’ This RBAC provides just enough permissions for read-only visibility into the fabric of the data center, but prevents escalation of privilege to fabric administration. (Source: Microsoft)

To create an RBAC role for VM administrator, go to Settings > User Roles > Create User Role > type in the name as ‘Virtual Machine Administrator’ > Next > select ‘Virtual Machine Administrator’ > Next > click Add > select Active Directory Users or Groups > OK > Next > narrow down the scope (e.g. ‘All Hosts’) > Next > put a check mark to each desired permissions (as listed below) > Next > Add Library Servers > Next > Add ‘Run As Accounts’ > Next > Finish

Virtual Machine Administrator Permissions:
- Migrate virtual machine (recommended)
- Migrate VM Storage (recommended)
- Pause and resume (recommended)
- Receive
- Remote connection
- Remove
- Save
- Share
- Shutdown (recommended)
- Start (recommended)
- Stop (recommended)
- Store and re-deploy
- Update VM functional level (recommended)

PowerShell: Technique to Pass Array Variable as Argument

Problem:

The subtle difference between invoke-command -scriptblock {} -Args vs -ArgumentList is elusive enough to waste a coder’s time trying to understand why a forced casting of an Array type variable doesn’t behave as expected. Here’s an illustration for Google searchers who has stumbled upon this puzzle.

The Correct Method of Passing Array into Invoke-Command

$accountsToAdd='intranet\user1','intranet\user2'
$localgroup='Remote Desktop Users'

# Check on whether certain accounts exist in a local group
invoke-command -scriptblock{
            param($principleNames,$groupName)
            $results=@()
            $currentMembers=try{
                (get-localgroupmember $groupName -ea stop).Name
            }catch{
                $x=net localgroup $groupName
                $x[6..$($x.length-3)]
            }
            write-host "Current members of $groupName`:`r`n$($currentMembers|out-string)"
            foreach($principle in $principleNames){
                $results+=[pscustomobject]@{
                    computername=$env:computername
                    groupname=$groupName
                    userName=$principle
                    usernameIsMember=[bool]($principle -in $currentMembers)
                }
            }
            return $results
        } -ArgumentList $accountsToAdd,$localGroup

The Incorrect Method of Passing Array into Invoke-Command

$accountsToAdd='intranet\user1','intranet\user2'
$localgroup='Remote Desktop Users'

# Check on whether certain accounts exist in a local group
invoke-command -scriptblock{
            param($principleNames,$groupName)
            $results=@()
            $currentMembers=try{
                (get-localgroupmember $groupName -ea stop).Name
            }catch{
                $x=net localgroup $groupName
                $x[6..$($x.length-3)]
            }
            write-host "Current members of $groupName`:`r`n$($currentMembers|out-string)"
            foreach($principle in $principleNames){
                $results+=[pscustomobject]@{
                    computername=$env:computername
                    groupname=$groupName
                    userName=$principle
                    usernameIsMember=[bool]($principle -in $currentMembers)
                }
            }
            return $results
        } -Args (,$accountsToAdd),$localGroup
# Sample Output:

WARNING: Cannot convert 'intranet\user1 intranet\user2' to the type 'Microsoft.PowerShell.Commands.LocalPrincipal' required by parameter 'Member'. Specified method is not supported.
Failed to compare two elements in the array.

PowerShell: Check IP Conflicts of Computers in Active Directory

We have ran into issues where a group of virtual machines living on a DHCP subnet get rebooted due unexpected events. Upon restarting, those machines would receive IP assignments from the DHCP server. In an ideal environment where Admins follow the strict procedure of creating IP reservations for each VM, using its MAC Address, everything would work fine. However, in the real world, human errors caused by skipping the IP Reservation steps would lead to instances where a DHCP server would assign duplicated IP addresses to certain machines. This is even more evidenced when IPs have already been set as static on machines that are in scope of DHCP. In such scenarios, IP conflicts would ensue. As many Windows machines are Active Directory & DNS integrated, erroneous a-records and reverse lookup results would also be incorrect. Here’s a quick script to detect those anomalies on a short list of known machine. Future versions would enable the program to scan a whole subnet to gather these machine names automatically. Until then…

$computernames=@(
    'server001',
    'server002',
    'server003'
)

function checkIpConflicts($computerNames){
  $results=@()
  foreach ($computer in $computernames){
    $ipAddress=[System.Net.Dns]::GetHostAddresses($computer)
    $ipReverseLookup=[System.Net.Dns]::GetHostEntry($ipAddress).HostName
    $isMismatched=$computer.split('.')[0] -ne $ipReverseLookup.split('.')[0]
    $dnsRecordMac=if($isMismatched){
      try{
        (Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter "IPEnabled='True'" -ComputerName $ipReverseLookup -EA Stop).MacAddress
      }catch{
        write-warning $_
        'ConnectionError'
      }
      }else{'N/A'}
    $results+=[pscustomobject]@{
      computerName=$computer
      ipAddress=$ipAddress
      ipReverseLookup=$ipReverseLookup
      macAddress=(Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter "IPEnabled='True'" -ComputerName $computer).MacAddress
      isMismatched=$isMismatched
      dnsRecordMac=$dnsRecordMac
    }
  }
  return $results
}

checkIpConflicts $computerNames
Sample Output:

computerName    ipAddress       ipReverseLookup                macAddress                             isMismatched dnsRecordMac
------------    ---------       ---------------                ----------                             ------------ ------------
server00001   {x.x.x.x}  server00008        00:15:5D:xx:xx:xx                              True ConnectionError
server00002      {x.x.x.x} server00002.kimconnect.com      00:0C:29:xx:xx:xx                             False N/A

How to Obtain Mac Address of Remote Computer

# PowerShell
$computername='TESTSERVER'
Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter "IPEnabled='True'" -ComputerName $computername|Select-Object -Property MACAddress, Description

# Sample output:
MACAddress        Description
----------        -----------
BC:30:5B:XX:XX:XX Intel(R) Ethernet 10G 4P X540/I350 rNDC #2
# Command-line (can also be invoked in PowerShell)
getmac.exe /s COMPUTERNAMEHERE

# Sample output:
PS C:\Windows\system32> getmac.exe /s TESTSERVER01

Physical Address    Transport Name
=================== ==========================================================
BC-30-5B-F8-XX-XX   Media disconnected
BC-30-5B-F8-XX-XX   Media disconnected
BC-30-5B-F8-XX-XX   Media disconnected
BC-30-5B-F8-XX-XX   \Device\Tcpip_{XXXXXXXX-7399-4307-87BA-XXXXXXXX}

IpConfig Shows Static IP Address Status as Duplicate

Just the other night, I’d received a call from the guys about NetApps changes affecting virtual machines in Hyper-V that has caused automatic migrations to be triggered. There was a lot of confusions, and our Hyper-V clusters had proven to be be mostly resilient. Most guest virtual machines (VMs) were back online after 10 minutes of confusion. However, there were some that still showed as unreachable by Nagios. I’d manually consoled into each VM to fix them. Generally there were two main issues causing machines to remain offline:

  1. Windows 7 blue screens
  2. Windows 7 automatic repair wizard causing reboots to become stuck
  3. Windows 10 machines with static IP addresses shown as duplicate due to a conflict with another machine on the network. Per protocol, the NIC would render itself as offline if it detect IP conflicts. In my case, I’ve traced the collisions and forcefully set 1 machine to be authoritative toward its assigned IP. Here is the command to reset the ARP count so that it will refresh the ARP table and not mark that IP address as a duplicate.
    Set-ItemProperty "REGISTRY::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -name "ARPRetryCount" -value 1; restart-computer

PowerShell: Set PasswordNeverExpires on SamAccountName

Quick 1-liner Code

$accounts=@(
    'orange',
    'apple',
    'pear',
    'dog',
    'cat',
    'dinosaur',
    'chicken',
    'cow',
    'yomama',
    'yodada'
)
$accounts|%{try{Set-ADUser -Identity $_ -PasswordNeverExpires $false;write-host "$_ : done"}catch{write-warning "$_ : error"}}

Result:

'orange': done
'apple': done
'pear': done
'dog': done
'cat': done
'dinosaur': done
'chicken': done
'cow': done
'yomama': done
'yodada': done

A Short List of Windows Remote Desktop Server Error Messages

Log Messages:

'Failed GetConnectionProperty' in CUMRDPConnection::QueryProperty at 2884 err=[0x80004001]
'Connection doesn't support logon error redirector' in CUMRDPConnection::GetLogonErrorRedirector at 4179 err=[0x80004001]
Disconnect trace:CUMRDPConnection Disconnect trace:'calling spGfxPlugin->PreDisconnect()' in CUMRDPConnection::PreDisconnect at 4595 err=[0xc], Error code:0xC

Assumption and proposed solution:

Issue occurs when Windows 10 1809 clients connect to Server 2019. Windows 10 1803 or older are not having this problem. Here’s an item to test on the server.

$tsServerClientRegKey="REGISTRY::HKLM\SOFTWARE\Microsoft\Terminal Server Client"
$keyName='UseURCP'
$value=0
Set-ItemProperty $tsServerClientRegKey -name $keyName -value $value

———————-
Log messages:

TCP socket READ operation failed, error 64
TCP socket WRITE operation failed, error 64

There appears to be a threshold on Windows to limit the number of connections. Client OS would be 100, and server OS as 3000 by default. Here’s how to set this to a maximum value.

$tsServerRegKey="REGISTRY::HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server"
$keyName='MaxOutstandingConnections'
$value=65536
Set-ItemProperty $tsServerRegKey -name $keyName -value $value

———————-

Event viewer messages:

RDP_TCP: An error was encountered when transitioning from StateUnknown in response to Event_Disconnect (error code 0x80070040).
RDP_SEC: An error was encountered when transitioning from FStatePassthrough in response to FEventCheckAndCompleteReadsFailed (error code 0x8007139F).
# Proposed solution
$tsServerClientRegKey="REGISTRY::HKLM\SOFTWARE\Microsoft\Terminal Server Client"
$keyName='RDGClientTransport'
$value=1
Set-ItemProperty $tsServerClientRegKey -name $keyName -value $value

————————

Event message:

The network characteristics detection function has been disabled because of Reason Code: 2(Server Configuration)..

Comment: this message appears to be expressing proper English. Although, I don’t know what to do with it.

————————

Event message:

The RDP display control module failed to change the session monitor layout. The operation failed with error code 0xFFFFFFFF.
onecoreuap\shell\roaming\settingsynccore\settingsyncreporting\settingsyncreporting.cpp(28)\SettingSyncCore.dll!00007FFC12C03D2A: (caller: 00007FFC2E177456) ReturnHr(3) tid(1060) 800708CA This network connection does not exist.
Restoring operations failed (Result: 0x800708CA).

Comment: I’m also unsure about any interpretation of the error above. Although, this correlates to a Windows 2019 Server with RDS role enabled. This machine is behind strict network zones (HIPPA). Clients often using Windows 10 to RDP-access this ‘bastion’ host.

————————

TerminalServices-ClientActiveXCore messages:

RDPClient_SSL: An error was encountered when transitioning from TsSslStateHandshakeInProgress to TsSslStateDisconnecting in response to TsSslEventHandshakeContinueFailed (error code 0x80004005).
RDPClient_SSL: An error was encountered when transitioning from TsSslStateDisconnected to TsSslStateDisconnected in response to TsSslEventInvalidState (error code 0x8000FFFF).

A possible workaround is to change the display setting on the .rdp to a lower display resolution setting (e.g. 1280×1024). This happens when client machine’s resolution is 2560 x 1440 and the [virtual] video card in the host machine isn’t as capable. Another idea is to peruse the Windows 10 Remote Desktop UWP app.

———————-

Event messages:

Failed to establish a network connection.
Error: The transport connection attempt was refused by the remote system.
Server name: dc02.kimconnect.ad
Server address: x.x.x.x:445
Instance name: \Device\LanmanRedirector
Connection type: Wsk
Guidance:
This indicates a problem with the underlying network or transport, such as with TCP/IP, and not with SMB. A firewall that blocks TCP port 445, or TCP port 5445 when using an iWARP RDMA adapter, can also cause this issue.
The server name cannot be resolved.
Error: The object was not found.
Server name: server006.intranet.kimconnect.ad
Guidance:
The client cannot resolve the server address in DNS or WINS. This issue often manifests immediately after joining a computer to the domain, when the client's DNS registration may not yet have propagated to all DNS servers. You should also expect this event at system startup on a DNS server (such as a domain controller) that points to itself for the primary DNS. You should validate the DNS client settings on this computer using IPCONFIG /ALL and NSLOOKUP.

Comment: pre-pending a username with DOMAIN\username would work when encountering these errors.

———————-

Error messages:

"Because of a protocol error (code: 0x112f), the remote session will be disconnected. Please try connecting to the remote computer again."
# Configure RemoteFX: Computer Configuration > Policies > Administrative Templates > Windows Components > Remote Desktop Services > Remote Desktop Session Host > Remote Session Environment > set RemoteFX to 0

# 1-liner command to execute task above
set-itemproperty "REGISTRY::HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations" -name 'fEnableRemoteFXAdvancedRemoteApp' -value 0

—————————-

Complain: Remote Desktop Session Does Not Show Login Prompt, and session would disconnect after 2 seconds…

Comment: Some Internet sources have alluded to CredSSP being the culprit. I have not yet tested setting CredSSP value to TRUE yet. On the same note, I’m guessing the issue would be more related to RemoteFX, rather than authentication. Will update this note once I gather more info. 

get-item "WSMan:\$env:computername\service\auth\credSSP"
WSManConfig: Microsoft.WSMan.Management\WSMan::winbastionhip04\Service\Auth

Type Name SourceOfValue Value
---- ---- ------------- -----
System.String CredSSP false

Update: issue seems to be related to the default MSTSC remote desktop client on Windows 10 machines. It’s a hit or miss workaround to configure MSTSC to reduce resolution and disable bitmap caching. Hence, a better hack is to use Microsoft’s newer RDP client here: https:// www.microsoft.com/en-us/p/microsoft-remote-desktop/9wzdncrfj3ps

——————

Log messages:

Automatic registration failed at join phase. 
Exit code: Unknown HResult Error code: 0x801c001d
Server error:
Tenant type: undefined
Registration type: undefined
Debug Output:
joinMode: Join
drsInstance: undefined
registrationType: undefined
tenantType: undefined
tenantId: undefined
configLocation: undefined
errorPhase: discover
adalCorrelationId: undefined
adalLog:
undefined
adalResponseCode: 0x0
Automatic registration failed. Failed to lookup the registration service information from Active Directory. Exit code: Unknown HResult Error code: 0x801c001d. See http://go.microsoft.com/fwlink/?LinkId=623042
Log Name: Microsoft-Windows-Security-Mitigations/KernelMode
Source: Microsoft-Windows-Security-Mitigations
Date: 3/4/2021 12:42:13 AM
Event ID: 1
Task Category: (1)
Level: Information
Keywords:
User:
Computer:
Description:
Process '\Device\HarddiskVolume4\Windows\System32\svchost.exe' (PID 33640) would have been blocked from generating dynamic code.
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-Security-Mitigations" Guid="{fae10392-f0af-4ac0-b8ff-9f4d920c3cdf}" />
<EventID>1</EventID>
<Version>0</Version>
<Level>0</Level>
<Task>1</Task>
<Opcode>0</Opcode>
<Keywords>0x8000000000000000</Keywords>
<TimeCreated SystemTime="2021-03-04T08:42:13.232916800Z" />
<EventRecordID>1266946</EventRecordID>
<Correlation />
<Execution ProcessID="33640" ThreadID="30788" />
<Channel>Microsoft-Windows-Security-Mitigations/KernelMode</Channel>
<Computer></Computer>
<Security UserID="S-1-5-21-2195821719-3162908599-1472692150-15697" />
</System>
<EventData>
<Data Name="ProcessPathLength">52</Data>
<Data Name="ProcessPath">\Device\HarddiskVolume4\Windows\System32\svchost.exe</Data>
<Data Name="ProcessCommandLineLength">55</Data>
<Data Name="ProcessCommandLine">C:\Windows\system32\svchost.exe -k wsappx -p -s AppXSvc</Data>
<Data Name="CallingProcessId">33640</Data>
<Data Name="CallingProcessCreateTime">2021-03-04T08:40:49.427147800Z</Data>
<Data Name="CallingProcessStartKey">13792273859390411</Data>
<Data Name="CallingProcessSignatureLevel">60</Data>
<Data Name="CallingProcessSectionSignatureLevel">12</Data>
<Data Name="CallingProcessProtection">81</Data>
<Data Name="CallingThreadId">30788</Data>
<Data Name="CallingThreadCreateTime">2021-03-04T08:40:50.984756900Z</Data>
</EventData>
</Event>
Log Name: Microsoft-Windows-User Device Registration/Admin
Source: Microsoft-Windows-User Device Registration
Date: 11/1/2021 10:44:22 PM
Event ID: 360
Task Category: None
Level: Warning
Keywords:
User:
Computer:
Description:
Windows Hello for Business provisioning will not be launched.
Device is AAD joined ( AADJ or DJ++ ): Not Tested
User has logged on with AAD credentials: Not Tested
Windows Hello for Business policy is enabled: Not Tested
Windows Hello for Business post-logon provisioning is enabled: Not Tested
Local computer meets Windows hello for business hardware requirements: Not Tested
User is not connected to the machine via Remote Desktop: No
User certificate for on premise auth policy is enabled: Not Tested
Machine is governed by none policy.
See https://go.microsoft.com/fwlink/?linkid=832647 for more details.
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<Provider Name="Microsoft-Windows-User Device Registration" Guid="{23b8d46b-67dd-40a3-b636-d43e50552c6d}" />
<EventID>360</EventID>
<Version>0</Version>
<Level>3</Level>
<Task>0</Task>
<Opcode>0</Opcode>
<Keywords>0x8000000000000000</Keywords>
<TimeCreated SystemTime="2021-11-02T05:44:22.442956600Z" />
<EventRecordID>2994</EventRecordID>
<Correlation />
<Execution ProcessID="12332" ThreadID="16156" />
<Channel>Microsoft-Windows-User Device Registration/Admin</Channel>
<Computer>TESTSERVER</Computer>
<Security UserID="S-1-5-21-2195821719-3162908599-1472692150-15697" />
</System>
<EventData>
<Data Name="Message">Windows Hello for Business provisioning will not be launched.</Data>
<Data Name="DeviceIsJoined">Not Tested</Data>
<Data Name="AADPrt">Not Tested</Data>
<Data Name="NgcPolicyEnabled">Not Tested</Data>
<Data Name="NgcPostLogonProvisioningEnabled">Not Tested</Data>
<Data Name="NgcHardwarePolicyMet">Not Tested</Data>
<Data Name="UserIsRemote">No</Data>
<Data Name="LogonCertRequired">Not Tested</Data>
<Data Name="MachinePolicySource">none</Data>
</EventData>
</Event>

Comment: This appears to be affecting Windows 2019 Servers. These machines have a scheduled task named ‘Automatic-Device-Join’ that facilitates ‘hybrid joins’. At the time of this writing, the environment of the affected machines are not hybrid. Here is some info from Microsoft: https:// docs.microsoft.com/en-US/troubleshoot/windows-server/deployment/event-307-and-304-logged-for-deploying

Considerations in Granting Access to Helpdesk Users via Group ‘Account Operators’

One consideration is to add Helpdesk users into the ‘Account Operators’ group. This would effectively grant limited account creation privileges to those personnel. Members of this group can administer many types of accounts, including users, local, and global groups. Operators could also log on to domain controllers. Overall, this is a rather high level of access.

Account Operators “can create and manage users and groups in the domain, but it cannot manage service administrator accounts. As a best practice, do not add members to this group, and do not use it for any delegated administration.” (source: https:// docs.microsoft.com/en-us/previous-versions/tn-archive/cc875827(v=technet.10)?redirectedfrom=MSDN#XSLTsection124121120120).

Therefore, Administrators are advised to create a custom AD group for this purpose. I’ve written an article toward this topic here (https://kimconnect.com/active-directory-helpdesk-admins-group-creation/)