Start-Process powershell with spaces - powershell

I have been at this for a long while now, getting to the point where I'm very frustrated. I'm hoping someone can point me in the right direction.
I need to run mysqldump, for 6 specific databases.
I need each spawn to run after the last has finished. It should not run all the commands at the same time. It needs to wait.
I've tried this:
$dump = "C:\Program Files\MySQL\MySQL Server 5.6\bin\mysqldump.exe"
$args = #('-u','databaseUser','-pMySuperAwesomePasswordHere','--single-transaction','--log-error=c:\backups\mysqldump_error.log',"$database > $backupFilePath\$database.sql")
Start-Process $dump $args -Wait
I've tried this:
$cmd = $backupCmd + $database + " > " + "$backupFilePath\$database.sql"
Write-Host $cmd
invoke-expression $cmd | out-null
How do I execute a command, especially one with redirecting the output to a file on the filesystem?
Thank you.

Redirection is a shell feature. Start-Process will dutifully include the last argument with the database name and the > in the actual argument passed to mysqldump which in turn has no idea what to do with the > at all.
You probably want something like
$args = '-u','databaseUser','-pMySuperAwesomePasswordHere','--single-transaction','--log-error=c:\backups\mysqldump_error.log',"$database"
& "C:\Program Files\MySQL\MySQL Server 5.6\bin\mysqldump.exe" #args | Out-File $backupFilePath\$database.sql
Since mysqldump is a console application it will wait anyway until it's done before continuing with the script.

Related

How to read a input in a python script on the PowerShell terminal [duplicate]

What is the required syntax to redirect standard input/output on Windows PowerShell?
On Unix, we use:
$./program <input.txt >output.txt
How do I execute the same task in PowerShell?
You can't hook a file directly to stdin, but you can still access stdin.
Get-Content input.txt | ./program > output.txt
If there is someone looking for 'Get-Content' alternative for large files (as me) you can use CMD in PowerShell:
cmd.exe /c ".\program < .\input.txt"
Or you can use this PowerShell command:
Start-Process .\program.exe -RedirectStandardInput .\input.txt -NoNewWindow -Wait
It will run the program synchronously in same window. But I was not able to find out how to write result from this command to a variable when I run it in PowerShell script because it always writes data to the console.
EDIT:
To get output from Start-Process you can use option
-RedirectStandardOutput
for redirecting output to file and then read it from file:
Start-Process ".\program.exe" -RedirectStandardInput ".\input.txt" -RedirectStandardOutput ".\temp.txt" -NoNewWindow -Wait
$Result = Get-Content ".\temp.txt"
For output redirection you can use:
command > filename Redirect command output to a file (overwrite)
command >> filename APPEND into a file
command 2> filename Redirect Errors
Input redirection works in a different way. For example see this Cmdlet http://technet.microsoft.com/en-us/library/ee176843.aspx
Or you can do:
something like:
$proc = Start-Process "my.exe" "exe commandline arguments" -PassThru -wait -NoNewWindow -RedirectStandardError "path to error file" -redirectstandardinput "path to a file from where input comes"
if you want to know if process errored out, add following code:
$exitCode = $proc.get_ExitCode()
if ($exitCode){
$errItem = Get-Item "path to error file"
if ($errItem.length -gt 0){
$errors = Get-Content "path to error file" | Out-String
}
}
I find that this way I do have a better handle on execution of your scripts, when you need to handle external program/process. Otherwise I have encountered situations where script would hang out on some of external process errors.
You can also do this to have standard error and standard out go to the same place (note that in cmd, 2>&1 must be last):
get-childitem foo 2>&1 >log
Note that ">" is the same as "| out-file", and by default the encoding is unicode or utf 16. Also be careful with ">>", because it can mix ascii and unicode in the same text file. "| add-content" probably works better than ">>". "| set-content" might be preferable to ">".
There's 6 streams now. More info: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_redirection?view=powershell-5.1
I think all you can do is save to a text file and then read it into a variable after.

Powershell Redirecting standard output to file from git-bash.exe

Ive got a very basic powershell script which uses Start-Process to start another .sh script, this is working and the scripts do execute but what I need is to be able to capture the output of the called script.
Content of the scripts is below:
main.ps1
Start-Process 'C:\Program Files\Git\git-bash.exe' -ArgumentList '-- C:\test\sub.sh' -Wait -RedirectStandardOutput output.txt
sub.sh
#!/bin/bash
echo "Hello World"
The sub.sh launches and prints out Hello World in its own console, but I really need the output to either go to the calling powershell scripts console window, or to a file. The file I specify in the -RedirectStandardOutput parameter is created, but is empty.
How can I get the sh script to print to standard out to the calling script?
Thank you
git-bash is in a different world than powershell so you can not directly redirect output or use -RedirectStandardOutput.
As you supposed, you can use an temporary file but the trick is to use internal bash operand ">" to redirect output to the file from bash process :
#!/bin/bash
echo "Hello from bash World" > /c/test/tempFile.txt
Then call it from powershell, you might hide the window also :
Start-Process 'C:\Program Files\Git\git-bash.exe' -ArgumentList C:\test\sub.sh -Wait -WindowStyle Hidden
$s = Get-Content c:\test\tempFile.txt
Write-Host "s=$s"
Remove-Item c:\test\tempFile.txt
Note : You have to specifilly fully qualified path.
Another option might be using Windows 10 own bash interpreter : https://stackoverflow.com/a/44359679/11867971
As written in sub.sh, the program to execute sh files is /bin/bash, not git-bash.exe.
$output = & 'C:\Program Files\Git\usr\bin\bash.exe' C:\test\sub.sh
$output
Hello World

Compile Micro Focus Net Express 5.1 Cobol in Powershell

I am hoping someone might be able to help me with writing a COBOL MF Net Express 5.1 compile command in Powershell. I have the command as it was used in the original batch script. I am currently working on reworking this in Powershell as a build script.
COBOL.EXE "%%inFile%%" OUTDD NOERRQ NOFLAGQ NOQUERY noALTER noanim nobound checkdiv COMP errlist list() FASTLINK omf"gnt" perform-type"osvs" SCHEDULER TARGET"PENTIUM" noTRUNC vsc2(1) listpath"","%%OUTPUT%%";,;,;
My attempt at converting this to Powershell has been like this:
$cobolExe = ".\COBOL.EXE"
$expression = "& $cobolExe `"$($inputfile)`" OUTDD NOERRQ NOFLAGQ NOQUERY noALTER noanim nobound checkdiv COMP errlist list() FASTLINK omf`"gnt`" perform-type`"osvs`" SCHEDULER TARGET`"PENTIUM`" noTRUNC vsc2(1) listpath`"`", `"$binPath\`";,;,;"
Invoke-Expression $expression
Invoke-Expression:
Line |
1 | Invoke-Expression $expression
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| At line:1 char:97 + … GQ NOQUERY noALTER noanim nobound checkdiv COMP errlist list() FASTLI … + ~
An expression was expected after '('. At line:1
| char:221 + … NTIUM" noTRUNC vsc2(1) listpath"", "C:\dev\dimensions\test\bin\";,;,; + ~
Missing expression after unary operator ','. At line:1
| char:223 + … NTIUM" noTRUNC vsc2(1) listpath"", "C:\dev\dimensions\test\bin\";,;,; + ~
Missing expression after unary operator ','.
I successfully have this working with CBLLINK.EXE, but it does not require as many parameters.
$cobolFile = "$Path\cobol.dir"
$cbllinkExe = ".\CBLLINK.EXE"
$expression = "$cbllinkExe -s -o$($outputFile) `"$($inputFile)`" adis adisinit adiskey -u`"$cobolFile`""
Invoke-Expression $expression
Anyone who might have any insight and could provide some assistance, I would very much appreciate it. Please let me know if I can provide anything else?
Calling external exe's/cmd's via PowerShell requires specific attention. It is a well-documented thing.
See these details from Microsoft and others: ---
PowerShell: Running Executables
The Call Operator &
# Example:
& 'C:\Program Files\Windows Media Player\wmplayer.exe' "c:\videos\my home video.avi" /fullscreen
Things can get tricky when an external command has a lot of parameters
or there are spaces in the arguments or paths!
With spaces you have to nest Quotation marks and the result it is not
always clear!
In this case it is better to separate everything like so:
$CMD = 'SuperApp.exe'
$arg1 = 'filename1'
$arg2 = '-someswitch'
$arg3 = 'C:\documents and settings\user\desktop\some other file.txt'
$arg4 = '-yetanotherswitch'
& $CMD $arg1 $arg2 $arg3 $arg4
# or same like that:
$AllArgs = #('filename1', '-someswitch', 'C:\documents and settings\user\desktop\some other file.txt', '-yetanotherswitch')
& 'SuperApp.exe' $AllArgs
cmd /c - Using the old cmd shell
** This method should no longer be used with V3
Why: Bypasses PowerShell and runs the command from a cmd shell. Often
times used with a DIR which runs faster in the cmd shell than in
PowerShell (NOTE: This was an issue with PowerShell v2 and its use of
.Net 2.0, this is not an issue with V3).
Details: Opens a CMD prompt from within powershell and then executes
the command and returns the text of that command. The /c tells CMD
that it should terminate after the command has completed. There is
little to no reason to use this with V3.
# Example:
#runs DIR from a cmd shell, DIR in PowerShell is an alias to GCI. This will return the directory listing as a string but returns much faster than a GCI
cmd /c dir c:\windows
Using Windows PowerShell to run old command line tools (and their
weirdest parameters)
Solution 2A: Use CMD /C
As with the first problem, you can run CMD.EXE itself and pass your
command and its parameters in quotes. Efficiency aside, this will work
fine, since PowerShell will not try to parse the string in quotes.
CMD.EXE /C "ICACLS.EXE C:TEST /GRANT USERS:(F)"
<#
# Results
processed file: C:TEST
Successfully processed 1 files; Failed processing 0 files
#>
..there are more like these.

Pass Powershell Variables to Command Prompt line

I want to make a PowerShell script that can be used to connect computers to various client's SonicWall VPNs (specifically through Global VPN and NetExtender). I would like to have it be like a user interface to prompt the user (which will set the variables) and then use that information to pass through to command lines in the command prompt.
I want to be able to have information entered in be applied in the cmd line in the script.
I have tried using the MobileConnect connection through (Using the the app from the app store) and connecting with the Microsoft VPN client, but that does not grab all the network information; specifically DNS servers.
The best way is to install either Global VPN or NetExtender and connect through cmd line; that way will grab the entire network information.
This is the basic command to run it:
Function Connect-VPN {
Set-Location -Path "C:\Program Files (x86)\SonicWALL\SSL-VPN\NetExtender"
cmd /c "NECLI connect -s address:4433 -u Uname -p Password -d Domain -A"
Set-Location -Path C:\
}
Basically, you change the directory and execute the commands with those arguments.
I would like to prompt in POSH, create the variables with the user input, then have those arguments passed down.
What I have right now is:
param(
[string]$Testadd ,
[string]$Testun ,
[string]$TestPW ,
[string]$TestDom
)
If ($Testadd -eq "")
{$Testadd = (Read-Host "test")
}
If ($Testun -eq "")
{$Testun = (Read-Host "test")
}
If ($TestPW -eq "")
{$TestPW = (Read-Host "test")
}
If ($TestDom -eq "")
{$TestDom = (Read-Host "test")
}
Set-Location -Path "C:\Program Files (x86)\SonicWALL\SSL-VPN\NetExtender"
cmd /c "NECLI connect -s "$($Testadd)" -u "$($Testun)" -p "$($TestPW)" -d "$($TestDom)" -A"
Set-Location -Path C:\
The problem is that the all the arguments come out null. I do not know if it is possible, but I wanted to see.
You can try to build the string before running the cmd
param (
[string]$Testadd,
[string]$Testun,
[string]$TestPW,
[string]$TestDom
)
If ($Testadd -eq "")
{
$Testadd = (Read-Host "testadd")
}
If ($Testun -eq "")
{
$Testun = (Read-Host "testun")
}
If ($TestPW -eq "")
{
$TestPW = (Read-Host "testpw")
}
If ($TestDom -eq "")
{
$TestDom = (Read-Host "testdom")
}
Set-Location -Path "C:\Program Files (x86)\SonicWALL\SSL-VPN\NetExtender"
#build the string before
$cmd = "NECLI connect -s " + $($Testadd) + " -u " + $($Testun) + " -p " + $($TestPW) + " -d " + $($TestDom) + " -A"
# Or even like this
$cmd = "NECLI connect -s $Testadd -u $Testun -p $TestPW -d $TestDom -A"
# exec command
cmd /c $cmd
Set-Location -Path C:\
To add to #Desinternauta, I suspect it is how the command is interpreting the quotes and the variables. i.e. when you write out the string as you have it, it adds spaces:
$b = "b"
Write-Host "a"$($b)"c"
Outputs:
a b c
The good news is that double quoted strings allow you to embed the variables into the string:
cmd /c "NECLI connect -s $Testadd -u $Testun -p $TestPW -d $TestDom -A"
Calling external exe / commands that use cmd.exe, require special consideration and outing specifics. You also do not need to call cmd.exe directly, as that will just happen. This is a well documented this. For example:
PowerShell: Running Executables
The Call Operator &
Why: Used to treat a string as a SINGLE command. Useful for dealing
with spaces.
In PowerShell V2.0, if you are running 7z.exe (7-Zip.exe) or another
command that starts with a number, you have to use the command
invocation operator &.
The PowerShell V3.0 parser do it now smarter, in this case you don’t
need the & anymore .
Details: Runs a command, script, or script block. The call operator,
also known as the "invocation operator," lets you run commands that
are stored in variables and represented by strings. Because the call
operator does not parse the command,it cannot interpret command
parameters
# Example:
& 'C:\Program Files\Windows Media Player\wmplayer.exe' "c:\videos\my home video.avi" /fullscreen
Start-Process (start/saps)
Why: Starts a process and returns the .Net process object Jump if
-PassThru is provided. It also allows you to control the environment in which the process is started (user profile, output redirection
etc). You can also use the Verb parameter (right click on a file, that
list of actions) so thatyou can, for example, play a wav file.
Details: Executes a program returning the process object of the
application. Allows you to control the action on a file (verb
mentioned above) and control the environment in which the app is run.
You also have the ability to wait on the processto end. You can also
subscribe to the processes Exited event.
#Example:
#starts a process, waits for it to finish and then checks the exit code.
$p = Start-Process ping -ArgumentList "invalidhost" -wait -NoNewWindow -PassThru
$p.HasExited
$p.ExitCode
10. Stop-Parsing Symbol --%
Why: Its a quick way to handle program arguments that are not standard. Also its the new cool way to do it.
Details: The stop-parsing symbol (--%), introduced in Windows PowerShell 3.0, directs Windows PowerShell to refrain from interpreting input as Windows PowerShell commands or expressions. When calling an executable program in Windows PowerShell, placethe stop-parsing symbol before the program arguments.
After the stop-parsing symbol --% , the arguments up to the end of the line (or pipe, if you are piping) are passed as is.
#Examples:
# icacls in V2
# You must use escape characters to prevent PowerShell from misinterpreting the parentheses.
icacls X:\VMS /grant Dom\HVAdmin:`(CI`)`(OI`)F
# In V3 you can use the stop-parsing symbol.
icacls X:\VMS --% /grant Dom\HVAdmin:(CI)(OI)F
See also:
Using Windows PowerShell to run old command line tools (and their weirdest parameters)
Solve Problems with External Command Lines in PowerShell
Quoting
About Quoting Rules
A Story of PowerShell Quoting Rules

Redirecting standard input\output in Windows PowerShell

What is the required syntax to redirect standard input/output on Windows PowerShell?
On Unix, we use:
$./program <input.txt >output.txt
How do I execute the same task in PowerShell?
You can't hook a file directly to stdin, but you can still access stdin.
Get-Content input.txt | ./program > output.txt
If there is someone looking for 'Get-Content' alternative for large files (as me) you can use CMD in PowerShell:
cmd.exe /c ".\program < .\input.txt"
Or you can use this PowerShell command:
Start-Process .\program.exe -RedirectStandardInput .\input.txt -NoNewWindow -Wait
It will run the program synchronously in same window. But I was not able to find out how to write result from this command to a variable when I run it in PowerShell script because it always writes data to the console.
EDIT:
To get output from Start-Process you can use option
-RedirectStandardOutput
for redirecting output to file and then read it from file:
Start-Process ".\program.exe" -RedirectStandardInput ".\input.txt" -RedirectStandardOutput ".\temp.txt" -NoNewWindow -Wait
$Result = Get-Content ".\temp.txt"
For output redirection you can use:
command > filename Redirect command output to a file (overwrite)
command >> filename APPEND into a file
command 2> filename Redirect Errors
Input redirection works in a different way. For example see this Cmdlet http://technet.microsoft.com/en-us/library/ee176843.aspx
Or you can do:
something like:
$proc = Start-Process "my.exe" "exe commandline arguments" -PassThru -wait -NoNewWindow -RedirectStandardError "path to error file" -redirectstandardinput "path to a file from where input comes"
if you want to know if process errored out, add following code:
$exitCode = $proc.get_ExitCode()
if ($exitCode){
$errItem = Get-Item "path to error file"
if ($errItem.length -gt 0){
$errors = Get-Content "path to error file" | Out-String
}
}
I find that this way I do have a better handle on execution of your scripts, when you need to handle external program/process. Otherwise I have encountered situations where script would hang out on some of external process errors.
You can also do this to have standard error and standard out go to the same place (note that in cmd, 2>&1 must be last):
get-childitem foo 2>&1 >log
Note that ">" is the same as "| out-file", and by default the encoding is unicode or utf 16. Also be careful with ">>", because it can mix ascii and unicode in the same text file. "| add-content" probably works better than ">>". "| set-content" might be preferable to ">".
There's 6 streams now. More info: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_redirection?view=powershell-5.1
I think all you can do is save to a text file and then read it into a variable after.