Config Values for Powershell Scripts

In this post I will share my favourite config approach to Powershell scripts

O ften you’ll find yourself writing one set of scripts that will be used for several machines or environments. Most of the commands will be the same for each server, just a few changes needed. If you’ve used a scripted installation tool for SharePoint, such as autospinstaller, then you’ll be all too familiar with using a config file. Autospinstaller uses an xml file to store its config values. while that’s ok, I find it becomes very hard to read and decypher. I much prefer using JSON notation instead.  Here is an example to get you started:

Create a config.json file using your favourite text editor. notice following key syntax elements:

  • All parameter names and values need to be in quotes. only integer values can/must skip the quotes.
  • The whole content needs to be wrappen in one set of curlies {}
  • arrays of sub objects, as in the disks array uses square brackets []
  • each sub object needs to be embedded in curlies {}
{
   "domain": "DMZ",
   "Name": "SQL01",
   "Role": "SQL",
   "IP" : "192.168.150.10",
   "DNS" : "192.168.100.1",
   "GateWay" : "192.168.100.1",
   "Description": "DMZ SQL Server 2016",
   "Disks": [
{
     "ID": 0,
     "Name": "OS",
     "SizeInBytes": 274877906944,
     "Partitions": [
     {
        "ID": 0,
        "Letter": "C",
        "Size": 261872,
        "Label": "OS"
     }
     ]
   },
   {
     "ID": 1,
     "Name": "Data",
     "SizeInBytes": 549755813888,
     "Partitions": [
     {
       "ID": 0,
       "Letter": "D",
       "Size": 524288,
       "Label": "Data"
     }
     ]
   }
   ]
 }

then you can import it into your powershell script, best via a command parameter. InitVM.ps1, and start addressing the values using simple dot notation:

param(
 $configPath 
) 
cls
$config = Get-Content -Raw -Path $configPath | ConvertFrom-Json
 New-NetIPAddress –InterfaceAlias "Ethernet" –IPAddress $config.IP –PrefixLength 24 -DefaultGateway $config.Gateway
 Set-DnsClientServerAddress –InterfaceAlias "Ethernet" -ServerAddresses ($config.DNS) 
 Rename-Computer -NewName $config.Name -Restart 


foreach ($disk in $config.Disks | Where {$_.ID -gt 0})
{
   Set-Disk $disk.ID -isOffline $false
   Get-Disk $disk.ID | Initialize-Disk -PartitionStyle GPT
   foreach ($partition in $disk.Partitions)
   {
      $sizeInBytes = $partition.Size * 1048576 
      New-Partition -DiskNumber $disk.ID -Size $sizeinBytes -DriveLetter $partition.Letter | Format-Volume -FileSystem NTFS -NewFileSystemLabel $partition.Label
   }
}
restart-computer

The above script is quite useful if you’re building machines from scratch. It first sets the IP address, with Gateway and DNS, then renames the computer. finally it initialises the disks and formats the volumes based on your configuration.

Need to restart the machine to make the name change stick though. so if you plan on doing more, you might want to consider splitting tasks into multiple scripts. thanks to your new config file approach, all you need to do is re-import the config and continue where you left off.

That’s it, now you can execute the script using a simple parameter and use a different config for each server/environment/farm:

InitVM.ps1 -configPath config.json