Automating Installers And Editing Config Files With PowerShell

In this post I’m going to take a deep dive into automating installers and editing config files with PowerShell.

I spent the last few weeks automating the installation and configuration of various 3rd party software components. It involved a fair bit of trail and error to get all of it working. I decided to compile all the scripts into a blog post in case someone else or even future me need a refresher or quick start.

Runnig MSI and Exe installers silently
MSI installers are easy to run silently and you can prevent it from rebooting the machine after installation. I also specified verbose logging, it comes in handy if the installer fails for some reason. Note the accent character  (`) used for escaping the double quotes (“) around the MSI file name. I enclosed the file name in double quotes in case it contained spaces. The second last line prints the command line parameters that are about to run to the console, in my case I was using Octopus and it was handy for debugging since the output is shown in the Octopus deployment log.

$msi = "/i `"AppToInstall.msi`""
$cmd = "MSIEXEC"
$q = "/qn"
$nrst = "/norestart"
$log = "/lv verbose.log"
$fullparam = $msi + " " + $q + " "+ $log + " " + $nrst
$fullparam  #optional, output the parameters to the console for debugging
Start-Process -file $cmd -arg $fullparam -PassThru | wait-process

You can write everything in a single line but I split the command and parameters up into different variables to make it more readable and easier when you want to change the script.

You also get Exe installers that wrap a MSI installer and in this case you have to pass some parameters to the Exe to make it silent /S and also a second set of parameters that it will pass to the MSI /V to hide the installer gui /qn and also to prevent rebooting in this case. Note the single qoutes (‘) on line two, this is another way to deal with double quotes in a string, PowerShell will treat this as a literal string.

$cmd = ".\Setup.exe"
$param = '/s /v"REBOOT=ReallySupress /qn"'  #note single qoutes
$cmd + " " + $param  #optional output to concole for debugging
Start-Process -file $cmd -arg $param -PassThru | wait-process

Note that everything after /V is passed as a single parameter to the MSI and should be enclosed in quotes.

Editing config files using PowerShell
The easiest ones are XML files, you find the node to change and you give it a value. In this case I am changing the InnerText of the element.

$file = 'PathToXmlFile.xml'
$xml = [xml](Get-Content $file)
$node = $xml.customconfig.usersettings.servers.FirstChild
$node.InnerText = 'localhost'
$xml.Save($file)

If you are dealing with .NET config files you can use the same technique as above. In this example I am changing the value of the UserEmailAddress setting in the AppSettings section. Note I am changing an attribute on the XML element this time.

$xml.configuration.appSettings.add | Foreach-Object {
if ( $_.key -eq 'UserEmailAddress' ) {
$_.value = "$internalEmailAddress";
}
}

You can also modify connection strings.

$xml.configuration.connectionStrings.add | Foreach-Object {
if ( $_.name -eq 'DefaultContext' ) {
$_.connectionString = "$connectionString";
$_.providerName = "$dbProvider";
}
}

Editing text files turned out to be a bit more work but luckily this was for a clean install so it always had the same values to start with. I build up a new config file by reading all the existing lines into a collection, replacing the current setting with the new value and then I overwrite the existing file with the new lines.

$fileName = "Custom.cfg"
$lines = Get-Content $fileName
$newlines = @()   #create the collection


Foreach($line in $lines) {
if ('[email protected]'.CompareTo($line) -eq 0)
{
$line =   $line.Replace('[email protected]',
'[email protected]')
}
$newlines += $line
}

Out-File $fileName -inputobject $newlines

Setting registry values was also pretty easy.

Set-ItemProperty -Path "HKLM:\Software\AppName\LicenseSettings" -Name "LicenseFile" -Value "PathToLicenceFile.lic"

I also had to create some environment variables, in this case it was a machine wide setting but you can also create one at user and process level.

[Environment]::SetEnvironmentVariable('USERCFG', 'PathToUserConfig.xml', 'Machine')

Hopefully this post covered most of the common tasks when it comes to automating installers, editing config files and registry settings to get you going quickly.

Francois Delport

Published by

Francois Delport

I am a cloud and devops consultant, technology fan and previously a professional C# developer with a keen interest in system design and architecture. Currently I am involved in projects using Azure, the Microsoft stack and DevOps. I am based in Melbourne, Australia. Email: [email protected]

Leave a Reply

Your email address will not be published. Required fields are marked *