21

I am very new to PowerShell and have some difficulty with understanding.
I want to install an .MSI inside PowerShell script.
Can please explain me how to do that or provide me beginners level tutorial.

$wiObject = New-Object -ComObject WindowsInstaller.Installer
?????
JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
New Developer
  • 3,245
  • 10
  • 41
  • 78

7 Answers7

23

When trying to silently install an MSI via PowerShell using this command:

Start-Process $webDeployInstallerFilePath -ArgumentList '/quiet' -Wait

I was getting the error:

The specified executable is not a valid application for this OS platform.

I instead switched to using msiexec.exe to execute the MSI with this command, and it worked as expected:

$arguments = "/i `"$webDeployInstallerFilePath`" /quiet"
Start-Process msiexec.exe -ArgumentList $arguments -Wait

Hopefully others find this useful.

deadlydog
  • 22,611
  • 14
  • 112
  • 118
  • Also you can do `-ArgumentList '/quiet /passive`. `/passive` removes any UI that will be shown with just `/quiet` – maxc137 Apr 09 '21 at 18:19
21

Why get so fancy about it? Just invoke the .msi file:

& <path>\filename.msi

or

Start-Process <path>\filename.msi

Edit: Full list of Start-Process parameters

https://ss64.com/ps/start-process.html

Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
Adi Inbar
  • 12,097
  • 13
  • 56
  • 69
  • And you can simply add switches and other parameters to this? – Brettski Jul 08 '16 at 20:33
  • 1
    Without passing more switches, this is the equivalent of double-clicking the .msi - This does not install the package, only loads it/hands it off to msiexec in the GUI. – Orangutech Jan 12 '23 at 17:03
7

You can use:

msiexec /i "c:\package.msi"

You can also add some more optional parameters. There are common msi parameters and parameters which are specific for your installer. For common parameters just call msiexec

Andrey Marchuk
  • 13,301
  • 2
  • 36
  • 52
6
#Variables
$computername = Get-Content 'M:\Applications\Powershell\comp list\Test.txt'
$sourcefile = "\\server\Apps\LanSchool 7.7\Windows\Student.msi"
#This section will install the software 
foreach ($computer in $computername) 
{
    $destinationFolder = "\\$computer\C$\download\LanSchool"
    #This section will copy the $sourcefile to the $destinationfolder. If the Folder does not exist it will create it.
    if (!(Test-Path -path $destinationFolder))
    {
        New-Item $destinationFolder -Type Directory
    }
    Copy-Item -Path $sourcefile -Destination $destinationFolder
    Invoke-Command -ComputerName $computer -ScriptBlock { & cmd /c "msiexec.exe /i c:\download\LanSchool\Student.msi" /qn ADVANCED_OPTIONS=1 CHANNEL=100}
}

I've searched all over for this myself and came up with zilch but have finally cobbled this working script together. It's working great! Thought I'd post here hopefully someone else can benefit. It pulls in a list of computers, copies the files down to the local machines and runs it. :) party on!

Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
bonedog73
  • 91
  • 2
  • 3
  • 7
2

After some trial and tribulation, I was able to find all .msi files in a given directory and install them.

foreach($_msiFiles in 
($_msiFiles = Get-ChildItem $_Source -Recurse | Where{$_.Extension -eq ".msi"} |
 Where-Object {!($_.psiscontainter)} | Select-Object -ExpandProperty FullName)) 
{
    msiexec /i $_msiFiles /passive
}
Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
micsea64
  • 109
  • 2
  • 8
1

In powershell 5.1 you can actually use install-package, but it can't take extra msi arguments.

install-package .\file.msi

Otherwise with start-process and waiting:

start -wait file.msi ALLUSERS=1,INSTALLDIR=C:\FILE
js2010
  • 23,033
  • 6
  • 64
  • 66
-1
#$computerList = "Server Name"
#$regVar = "Name of the package "
#$packageName = "Packe name "
$computerList = $args[0]
$regVar = $args[1]
$packageName = $args[2]
foreach ($computer in $computerList)
{
    Write-Host "Connecting to $computer...."
    Invoke-Command -ComputerName $computer -Authentication Kerberos -ScriptBlock {
    param(
        $computer,
        $regVar,
        $packageName
        )

        Write-Host "Connected to $computer"
        if ([IntPtr]::Size -eq 4)
        {
            $registryLocation = Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\"
            Write-Host "Connected to 32bit Architecture"
        }
        else
        {
            $registryLocation = Get-ChildItem "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
            Write-Host "Connected to 64bit Architecture"
        }
        Write-Host "Finding previous version of `enter code here`$regVar...."
        foreach ($registryItem in $registryLocation)
        {
            if((Get-itemproperty $registryItem.PSPath).DisplayName -match $regVar)
            {
                Write-Host "Found $regVar" (Get-itemproperty $registryItem.PSPath).DisplayName
                $UninstallString = (Get-itemproperty $registryItem.PSPath).UninstallString
                    $match = [RegEx]::Match($uninstallString, "{.*?}")
                    $args = "/x $($match.Value) /qb"
                    Write-Host "Uninstalling $regVar...."
                    [diagnostics.process]::start("msiexec", $args).WaitForExit() 
                    Write-Host "Uninstalled $regVar"
            }
        }

        $path = "\\$computer\Msi\$packageName"
        Write-Host "Installaing $path...."
        $args = " /i $path /qb"
        [diagnostics.process]::start("msiexec", $args).WaitForExit()
        Write-Host "Installed $path"
    } -ArgumentList $computer, $regVar, $packageName
Write-Host "Deployment Complete"

}
Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
sumit
  • 7
  • 1