A Bit of PowerShell Scripting
Almost every large deployment ends up with a stray Windows machine somewhere. Actually, that’s not quite right: plenty of organizations run on Windows exclusively. The reason is simple: most closed-source SDKs only work on Windows, so to use their features you have to build a Windows service. Luckily for anyone who loves the command line, Microsoft provides an outstanding toolset in PowerShell.
When writing PowerShell code, keep two things in mind:
- Script files should use the .ps1 extension instead of .bat. You will usually also need to change a security setting (the execution policy) before the system lets you run them.
- Most tasks can be done in a single line.
If you come from Linux scripting, some behavior may seem strange. For example, you can’t directly move a directory; you have to copy it recursively and then delete the original. Still, the work gets done. Below are a few basic tasks you may need at some point.
$source_file = "http://internal.repo/package/module.zip"
$tmp_folder = "C:\Temp"
$dest_folder = "C:\Program Files\Internal\Application"
$source_file_name = [io.path]::GetFileNameWithoutExtension($source_file)
$dest_zip = "$tmp_folder\$source_file_name"
New-Item -ItemType Directory -Force -Path $tmp_folder
Invoke-WebRequest $source_file -OutFile $dest_zip
New-Item -ItemType Directory -Force -Path $dest_folder
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory($dest_zip, $dest_folder)
Remove-Item -Path "$dest_zip" -Force
### No -Force for the temp folder
Remove-Item -Path "$tmp_folder"
New-Service -BinaryPathName $exePath -Name $serviceName -DisplayName $serviceName -description $serviceDescription -StartupType Automatic
Start-Service $serviceName
$existingService = Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'"
if ($existingService)
{
Stop-Service $serviceName
### We should sleep for a few seconds to give time for the service to stop
Start-Sleep -s 5
$existingService.Delete()
### When upgrading an existing service, if we are to put a new binary for the same name, we should also sleep a few seconds here
}
$port = "30000"
$existing_fw_rule = netsh advfirewall firewall show rule name="access to port $port"
if ($existing_fw_rule -match "No rules match")
{
netsh advfirewall firewall add rule name="access to port $port" dir=in action=allow protocol=TCP localport=$port
}
That wraps up today’s PowerShell tips. Enjoy!