How to use .INI files parameters to start a service

Written by Catalin Gheorghe · August 30th, 2021

#SERVICES #TIPS #POWERSHELL

We got a question in the Advanced Installer forum about the possibility of passing arguments to a service when the parameters are received from a configuration file, such as an .INI file.

Can it be done? The answer is yes.

In this article, we will show you how to achieve just that.

NoteWe have multiple tutorials about services on our user guide. Have a look at the topics we've covered: how to Detect or stop a service, Install a Win32 service, Install a service for a custom user, Install a service under NetworkService.

It's important to note that the process of starting a service with parameters received from an .INI file includes two possible situations. Let's describe them first.

How to start a service based on the location of the .INI file?

Passing arguments to a service when the settings come from an .INI file can happen in two scenarios:

  1. The .INI file is present on the target machine - and this can be achieved through our predefined support for searching properties .
  2. The .INI file is not present on the target machine and the file is intended to be delivered with the setup - for this situation, there is no predefined support and we will need to use custom actions.

For this tutorial, we will use the following mock .INI file :

[SectionSample]
MyName = Catalin

[SectionSample2]
MyAge = 23

Now that we have our example file, let's have a look at how to approach each scenario.

First Scenario: The .INI file is present on the machine

In our example, we would like to pass the value of "MyName" (which is "Catalin" - without quotes) as a parameter to our service.

As previously mentioned, Advanced Installer has predefined support for searches which simplifies this process.

If the .INI file is already present on the machine, the first thing to do is navigate to the Search Page. In the Search Page, we can create a property that will get the value from the .INI file.

It will look like this:

Create property search page

It's important to know exactly where the .INI file resides. In our case, the .INI file is located under the "C:\" volume. Therefore, we used the [WindowsVolume] property, so at the time of installation, the search will refer to the volume where the OS is installed (C:/ in this example).

NoteFor more information about directory properties, you can have a look over our "Paths of the folders in the "Files and Folders" Page" article.

Here's what happens during installation:

  1. Windows Installer searches for the .INI file in the specified location ([WindowsVolume] in this tutorial).
  2. Once located, it looks for the “SectionSample” and gets the value from the “MyName” key.
  3. The retrieved value is then stored in the RESULT_PROPERTY.

After configuring the search, go to Services Page and add our argument:

 --someParameter = [RESULT_PROPERTY]
Add argument

As a result, if we look at the log file now, we can see that the service will start with the required parameters:

InstallServices: Service:
MSI (s) (C4:C0) [11:52:13:639]: Executing op: ActionStart(Name=StartServices,Description=Starting services,Template=Service: [1])
Action 11:52:13: StartServices. Starting services
MSI (s) (C4:C0) [11:52:13:639]: Executing op: ProgressTotal(Total=1,Type=1,ByteEquivalent=1300000)
MSI (s) (C4:C0) [11:52:13:639]: Executing op: ServiceControl(,Name=sample.exe,Action=1,Wait=1,StartupArguments=--someParameter=Catalin)

Second scenario - The .INI file is not present on the machine

For this scenario, the file is intended to be delivered with the setup.

The problem we encounter is that the searches are executed when the setup starts, at which point the .INI file is not available, so the search turns up empty.

When we come across this situation, we need to create a custom action. If we navigate to the Custom Actions Page, we see that the "Searches" action group is placed at the top of the installation sequence.

Searches action group

The only solution is to have a custom action (e.g. a script / .EXE / .DLL file) to look for the .INI file, extract the data from it and then set a property to the extracted value.

To create a custom action, follow these steps:

1. Navigate to the Files and Folders page and add the .INI file as a temporary file using the "Add Temporary Files" button from the toolbar.

TipUsually, temporary files are deleted when the installation process ends. To avoid this step, you can double click on the temporary file which was previously added, and check the "Do not remove the file when setup ends" option.

Edit temporary file

2. Navigate to the Custom Actions Page and add a “Run PowerShell inline script” custom action, with sequence.

3. Then, apply the following settings to the custom action:

3.1. Uncheck the "Uninstall" and "Maintenance" options from under the "Dialogs Stage Condition" section (as we only want this executed during the installation).

3.2. Schedule the PowerShell custom action as it follows: Wizard Dialogs Stage --> after "Paths Resolution" action group.

Installation sequence

The PowerShell script will look something like this:

# Block for declaring the script parameters.
Param()

# Your code goes here.

# get the value of the TempFolder property and store it in a variable

$tempFolder = AI_GetMsiProperty TempFolder

# as the path to the .INI file is %temp%\NameOfTheIniFile.ini, we join the paths to create the full path to our INI file

$pathToIni = Join-Path -Path $tempFolder -ChildPath "sample.ini"

$sampleIni = Get-Content $pathToIni | Where-Object {$_ -match "="} | ConvertFrom-StringData

# set a property to our required INI value

AI_SetMsiProperty MY_PROP $sampleIni.MyName

Here's a key line from the script, that we need to pay attention to:

$sampleIni = Get-Content $pathToIni | Where-Object {$_ -match "="} | ConvertFrom-StringData

We use the Get-Content PowerShell cmdlet to get the content of a file.

This scenario shows that we can use the ConvertFrom-StringData cmdlet, to convert a string containing one or more key and value pairs to a hash table.

This cmdlet only accepts the "key=value", meaning that, if the .INI file contains sections (e.g. "[Section]"), the cmdlet will fail. This happens because the [Section] does not respect the key=value format.

To avoid this situation, the content returned by the Get-Content cmdlet is piped to only match objects that contain “=” (as in “key=value").

We hope you found this quick tutorial useful. Do you have any questions or suggestions? Let us know.

Subscribe to Our Newsletter

Sign up for free and be the first to receive the latest news, videos, exclusive How-Tos, and guides from Advanced Installer.

Comments: