I'm executing remotely some scripts to get information from a server, using Plink tool from putty. The trouble comes when I use a .ps1 file, because one '?' appears on the beginning, making the first line incorrect, but with .bat files works as desired.
For example, I want to print the content of a file:
GetDate.bat:
type C:/Data/DateOfCompilation.txt
And then:
PS C:/Users/MyUser> plink -ssh <User>#<IP> -i C:\Key.ppk -m C:\Scripts\GetDate.bat
10/09/2018 14:32:02,72
Everything okay
GetDate.ps1:
Get-Content -Path C:/Data/DateOfCompilation.txt
Execution:
PS C:/Users/MyUser> plink -ssh <User>#<IP> -i C:\Key.ppk -m C:\Scripts\GetDate.ps1
?Get-Content : The term '?Get-Content' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the spelling of
the name, or if a path was included, verify that the path is correct and try
again. At line:1 char:1
+ ?Get-Content -Path C:/Data/DateOfCompilation.txt
+ ~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (?Get-Content:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Also, if I add more code, the other lines work fine, it's just the first one which fails with that '?' added at the beginning.
(However, running locally the script works fine)
I have other ps1 scripts much more extended, so using only bat files is not the best option.
I have looked at the documentation, other forums and here, but I'm not able to find anything. Maybe I do not know anything about ps1 files.
Check if there's UTF-8 BOM at the beginning of GetDate.ps1 - If there is, remove it.
Though the root cause your problem may be your misunderstanding of that -m switch of Plink does. It makes Plink read the file and send its contents (and only the contents) to the server. The server never learns, what the file extension is. So it makes no sense to use .ps vs .bat. No matter, what the extension is, the file will be interpreted by the default shell of your Windows SSH server. What is PowerShell (according to the error message).
So even your type command in .bat file was executed by PowerShell, not by cmd.exe. In PowerShell, type is an alias to Get-Content.
The reason why your .bat file works is most probably that it has no BOM, while your .ps1 has BOM. Had you executed your .ps1 with PowerShell, it would handle the BOM correctly. But you are not executing .ps1 with PowerShell, you are executing its contents, and in that case the BOM probably causes problems.
The difference is basically like between:
powershell.exe -File GetDate.ps1
and
powershell.exe < GetDate.ps1
Both do basically the same, but the latter fails with BOM, while the first handles it correctly.
Related
I'm trying to use psexec.exe to fire up Excel and then use Excel to open a specific .xlsx file.
I've just started learning psexec and I have written commands that work 'incrementally' in order to be sure my initial building blocks were correct along the way. Decided to actually start with NOTEPAD and a specific TEXT FILE to start:
(Please note, my goal is to execute this process on the local machine, not a remote machine, and for it to be Interactive, thus the -i switch)
This Works (just opens a blank Notepad window)
"C:\Users\Username\OneDrive - OrgName\Desktop\RunAs Test\psexec.exe" -i -u domain\username -p Password C:\Windows\system32\notepad.exe
This does not work - and I am positive the exe path and the file path are correct, I've tried them separately
"C:\Users\Username\OneDrive - OrgName\Desktop\RunAs Test\psexec.exe" -i -u domain\username -p Password C:\Windows\system32\notepad.exe \\server\data\mpsc-users\UserName\Test\sadf.txt
(It just returns the boilerplate 3 lines copyright, but with no mention of Error Code or results at all. Nothing else happens)
PsTools.chm is very clear on why it wont work
"Arguments to pass (note that file paths must be absolute paths on the
target system)"
"psexec.exe" -i \\somewhere.... C:\Windows\system32\notepad.exe c:\users\Isaac\desktop\hello.txt
should work (if the file exists on the remote system)
I am attempting to run a build task from a .cmd file where Powershell extracts a zip file, which helps bypass a problem with Visual Studio's limit on the number of directory characters. However, I am having problems getting the Powershell command to execute correctly. I've tried a number of variations with the quotations, and I either get a termination error, or the Powershell command outputs as a string with the zip file not extracted. Below is an example of my current .cmd file:
//%1% is a passed in command line argument for the absolute path, e.g. C:\path\to\dir
set Source=%1%directory.zip
set Destination=%1%directory
powershell -Command $pscmd = '{Add-Type -assembly "system.io.compression.filesystem";[io.compression.zipfile]::ExtractToDirectory("%Source%", "%Destination%");}'; Write-Host $pscmd;
I'm very open to a number of variations that can get this to work, provided that this task runs on the command line, uses Powershell, and can be executed from a .cmd file, which is triggered by our app's build process. I'll be happy to provide additional information if needed. Thanks!
This was a strange one. Your code above has some sort of hidden character in it. I took the code and opened it in notepad, saved as ANSI, and when you type it to command line or open it again in a new instance of notepad you can see the error.
Neither add-type nor ExtractToDirectory give output, so I removed your pscmd var.
I would open your existing script, save as ansi as a new file name, delete the original, rename the new one back to the original name.
Here is what I came up with to troubleshoot your script, and it works on my machine.
I named my script L:\util\unzip.cmd
setlocal
//%1% is a passed in command line argument for the absolute path, e.g. C:\path\to\dir
set _Source='%1\directory.zip'
set _Destination='%1\directory'
echo _Source=%_Source%
echo _Destination=%_Destination%
set _c1=Add-Type -assembly system.io.compression.filesystem;
set _c2=[io.compression.zipfile]::ExtractToDirectory(%_Source%, %_Destination%)
echo _c1=%_c1%
echo _c2=%_c2%
set _Command=^& {%_c1% %_c2%};
: to echo, use double quotes or cmd thinks text after & is another command
echo _Command="%_Command%"
pause
powershell -Command "%_Command%"
endlocal
I ran it like this, and it worked: unzip.cmd L:\util
I'll bet this this info, you are good to go.
I am using the portable version of Git for Windows, but when I use git-bash.exe to run a single command, it looks like it does not work. Can you help me find out where is the problem?
I have a PowerShell script to call below command. But looks like it does not work. I am not able to let the new cmd window to pause to see the error log:
cmd /c "d:\git\git-bash.exe dos2unix d:\test\my-script.sh"
But If double click and run bash-exe.sh, then in the git-bash.exe window type
dos2unix d:\test\my-script.sh
then it works.
There are a few different ways to call EXEs from PowerShell. One of the best ways I've found that allows you the most control is the Start-Process cmdlet. Instead of calling a cmd.exe window try this:
Start-Process -FilePath 'd:\git\git-bash.exe' -ArgumentList 'dos2unix d:\test\my-script.sh'
Better yet convert that shell script into native PowerShell! :)
Anyway, I got a walkaround. In the portable git, under \usr\bin, there is a exe called dos2unix.exe, so that I can directly call dos2unix.exe from my powershell scripts, not from git-bash.exe then call dos2unix command.
cmd /c "d:\git\usr\bin\dos2unix.exe d:\test\my-script.sh"
With this walkaround, the problem resolved. But I still don't know why powershell calls dos2unix to parse my file does not work (I mean the file is not converted after call that command).
Another solution is use the base.exe, e.g:
"%ProgramFiles%\Git\bin\bash.exe" start.sh
I am trying to make a simple script to set my gcc variables. as a .bat file.
the variable is set like this
$env:Path += ";C:\Users\Brett\Compilers\MinGW\bin"
this runs just fine when I type/paste it into power shell.
but when I paste into a script myscript.bat, and run it through powershell I get this error:
C:\Users\Brett\Compilers>"$env:Path += ";C:\Users\Brett\Compilers\MinGW\bin""
The filename, directory name, or volume label syntax is incorrect.
PS C:\Users\Scruffy\Compilers>
PowerShell is a seperate execution enviroment from with Windows Command Line (cmd.exe)
If you want to run powershell commands from a batch file you need to save the powershell script (.ps1) and pass it into powershell.exe as a command line argument.
Example:
powershell.exe -noexit c:\scripts\test.ps1
More Information is available here on Microsoft TechNet
In general, leave batch stuff to .BAT files and put PowerShell stuff into .ps1 files.
I can duplicate your results here - but those are to be expected. Cmd.exe sees a string then a path and then gets quite confused as the syntax is not one that the command prompt can handle. So it gives that error message.
If you want to add stuff to your path, then why not put the statement inside a .ps1 script file?
As mentioned by others, you need to save the code in a .ps1 file and not .bat.
This line (from Setting Windows PowerShell path variable) will do the trick:
$env:Path = $env:Path + ";C:\Users\Brett\Compilers\MinGW\bin"
Or even shorter:
$env:Path += ";C:\Users\Brett\Compilers\MinGW\bin"
In cmd (and bash), pipe "|" pushes output to another command in the original format of the first command's output (as string).
In PowerShell, everything that comes out the pipe is an object (even a string is a string object).
Because of that, some commands fail when run in a PowerShell command window as opposed to a Windows command window.
Example:
dir c:\windows | gzip > test.gz
When this command is run in the Windows command prompt window it works properly - directory listing of C:\windows gets compressed into test.gz file.
The same command in PowerShell fails, because PowerShell does not use cmd-style pipe and replaces it with PowerShell pipe (working with array of file system items).
Q. How do you disable the default piping behavior in PowerShell to make traditional Windows commands work identically in PowerShell?
I tried using the escape character "`" before the pipe "`|", but it didn't work. I also tried invoke-expression -command "command with | here", but it also failed.
if you want to send strings down the pipeline you can use the cmdlet "out-string"
For Example:
get-process | out-string
If you are specifically looking for a PowerShell way to zip up files, check out the PowerShell Community Extensions. there are a bunch of cmdlets to zip and unzip all kinds of files.
http://pscx.codeplex.com
If you can pipe the output of (CMD) dir into gzip, then gzip apparently knows how to parse dir output. The (string) output from the PowerShell dir command (aka Get-ChildItem) doesn't look the same, so gzip likely would not be able to parse it. But, I'd also guess that gzip would be happy to take a list of paths, so this would probably work:
dir c:\windows | select -ExpandProperty FullName | gzip > test.gz
No warrantees express or implied.
If you really need to use the old school DOS pipe system in PowerShell, it can be done by running a command in a separate, temporary DOS session:
& cmd /c "dir c:\windows | gzip > test.gz"
The /c switch tells cmd to run the command then exit. Of course, this only works if all the commands are old school DOS - you can't mix-n-match them with PowerShell commands.
While there are PowerShell alternatives to the example given in the question, there are lots of DOS programs that use the old pipe system and will not work in PowerShell. svnadmin load is one that I've the pleasure of having to deal with.
You can't. PowerShell was designed to pass objects down a pipeline, not text. There isn't a backwards-compatability mode to DOS.