2

I'm trying to pass arguments to a MSI installer:

$Servers = @("ServerOne", "ServerTwo", "ServerThree")

$InstallerArguments = @(
    "/i `"$InstallerPath`"",
    "/quiet",
    "/log `"$LogFile`"",
    "EMAILSERVER=`"$Servers[0]`"",
    "DATABASESERVER=`"$Servers[1]`"",
    "SHAREPOINTSERVER=`"$Servers[2]`"",
    "USERNAME=`"$UserName`""
)

Reviewing the installer logfile shows the result:

Property(S): EMAILSERVER = ServerOne ServerTwo ServerThree[0]
Property(S): DATABASESERVER = ServerOne ServerTwo ServerThree[0]

Expected result:

Property(S): EMAILSERVER = ServerOne

I think I need to escape the index somehow, what is wrong with the code?

Edit (passing arguments to installer):

Start-Process -FilePath msiexec.exe -ArgumentList $InstallerArguments -Wait
4
  • How are you actually passing that to the installer? Show us the code that actually calls the MSI. Commented Mar 20, 2018 at 18:11
  • Also, personally I would build the args as a string. Commented Mar 20, 2018 at 18:12
  • @EBGreen I've edited the post. Also added a single argument $Username which is correct. The issue is passing array elements. Commented Mar 20, 2018 at 18:25
  • Generally speaking MSI parameters are not quoted. Commented Mar 20, 2018 at 18:33

4 Answers 4

1

The subexpression operator - $() - is one way you can embed an array element (or the output of an arbitrary expression) within a string:

$Servers = @("ServerOne", "ServerTwo", "ServerThree")

$InstallerArguments = @(
  "/i ""$InstallerPath"""
  "/quiet"
  "/log ""$LogFile"""
  "EMAILSERVER=""$($Servers[0])"""
  "DATABASESERVER=""$($Servers[1])"""
  "SHAREPOINTSERVER=""$($Servers[2])"""
  "USERNAME=""$UserName"""
)

Start-Process msiexec.exe $InstallerArguments -Wait

The subexpression operator is documented in the about_Operators help topic.

For an even more readable array, you can use the -f string formatting operator and single-quotes; example:

$InstallerArguments = @(
  ('/i "{0}"' -f $InstallerPath)
  '/quiet'
  ('/log "{0}"' -f $LogFile)
  ('EMAILSERVER="{0}"' -f $Servers[0])
  ('DATABASESERVER="{0}"' -f $Servers[1])
  ('SHAREPOINTSERVER="{0}"' -f $Servers[2])
  ('USERNAME="{0}"' -f $UserName)
)
Sign up to request clarification or add additional context in comments.

Comments

0

This does exactly what you want. I presume you did want the quotes.

$Servers = @("ServerOne", "ServerTwo", "ServerThree")

$InstallerArguments = @(
    "/i `"$InstallerPath`"",
    "/quiet",
    "/log `"$LogFile`"",
    "EMAILSERVER=`"$($Servers[0])`"",
    "DATABASESERVER=`"$($Servers[1])`"",
    "SHAREPOINTSERVER=`"$($Servers[2])`"",
    "USERNAME=`"$UserName`""
)

Comments

0

If you use ", PowerShell will recognize variables and replace them with their content. If it's an array, the elements will be joined by $OFS.

If you want to specify properties, elements, etc. you have to use $() to make shure, PowerShell understand that this is part of the variable (e.g. $($Servers[0]).

If you need in addition " inside a string, I recommend to work with ' (which does not replace variables) and the -f operator.

'EMAILSERVER="{0}"' -f $Servers[0]

Also there is no need for all those arrays.

$InstallerPath = 'C:\'
$LogPath = 'D:\'
$MailServer = 'mail'

$InstallerArguments = '/i "{0}" /quiet /log "{1}" EMAILSERVER="{2}"' -f $InstallerPath, $LogPath, $MailServer

Start-Process -FilePath msiexec.exe -ArgumentList $InstallerArguments -Wait

I think that's much more readable.

Comments

0

So much unneeded complexity with the array. This should work:

$Servers = @("ServerOne", "ServerTwo", "ServerThree")
$args = '/i "{0}" /quiet /log "{1}" EMAILSERVER={2} DATABASESERVER={3} SHAREPOINTSERVER={4} USERNAME={5}' -f $InstallerPath, $LogFile, $servers[0], $servers[1], $servers[2], $username
Start-Process msiexec.exe $args

5 Comments

Aaah yes. I will replace hash with array and my comment stands. :)
The array may be to keep from having a single extremely long string to edit, and to make it easier to insert other needed parameters. The sticky point, as I understand the original question, was how to embed an array element within a string; my answer and another shows one way using the $() (subexpression) operator.
I understand why someone would do it this way. I just feel it is trading complexity for scrolling. Just an opinion I prefer a nice clean string formatter built string even if I have to scroll a little.
I like this also, and updated my array answer with -f (middle-ground approach) -- although I would recommend quoting the MSI property values in your example (in case any contain whitespace).
I did quote paths. I wouldn't consider it likely that server names or user names would have spaces but certainly quote whatever makes you happy.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.