With msiexec, what's the difference between these different ways to direct to the installer?

試著忘記壹切 提交于 2020-07-03 13:00:45

问题


I've got a simple problem. I've only found two ways that will actually run my msi file, and neither of them will work.

Pay close attention to my usage of ' and ".

Simply put, I want a way to do this:

$Basics = "$PSScriptRoot"
Start-Process msiexec.exe -Wait -ArgumentList "/i $Basics\Installer_.64 bit_.msi /passive /norestart"

However the string being given to -ArgumentList is invalid, and I'm not sure why. I've done a lot of attempts as you can see below, in trying to get this right.
$Basics is just a copy of $PSScriptRoot for now, but I want it has a separate variable in case if I change it in the future.
/passive /norestart is removed for testing purposes.

Note: This is not the actual installer file's name. This is made just to contain all the weird characters (.,_,) that some of the installers I'm trying to run with this, have. Basically a worst case scenario.

Also, sorry in advance that this is a lot to read, I'm not really sure how to format it better. Go ahead and edit if you know a better way.

Attempts:

Not in order, organized by what kind of attempt it was. My first attempt was "/i '$Basics\Installer_.64 bit_.msi'"

Start-Process msiexec.exe -Wait -ArgumentList "/i $Basics\Installer_.64 bit_.msi"

^ Result: Opens generic Windows Installer help window.

Start-Process msiexec.exe -Wait -ArgumentList "/i '$Basics\Installer_.64 bit_.msi'"

^ Result: Opens generic Windows Installer help window.

Start-Process msiexec.exe -Wait -ArgumentList '/i $Basics\Installer_.64 bit_.msi'

^ Result: "This installation package could not be opened. Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer package."

Start-Process msiexec.exe -Wait -ArgumentList '/i "$Basics\Installer_.64 bit_.msi"'

^ Result: "This installation package could not be opened. Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer package."

Start-Process msiexec.exe -Wait -ArgumentList "/i Installer_.64 bit_.msi"

^ Result: Works; However, this isn't acceptable as I need to be able to put a variable in the directory.

Start-Process msiexec.exe -Wait -ArgumentList '/i "C:\Users\Administrator\Downloads\flashdrive\redist\Install (x86 Office)\Installer_.64 bit_.msi"'

^ Result: Works; However, this isn't acceptable as I need to be able to put a variable in the directory.

Start-Process msiexec.exe -Wait -ArgumentList "/i C:\Users\Administrator\Downloads\flashdrive\redist\Install (x86 Office)\Installer_.64 bit_.msi"

^ Result: Opens generic Windows Installer help window.

Start-Process msiexec.exe -Wait -ArgumentList "/i .\Installer_.64 bit_.msi"

^ Result: "This installation package could not be opened. Verify that the package exists and that you can access it, or contact the application vendor to verify that this is a valid Windows Installer package."


回答1:


Powershell treats everything between single quotes as a literal string. Your variables won't get expanded if you use single quotes. So you need to use double quotes if you want to use variable expansion.
The problem with your example with the double quotes is that powershell interprets all the characters until a whitespace as a single variable. And since "$Basics\Installer_.64 bit_.msi" is not the variable that you want, this doesn't work either. You can put your variable name between curly brackets ({}) to delimit it from the rest of the string. So an example that would work is this:

Start-Process msiexec.exe -Wait -ArgumentList "/i ${Basics}\Installer_.64 bit_.msi"

Another option would be to use the format string operator:

'/i {0}\Installer_.64 bit_.msi' -f $Basics

This operator gives you a lot more freedom and you can do some very advanced string formatting with it. Another added benefit is that this way you can use single quotes. This makes sure that no expansion will take place. For example, in case your msi files have dollar signs in the name, the first example will not work, since powershell will try to expand the variables.




回答2:


PowerShell Module: There is now a Windows Installer PowerShell Module courtesy of Heath Stewart of Microsoft. I haven't tested it much, just a smoke test. See below for another alternative using MSI API directly via COM.


Re-Quoting: I saw someone write a lot about PowerShell and escape sequences. It looks pretty complicated: Setting Public Property Values on the Command Line - there were other posts too.

Alternatives?: Perhaps you can go via MSI API COM calls? I have this old answer on various ways to uninstall MSI packages. I'll see if I can dig up a PowerShell example, in the meantime here is a VBScript version using MSI API COM calls:

Set installer = CreateObject("WindowsInstaller.Installer")
installer.InstallProduct "C:\Product.msi", "REBOOT=ReallySuppress"

There is also WMI - which I never use. See section 10 here.


Link:

  • Different ways to invoke MSI
  • https://github.com/heaths/psmsi
  • Get the Windows Installer PowerShell Module easier with WMF 5.0
  • Other answers: 1


来源:https://stackoverflow.com/questions/58139793/with-msiexec-whats-the-difference-between-these-different-ways-to-direct-to-th

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!