Get-Content -Raw alternative for older Shell - powershell

According to my last question Compare two Files I finally mentioned to get all to work inside my .bat. Thanks again for all the support.
However, as I find out today my supervisor is using Powershell in Version 2 instead of 5.1 than I do.
The problem now is that the -Raw paramterer of this code:
$target = Get-Content "C:/pbr_tmp/PBreport/trc/TlsTrace.prn" -Raw is not recognized.
Is there some alternative implementation instead of using -Raw?
Pupose of -Raw: The commands in this example get the contents of a file as one string, instead of an array of strings.
I am not sure If an upgrade from PS2 to PS5.1 is possible.

When using PowerShell version 2 you can use
$target = [System.IO.File]::ReadAllText("C:/pbr_tmp/PBreport/trc/TlsTrace.prn")
From SS64:
-Raw
Return multiple lines as a single string (PowerShell 3.0)
In PowerShell 2.0 use the static method: [System.IO.File]::ReadAllText(string path)

Related

Converting to and from Base64 in Powershell 5.1

I've found a couple of resources (including Convert base64 string to file, which is practically a duplicate here since it's one of the resources I used to build this) but I can't seem to get it working.
I've got the following code (roughly - obviously it's stripped down,) and I can verify most of the steps of the process as per the comments.
$pic = Get-Content 'testpic.png'
# $pic looks like a binary dump.
$picBytes = [System.Text.Encoding]::Unicode.GetBytes($pic)
$ $picBytes is an array of bytes. Quite spammy.
$picEncoded = [Convert]::ToBase64String($picBytes)
# $picEncoded is indeed a Base64 string. Halfway there!
$picDecoded = [Convert]::FromBase64String($picEncoded)
# Also an array of bytes. I'm assuming they're right for now...
$outFile = "pic.png"
[IO.File]::WriteAllBytes($outFile,$picDecoded)
# but I get no output file and no error?
What am I missing here? For what it's worth, I'm willing to look at other solutions - but the Base64 is somewhat important (since I'm storing the data in the script.)
To read a binary file as-is into memory in PowerShell, use Get-Content's -AsByteStream switch (PowerShell (Core) 7+) / -Encoding Byte (Windows PowerShell, versions up to v5.1), and add the -Raw switch for efficiency when you're reading all bytes into memory at once:
# Windows PowerShell (up to v5.1).
# Note: In PowerShell (Core) v7+, you must use -AsByteStream instead of
# -Encoding Byte
$picBytes = Get-Content testpic.png -Encoding Byte -Raw
Note: This change in syntax between the PowerShell editions is unfortunate, as discussed in GitHub issue #7986. If enough people show interest, it is conceivable that -Encoding Byte will be reintroduced for cross-edition consistency and compatibility.
$picBytes, as a [byte[]] array, can then be passed directly to [Convert]::ToBase64String()
To pass a file name/path to a .NET method, always pass a full path, never a relative path or mere file name:
This is necessary, because .NET's working directory usually differs from PowerShell's.
This discrepancy is unfortunate, but cannot be avoided, as explained in this answer.
In the simplest case - if your current location is a file-system location that is not based on a PowerShell-specific drive:
$outFile = "$PWD/pic.png" # Use *full path*
[IO.File]::WriteAllBytes($outFile, $picDecoded)
The fully robust approach requires more work:
$outFile = Join-Path (Get-Location -PSProvider FileSystem).ProviderPath pic.png
[IO.File]::WriteAllBytes($outFile, $picDecoded)

Running a command with arguments assistance

I have a command which runs a program in silent mode, it uses an XML file for the data repository and a word template to create multiple word documents based on a filter xml file.
The command I use is:
"P:\ath to\executable" -Username:Admin -Password:Pa55w0rd -Datadefinition:"C:\Data.xml" -Datafilter:"C:\Filter.xml" -wordtemplate:"C:\Batch\Paul1.dotx" -Targetdocument:="C:\Batch\Paul1.pdf" -filetype:PDF -Log:"C:\Logs\error.log" -Usage:DOCGENSILENT
I need to run this as a PowerShell script which I have mostly managed:
set-executionpolicy unrestricted
$datadefinition = Get-Content "C:\Data file.xml"
$datafilter = Get-Content "C:\Filter for data file.xml"
$wordTemplate = Get-Content "C:\"C:\Template\Paul1.dotx"
$targetFolder = Get-Content "C:\"C:\Paul\Paul.pdf"
Stop-Job = "Executable path" -Username:Admin -Password:Pa55w0rd -Datadefinition:%dataDefinition% -Datafilter:%dataFilter% -wordtemplate:%wordTemplate% -Targetdocument:%targetFolder% -filetype:docx -Log:%logPath% -Usage:DOCGENSILENT
Stop-Job 1
set-executionpolicy restricted
Write-Host -NoNewLine "Press any key to continue..."
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
My issue is that the script starts the executable but then doesnt pass the Variables, can anyone guide me in the right direction to fix this?
Getting this working depends on the behavior of your executable. Some things I noticed:
Shouldn't this:
$wordTemplate = Get-Content "C:\"C:\Template\Paul1.dotx"
be this:
$wordTemplate = "C:\Template\Paul1.dotx"
Are you sure you need Get-Content? (Aside from that, the path and quoting in your sample are not correct.)
Shouldn't this:
$targetFolder = Get-Content "C:\"C:\Paul\Paul.pdf"
be this:
$targetDocument = "C:\Paul\Paul.pdf"
I doubt Get-Content is correct here, since presumably your output file doesn't exist yet? I also renamed the variable so it makes more sense in your command.
In fact, are you sure you need Get-Content for any of those? Aren't you specifying filenames, not the content of the files?
In PowerShell, variables are prefixed with $ rather than being surrounded by %.
Using Set-ExecutionPolicy within a script to enable scripts to run is pointless, because the script is already running. (That is, if execution policy prevented script execution, PowerShell wouldn't let you run the script in the first place.)
If my guesses regarding your variables are correct, I think your script should look something like this (note also that I specified a $logFile variable, which I didn't see in your script):
$datadefinition = "C:\Users\Administrator\data\Sample Model_146_object type(s).xml"
$datafilter = "C:\Users\Administrator\data\Sample Model_146_object type(s).xml"
$wordtemplate = "C:\Users\Administrator\Templates\Base object.docx"
$targetdocument = "C:\Users\Administrator\Result\sample test15"
$logfile = "C:\Users\Administrator\Logs\C4W Error.log"
& "C:\Program Files (x86)\Communicator4Word.exe" -Username:Admin -Password: -Datadefinition:$datadefinition -Datafilter:$datafilter -wordtemplate:$wordtemplate -Targetdocument:$targetdocument -filetype:docx -Log:$logfile -Usage:DOCGENSILENT
I don't know the behavior of Communicator4Word.exe when you use -Password: with no password after it. (Is that a syntax error, or should you just omit -Password: altogether?)

Atlassian Bamboo - Inject variable having '?' in string, possible encoding issue

I have a script task in powershell inline script in which i use
$text2 = "isApproved=$isApproved"
then i use,
Out-File -FilePath "${bamboo.build.working.directory}\repovar.properties" -InputObject $text2 -Append -Encoding utf8
$isApproved is determined in the script and can have value 0/1.
the properties file is showing proper key-value pair (isApproved=0). However, when i run the inject bamboo variable task, it injects a '?' symbol in the variable name
10-Aug-2020 05:17:58 key: [inject.?isApproved] value: [0] type: RESULT
It's a peculiar problem as it sometimes inject properly but sometimes doesn't. All other variables are injected in proper format.
When i remove the -Encoding utf8 in the cmdlet to default (utf8 with NoBOM), it then writes like this
i s A p p r o v e d = 0 and bamboo injects like this
bamboo.inject._i_s_A_p_p_r_o_v_e_d
I have tried with batch script as well, i still see a '?'. Can anybody help me with an workaround?
If i switch to script file instead of inline script, can i still use the previous inject variables??
This is not well documented indeed - you need to replace dots with underscores, i.e. for a plan variable named your.plan.variable, which you would reference in a regular Bamboo task as ${bamboo.your.plan.variable}, the resp. PowerShell syntax for use within the Script task is $bamboo_your_plan_variable.
I found the answer from the Atlassian forum, here it is
Out-File -FilePath "${bamboo.build.working.directory}\repovar.properties" -InputObject $text2 -Append -Encoding ascii
Changing encoding to ASCII did the trick.

Calling a powershell script from another powershell script and guaranteeing it is UTF8

I assembled a Powershell script that is designed to grab other scripts that are hosted on Azure blobs, and execute them.
The relevant code blocks:
Obtaining the script:
$resp = (Invoke-WebRequest -Uri $scriptUri -Method GET -ContentType "application/octet-stream;charset=utf-8")
$migrationScript = [system.Text.Encoding]::UTF8.GetString($resp.RawContentStream.ToArray());
$tempPath = Get-ScriptDirectory
$fileLocation = CreateTempFile $tempPath "migrationScript.ps1" $migrationScript
Creating the file:
$newFile = "$tempFolder"+"\"+"$fileName"
Write-Host "Creating temporary file $newFile"
[System.IO.File]::WriteAllText($newFile, $fileContents)
And then I invoke the downloaded file with
Invoke-Expression "& `"$fileLocation`" $migrationArgs"
This is working well, for what I need. However, the Invoke-Expression is not correctly reading the encoding of the file. It opens correctly in Notepad or Notepad++, but not in ISE (where I am executing the script right now).
Is there a way I can ensure the script is read correctly? It is necessary to support UTF8, as there is a possibility that the scripts will need to perform operations such as setting an AppSetting to a value that contains special characters.
EDIT: Behaviour is the same on "vanilla" non-ISE Powershell invocation.
As per #lit and #PetSerAI, the BOM is required for Powershell to work correctly.
My first attempt had not been successful, so I switched back to non-BOM, but, with the following steps, it worked:
Perform the Invoke-WebRequest with -ContentType "application/octet-stream;charset=utf-8"
Grab the Raw content (you will see it in Powershell as a series of numbers, which I assume are the ascii codes?) and convert its bytes with [system.Text.Encoding]::UTF8.GetString($resp.RawContentStream.ToArray()); to an array containing the characters you want.
When saving the file via .NET's WriteAllText, ensure you use UTF8,
[System.IO.File]::WriteAllText($newFile, $fileContents, [System.Text.Encoding]::UTF8). In this case, UTF8 is understood to be UTF8 with a byte order mark, and is what Powershell needs.

How to find new cmdlets in Powershell v3.0

I wanted to find the new cmdlets / functions in Powershell. I used the following approach, but not sure if it is comprehensive / correct. Any ideas to find this in a better / different way?
Run the below once from v2 and once from v3 ( and write to a different file)
get-command -Module Microsoft.PowerShell.* |
select -expand name | out-file e:\poshv2.txt
Then use Compare-Object to see what's added ( or removed)
Compare-Object (gc e:\poshv2.txt) (gc e:\poshv3.txt)
My observation based on this is that there were 25 new cmdlets added ( and none were removed)
One question that was raised as a comment on my blog was that Disable-PsRemoting, which appeared in this list, is not really new. The reason it appeared was that it was not in the modules under Microsoft.Powershell.* ( and it was not a cmdlet), but it is in v3.0.
The only difference which you already noted is that in v2 Disable-PsRemoting was a function and in v3 it's a cmdlet. I wrote about cmdlet and parameter changes in v3 (using a similar compare method) on the PowerShell Magazine website.
http://www.powershellmagazine.com/2011/09/15/how-to-find-out-whats-new-in-powershell-vnext/