Aug 08 2022 09:44 AM - edited Aug 08 2022 12:56 PM
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
Aug 08 2022 05:59 PM
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:
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
Param($InternalCredential);
# 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$";
}
Cheers,
Lain