I am experimenting with the following script in Powershell ISE, but this returns an error when executed.
$computerName = Read-Host "Enter name of remote computer"
psexec \\"$computerName" cmd
The Read-Host part works fine, but when it moves to the psexec line it returns
Enter name of remote computer: Computer
psexec :
At line:2 char:1
+ psexec \\"$computerName" cmd
+ CategoryInfo : NotSpecified: (:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
PsExec v2.11 - Execute processes remotely
Copyright (C) 2001-2014 Mark Russinovich
Sysinternals - www.sysinternals.com
So it seems that the script is not passing the value of $computer. I have tried various " ' combinations to no avail.
Any help would be much appreciated, I'm rather novice at powershell scripting.
To expand on some of the other answers, a method a coworker showed me for more complex psexec strings is as follows:
#Use Psexec to Allow all remote connections and Enable PSRemoting
$psexec = "psexec -accepteula \\"+$targetIP+" -u "+$localadmin+" -p "+'"'+$str+'"'+' -h powershell.exe "&{"Set-Item wsman:localhost\client\trustedhosts -Value * -Force" ; "Enable-PSRemoting -SkipNetworkProfileCheck -Force"}"'
invoke-command -ScriptBlock {cmd /c $args[0]} -Argumentlist $psexec
While the above code actually calls psexec on the remote machine then delivers two powershell commands, the problem of authentication causes all sorts of crazy errors in PS.
Hope this helps someone or the OP.
updated:
right, I tried this, seems to work:
$computerName = Read-Host "Enter Name of computer"
$cred = Get-Credential
psexec \\$computerName -u $cred.UserName -p $cred.GetNetworkCredential().Password ipconfig 2> $null #hide errors
You don't need to quote anything. PowerShell will quote automatically if needed.
psexec \\$computerName cmd
Related
I am trying to generate some IDs using a adobe tool called adobe-licensing-toolkit.exe.
I need to run the command remotely in 100 computers.
Executing the command manually works flawless
C:\temp\adobe-licensing-toolkit.exe -c -f \\XXXXXXX\c$\temp\IDs.csv
Adobe Licensing Toolkit (1.1.0.98)
Operation Successfully Completed
Now I tried to replicate that using remote PS without success. I think it is a matter of parameters.
The following command ends correctly but it generates the file locally in the remote computer.
Invoke-Command -ComputerName $comp -ScriptBlock { param($whatToDo,$targetCSV) &('C:\TEMP\adobe-licensing-toolkit.exe') --$whatToDo --$targetCSV "C:\temp\ID.csv"} -ArgumentList "generateChallengeKey","filepath"
If I try to use the UNC in the parameter, the result is Operation failed.
Invoke-Command -ComputerName $comp -ScriptBlock { param($whatToDo,$targetCSV) &('\\XXXXXXXX\c$\TEMP\adobe-licensing-toolkit.exe') --$whatToDo --$targetCSV "C:\temp\ID.csv"} -ArgumentList "generateChallengeKey","filepath"
I also tried to add path in the parameter. In that case is powershell who complains.
Invoke-Command -Session $Server01 -ScriptBlock { param($whatToDo,$targetCSV) &('C:\TEMP\FRL\adobe-licensing-toolkit.exe') --$whatToDo --$targetCSV } -ArgumentList #("generateChallengeKey","filepath \\XXXXXXX\c$\temp\ID.csv")
unknown option -- filepath \\XXXXX\c$\temp\ID.csv
+ CategoryInfo : NotSpecified: (unknown option ...c$\temp\ID.csv:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
+ PSComputerName : XXXXXXX
I have the feeling that the issue is in the way parameter is passed but I haven't managed to find the solution.
The exe file is already present in all target computers.
Any suggestion?
Thanks
I would presume you have toolkit present in all remote computer in path: "C:\TEMP\adobe-licensing-toolkit.exe". You can simply use
Invoke-Command -ComputerName $comp -ScriptBlock { & "C:\TEMP\adobe-licensing-toolkit.exe" -c -f \\XXXXX\$env:Computername-IDs.csv}
Adding $env:Computername in share path would generate unique file for each computer.
I can right click on the DEC16.bat file and it will run. I am having trouble including it in a script to run from a flash drive.
The PowerShell script essentially copies over a bunch of install files onto a client's computer.
Windows PowerShell
Copyright (C) 2013 Microsoft Corporation. All rights reserved.
PS H:\> $script = "\\xxxhsfmsl03\adap\Database\Install\AugKA\DEC16.bat"
PS H:\>
PS H:\> Start-Process powershell -Credential “xxx\xxxvis_desktop” -ArgumentList '-noprofile -command &{Start-Process $script -verb runas}'
Start-Process : This command cannot be run due to the error: The directory name is invalid.
At line:1 char:1
+ Start-Process powershell -Credential “xxx\xxxvis_desktop” -ArgumentList '-noprof ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
PS H:\> $script
\\xxxhsfmsl03\adap\Database\Install\AugKA\DEC16.bat
PS H:\>
(I have inserted "xxx"'s to protect the innocent)
Try the following:
Start-Process powershell `
-WorkingDirectory (Split-Path $script) `
-Credential xxx\xxxvis_desktop `
-ArgumentList '-noprofile', '-command', "
& { start-process powershell -ArgumentList '-File', '$script' -Verb RunAs }
"
Your primary problem was most likely that the target user - xxx\xxxvis_desktop - lacked permission to access what happened to be the current directory at the time of invocation.
Setting the working directory explicitly to a directory the target user is allowed to access should fix that problem - -WorkingDirectory (Split-Path $script) sets the working dir. to the dir. in which the target script is located.
Your secondary problem - as pointed out in a comment on the question by Matt - is that the command string you passed to Start-Process was enclosed in '...' (single quotes), causing the embedded $script variable reference not to be expanded (interpolated).
Using "..." (double quotes) fixes that problem; note, however, that the command line to pass to the powershell executable is split into individual arguments passed via -ArgumentList - the (literal, single-quoted) options, followed by the (interpolated, double-quoted) command string, which is the preferable way to pass arguments, because it is more robust.
Note, how the $string reference inside the command string is enclosed in embedded '...' so as to ensure that when the invoked powershell instance parses the command string, the value of $string is recognized as a single argument (although this happens not to be necessary for the value at hand, \\xxxhsfmsl03\adap\Database\Install\AugKA\DEC16.bat).
If there's a chance that the value of $script has embedded ' instances, you must use the following (double the ' instances to escape them):
$($script -replace "'", "''")
The final problem is that you cannot use Start-Process directly on a script - as in the outer call, you need to call powershell and pass it the script filename as an argument.
Additional notes:
The & { ... } wrapper around the start-process call in the command string shouldn't be necessary.
Generally, you could use a single Start-Process call with -Verb RunAs to elevate the run of $script, but, unfortunately, -Verb RunAs and -Credential cannot be combined, so that means:
If the current user is an administrative account, the elevated session will invariably run as that user - you'll just get a yes/no prompt to confirm elevation.
Otherwise, the credentials will be prompted for, but you cannot pre-populate the username in that dialog.
Start-Process -Verb RunAs powershell -ArgumentList '-noprofile', '-File', $script
I'm automating the testing of the installation, detection, and uninstallation of some Windows applications. In order to run most of those installers silently, they must be run as nt authority\system. That is easy enough to accomplish on a local machine by invoking psexec something like this:
psexec -s setup.exe /S
I need to be able to automatically roll back the test target computer to known-good states, so I'm using another computer to orchestrate all this. Ideally I could use PowerShell remoting to start the installer on the target computer. I haven't yet found a way to achieve that.
Attempt 1: psexec from a Remote Session
The most obvious thing to do is to connect to the target computer using remoting and invoke psexec -s. Here's what that looks like:
[target.ad.example.com]: PS C:\Users\un1\Documents> C:\PsTools\PsExec.exe -s whoami
C:\PsTools\PsExec.exe :
+ CategoryInfo : NotSpecified: (:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
PsExec v2.11 - Execute processes remotely
Copyright (C) 2001-2014 Mark Russinovich
Sysinternals - www.sysinternals.com
The problem is, the process just hangs at that point.
Attempt 2: Start-Process with -Verb RunAs
Using the RunAs verb with Start-Process may well run a process elevated, but it doesn't seem to run it as nt authority\system:
whoami-to-file.bat
whoami > out.txt
PowerShell Session
[target.ad.example.com]: PS C:\> Start-Process .\whoami-to-file.bat -Verb RunAs -WorkingDirectory
[target.ad.example.com]: PS C:\> Get-Contents out.txt
example\un1
The process is not started as nt authority\system.
The Question
Is it possible to start a process as nt authority\system over PowerShell remoting? If so, how?
Note: I'm no expert at Windows security and credentials, so I don't understand the exact security implications of this technique. In my case the only credentials in question are those a temporary test computer, so there isn't much risk. I doubt this technique is a good idea for production.
It's a Double-Hop (I think)
clymb3r's article about CredSSP I think explains why psexec -s fails over PowerShell remoting. I think that PowerShell remoting counts as one hop and invoking psexec -s counts as a second hop. If that's the case we have a manifestation of the double-hop authentication problem.
Use CredSSP
I suppose there are a variety of ways to overcome the double-hop problem. This being a testing scenario, CredSSP seems appropriate (beware the security risk). Here's the proof of concept.
First you have to enable CredSSP on both computers:
PS C:\> Enable-WSManCredSSP Client -DelegateComputer target.ad.example.com
PS C:\> Invoke-Command { Enable-WSManCredSSP Server} -ComputerName target.ad.example.com
Then you can remote to the target using CredSSP:
PS C:\> $credential = Get-Credential example\target-admin
PS C:\> Enter-PSSession target.ad.example.com -Credential $credential -Authentication CredSSP
[target.ad.example.com]: PS C:\>
And psexec -s works:
[target.ad.example.com]: PS C:\> psexec -s whoami
C:\PsTools\PsExec.exe :
+ CategoryInfo : NotSpecified: (:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
PsExec v2.11 - Execute processes remotely
Copyright (C) 2001-2014 Mark Russinovich
Sysinternals - www.sysinternals.com
Connecting to local system...Starting PSEXESVC service on local system...Connecting with PsExec service on
target...Starting whoami on target...
whoami exited on target with error code 0.
nt authority\system
https://github.com/mkellerman/Invoke-CommandAs
Made a function to Invoke-Command as SYSTEM, or provided credential, against local/remote computer. Returns PSObjects, handles network interruptions and resolves any Double-Hop issues.
Try it out let me know if this resolves your issues.
PSEXEC started to give me some trouble, and I decided to recode in PowerShell.
This batch command used to work for me, before PSEXEC started messing things up:
psexec -accepteula \\<ServerToBeUpdated> -u <User> -p <Password> cmd /c "\\<ServerWithInstallationFile>\SystemEnv\Bin\Setup.exe /silent /Update"
I'm trying to do this with Invoke-Command in Powershell, but with no luck so far.
I've tried many combinations, and googled a lot, and overall it seems that PowerShell is not fond of the UNC path I'm trying to install from.
Here is what I've got:
Invoke-Command -ComputerName <ServerToBeUpdated> -ScriptBlock { Start-Process -FilePath "\\<ServerWithInstallationFile>\SystemEnv\Bin\Setup.exe" -ArgumentList "/update /silent" -wait }
I get this error message:
This command cannot be run due to the error: Access is denied.
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
+ PSComputerName : DE5441
Some people say that the setup.exe has be copied locally on the remote server. But this does not seem to be an option for me, mainly for two reasons.
My setup.exe identifies that it is not in the right path, then it kills the local the setup.exe process, and automatically starts a new setup.exe from the UNC path.
I also need the ExitCode from my setup.exe, which gets lost when the "killing" starts as mentioned in reason number 1.
As a final note, I did grant access for PowerShell to run remotely with the Enable-PSRemoting command, and I also get expected results from this simple test:
Invoke-Command -ComputerName <ServerToBeUpdated> -ScriptBlock { Hostname }
You are experiencing a so called double-hop authentication issue. If using normal authentication you will not be able to authenticate to a second computer from the machine you are invoking the command on.
To solve this you can use CredSSP.
To enable CredSSP on the machine that is being called:
Enable-WSManCredSSP -Role Server -force
To enable CredSSP on the client:
Enable-WSManCredSSP -Role Client -DelegateComputer server.domain.com -force
The -delegateComputer parameter expects a FQDN but also takes wildcards.
After enabling CredSSP you can use it to invoke your command with the parameter -authentication CredSSP
Powershell script executes commandline on local machine
$j = "remote_machine"
$comp = "\\"+$j
$command = 'D:\PSTools\PsExec.exe $comp -u Administrator -p plaintextpassword -accepteula powershell.exe c:\share\script.ps1'
Invoke-Expression "& $command"
This works, but it outputs following
PsExec.exe : At line:1 char:1
+ & D:\PSTools\PsExec.exe $comp -u Administrator -p plaintextpassword -accepteula powersh ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError PsExec v2.0 - Execute processes remotely Copyright (C) 2001-2013 Mark Russinovich
Sysinternals - www.sysinternals.com Connecting to
remote_machine...Starting PSEXESVC service on
remote_machine...Connecting with PsExec service on
remote_machine...Starting powershell.exe on remote_machine...
powershell.exe exited on remote_machine with error code 0.
How to fix?
After re-reading your question I see that this is the standard PSExec vs PowerShell issue that has been seen and discussed before. This is due to the fact that PSExec outputs its header lines to the stderr (Standard Error) stream for some of its text. The execution works fine, and it does show an exit code of 0 indicating that there is not actually an error.
This issue is only evident in PowerShell ISE, not the standard PowerShell console (unless you redirect StdErr to StdOut with PSExec <command & args> 2>&1 or something similar). To work around this, if you are going to run the script in the ISE, you can use Start-Process's -RedirectStandardError argument, or redirect StdErr through other means.