powershell invoke-expression issue - powershell

I have a command to extract a file using 7z and it works in a DOS command line. The command is:
"C:\Documents and Settings\e.DEV\My Documents\7z.exe" x -o"C:\Documents and Settings\e.DEV\My Documents\utils" "C:\Documents and Settings\e.DEV\My Documents\rsasecureidtoken411.zip"
Now I have to run the upper command in powershell, I use a call operator & to call it (in Powershell command line), but it seems there are some errors with it. It just shows >> at the next line when I press enter, and I have to press Ctrl + c to stop the command.
PS C:\> & "C:\Documents and Settings\e.DEV\My Documents\7z.exe" x -o"C:\Documents and Settings\e.DEV\My Documents\utils" "C:\Documents and Settings\e.DEV\My Documents\RSASecurIDToken411.zip"
>>
>>
>>
>>
>>
>>
PS C:\>
I've also tried invoke-expression but still can't make it work. Anyone can help with it?
Thanks.

try this:
[string]$pathToZipExe = "C:\Documents and Settings\e.DEV\My Documents\7z.exe"
[Array]$arguments = "x", "-oC:\Documents and Settings\e.DEV\My Documents\utils", "C:\Documents and Settings\e.DEV\My Documents\RSASecurIDToken411.zip"
& $pathToZipExe $arguments

Related

Multiple "pg_dump" calls in Powershell, only one is run

I'm creating a Powershell script to backup 2 PostgreSQL databases using Postgres' pg_dump tool. I'm using Powershell 2.0 on Windows 7 and PostgreSQL 9.3.
The simplified script looks like this:
$postgresDir="C:\PostgreSQL\9.3"
$pgUser="postgres"
$pgPort="5432"
$dbName1="db1"
$dbName2="db2"
$currentBackupFile1 = "C:\temp\backup\1.backup"
$currentBackupFile2 = "C:\temp\backup\2.backup"
& ($postgresDir + "\bin\pg_dump.exe") ("-U" + $pgUser) ("--dbname=" + $dbName1) ("--port=" + $pgPort) ("--file=`"" + $currentBackupFile1 + "`"") -v 2>&1 | out-host
& ($postgresDir + "\bin\pg_dump.exe") ("-U" + $pgUser) ("--dbname=" + $dbName2) ("--port=" + $pgPort) ("--file=`"" + $currentBackupFile2 + "`"") -v 2>&1 | out-host
Everything works as expected when the script is run from Windows Powershell IDE. But when the script is started from commandline or via a batch file like this:
powershell -file pg_dump.ps1
, only the first pg_dump gets executed, the second is simply ignored without any errors. Other Powershell cmdlets that follow after these statements are executed normally.
The problem vanishes as soon as I remove the stderr redirection (2>&1) at the end of the statements, making it
& ($postgresDir + "\bin\pg_dump.exe") ("-U" + $pgUser) ("--dbname=" + $dbName1) ("--port=" + $pgPort) ("--file=`"" + $currentBackupFile1 + "`"") -v | out-host
Also, the problem does not apply to other programs per se. For example, when substituting the pg_dumps with two & dir 2>&1 statements, these statements are both executed when run from a batch script. It may be a pg_dump thing.
Update in reply to Ansgar Wiechers comment.
Using splatting like this:
$exe=($postgresDir + "\bin\pg_dump.exe")
$args1= '-U', $pgUser, '--dbname', $dbName1, '--port', $pgPort, '--file', $currentBackupFile1, '2>&1'
& $exe #args1
leads to pg_dump complaining about having too many command line arguments. Using it like this:
$exe=($postgresDir + "\bin\pg_dump.exe")
$args1 = '-U', $pgUser, '-d', $dbName1, '-p', $pgPort, '-f', $currentBackupFile1
& $exe #args1 2>&1
$args2 = '-U', $pgUser, '-d', $dbName2, '-p', $pgPort, '-f', $currentBackupFile2
& $exe #args2 2>&1
yields the same result as the first example.

How to correctly escape spaces and backslashes in command line arguments?

I had some issues passing an array of strings to a command in PowerShell, so I'm debugging my script. I'm using the EchoArgs.exe program found in the PowerShell Community Extension Project (PSCX).
If I execute this script:
Import-Module Pscx
cls
$thisOne = 'this_one\';
$secondOne = 'second one\';
$lastOne = 'last_one'
$args = $thisOne `
, "the $secondOne" `
, "the_$lastOne"
EchoArgs $args
I get this result:
Arg 0 is <this_one\>
Arg 1 is <the second one" the_last_one>
Command line:
"C:\Program Files (x86)\PowerShell Community Extensions\Pscx3\Pscx\Apps\EchoArgs.exe" this_one\ "the second one\" the_last_one
It seems that if a string contains spaces, the last backslash escapes the double quote. In fact all seems working if I escape only that backslash:
Import-Module Pscx
cls
$thisOne = 'this_one\';
$secondOne = 'second one\\';
$lastOne = 'last_one'
$args = $thisOne `
, "the $secondOne" `
, "the_$lastOne"
EchoArgs $args
with this result:
Arg 0 is <this_one\>
Arg 1 is <the second one\>
Arg 2 is <the_last_one>
Command line:
"C:\Program Files (x86)\PowerShell Community Extensions\Pscx3\Pscx\Apps\EchoArgs.exe" this_one\ "the second one\\" the_last_one
Is there a "smart" way in PowerShell (i.e. a cmdlet) to escape any string in order to avoid such issues?
Try using Start-Process instead. It has an $Arguments parameter that would suit this better.
See here: PowerShell - Start-Process and Cmdline Switches

Invoke-Command Powershell parameter issue

I need to pass a comma delimited parameter to a batch file via powershell and can't seem to get it to work. Here's how I call the batch file if I call it directly in powershell:
PS C:\Users\Mike> type zz.cmd
#echo off
echo/* = [%*}
echo/1 = [%1]
echo/2 = [%2]
echo/3 = [%3]
pause
PS C:\Users\Mike> cmd /c zz "q,w,e"
* = [q,w,e}
1 = [q]
2 = [w]
3 = [e]
Press any key to continue . . .
If I use cmd /c zz """q,w,e""" or cmd /c zz '"q,w,e"' I will get "q,w,e" for arg 1. This is good. However, I must call powershell using Invoke-Command. When doing this, the script doesn't work:
powershell.exe Invoke-Command -ScriptBlock { "cmd /c E:\\npoess\\oo\\WoD\\zzz" '"q,w,e"'}
Any idea how to get the powershell call from the command prompt to get "q,w,e" as one parameter to the batch file?
Thanks,
-Mike
this invoke-command without all the quotes works for passing a for me :
I think that the quotes around the variables passes the set as a string instead of separate values.
Invoke-Command -ScriptBlock {
cmd /c C:\scripts\zz.cmd q,w,e
}

start-process in PowerShell 3.0 script doesn't work but it was working in 2.0

I upgraded our PS version to 3.0 and some of our scripts stopped working. After a lot of debugging I realized there is an issue with the Start-Process command.
Basically, when I run the Start-Process directly in the PowerShell cmd it does run the program with the correct arguments. However, when I run the script, it won't give any error but the program will not run.
The script is a bit long, but this is the way I can test the snippet that's failing.
$SERVER = 'servername'
$PORT = 'xxxx'
$TPath = 'E:\epicor\PowerShell\export\POAutomation\'
$User = 'username'
$Psw = 'password'
$Import = 'PO Combined'
$file = $TPath + 'AutomaticPOHeaders.csv'
$DMTPATH = 'E:\epicor\Epicor905\Client\dmt.exe'
$Param = "-ArgumentList `'-user=`"$User`" -pass=`"$Psw`" -server=$SERVER -port=$PORT -import=`"$Import`" -source=`"$file`" -add=true -update=false -noui=true`'"
Start-Process $DMTPATH $Param -Wait
"Finished"
I even wrote to a log file to check if the $Param string is well formed and if the Start-Process command is also well written. When I copy paste the strings in the log file into the PS command line, they run successfully.
I've been stuck with this more than 4 hours now.
Thanks in advance.
i dont know what dmt is waiting for but this command runs successfully on ps V3.
are you sure about you argumentlist parameter ? and seems to be a mess with your quotes
slight changes : use echoargs.exe instead of DMT and add a switch to not open a new window :
$DMTPATH = 'echoargs.exe'
$Param = "-ArgumentList `'-user=`"$User`" -pass=`"$Psw`" -server=$SERVER -port=$PORT -import=`"$Import`" -source=`"$file`" -add=true -update=false -noui=true`'"
Start-Process -nonewwindow $DMTPATH $Param -Wait
"Finished"
results :
Arg 0 is <-ArgumentList>
Arg 1 is <'-user=username>
Arg 2 is <-pass=password>
Arg 3 is <-server=servername>
Arg 4 is <-port=xxxx>
Arg 5 is <-import=PO Combined>
Arg 6 is <-source=E:\epicor\PowerShell\export\POAutomation\AutomaticPOHeaders.csv>
Arg 7 is <-add=true>
Arg 8 is <-update=false>
Arg 9 is <-noui=true'>
Command line:
"C:\Windows\EchoArgs.exe" -ArgumentList '-user="username" -pass="password" -server=servername -port=xxxx -import="PO Combined" -source="E:\epicor\PowerShell\export\POAutomation\AutomaticPOH
aders.csv" -add=true -update=false -noui=true'
Finished
Can you try to start dmt from cmd.exe ? something like :
$p=#("/C";"dmt.exe";"-user'test'" ....)
Start-Process -NoNewWindow cmd.exe $p
I run into the same problem. I noticed if the -noui=true is removed, it seems to work.

Piping from a variable instead of file in Powershell

Is ther any way in Powershell to pipe in from an virable instead of a file?
There are commands that I need to pipe into another command, right now that is done by first creating a file with the additional commands, and then piping that file into the original command. Code looks somehting like this now:
$val = "*some command*" + "`r`n" + "*some command*" + "`r`n" + "*some command*"
New-Item -name Commands.txt -type "file" -value $val
$command = #'
db2cmd.exe /C '*custom db2 command* < \Commands.txt > \Output.xml'
'#
Invoke-Expression -Command:$command
So instead of creating that file, can I somehow just pipe in $val insatead of Commands.txt?
Try this
$val = #("*some command*1","*some command2*","*some command3*")
$val | % { db2cmd.exe /C $_ > \Output.xml }
You should be able to pipe in from $val provided you use Write-Output or its shorthand echo, but it may also be worth trying passing the commands directly on the command line. Try this (and if it doesn't work I can delete the answer):
PS C:\> filter db2cmd() { $_ | db2cmd.exe ($args -replace '(\\*)"','$1$1\"') }
PS C:\> $val = #"
>> *custom db2 command*
>> *some command*
>> *some command*
>> *some command*
>> "#
>>
PS C:\> db2cmd /C $val > \Output.xml
What happens here is that Windows executables receive their command line from a single string. If you run them from cmd.exe you cannot pass newlines in the argument string, but Powershell doesn't have that restriction so with many programs you can actually pass multiple lines as a single argument. I don't know db2cmd.exe so it might not work here.
The strange bit of string replacement is to handle any double quotes in the arguments: Powershell doesn't quote them and the quoting rules expected by most exe files are a bit bizarre.
The only limitation here would be that $val must not exceed about 32,600 characters and cannot contain nulls. Any other restrictions (such as whether non-ascii unicode characters work) would depend on the application.
Failing that:
echo $val | db2cmd.exe /C '*custom db2 command*' > \Output.xml
may work, or you can use it in combination with the filter I defined at the top:
echo $val | db2cmd /C '*custom db2 command*' > \Output.xml