ashtond18
ashtond18

Reputation: 23

Installing an MSI file on a remote machine with PowerShell

I'm working on a utility to automate some processes and one task is to install a .msi file on a remote machine. The file is found in C:\Users\username on the remote machine and for simplicity's sake, the filename is file.msi. The command I'm using is:

Invoke-Command -ComputerName $remoteMachine -ScriptBlock{cmd /c start /wait msiexec /i $installPath /quiet}

When I execute this on my local dev machine, it doesn't show any errors, but doesn't install the file.

However, when I copy the exact command inside the brackets and run it in a PowerShell script on the remote machine, it installs successfully. I know my $remoteMachine is correct because I use it extensively throughout the rest of the script.

I know the $installPath variable also isn't the issue because for testing purposes I hardcoded the full path and it still doesn't install.

I also have proper permissions on the remote machine because earlier in the script I copy and paste the .msi from one machine to another without a problem.

I've tried a combination of commands and have been stuck here for a while, so any help would be greatly appreciated!

Upvotes: 0

Views: 9988

Answers (2)

Ashish Jain
Ashish Jain

Reputation: 2977

Beginning in PowerShell 3.0, you can use the Using scope modifier to identify a local variable in a remote command.

syntax of Using :- $Using:<VariableName>

In your case :

Invoke-Command -ComputerName $remoteMachine -ScriptBlock{cmd /c start /wait msiexec /i $Using:installPath /quiet}

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_remote_variables?view=powershell-7.2#using-local-variables

Upvotes: 1

Sid
Sid

Reputation: 2676

Ideally, this should work.

Invoke-Command -ComputerName $remoteMachine -ScriptBlock{msiexec /i $installPath /quiet}

The reason it is failing is coz you are not passing the $installPath as argumentlist. Modify it like this.

Invoke-Command -ComputerName $remoteMachine -ScriptBlock{
param(
    [Parameter(Mandatory=$true,
                   Position=0)]
    $installPath
    )
cmd /c start /wait msiexec /i $installPath /quiet
} -ArgumentList $installPath

But if it isn't working, here is a workaround that I used a while ago. Create a .bat file with the command msiexec /i $installPath /quiet and push it to the location just like you pushed the msi file.

Now from the invoke scriptblock, simply call the bat file instead.

Invoke-Command -ComputerName $remoteMachine -ScriptBlock{C:\Users\Username\Install.bat}

where Install.bat is the name of your bat file.

Note: You might want to use the /norestart switch as well if you are not looking to cause a reboot. Depends on what you are trying to install.

Upvotes: 2

Related Questions