Which symbol is escape character in cmd? - powershell

I have this code:
powershell -command "& { (New-Object Net.WebClient).DownloadFile('linkToMyFile.file', 'C:\my.file') }"
it's for download file.
When I execute it in cmd on remote server - everything is ok.
But when I want to execute this code from my computer on remote server using paexec, I have some troubles with escape characters.
Command in my CMD:
psexec.exe \\remoteServer.0.1 -u username -p password -dbg -lo D:\PsExec.log cmd /c "powershell -command "& { (New-Object Net.WebClient).DownloadFile('linkToMyFile.file', 'C:\my.file') }""
I try to use ^ symbol, but the same error;
Code using ^ symbol for double-quotes:
psexec.exe \\remoteServer.0.1 -u username -p password -dbg -lo D:\PsExec.log cmd /c "powershell -command ^"& { (New-Object Net.WebClient).DownloadFile('linkToMyFile.file', 'C:\my.file') }^""
Also, I tried to use \ (like in PHP) for escape, but have the same result.
Help with this or give advice how I can remotely download a file using the command line.

Unfortunately CMD uses different escape characters depending on what is escaped and where. There is no single one escape character that would be used everywhere.
In most cases the next character is escaped by prepending it with a caret (^), e.g. in for /f loops:
for /f "tokens=1" %%a in ('type file.txt ^| find "something"') do ...
But sometimes characters are escaped by doubling them, e.g. percent characters (%) in batch scripts:
#echo off
echo %%DATE%%=%DATE%
Sometimes you may even need need to put in other escape characters (like backslashes) because you need to escape something not for CMD, but for the command the string is being passed to:
mountvol | findstr /r \\\\
Your particular scenario shouldn't require additional quotes or escaping, though. Just run the PowerShell commandline directly, without cmd /c:
paexec.exe \\remoteServer.0.1 -u username -p password powershell -command "&{...}"

Is it possible to use powershell the complete way? If so, you could try the following:
New-PsDrive -Name X -Root \\127.0.0.1\c$ -PsProvider FileSystem -Credential (Get-Credential)
Copy-Item -Path X:\RequestedFile.txt -Destination C:\Temp
Remove-PsDrive -Name X
If your destination is a http address you could perform following actions:
Invoke-WebRequest -Uri http://some.uri -Method Get -OutFile C:\temp\myfile -Credential (Get-Credential)
Hope that helps

Instead Of this:
psexec.exe \\remoteServer.0.1 -u username -p password -dbg -lo D:\PsExec.log cmd /c "powershell -command "& { (New-Object Net.WebClient).DownloadFile('linkToMyFile.file', 'C:\my.file') }""
DO this:
psexec.exe \\remoteServer.0.1 -u 'username' -p 'password' powershell.exe -Command "& {(New-Object System.Net.WebClient).DownloadFile('linkToMyFile.file', 'C:\my.file')}"
This should do your work.
Hope it helps.

Related

Prepend a command in Start-Process to provide "y" input to Plink

I saw a solution to cache a server host key by adding the command just below on the top of my script before running the other Plink tasks.
& "echo y | C:\Program Files\PuTTY\plink.exe" -ssh -batch -i $PrivateKeyPath $username "exit" 2>&1
Error message:
The term 'echoy| C:\ProgramFiles\PuTTY\plink.exe' is not recognized as the name of a cmdlet,...
So the spaces prior the pipe symbol are removed and therefore the command is not recognized.
My other attempt is to use Start-Process but I do not know how I am able to prepend echo y | to the plink.exe path.
Start-Process -FilePath 'C:\Program Files\PuTTY\plink.exe' -Argumentlist "-ssh -batch -i $PrivateKeyPath $username $command 2>&1"
Is there an option to prepend something to the -FilePath?
Do not blindly answer "y" to Plink host key verification prompt. You lose a protection against man-in-the-middle attacks.
You should use the -hostkey switch with your host key fingerprint.
Similarly for pscp: Using echo y as an automated response to a pcp hostkey prompt
& "echo y | C:\Program Files\PuTTY\plink.exe" makes echo y | part of the path to the executable.
Change this:
& "echo y | C:\Program Files\PuTTY\plink.exe" -ssh -batch -i $PrivateKeyPath $username "exit" 2>&1
into this:
echo 'y' | & 'C:\Program Files\PuTTY\plink.exe' -ssh -batch -i $PrivateKeyPath $username "exit" 2>&1

Execute powershell script using psexec

I am trying to execute PowerShell script on 10 computers on same $env:userprofile path using psexec.But it won't work. If i specify path like "c:\Users\bob\" , it works. Below script is not working.
psexec -u domain\bob -p password -h -d cmd /c powershell.exe -Command "(New-Object System.Net.Webclient).DownloadFile('http://x.x.x.x/1.exe','$env:userprofile\1.exe')"

Downloading a file from a webpage on remote computers using a batch file

When I run this command locally on a remote machine it works:
powershell -Command "(New-Object Net.WebClient).DownloadFile('<WebPath>', 'C:\Users\<user>\Desktop\file.exe')"
When I try the same command remotely using PsExec in a batch file:
(Set downloadFileCommand = powershell -Command "(New-Object Net.WebClient).DownloadFile('%WebPath%', 'C$\Users\<user>\Desktop\file.exe')")
PsExec.exe \\<remote_machine> -u %username% -p %password% -s -d cmd /c %downloadFileCommand%
I am getting "cmd started on remote_machine with process ID #id_number."
However, nothing happened and the download wasn't executed. The suggestions here:
Run PowerShell scripts on remote PC
didn't work for me.
Any suggestions?
Edit:
I managed to download the file through the command line (in cmd) using this command:
PsExec.exe \\<remote_machine> -u <username> -p <password> -d powershell -Command (New-Object Net.WebClient).DownloadFile('<url address','C:\file.exe')
But it doesn't work when I try this in a batch file:
(Set DownloadInstaller = "powershell -Command (New-Object Net.WebClient).DownloadFile('<url address','C:\file.exe')")
PsExec.exe \\<remote_machine> -u %username% -p %password% -h -d cmd /c %DownloadInstaller%
This worked - all in one line. I have a loop variable, a remote computer (%%a). I assumed that when I use PsExec, C:\ ... \file.exe "thinks" of C:\ locally in the remote computer, but that probably wasn't the case.
I had to write it all in one line, since the path in DownloadFile (The location I want to download the file to) is locally in the remote computer (which is a loop variable):
PsExec.exe \\%%a -u %username% -p %password% -h -d cmd /c powershell.exe -Command "&{ (New-Object System.Net.WebClient).DownloadFile('%url%','\\%%a\C$\Users\<username>\Desktop\%file%')}")

PowerShell: passing parameters

I run the script from the file in Jenkins. Command:
psexec -i -s cmd.exe /c echo . | powershell.exe -file "c:\Program Files (x86)\Applications\Jenkins\jobs\Deploy\workspace\Deploy\script.ps1"
How can I pass a value for the "build" variable?
Please, help me
Thanks
You would simply follow the path with your arguments. Such as:
psexec -i -s cmd.exe /c echo . | powershell.exe -file "c:\Program Files (x86)\Applications\Jenkins\jobs\Deploy\workspace\Deploy\script.ps1" '-build 1.0'
You can see the command line syntax for PowerShell.exe here. It shows:
PowerShell[.exe]
[-File <FilePath> [<Args>]]
If that does not work for you, you can try and dot source the script in a -command scriptblock, such as:
psexec -i -s cmd.exe /c echo . | powershell.exe -command {. "c:\Program Files (x86)\Applications\Jenkins\jobs\Deploy\workspace\Deploy\script.ps1" -build 1}
I made mistake in the script. I forgot to insert the following code:
Param(
[int32]$build=0
)
As TheMadTechnician said, the command to run the script is:
psexec -i -s cmd.exe /c echo . | powershell.exe -file "c:\Program Files (x86)\Applications\Jenkins\jobs\Deploy\workspace\Deploy\script.ps1" -build %BUILD_NUMBER%

Passing double quotes through PowerShell + WinRM

I am using this code to execute remote code (MSI installs) on a server. Passing double quote through the script is just not working. I tried two variations as given below (#3 and #4) along with the outputs.
Input #1 (Simple case to test double quotes in the command)
powershell.exe -inputformat none -File client.ps1 -target 1.2.3.4 -port 5985 -password "pass" -username "user" -command "echo hello"
Output (Works)
hello
Input #2 (Understandable, this won't work)
powershell.exe -inputformat none -File client.ps1 -target 1.2.3.4 -port 5985 -password "pass" -username "user" -command "echo hello world"
Output
hello
world
Input #3
powershell.exe -inputformat none -File client.ps1 -target 1.2.3.4 -port 5985 -password "pass" -username "user" -command "echo `"hello world`""
Output (What happened to the other word?)
hello
Input #4
powershell.exe -inputformat none -File client.ps1 -target 1.2.3.4 -port 5985 -password "pass" -username "user" -command #'
>> echo "hello world"
>> '#
>>
Output (Again, the 2nd word is missing)
hello
If the echo works, I should be able to incorporate the changes to the MSI commands in the Runspace based usage I am doing.
MSI setup works fine if I use the following. Notice the single quotes.
msiexec /qn /i 'C:\setups\My Software.msi'
But, I need to pass public properties and MSI does not like single quote in it. Trying to run the following opens up the MSI arguments dialog.
msiexec /qn /i 'C:\setups\My Software.msi' MYPROP='My Value'
Running this from the local command prompt on the server works fine.
msiexec /qn /i "C:\setups\My Software.msi" MYPROP="My Value"
If you're calling this from cmd.exe, you'll have to escape the double quotes according to CMD's rules.
powershell.exe -command "echo \"hello world\""
Output
hello world
Personally, I would recommend avoiding passing the parameters in from the command line if at all possible. Maybe you could store the parameter values in a file (eg. serialized XML, JSON), and have the PowerShell script read the file?
Better yet, I would suggest doing any work with processes (eg. msiexec.exe) through the Start-Process cmdlet. That way, you can build up the value for the -ArgumentList parameter in a variable, and then be guaranteed that it will get passed through exactly the way you want it, and furthermore, you will not be restricted to the quoting rules of cmd.exe.
Consider the following:
$ArgumentList = '/package "c:\setups\My Software.msi" /passive /norestart /l*v "{0}\temp\Install My Software.log" MYPROP="My Value With Spaces"' -f $env:windir;
Start-Process -FilePath msiexec.exe -ArgumentList $ArgumentList;
Or you can encode your command as base64 strings to avoid any special characters from accidentally being interpreted, like encapsulated double quotes.
powershell.exe -EncodedCommand "ZQBjAGgAbwAgACIAaABlAGwAbABvACAAdwBvAHIAbABkACIA"
Result
hello world
ZQBjAGgAbwAgACIAaABlAGwAbABvACAAdwBvAHIAbABkACIA .... is base64 representation of this. See how I didn't need to escape anything.
echo "hello world"