Last active
February 3, 2016 09:52
-
-
Save anuriq/ecbd675d4a680f06afce to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Get-PendingReboot { | |
<# | |
.SYNOPSIS | |
Gets the pending reboot status on a local or remote computer. | |
.DESCRIPTION | |
This function will query the registry on a local or remote computer and determine if the | |
system is pending a reboot, from either Microsoft Patching or a Software Installation. | |
For Windows 2008+ the function will query the CBS registry key as another factor in determining | |
pending reboot state. "PendingFileRenameOperations" and "Auto Update\RebootRequired" are observed | |
as being consistent across Windows Server 2003 & 2008. | |
CBServicing = Component Based Servicing (Windows 2008) | |
WindowsUpdate = Windows Update / Auto Update (Windows 2003 / 2008) | |
PendFileRename = PendingFileRenameOperations (Windows 2003 / 2008) | |
.PARAMETER ComputerName | |
A single Computer or an array of computer names. The default is localhost ($env:COMPUTERNAME). | |
.PARAMETER ErrorLog | |
A single path to send error data to a log file. | |
.EXAMPLE | |
PS C:\> Get-PendingReboot -ComputerName (Get-Content C:\ServerList.txt) | Format-Table -AutoSize | |
Computer CBServicing WindowsUpdate PendFileRename RebootPending | |
-------- ----------- ------------- -------------- ------------- | |
DC01 False False False False | |
DC02 False False False False | |
FS01 False True True True | |
This example will capture the contents of C:\ServerList.txt and query the pending reboot | |
information from the systems contained in the file and display the output in a table | |
.EXAMPLE | |
PS C:\> Get-PendingReboot | |
Computer : WKS01 | |
CBServicing : False | |
WindowsUpdate : True | |
PendFileRename : False | |
RebootPending : True | |
This example will query the local machine for pending reboot information. | |
.EXAMPLE | |
PS C:\> $Servers = Get-Content C:\Servers.txt | |
PS C:\> Get-PendingReboot -Computer $Servers | Export-Csv C:\PendingRebootReport.csv -NoTypeInformation | |
This example will create a report that contains pending reboot information. | |
.LINK | |
Component-Based Servicing: | |
http://technet.microsoft.com/en-us/library/cc756291(v=WS.10).aspx | |
PendingFileRename/Auto Update: | |
http://support.microsoft.com/kb/2723674 | |
http://technet.microsoft.com/en-us/library/cc960241.aspx | |
http://blogs.msdn.com/b/hansr/archive/2006/02/17/patchreboot.aspx | |
.NOTES | |
Author: Brian Wilhite | |
Email: bwilhite1@carolina.rr.com | |
Date: 08/29/2012 | |
PSVer: 2.0/3.0 | |
#> | |
[CmdletBinding()] | |
param( | |
[Parameter(Position=0,ValueFromPipeline=$true)] | |
[Alias("CN","Computer")] | |
[String[]]$ComputerName="$env:COMPUTERNAME" | |
) | |
Begin | |
{ | |
#Adjusting ErrorActionPreference to stop on all errors | |
$TempErrAct = $ErrorActionPreference | |
$ErrorActionPreference = "Stop" | |
}#End Begin Script Block | |
Process | |
{ | |
foreach ($Computer in $ComputerName) { | |
$Computer = $Computer.ToUpper().Trim() | |
try { | |
#Setting pending values to false to cut down on the number of else statements | |
$CBS,$WUAU,$PendFileRename,$Pending = $false, $false, $false, $false | |
#Querying WMI for build version | |
$WMI_OS = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $Computer | |
#Making registry connection to the local/remote computer | |
$RegCon = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]"LocalMachine",$Computer) | |
#If Vista/2008 & Above query the CBS Reg Key | |
If ($WMI_OS.BuildNumber -ge 6001) { | |
$RegSubKeysCBS = $RegCon.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\").GetSubKeyNames() | |
$CBSRebootPend = $RegSubKeysCBS -contains "RebootPending" | |
If ($CBSRebootPend) { | |
$CBS = $true | |
} | |
} | |
#Query WUAU from the registry | |
$RegWUAU = $RegCon.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\") | |
if($RegWUAU -ne $null) { | |
$RegWUAURebootReq = $RegWUAU.GetSubKeyNames() | |
$WUAURebootReq = $RegWUAURebootReq -contains "RebootRequired" | |
} | |
#Query PendingFileRenameOperations from the registry | |
$RegSubKeySM = $RegCon.OpenSubKey("SYSTEM\CurrentControlSet\Control\Session Manager\") | |
$RegValuePFRO = $RegSubKeySM.GetValue("PendingFileRenameOperations",$null) | |
#Closing registry connection | |
$RegCon.Close() | |
#If values from the registry are present, setting each respective variable to $true | |
If ($WUAURebootReq) { | |
$WUAU = $true | |
} | |
If ($RegValuePFRO) { | |
$PendFileRename = $true | |
} | |
If ($CBS -or $WUAU -or $PendFileRename) { | |
$Pending = $true | |
} | |
#Creating $Data Custom PSObject | |
$Data = New-Object -TypeName PSObject -Property @{ | |
Computer=$Computer | |
CBServicing=$CBS | |
WindowsUpdate=$WUAU | |
PendFileRename=$PendFileRename | |
RebootPending=$Pending | |
}#End $Data Custom object | |
#Returning $Data object in a selected order to the user | |
$Data | Select-Object -Property Computer, CBServicing, WindowsUpdate, PendFileRename, RebootPending | |
} | |
catch { | |
Write-Warning "$Computer`: $_" | |
} | |
}#End Foreach ($Computer in $ComputerName) | |
}#End Process | |
End | |
{ | |
#Resetting ErrorActionPref | |
$ErrorActionPreference = $TempErrAct | |
}#End End | |
} | |
function Test-PendingReboot { | |
<# | |
.SYNOPSIS | |
Checks to see if Windows is pending a reboot | |
.DESCRIPTION | |
Uses a script from Brian Wilhite | |
http://gallery.technet.microsoft.com/scriptcenter/Get-PendingReboot-Query-bdb79542 | |
that queries the registry, Windows Update and System | |
Configuration Manager to determine if a pending reboot is | |
required. | |
One may want to check this before installing software | |
or doing anything that may fail if there is a pending | |
reboot. If this command returns $true, one may want to | |
call Invoke-Reboot to restart the local machine. | |
.LINK | |
http://boxstarter.org | |
http://gallery.technet.microsoft.com/scriptcenter/Get-PendingReboot-Query-bdb79542 | |
Invoke-Reboot | |
about_boxstarter_bootstrapper | |
#> | |
$rebootPending = Get-PendingReboot | |
if($rebootPending.RebootPending) { | |
echo "Detected Pending reboot" -Verbose | |
echo "$rebootPending" | |
return $true | |
} | |
return $false | |
} | |
function Invoke-Reboot { | |
Restart-Computer -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | |
} | |
function Install-WindowsUpdate { | |
<# | |
.SYNOPSIS | |
Downloads and installs updates via Windows Update | |
.DESCRIPTION | |
This uses the windows update service to search, download and install updates. By default, only critical updates are included and a reboot will be induced if required. | |
.PARAMETER GetUpdatesFromMS | |
If this switch is set, the default windows update server, if any, is bypassed and windows update requests go to the public Microsoft Windows update service. | |
.PARAMETER AcceptEula | |
If any update requires a Eula acceptance, setting this switch will accept the Eula and allow the update to be installed. | |
.PARAMETER SuppressReboots | |
Setting this switch will suppress a reboot in the event that any update requires one. | |
.PARAMETER Criteria | |
The criteria used for searching updates. The default criteria is "IsHidden=0 and IsInstalled=0 and Type='Software'" which is effectively just critical updates. | |
.LINK | |
http://boxstarter.org | |
#> | |
param( | |
[switch]$getUpdatesFromMS, | |
[switch]$acceptEula, | |
[switch]$SuppressReboots, | |
[string]$criteria="IsHidden=0 and IsInstalled=0 and Type='Software' and BrowseOnly=0" | |
) | |
try{ | |
$updateSession =new-object -comobject "Microsoft.Update.Session" | |
$Downloader =$updateSession.CreateUpdateDownloader() | |
$Installer =$updateSession.CreateUpdateInstaller() | |
$Searcher =$updatesession.CreateUpdateSearcher() | |
if($getUpdatesFromMS) { | |
$Searcher.ServerSelection = 2 #2 is the Const for the Windows Update server | |
} | |
$wus=Get-WmiObject -Class Win32_Service -Filter "Name='wuauserv'" | |
$origStatus=$wus.State | |
$origStartupType=$wus.StartMode | |
echo "Update service is in the $origStatus state and its startup type is $origStartupType" -verbose | |
if($origStartupType -eq "Auto"){ | |
$origStartupType = "Automatic" | |
} | |
if($origStatus -eq "Stopped"){ | |
if($origStartupType -eq "Disabled"){ | |
Set-Service wuauserv -StartupType Automatic | |
} | |
echo "Starting windows update service" -verbose | |
Start-Service -Name wuauserv | |
} | |
else { | |
# Restart in case updates are running in the background | |
echo "Restarting windows update service" -verbose | |
try { | |
Restart-Service -Name wuauserv -Force -WarningAction SilentlyContinue | |
} | |
catch {} | |
} | |
$Result = $Searcher.Search($criteria) | |
$totalUpdates = $Result.updates.count | |
If ($totalUpdates -ne 0) | |
{ | |
echo "$($Result.updates.count) Updates found" | |
$currentCount = 0 | |
foreach($update in $result.updates) { | |
++$currentCount | |
if(!($update.EulaAccepted)){ | |
if($acceptEula) { | |
$update.AcceptEula() | |
} | |
else { | |
echo " * $($update.title) has a user agreement that must be accepted. Call Install-WindowsUpdate with the -AcceptEula parameter to accept all user agreements. This update will be ignored." | |
continue | |
} | |
} | |
$Result= $null | |
if ($update.isDownloaded -eq "true" -and ($update.InstallationBehavior.CanRequestUserInput -eq $false )) { | |
echo " * $($update.title) already downloaded" | |
$result = Install-Update $update $currentCount $totalUpdates | |
} | |
elseif($update.InstallationBehavior.CanRequestUserInput -eq $true) { | |
echo " * $($update.title) Requires user input and will not be downloaded" | |
} | |
else { | |
Download-Update $update | |
$result = Install-Update $update $currentCount $totalUpdates | |
} | |
} | |
if($result -ne $null -and $result.rebootRequired) { | |
if($SuppressReboots) { | |
echo "A Restart is Required." | |
} else { | |
$Rebooting=$true | |
echo "Restart Required. Restarting now..." | |
if(test-path function:\Invoke-Reboot) { | |
return Invoke-Reboot | |
} else { | |
Restart-Computer -force | |
} | |
} | |
} | |
} | |
else { | |
echo "There is no update applicable to this machine" | |
} | |
} | |
catch { | |
echo "There were problems installing updates: $($_.ToString())" | |
throw | |
} | |
finally { | |
if($origAUVal){ | |
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\WindowsUpdate\AU -Name UseWuServer -Value $origAUVal -ErrorAction SilentlyContinue | |
} | |
if($origStatus -eq "Stopped") | |
{ | |
echo "Stopping win update service and setting its startup type to $origStartupType" -verbose | |
Set-Service wuauserv -StartupType $origStartupType | |
try { | |
stop-service wuauserv -WarningAction SilentlyContinue | |
} | |
catch {} | |
} | |
} | |
} | |
function Download-Update($update) { | |
$updates= new-Object -com "Microsoft.Update.UpdateColl" | |
$updates.Add($update) | out-null | |
$Downloader.Updates = $updates | |
$Downloader.Download() | Out-Null | |
} | |
function Install-Update($update, $currentCount, $totalUpdates) { | |
$updates=new-Object -com "Microsoft.Update.UpdateColl" | |
$updates.Add($update) | out-null | |
$Installer.updates = $Updates | |
try { $result = $Installer.Install() } | |
catch { | |
if(!($SuppressReboots) -and (test-path function:\Invoke-Reboot)){ | |
if(Test-PendingReboot) { | |
$global:error.RemoveAt(0) | |
Invoke-Reboot | |
} | |
} | |
# Check for WU_E_INSTALL_NOT_ALLOWED | |
if($_.Exception.HResult -eq -2146233087) { | |
echo "There is either an update in progress or there is a pending reboot blocking the install." | |
$global:error.RemoveAt(0) | |
} | |
else { throw } | |
} | |
return $result | |
} | |
function Set-WindowsExplorerOptions { | |
<# | |
.SYNOPSIS | |
Sets options on the Windows Explorer shell | |
.PARAMETER EnableShowHiddenFilesFoldersDrives | |
If this flag is set, hidden files will be shown in Windows Explorer | |
.PARAMETER DisableShowHiddenFilesFoldersDrives | |
Disables the showing on hidden files in Windows Explorer, see EnableShowHiddenFilesFoldersDrives | |
.PARAMETER EnableShowProtectedOSFiles | |
If this flag is set, hidden Operating System files will be shown in Windows Explorer | |
.PARAMETER DisableShowProtectedOSFiles | |
Disables the showing of hidden Operating System Files in Windows Explorer, see EnableShowProtectedOSFiles | |
.PARAMETER EnableShowFileExtensions | |
Setting this switch will cause Windows Explorer to include the file extension in file names | |
.PARAMETER DisableShowFileExtensions | |
Disables the showing of file extension in file names, see EnableShowFileExtensions | |
.PARAMETER EnableShowFullPathInTitleBar | |
Setting this switch will cause Windows Explorer to show the full folder path in the Title Bar | |
.PARAMETER DisableShowFullPathInTitleBar | |
Disables the showing of the full path in Windows Explorer Title Bar, see EnableShowFullPathInTitleBar | |
.LINK | |
http://boxstarter.org | |
#> | |
[CmdletBinding()] | |
param( | |
[switch]$EnableShowHiddenFilesFoldersDrives, | |
[switch]$DisableShowHiddenFilesFoldersDrives, | |
[switch]$EnableShowProtectedOSFiles, | |
[switch]$DisableShowProtectedOSFiles, | |
[switch]$EnableShowFileExtensions, | |
[switch]$DisableShowFileExtensions, | |
[switch]$EnableShowFullPathInTitleBar, | |
[switch]$DisableShowFullPathInTitleBar | |
) | |
$PSBoundParameters.Keys | % { | |
if($_-like "En*") { | |
$other="Dis" + $_.Substring(2) | |
} | |
if($_-like "Dis*") { | |
$other="En" + $_.Substring(3) | |
} | |
if($PSBoundParameters[$_] -and $PSBoundParameters[$other]) { | |
throw new-Object -TypeName ArgumentException "You may not set both $_ and $other. You can only set one." | |
} | |
} | |
$key = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer' | |
$advancedKey = "$key\Advanced" | |
$cabinetStateKey = "$key\CabinetState" | |
echo "Setting Windows Explorer options..." | |
if(Test-Path -Path $advancedKey) { | |
if($EnableShowHiddenFilesFoldersDrives) {Set-ItemProperty $advancedKey Hidden 1} | |
if($DisableShowHiddenFilesFoldersDrives) {Set-ItemProperty $advancedKey Hidden 0} | |
if($EnableShowFileExtensions) {Set-ItemProperty $advancedKey HideFileExt 0} | |
if($DisableShowFileExtensions) {Set-ItemProperty $advancedKey HideFileExt 1} | |
if($EnableShowProtectedOSFiles) {Set-ItemProperty $advancedKey ShowSuperHidden 1} | |
if($DisableShowProtectedOSFiles) {Set-ItemProperty $advancedKey ShowSuperHidden 0} | |
} | |
if(Test-Path -Path $cabinetStateKey) { | |
if($EnableShowFullPathInTitleBar) {Set-ItemProperty $cabinetStateKey FullPath 1} | |
if($DisableShowFullPathInTitleBar) {Set-ItemProperty $cabinetStateKey FullPath 0} | |
} | |
} | |
function Stop-UpdateServices { | |
echo "Disabling Automatic Updates from Windows Update" | |
$winUpdateKey = "HKLM:SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\au" | |
if(!(Test-Path $winUpdateKey)) { | |
New-Item $winUpdateKey -Type Folder -Force | Out-Null | |
} | |
try { | |
New-ItemProperty -Path $winUpdateKey -name 'NoAutoUpdate' -value '1' -propertyType "DWord" -force -ErrorAction Stop | Out-Null | |
} | |
catch { $global:error.RemoveAt(0) } | |
try { | |
New-ItemProperty -Path $winUpdateKey -name 'NoAutoRebootWithLoggedOnUsers' -value '1' -propertyType "DWord" -force -ErrorAction Stop | Out-Null | |
} | |
catch { $global:error.RemoveAt(0) } | |
} | |
function InstallChocolatey { | |
echo "Installing chocolatey..." | |
if(-not $env:ChocolateyInstall -or -not (Test-Path "$env:ChocolateyInstall")) { | |
$env:ChocolateyInstall = "$env:programdata\chocolatey" | |
New-Item $env:ChocolateyInstall -Force -type directory | Out-Null | |
$wc=New-Object Net.WebClient | |
$wp=[System.Net.WebProxy]::GetDefaultProxy() | |
$wp.UseDefaultCredentials=$true | |
$wc.Proxy=$wp | |
iex ($wc.DownloadString("https://chocolatey.org/install.ps1")) | |
$env:path="$env:path;$env:ChocolateyInstall\bin" | |
} | |
} | |
function InstallWinFeatures { | |
echo "Installing Windows features..." | |
$tries = 3 | |
for ($i = 1; $i -le $tries; $i++) { | |
try { | |
$wc=New-Object Net.WebClient | |
$wp=[System.Net.WebProxy]::GetDefaultProxy() | |
$wp.UseDefaultCredentials=$true | |
$wc.Proxy=$wp | |
$features=$wc.DownloadString("https://gist.githubusercontent.com/anuriq/5a0ae450305e9d790736/raw/e8370f2f3682932682ebe916a646696eb13f512f/windowsfeatures2.xml") | |
Set-Content -Path $env:bootstrap\windowsfeatures.xml -Value $features | |
Install-WindowsFeature -ConfigurationFilePath $env:bootstrap\windowsfeatures.xml | |
break; | |
} | |
catch { | |
echo "Error during access to gist.github.com page." | |
if ($i -eq $tries) { throw $_.Exception; } | |
sleep 2; | |
} | |
} | |
} | |
function ConfigureWinFeatures { | |
echo "Configuring Windows features..." | |
NewDir "$env:systemdrive\share" | |
ICACLS "$env:systemdrive\share" /Grant IUSR:R /T | |
New-WebFtpSite -Name "FtpSite" -IPAddress "0.0.0.0" -Port 21 -PhysicalPath "$env:systemdrive\share" -Force | |
# Allow SSL connections | |
Set-ItemProperty "IIS:\Sites\FtpSite" -Name ftpServer.security.ssl.controlChannelPolicy -Value 0 | |
Set-ItemProperty "IIS:\Sites\FtpSite" -Name ftpServer.security.ssl.dataChannelPolicy -Value 0 | |
# Enable Basic Authentication | |
Set-ItemProperty "IIS:\Sites\FtpSite" -Name ftpServer.security.authentication.basicAuthentication.enabled -Value $true | |
# Give Authorization to All Users and grant "read"/"write" privileges | |
Add-WebConfiguration "/system.ftpServer/security/authorization" -value @{accessType="Allow";roles="Administrators";permissions="Read,Write"} -PSPath IIS:\ -location "FtpSite" | |
# Restart the FTP site for all changes to take effect | |
Restart-WebItem "IIS:\Sites\FtpSite" | |
} | |
function CleanSxs { | |
echo "Cleaning SxS and other cache..." | |
Dism.exe /online /Cleanup-Image /StartComponentCleanup /ResetBase | |
@( | |
"$env:localappdata\Nuget", | |
"$env:localappdata\temp\*", | |
"$env:windir\logs", | |
"$env:windir\panther", | |
"$env:windir\temp\*", | |
"$env:windir\winsxs\manifestcache" | |
) | % { | |
if(Test-Path $_) { | |
echo "Removing $_" | |
Takeown /d Y /R /f $_ | Out-Null | |
Icacls $_ /GRANT:r administrators:F /T /c /q 2>&1 | Out-Null | |
Remove-Item $_ -Recurse -Force -ErrorAction SilentlyContinue | Out-Null | |
} | |
} | |
} | |
function NewDir ($dirpath) { | |
New-Item $dirpath -ItemType dir -Force -ErrorAction SilentlyContinue; | |
} | |
function NewFile ($filepath) { | |
New-Item $filepath -ItemType file -Force -ErrorAction SilentlyContinue; | |
} | |
$ErrorActionPreference = "Continue"; | |
$n = NewDir "$env:systemdrive\bootstrap"; | |
[Environment]::SetEnvironmentVariable("bootstrap", "$env:systemdrive\bootstrap", "Machine"); | |
$env:bootstrap = "$env:systemdrive\bootstrap"; | |
if (Test-Path "$env:bootstrap\__shutdown") { | |
exit 0; | |
} | |
# Install-WindowsUpdate -AcceptEula | |
if(Test-PendingReboot) { Invoke-Reboot } | |
if (-not (Test-Path "$env:bootstrap\__chocoinstall")) { | |
InstallChocolatey | |
$step1 = NewFile "$env:bootstrap\__chocoinstall"; | |
} | |
if (-not (Test-Path "$env:bootstrap\__packageinstall")) { | |
#cinst "dotnet4.5.1" -y | |
#cinst jre8 -y | |
#cinst adobereader -y | |
cinst tightvnc -y | |
$step2 = NewFile "$env:bootstrap\__packageinstall"; | |
} | |
if (-not (Test-Path "$env:bootstrap\__winfeatureinstall")) { | |
InstallWinFeatures | |
ConfigureWinFeatures | |
echo "Removing unused features..." | |
Remove-WindowsFeature -Name 'Powershell-ISE' | |
Get-WindowsFeature | ? { $_.InstallState -eq 'Available' } | Uninstall-WindowsFeature -Remove | |
$step3 = NewFile "$env:bootstrap\__winfeatureinstall"; | |
} | |
if (-not (Test-Path "$env:bootstrap\__winoptions")) { | |
echo "Disabling display turning off..." | |
powercfg -change -monitor-timeout-ac 0 | |
powercfg -change -monitor-timeout-dc 0 | |
Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name "ScreenSaveActive" -Value 0 | |
Set-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name "SCRNSAVE.EXE" -Value "" | |
echo "Disabling UAC..." | |
New-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\policies\system -Name EnableLUA -PropertyType DWord -Value 0 -Force | |
Set-WindowsExplorerOptions -EnableShowHiddenFilesFoldersDrives -EnableShowFileExtensions -EnableShowFullPathInTitleBar | |
$step4 = NewFile "$env:bootstrap\__winoptions"; | |
} | |
if(Test-PendingReboot) { Invoke-Reboot } | |
Stop-UpdateServices | |
CleanSxs | |
echo "Enabling RDP configuration in EC2Config..." | |
$ec2configfile = "$env:programfiles\Amazon\Ec2ConfigService\Settings\config.xml" | |
$xml = [xml](Get-Content $ec2configfile) | |
foreach ($element in $xml.get_DocumentElement().Plugins.Plugin) { | |
if ($element.Name -eq "Ec2ConfigureRDP") { $element.State = "Enabled" } | |
if ($element.Name -eq "Ec2SetPassword") { $element.State = "Enabled" } | |
} | |
$xml.Save($ec2configfile) | |
Copy-Item -Path "$env:programfiles\Amazon\Ec2ConfigService\Logs\*" -Destination $env:bootstrap; | |
NewFile "$env:bootstrap\__done" | |
NewFile "$env:bootstrap\__shutdown" | |
& "$env:programfiles\Amazon\Ec2ConfigService\ec2config.exe" -sysprep | |
# Stop-Computer -Confirm:$false -Force |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment