Running an exe install remotely

Brass Contributor

I want to have a script run through an OU and install an exe on each server but I'm having difficulty putting everything together. What am I doing wrong? Is there a better way to script this?

This is what I currently have.



$cmd = '\\server\share\install.exe'
$parm1 = '/S /Token='
$parm2 = 'Test$'

foreach($server in Get-ADComputer -Filter * -SearchBase "OU=Servers,DC=Domain,DC=Local")
        Invoke-Command -ComputerName $server $cmd $parm1"'"$parm2"'"



This is the error I'm currently getting.



Invoke-Command : A positional parameter cannot be found that accepts argument '/S /TOKEN='Test$''.
At C:\Scripts\Nagios-Push.ps1:7 char:9
+         Invoke-Command -ComputerName $server $cmd $parm1"'"$parm2"'"
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Invoke-Command], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.InvokeCommandCommand




1 Reply



There's a couple of issues going on here.


First, the Invoke-Command parameters are a mess and need fixing.


Secondly, because you're using a UNC to refer to the file - meaning that file you want to execute is stored on a different server to the one being targeted by the Invoke-Command statement, you're going to run into another error relating to credentials delegation.


For the credentials delegation issue, you can either:


  1. Implement something called Kerberos Constrained Delegation; or
  2. Since this is only a basic SMB access issue, use the SMB commandlets to establish an SMB session within the remote command itself.


The first point (Kerberos Constrained Delegation) is complex and more than I'm inclined to discuss here, so I'll provide an example of the second point.


I've also shifter the Get-ADComputer into the -ComputerName parameter of Invoke-Command so that the commands can be run in parallel rather than synchronously, as this will scale up significantly better.


Because of the issues with the arguments, I've taken a "best guess" approach to them in my example, so be sure to double-check what I've put in as it may not be what you had intended.


# Fetch the credential under which the remote job will be running, and for convenience, also used to establish the SMB mapping.
$LocalCredential = Get-Credential;

Invoke-Command -Credential $LocalCredential -ComputerName ((Get-ADComputer -Filter { dNSHostName -like "*" } -SearchBase "OU=Servers,DC=Domain,DC=Local" -Properties dNSHostName).dNSHostName) -ArgumentList $LocalCredential -ScriptBlock {
    # Fetch the Credential object passed in via -ArgumentList

    # Create the network credentials mapping
    New-SmbMapping -RemotePath "\\server\share" -UserName ($InternalCredential.GetNetworkCredential().Username) -Password ($InternalCredential.GetNetworkCredential().Password) -Persistent:$false;

    # Run the command
    \\server\share\install.exe /S /Token="Test$";