Set encoding in curl command in powershell - powershell

I have curl command stored in variable ($command). The command looks like this:
curl -F "login=xxx" -F "password=xxx" "title=Some title" -F "img=#/path/to/image" https://example.com/api/import
Then i execute the command:
Invoke-Expression ($command)
Everything is fine unless title contains special characters like "č,š,ý..." because server expects UTF8 encoded parameters. In such case special characters are replaced with questionmarks on the website.
I tried setting [Console]::OutputEncoding and $OutputEncoding to UTF8 but it didn't solve the problem.When i run the command on linux (ubuntu) everything is fine because it uses UTF8 as default encoding, so i rewrote the script to bash to get the job done. But i'm still wondering if it's possible in powershell somehow. Any suggestions appreciated.

Settting [Console]::OutputEncoding works for me. Are you sure you're setting it correctly?
C:\PS> [console]::OutputEncoding = [text.encoding]::UTF8
C:\PS> echoargs "title=č,š,ý"
Arg 0 is <title=č,š,ý>
Command line:
"C:\Program Files (x86)\PowerShell Community Extensions\Pscx3\Pscx\Apps\EchoArgs.exe" title=č,š,ý
Echoargs is a tool from PSCX.

Related

PowerShell Producing Unreadable Output

Image Here For Reference
Specifically the text after "Similarity" and "->"
I have a small PowerShell script that uses ssh to connect to a server and run a command.
I believe it produces unreadable output due to some of the text having to be in colour.
I've tried adding the following, but still no luck:
$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding
To define console encoding you can use following expressions.
Choose encoding you need.
$ConsoleEncoding = [System.Text.Encoding]::UTF8
Apply your encoding to console.
[Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding( "$( $ConsoleEncoding.BodyName )" )
Solved it, turns out that the command I needed was ssh -t host command to enable the colour display
More info here: https://explainshell.com/explain?cmd=ssh+-t+my_host+my_command

Script in powershell not working with array variables

I am creating a PowerShell script just to backup my WSL distros, but when I try to run the command with variables it's not working, it displays the usage text as though I provided the incorrect arguments.
$DistrosArray1 = (wsl -l --quiet) | where {$_ -ne ""}
$DistrosArray2 = 'Arch', 'Ubuntu-22.04', 'docker-desktop-data', 'docker-desktop'
$CheckArrayDifference = Compare-Object -ReferenceObject $DistrosArray1 -DifferenceObject $DistrosArray2 -PassThru
echo $CheckArrayDifference
# Does not return anything (there is no difference)
foreach ($Distro in $DistrosArray1) {
wsl --export $Distro "$Distro.tar"
# This method is not working
}
foreach ($Distro in $DistrosArray2) {
wsl --export $Distro "$Distro.tar"
# This method is working
}
It sounds like you are running into complications from issue #4607 -- The wsl.exe command outputs some oddly mangled UTF16 encoding that creates issues when attempting to process it from PowerShell (or even from inside WSL).
This is now fixed in the latest WSL Preview release 0.64.0, but you do have to "opt-in" to the fix so that older workarounds (like the ones #Bender and I provided) don't inadvertently break.
Simply set:
$env:WSL_UTF8=1
... before your code, and WSL will no longer spit out the "mangled UTF16."
Other examples in my answers to:
Why cannot I match for strings from wsl.exe output?
Powershell - Strange WSL output string encoding
How to ask WSL to check if the distribution exists, using Bash and wsl.exe?
Older solution:
Let's simplify the problem and make a "safe" example that doesn't attempt to export:
$DistrosArray1 = (wsl -l --quiet) | where {$_ -ne ""}
wsl -d $DistrosArray1[0]
Results in:
There is no distribution with the supplied name.
I've successfully used the method in this comment to handle it. For this particular example:
$console = ([console]::OutputEncoding)
[console]::OutputEncoding = New-Object System.Text.UnicodeEncoding
$DistrosArray1 = (wsl -l --quiet) | where {$_ -ne ""}
wsl -d $DistrosArray1[0]
This will run the first distribution in the list correctly.
Reset the encoding after with:
[console]::OutputEncoding = $console
That shouldn't be a problem for most non-interactive scripts since it will just be the final line of the "wrapper", but as #BendertheGreatest pointed out in the comments, it's a critical step.
This is part of a known issue with wsl.exe output. Here is what I put together from workarounds provided on that issue:
$DistrosArray1 = wsl -l --quiet | wsl iconv -c -f utf16 -t ascii
foreach ($Distro in $DistrosArray1) {
wsl --export $Distro "$Distro.tar"
}
Unfortunately I could not get this working with a conversion to UTF8 (changing ascii to utf8 produces additional garbage characters although they are consistent and detectable in my limited testing), so only any characters outside of the ASCII range will likely cause problems for you.

Running executable with command line parameters in PowerShell

This has to be possible. I am able to open a command prompt in windows and do the following:
<some exe> <some exe command line parameters>
There must be an equivalent way to do this in PowerShell or even a standard windows batch file. For example, from the windows command prompt I can start a docker container with:
docker run –-net=kafka -d –-name=zookeeper -e ZOOKEEPER_CLIENT_PORT=2181 confluentinc/cp-zookeeper:4.1.0
however if I try something like this with PowerShell
& "docker" run –-net=kafka -d –-name=zookeeper -e ZOOKEEPER_CLIENT_PORT=2181 confluentinc/cp-zookeeper:4.1.0
it fails with an generic error:
invalid reference format.
Perhaps PowerShell is not suited for this type of advanced use case. Any suggestions would be appreciated!
Is there a better scripting language for advanced usages like this?
I think Start-Process cmdlet will be useful. ArgumentList can be single or double quoted.
Start-Process docker -ArgumentList "run –-net=kafka -d –-name=zookeeper -e ZOOKEEPER_CLIENT_PORT=2181 confluentinc/cp-zookeeper:4.1.0"
By and large, external programs in PowerShell are called the same way as from cmd.exe - there are differences, due to PowerShell having additional metacharacters such as $ and #, but they do not come into play in your specific case.
(Your & "docker" ... variant would work in principle too, but the use of & is only necessary if you must use a quoted or variable-based command name or path).
The problem is that your original command line contains two instances of – (EN DASH, U+2013) instead of the expected ASCII-range - dash (hyphen), which docker doesn't recognize.
A quick way to discover the problem:
# Print the code points of characters outside the ASCII range.
PS> [int[]] [char[]] '& "docker" run –-net=kafka -d –-name=zookeeper -e ZOOKEEPER_CLIENT_PORT=2181 confluentinc/cp-zookeeper:4.1.0' -gt 127
8211
8211
Decimal 8211 is hex. 0x2013, the code point of en-dash, whereas the code point of the regular - is 45 (0x2d).
All that is needed is to replace these – instances with - (and, since docker needn't be quoted, there is no need for &):
docker run --net=kafka -d --name=zookeeper -e ZOOKEEPER_CLIENT_PORT=2181 confluentinc/cp-zookeeper:4.1.0
Your own answer shows a variable-based implementation of the command that is effectively the same as the command above - if all the arguments are known in advance, there is never a need to use variables.
If you do want to use variables, it is much simpler to use a single array variable for all the arguments and pass that:
$dockerExe = 'docker'
$dockerArgs = 'run',
'--net=kafka',
'-d',
'--name=zookeeper',
'-e',
'ZOOKEEPER_CLIENT_PORT=2181',
'confluentinc/cp-zookeeper:4.1.0'
& $dockerExe $dockerArgs
Note:
The executable name/path must always be specified separately, and if it is quoted or involves variable references (as in this case), &, the call operator must be used for invocation, for syntactic reasons.
Passing the arguments as an array this way works with external programs; for PowerShell commands, you'd create a hashtable variable that you pass with sigil # instead of $, a feature known as splatting.
There is a lot of complexities in powershell escaping. I wrote this module to assist with running of external commands:
https://github.com/choovick/ps-invoke-externalcommand
Demo:
https://terminalizer.com/view/49acb54a979
Install-Module -Name ExternalCommand -Scope CurrentUser
Invoke-ExternalCommand -Command "docker" -Arguments #("run","-d","--name=zookeeper","--net=kafka","-e","ZOOKEEPER_CLIENT_PORT=2181", "confluentinc/cp-zookeeper:4.1.0")
Here's how to do it.
$app = 'docker'
$a1 = 'run'
$a2 = '--net=kafka'
$a3 = '-d'
$a4 = '--name=zookeeper'
$a5 = '-e'
$a6 = 'ZOOKEEPER_CLIENT_PORT=2181'
$a7 = 'confluentinc/cp-zookeeper:4.1.0'
& $app $a1 $a2 $a3 $a4 $a5 $a6 $a7

How to run a large base64 encoded file via powershell

I have a powershell.ps1 script that I performed base64 encoding upon as below
$Base64 = [System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes('c:\path\to\powershell.ps1'));
Now I have stored this output to base64.txt file.
I tried to launch this script as below via CMD,
powershell.exe -EncodedCommand (Base64String)
But I ended up in the below error
Cannot process the command because the value specified with -EncodedCommand is not properly encoded. The value must be Base64 encoded.
I realized that the CMD is not taking the entire (Base64String). The full length of my (Base64String) is 11,133 characters. But CMD is accepting only 8160 characters.
Is there any way or workaround to run this base64 encoding?
Thanks in advance.
This worked for me (myscript.ps1 contains the base64 encoded command):
powershell -encodedcommand (Get-Content 'myscript.ps1' -Raw)
Which is very similar to what you would do in Bash:
$ powershell -encodedcommand `cat myscript.ps1`
Obs: Addressing some comments, this is sometimes indeed needed. My particular use case was to do a reverse shell while dodging an AV on a windows machine that was detecting my plaintext shell code.

UTF8 Script in PowerShell outputs incorrect characters

I've created a UTF8 script for PowerShell with non-ascii characters.
characters.ps1:
Write-Host "ç â ã á à"
When the script is run in PowerShell console, it outputs wrong characters.
However, if I write the chars directly in the console, they are shown as expected:
Does anyone knows what causes that behavior?
The problem arised from a script I wrote who has hardcoded paths which include non-ascii characters. When I try to pass the path as argument to cmdlets (in the case I was gonna robocopy a folder) the command fails because it cannot find the path (which is output wrongly in the screen).
Changing the encoding of the script to UTF-8 with BOM solved the issue.
I was using SublimeText with the EncodingHelper plugin to control the character-set of the script. It was set correctly to UTF8.
I changed the encoding of the script in SublimeText to "UTF-8 with BOM" and the output was shown correctly.
I created the same script with Notepad++, which defaults to "UTF-8 with BOM", and the string was shown correctly in the console.
I changed the encoding of the script in Notepad++ to "UTF-8 without BOM" and it was shown incorrectly.
It seems PowerShell cannot guess correctly the encoding of UTF-8 files with no BOM.
In my case the problem was caused by creating a new PowerShell script with Visual Studio Code which has the default encoding of UTF-8 without BOM. Set the encoding to "Windows 1252" solved the problem.
It seems that PowerShell can't handle UTF-8 without BOM, it needs "Windows 1252" or "UTF8 with BOM" encodings.
try this before invoking your script :
$OutputEncoding = [Console]::OutputEncoding
There is a reliable way to detect utf8nobom (https://unicodebook.readthedocs.io/guess_encoding.html). Like a lot of other little things, this seems to work better in PS 6. Even my beloved emacs 25 for windows gets the encoding wrong.
PS C:\users\admin> pwsh
PowerShell 6.1.0
Copyright (c) Microsoft Corporation. All rights reserved.
https://aka.ms/pscore6-docs
Type 'help' to get help.
PS C:\users\admin> "write-host 'ç â ã á à'" | set-content -Encoding utf8NoBOM accent.ps1
PS C:\users\admin> .\accent
ç â ã á à