Powershell Putty Connection and Automating Tasks - powershell

I want to use PowerShell to connect to a PuTTY "saved session" and then specify a file that contains some batch commands. Using CMD this would look like
d:\putty\psftp 'Saved Session Name' -b d:\location.txt.
I think that the PS equivalent should look like
Start-Process d:\putty\psftp.exe 'Saved Session Name'
(and then a call to pass a 'get' script) i.e. cd Outgoing get <date>.txt
However, I get the following error:
a positional parameter cannot be found that accepts the argument
How can I accomplish this using PowerShell?

All you need is plink:
plink 'Saved Session Name'

You don't necessarily need Start-Process.
What happens when you try to run d:\putty\psftp.exe 'Saved Session Name' -b d:\location.txt from Powershell? The first thing I do is try it exactly like I'd run it from the command line.
The biggest catch is if you have spaces in path names. You might need to use quotes and the call operator (ampersand): &"d:\putty\psftp.exe" 'Saved Session Name' -b "d:\location.txt".
If you do need to use Start-Process, you can do this:
Start-Process -FilePath "d:\putty\psftp.exe" `
-ArgumentList "'Saved Session Name' -b d:\location.txt" -Wait
Or like this:
Start-Process -FilePath "d:\putty\psftp.exe" `
-ArgumentList 'Saved Session Name', '-b', "d:\location.txt" -Wait
Note that the argument list in the first is a single string with every argument in it, and in the second it is an array of strings with one string for every argument. Everything needs to be in the same order that they'd be on the command line, and it's not uncommon for it to be a bit flaky. Usually one method or the other works better, but it depends on the application you're calling. Usually with quotes and spaces in path names because you're going through multiple levels of escaping depending on the program you're calling (noticing a theme?).
I added the -Wait parameter to my code above because, by default, Start-Process continues to the next line without waiting since it actually spawns a separate process. -Wait forces Powershell to, well, wait, which is what people usually want in a non-interactive script.
See Get-Help about_Operators or Get-Help "call operator" for more topics for help with the call operator. See Get-Help Start-Process for help with that.

Adding the below Technet Wiki link which contains various ways to run executables in PowerShell.
PowerShell: Running Executables

Try this:
$Path = "d:\putty\psftp.exe"
$Prm1 = 'Saved Session Name'
$Prm2 = "-b"
$Prm3 = "d:\location.txt"
&$Path $Prm1 $Prm2 $Prm3

Related

Command Line Command Output in start-process from exe file

Here is the program. I am using dell command | configure. The command-line command is as follows:
"C:\Program Files (x86)\Dell\Command Configure\X86_64>cctk.exe" --wakeonlan
In Powershell you can navigate to the folder and run:
./cctk.exe --wakeonlan
I can pipe the above command into a variable and get the information I need. This requires my shell to cd into the folder accordingly and run accordingly.
$test = ./cctk.exe --wakeonlan
This will give you an output. However when you use start-process, you get no output as this is a command-line command. A cmd screen appears and runs the command. So, I added a -nonewwindow and -wait flags. The output now appears on the screen, but I can't seem to capture it.
$test = start-process "C:\Program Files (x86)\Dell\Command Configure\X86_64\cctk.exe" -ArgumentList #("--wakeonlan") -NoNewWindow -Wait
At this point test is empty. I tried using the Out-File to capture the information as well. No success. The command outputs to the screen but nowhere else.
I also tried the cmd method where you pipe the information in using the /C flag.
$test = Start-Process cmd -ArgumentList '/C start "C:\Program Files (x86)\Dell\Command Configure\X86_64\cctk.exe" "--wakeonlan"' -NoNewWindow -Wait
However, I have tried many variations of this command with no luck. Some say C:\Program is not recognized. Some just open command prompt. The above says --wakeonlan is an unknown command.
Any pointers would help greatly.
There are various ways to run this without the added complication of start-process.
Add to the path temporarily:
$env:path += ';C:\Program Files (x86)\Dell\Command Configure\X86_64;'
cctk
Call operator:
& 'C:\Program Files (x86)\Dell\Command Configure\X86_64\cctk'
Backquote all spaces and parentheses:
C:\Program` Files` `(x86`)\Dell\Command` Configure\X86_64\cctk
To elaborate on js2010's helpful answer:
In short: Because your executable path is quoted, direct invocation requires use of &, the call operator, for syntactic reasons - see this answer for details.
To synchronously execute console applications or batch files and capture their output, call them directly ($output = c:\path\to\some.exe ... or $output = & $exePath ...), do not use Start-Process (or the System.Diagnostics.Process API it is based on) - see this answer for more information.
If you do use Start-Process, which may be necessary in special situations, such as needing to run with a different user identity:
The only way to capture output is in text files, via the -RedirectStandardOutput / -RedirectStandardError parameters. Note that the character encoding of the output files is determined by the encoding stored in [Console]::OutputEncoding[1], which reflects the current console output code page, which defaults to the system's active legacy OEM code page.
By contrast, even with -NoNewWindow -Wait, directly capturing output with $output = ... does not work, because the launched process writes directly to the console, bypassing PowerShell's success output stream, which is the one variable assignments capture.
[1] PowerShell uses the same encoding to decode output from external programs in direct invocations - see this answer for details.

How to run an executable (exe) by providing a config file in powershell

I'm trying to run an exe in the background by providing a config file (yml in my case)
Tried the below, however this is not pushing the execution to background. -
./my.exe start --config-file $my_config_file
Found 'start-process' command which are specifically used for this case. With argument list is there any way to send the config file?
Start-Process -Wait -FilePath "my.exe" -ArgumentList
Remove the -Wait argument and pass the process arguments as an array via -ArgumentList parameter:
Start-Process -FilePath "my.exe" -ArgumentList 'start', '--config-file', "`"$my_config_file`""
The strange quoting for $my_config_file is required because a path may contain spaces. Start-Process does not do automatic quoting. From the docs:
If parameters or parameter values contain a space, they need to be surrounded with escaped double quotes.
Note that you won't receive output of the started process, if that matters to you. You can redirect to a file, using parameters -RedirectStandardOutput and -RedirectStandardError, but you can't (easily) store the output in a variable.
A way to start a process in the background, while being able to receive its output, is to create a job.

PowerShell run Ultraedit Script

Is it possible to run an UltraEdit macro or script from the PowerShell? Something like following:
uedit64.exe c:\temp\test.txt /s,e="c:\temp\script.js"
I have nothing special. I just want to open the log file with UltraEdit and as soon the log file is opened the UltraEdit Script should be executed on that. The following code opens the log file but does not execute the script on that.
$ultraEdit = "C:\...\UltraEdit\uedit64.exe"
$logFile = "C:\...\res.log"
$scriptFile = "C:\...\ultraEditScript.js"
Start-Process -FilePath $ultraEdit -ArgumentList "$logFile /s=`"$scriptFile`""
Absolutely! Powershell has a few different "call" operators.
https://ss64.com/ps/call.html
Take a look at the documentation for Start-process.
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/start-process?view=powershell-6
Start-Process -FilePath "c:\pathtoexe\uedit64.exe" -ArgumentList "c:\temp\test.txt /s,e=`"c:\temp\script.js`""
Should work for you (change the path of course.
Yes, it is possible. The problem with your current example is surrounding quoting rules with arguments:
uedit64.exe c:\temp\test.txt '/s,e="c:\temp\script.js"'
This form should work. When you use commas, powershell will interpret that as an array. The safest way to pass arguments to an external executable is to use the stop-parser operator (--%) to avoid powershell's interpretation, but note this falls back to the cmd parser on Windows:
#requires -Version 3
uedit64.exe --% C:\Temp\test.txt /s,e="C:\Temp\script.js"
What the difference in parsers means is that you can't expand variables (if you wanted $path\script.js) in the arguments after the stop-parser, but you can still utilize environment variables using the batch syntax %VAR%.
As a best-practice, it's recommended to fully-qualify your path and use the call operator for clarity:
& C:\Temp\uedit64.exe
Thanks everyone,
The problem was with Select-String that split the matched lines, therefore, the script did not perform any action due to improper file structure.
These two works great :-)
1. & $ultraEdit /fni $logFile /S=$scriptFile
2. Start-Process -FilePath $ultraEdit -ArgumentList "$logFile /S=$scriptFile"

Launch PowerShell script into new window while passing variables

I've been using the site for a while, searching through the questions and answers, trying to map them to my scenario, but I'm either missing something, or what I'm looking to do isn't possible (at least the way I'm trying to do it), hence I'm hoping for a push in the right direction. Thanks in advance for reading.
I've been working on a fairly sizeable automation project. My main script performs a number of tasks, and generally works well, and reliably. At one stage of the script, I execute another PowerShell script, which was written by another team. I call the script as follows:
.\DeployMySQLProvider.ps1 -AzCredential $asdkCreds `
-VMLocalCredential $vmLocalAdminCreds `
-CloudAdminCredential $cloudAdminCreds
-PrivilegedEndpoint $ERCSip `
-DefaultSSLCertificatePassword $secureVMpwd -AcceptLicense
When I call it this way, from my main script, it works fine, however, this script uses and registers a DLL file during it's deployment, and locks it until the PowerShell window and session is closed. At the end of my main script, I have a cleanup phase, which can't complete it's job because of this locked DLL.
My thoughts therefore, were to launch the 2nd script into a new PowerShell window and session, either using Start-Process or Invoke-Expression, but I just can't seem to get either right. Most of the variables I'm passing through to the 2nd script aren't just strings, which is probably where I'm falling over. They are a mix of usernames and passwords (secure strings) along with $ERCSip which is a string.
Should I be looking at Start-Process / Invoke-Expression, or something else entirely? When I was testing with Start-Process, I had the following defined, but couldn't get the ArgumentList side working correcly for me (blank below):
Start-Process "$pshome\powershell.exe" -PassThru -Wait `
-Verb RunAs -ErrorAction Stop -ArgumentList ""
Any pointers in the right direction would be much appreciated.
Thanks!
I've used something similar to this in my scripting:
$scriptpath="c:\pathto\deploysqlProvider"
$a = "$scriptpath\DeployMySQLProvider.ps1 -AzCredential $asdkCreds `
-VMLocalCredential $vmLocalAdminCreds `
-CloudAdminCredential $cloudAdminCreds
-PrivilegedEndpoint $ERCSip ` "
-DefaultSSLCertificatePassword $secureVMpwd -AcceptLicense
Start-Process -Verb runas -FilePath powershell.exe -ArgumentList $a -wait -PassThru ;
Not sure if you need it to runas admin or not (-verb runas).
I'd suggest you then look for the Powershell process and path. So that if you have to kill this separate process you can.

Run Powershell script that uses -List (parameter) with alternate credentials that

I was struggling to get this simple (?) function working today.
I have a PowerShell script that reads computer names from a txt-based file. It works fine when run from a PowerShell session by the following one-liner:
./"Server Health Check.ps1" -List One-off.txt
As you can see, it's got a long file name, so it's wrapped with quotes.
However, I'm building a PowerShell GUI form with radio boxes that will pass on a choice for a text file that will be used to a call the script. Trick is, the script needs to be run with alternate admin account, and i'm not clear how to make that work.
For another script I've got that doesn't use I know i can use something along the lines of the following, this uses the old DOS "runas", however, it doesn't work with the -list function.
invoke-command -scriptblock {runas.exe /user:domain\$Env:Username"admin" "powershell.exe -file \"\\Server\c$\LONG FOLDER\Server Health Check.PS1""}
So, in a nutshell, how do get a script to launch with alternate credentials that reads a parameter (-List) from the command line? I'm also keen to preserve my directory structure, which includes folders with spaces. The script is titled: "Server health check.ps1"
The last thing I tried was the following
$ScriptPath = "C:\SCRIPTS FOLDER\Server Health Check.ps1"
$ArgList = "-List C:\SCRIPTS FOLDER\One-off.txt"
Invoke-Command -filepath $ScriptPath -Credential DragonBallDomain\$Env:UserName"Admin" -ArgumentList $ArgList
The result was the following message:
Invoke-Command : Parameter set cannot be resolved using the specified named parameters.
I'm almost certain this is do-able by invoke-command or start-process, it's just a matter of getting the correct formatting? I'm probably missing a / or a ' or "" somewhere in my trials with start-process or invoke-command.
Any help appreciated!
Update for April 30:
I've tried some more to make this work, i'm close, but still not quite there.
$LongScriptPath = resolve-path Script.ps1
$LongFolderPath = \\UNC\PATH TO FOLDER\WITH LONG NAME\
start-process -filepath powershell.exe -argumentlist " -file``"$($FilePath.path)`"" -cred DOMAIN\USERID -WorkingDirectory "$LongFolderPath"
Adding the -credential is what causes an error that states that the -file parameter is invalid. I'm sure there's a way to do this.
Note: Completely rewritten after the requirements became clearer.
To run a command as a different user locally, use Start-Process -Credential ...
That is what you've attempted in your update in principle, but there are problems with how you're passing parameters; try this instead:
$LongScriptPath = resolve-path Script.ps1
$LongFolderPath = '\\UNC\PATH TO FOLDER\WITH LONG NAME\'
start-process `
powershell.exe `
-ArgumentList '-file', $LongScriptPath, '-List', 'One-off.txt' `
-Credential DOMAIN\USERID `
-WorkingDirectory $LongFolderPath
The key to making this work is to pass all parameters to pass to powershell.exe as an array via Start-Process's -ArgumentList parameter, which means that the parameters must be ,-separated.
Note how an array is always parsed in expression mode, which means that literal string elements such as -file and -List must be quoted.
It is important in general to understand the difference between PowerShell's two fundamental parsing modes, argument mode and expression mode, and which is applied when - see https://technet.microsoft.com/en-us/library/hh847892.aspx
Add -Wait to wait for the script to finish; Start-Process is asynchronous by default (all PS cmdlets named Start-* are).
Caveat: For commands invoked as a different user, you can only wait from an elevated prompt.
If it isn't, the command will still execute, but will do so asynchronously, and you'll get an Access denied error message in the current console; in effect, -Wait is ignored.
Only if not running as a different user: Add -NoNewWindow -Wait if you want to run the script in the current console window; Start-Process opens a new window by default for console applications such as powershell.exe and cmd.exe.
If you do run the command as a different user, -NoNewWindow is quietly ignored.
As for the original symptom and why using Invoke-Command to run a command locally as a different user is ill-advised:
Invoke-Command -Credential ... requires that the -ComputerName parameter be specified too.
Run Get-Help Invoke-Command to see all parameter sets that involve the -Credential parameter. The OP's original command had only -Credential, but not -ComputerName, which caused PS to complain that no parameter set could be unambiguously identified.
Once you use -ComputerName, PowerShell remoting is invariably used, even if you specify . - the local computer - as the only computer to target.
Using remoting has two implications:
Remoting is not available by default, and must be configured on the target computer (the local computer, in this case).
Using remoting requires invocation with admin privileges.
In short:
While you can perform purely local invocations with Invoke-Command, you cannot do so as another user, because that invariably involves remoting.
Start-Process, by contrast, solely exists to run commands locally, optionally as a different user.