Skip to main content

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.

1. Download a zip file from an HTTP server and extract it

$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"

2. Register and start a new service

New-Service -BinaryPathName $exePath -Name $serviceName -DisplayName $serviceName -description $serviceDescription -StartupType Automatic
Start-Service $serviceName

3. Stop and delete a service

$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
}

4. Open a firewall port (TCP)

$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!