2goarray works in cmd but not powershell - powershell

I am trying to use 2goarray to write a .ico file to a go file so that I can use it in systray.
My problem is that this works in cmd:
TYPE icon.ico | 2goarray Data icon > icon.go
But running the equivalent command in powershell does not:
Get-Content .\icon.ico | 2goarray Data icon | Out-File -FilePath .\icon.go -Encoding UTF8
When I say it doesn't work, I don't mean an error occurs, I mean that the array produced by 2goarray is not correct, it contains data that systray doesn't recognize as an icon.
For reference, here is the working icon.go, here is the broken/corrupted one produced by powershell, and here is the icon I am using.
I suspect it has something to do with the way that powershell passes things as objects, but I'm not sure?

Your challenge is to pipe binary data in PowerShell, which is not that straight forward. I tested your example with this command and I get the "working" icon.go:
Start-Process 2goarray -ArgumentList "Data icon" -RedirectStandardInput .\icon.ico -RedirectStandardOutput .\icon.go
But this solution seems to be quite slow compared to cmd. From PowerShell you can also always call cmd if you want to, which works surprisingly faster for your example:
Start-Process cmd -ArgumentList "/c TYPE icon.ico | 2goarray Data icon > icon.go"
Often, it is a bad design to call cmd from PowerShell, because PowerShell can nearly do everything that cmd can do, and often more, but for your example, this seems to be the better solution.

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.

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.

Running executables in Powershell with complex arguments

I am working on converting an old massive batch file logging script to Powershell. Creating the data has not been a major issue, but I am having an issue with the final step. The final step in the old batch file converts an ugly CSV into a more pretty and easy-on-the-eyes CSV. This is done using an old AWK script and a gawk command. I am content leaving that step in place, but I want it to be executed from within the Powershell script.
The command looks something like this:
<gawk.exe> -f <path>\PrepareReport.awk <original.csv> >> <final.csv>
I have tried different ways of calling gawk and the arguments. Invoke-Expression, Invoke-Command, etc. Nothing seems to work to run this command properly. Any insight or ideas would be appreciated.
Thanks!
EDIT: Following all the comments, I have found the & is the option that works to make this happen. The Start-Process cmdlet causes a fatal error. One weird thing is still happening though. For some reason the resulting CSV file does not display normally in Excel. Even though the resulting file seems to be perfectly normal, Excel won't display it using the appropriate comma breaks. Any thoughts?
You could always use Start-Process.
Start-Process -NoNewWindow -Wait -PassThru -FilePath <gawk.exe> -ArgumentList "-f <path>\PrepareReport.awk <original.csv> >> <final.csv>"
It's a little wordy, but very customisable and very flexible.

Get-Content with wait parameter doesn't update in Powershell

I'm trying to monitor a file using Get-Content $path -wait in Windows Powershell V3.0. Sometimes when I execute this command line in Powershell it will function as expected. But sometimes it will only execute (or at least it seems like) get-content but without the -wait parameter. Even though the file get's updated it won't be shown in Powershell. If I cancel the command and rerun it it will show the updated file content.
What do I need to do?
EDIT: It seems to update blocks after a while. But it's not real-time really.
Not allowed to comment (don't have a 50 reputation), so have to give an Answer....
Less for Windows (http://gnuwin32.sourceforge.net/packages/less.htm) with the +F or Shift-F option (http://www.commandlinefu.com/commands/view/1024/make-less-behave-like-tail-f.) showed updated file content where PowerShell "get-content $path -wait" did not.