Converting batch file to powershell with special characters in path - batch-file

I'm having a hard time to write a simple batch file as powershell script.
Consider this folder structure. Note the directory with the cool [1] in it...
exiftool.exe
Is a command utility to (for example) extract pictures from embedded MP3 tags.
I uploaded its help if you need more info.
oldscript.cmd
exiftool -picture -b input.mp3 > output.jpg
This line is the one to write in powershell. I found the syntax in a forum post from the author
-picture stands for the tag to extract and -b stands for binary mode
input.mp3 is my test mp3 which can contain special characters in its path like [ and ]
> output.jpg defines the name and saves the resulting image in the same folder
newscript.ps1
My best current non-working code is:
$ownpath = Split-Path $MyInvocation.MyCommand.Path
$exe = $ownpath + '\exiftool.exe'
$input = $ownpath + '\input.mp3'
$outimg = $ownpath + '\output.jpg'
& $exe -picture -binary $input| Set-Content -literalPath $outimg -encoding UTF8
I found Set-Content which is able to handle special characters in pathes through "-literalpath". But I'm still not able to convert the batch to a Powershell script because
Set-Content (and Out-File method too) seems work different compared to old batch piping (">"). The resulting image is not viewable regardless which encoding I use. The help file from above says that exiftool is using UTF8 encoding.
Of course I tried other available encodings, but all of them failed to produce a viewable image. I'm stuck at this point. So my initial question still stands partly "How do I convert this batch file to powershell".
So why is it working when using the old batch command?
For example: create a folder "D:folder" and place this MP3 file with a cover image in it.
Download exiftool.exe from above and place it there too.
The old batch command will work and give you a viewable image
D:\folder\exiftool -picture -binary D:\folder\input.mp3 > D:\folder\output.jpg
The new Powershell V2 script with the same syntax will fail. Why?
& D:\folder\exiftool.exe -picture -binary D:\folder\input.mp3 > D:\folder\output.jpg

You can try this, though I've not tested it 'cause I've not an mp3 with embedded images:
$file = & "D:\folder\exiftool.exe" -picture -binary "D:\folder\input.mp3"
[io.file]::WriteAllBytes('D:\folder\input[1].jpg',$file)
Edit:
using this line from a powershell console return a readable image:
cmd.exe /c "D:\folder\exiftool.exe -picture -binary `"D:\folder\input.mp3`" > image.jpg"
You can use special characters in path and in file name as:
$exe = "c:\ps\exiftool.exe"
$mp3 = "c:\ps\a[1]\input.mp3"
$jpg = " c:\ps\a[1]\image[1].jpg"
cmd.exe /c "$exe -picture -binary $mp3 > $jpg"
with spaces inside path:
$exe = "c:\ps\exiftool.exe"
$mp3 = "`"c:\ps\a [1]\input.mp3`""
$jpg = "`"c:\ps\a [1]\image [1].jpg`""
cmd.exe /c "$exe -picture -binary $mp3 > $jpg"

Try this:
& $exe -picture -b $input | Out-File -LiteralPath $output
There is no need to complicate things by using Start-Process. Because you compute the path to the exe and put that result in a string, you only need use the call operator & to invoke the command named by the string that follows it.

Here is a work around. It seems you can't avoid good old cmd.exe completely.
Thanks should go # C.B.
$ownpath = Split-Path $MyInvocation.MyCommand.Path
$exe = $ownpath + '\exiftool.exe'
$input = $ownpath + '\input.mp3'
$output = $ownpath + '\output.jpg'
cmd.exe /c " `"$exe`" -picture -binary `"$input`" > `"$output`" "
Note:
This way all pathes can contain special characters like [ and ] or spaces
That extra space in " `"$exe is important. It won't work without it.
The normal Powershell way with set-content, Out-File (">" is an alias) and [io.file]::WriteAllBytes all don't work with the exiftool.exe utility. For me its a miracle.

Related

Read text file content using batch file command

I have text file having content like
8.4.0.154
newline
I have written below command in a batch file to read the first line means 8.4.0.154
set /p ClientSideUnitTestDestinationLocation=<%scriptLocation%\assemblyVersion.txt
Echo %ClientSideUnitTestDestinationLocation%
here it is just printing 8 prefixes with some special symbol as shown in below image
could anyone help me out here to figure it out that why am not able to read complete number in batch file and print it out.
Thanks in advance
I was creating this text file using PowerShell script using below command:
param ([string] $dllPath = $null,[string] $textFile = $null)
$version = [System.Reflection.Assembly]::LoadFrom($dllPath).GetName().Version.ToString()
$version > $textFile
The text file was not getting created with ANSI encoding hence, unable to read using a batch file.
Now, I changed the above code as below and it is working.
param ([string] $dllPath = $null,[string] $textFile = $null)
$version = [System.Reflection.Assembly]::LoadFrom($dllPath).GetName().Version.ToString()
$version | Out-File $textFile -Encoding Ascii
I am able to read the text file content using below command
set /p ClientSideUnitTestDestinationLocation=<%scriptLocation%\assemblyVersion.txt
Echo %ClientSideUnitTestDestinationLocation%

CMD runs in terminal but not in .BAT

I'm trying to combine all my commands into a .BAT file. This line use to find and replace text in a file, works just fine in CMD, but when i put this in to a .BAT file, it does not. I am using windows 7
powershell -Command "(gc src\template.html) -replace 'xxxxx', '%1' | Out-File src\%1.html"
Error
After extensive googling, I guess the % needs to be an escape, however, when I do that, the filename becomes %1.html and not the variables of %1.hmtl. How do I get the variables in?

Powershell redirection of an array to a file

I'm using this site for a some time without ever finding the need to ask a question myself as most of the time I find the answer fairly easily
But my next question is kinda hard to search for with keywords, so here I am asking.
I am trying to take an output of an array, and redirect it to a batch file.
For example:
PS C:\Users\Administrator> $Exmpl = "echo one","echo two"
PS C:\Users\Administrator> $Exmpl
echo one
echo two
PS C:\Users\Administrator> $Exmpl > ExmplFile.bat
So far so good. The problem begins when I want to execute this new script
(In this example I'm using the same shell but it works the same in a CMD shell).
PS C:\Users\Administrator> .\ExmplFile.bat
C:\Users\Administrator>■e
'■e' is not recognized as an internal or external command, operable program or batch file.
After a little exploring, I found:
It acts the same even if I create the file with no extentions and later on add the .bat extension.
If I open the file, and change the entire content to something else like "cd .." - the same error occurs. Like the whole file is damaged from its' creation.
The "e" in the string in the error ■e refers to the first letter in the file. For example after I've changed the content to the command "cd .." - the string in the execution error was ■c. Like it detects an unknown character before the first letter, and after the first letter it detects some sort of a line break.
Can you guys please share your knowledge as I assume it's not a hard question for those of you who know how the redirection to a file in powershell works?
Thanks in advance.
Sounds like an encoding problem. Output redirection is probably using multibyte characters, e.g., UTF-16 or what .Net calls "Unicode". Alternately, it's UTF-8 with a byte order mark.
Try:
Set-Content -Path 'ExmplFile.bat' -Value $Exmpl -Encoding Ascii
Or:
$Exmpl | Out-File -FilePath 'ExmplFile.bat' -Encoding ascii

Powershell Rename & Move Files via CSV

I've tried searching for a solution to my dilemma, I've even tried combining a few solutions from here, but have had no success.
My dilemma is that I download a lot of files all at once, and they tend to be given non descriptive names. I want a script that will read a CSV file with the following format:
current path,new path
Where current path is the full current path including file name, and new path is the full new path including file name.
I need this as a powershell script preferably, since that's my default, though cmd is usable as well. I'm currently running Windows 8.1 if that's needed info.
I would include the code I've already tried, but that would take up a lot of space, and I'm on my phone.
As a rule I wouldn't do this, but I had this one from a while back, it should put you on the right track.
$Files = "Path:\to\Files\"
$CSV = "Path:\to\CSV\file.csv"
$Import = import-csv $CSV
$RENAME = get-childitem $Files
$Import | % {
$old = $_.old #Column Title for Old file name
$new = $_.new #Column Title for New file name
rename-item $old $new
}

Convert PowerShell script into non-readable format

I have a PowerShell script which installs a patch (contains set of files to be added) on a customer machine. For this, I have created a batch file which executes this PowerShell script.
For the customer to run this batch file, the PowerShell script file must be placed onto the customer machine as well.
The PowerShell script is in text format, which can be read and understood by the customer easily.
Can we convert this script file into some non-readable format (e.g. bin or exe), so that it is not readable by the customer?
You can convert the script to Base64 encoding, so that it's not immediately readable. To convert a PowerShell script file to a Base64 String, run the following command:
$Base64 = [System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes('c:\path\to\script file.ps1'));
To launch the Base64-encoded script, you can call PowerShell.exe as follows:
powershell.exe -EncodedCommand <Base64String>
For example, the following command:
powershell.exe -EncodedCommand VwByAGkAdABlAC0ASABvAHMAdAAgAC0ATwBiAGoAZQBjAHQAIAAiAEgAZQBsAGwAbwAsACAAdwBvAHIAbABkACEAIgA7AA==
Will return the following results:
Hello, world!
I tried the solution proposed by #TrevorSullivan, but it gave me error
The term '????' is not recognized as the name of a cmdlet, function,
script file or operable program...
As I found out later there was a problem with bad encoding. I found somewhere another approach and when I combined those two, I got working PS command:
$Base64 = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes([System.IO.File]::ReadAllText("script.ps1")))
Then I can redirect the result to file:
$Base64 > base64Script.txt
from where I just copy the encoded command and paste it here instead of <Base64String>:
powershell.exe -EncodedCommand <Base64String>
and it works without any problem.
Thanks guys for your posts. I took #Frimlik's post and created my own script to automate the process. I hope this helps someone.
Save the script to a ps1 file and run it.
Function Get-FileName($initialDirectory)
{
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.initialDirectory = $initialDirectory
$OpenFileDialog.ShowDialog() | Out-Null
$OpenFileDialog.filename
}
Function EncodePS1ToBat {
$ScriptToEncode = Get-FileName
# Encode the script into the variable $Base64
$Base64 = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes([System.IO.File]::ReadAllText($ScriptToEncode)))
# Get the path and name to be used as output
$filePath = Split-Path $ScriptToEncode -Parent
$fileName = (Split-Path $ScriptToEncode -Leaf).Split(".")[0]
# Output the encoded script into a batch file on the same directory of the origial script
"#echo off`n powershell.exe -ExecutionPolicy Bypass -EncodedCommand $Base64" |
Out-File -FilePath "$filePath\$fileName`_Encoded.bat" -Force -Encoding ascii
}
# Call the funtion to encode the script to a batch file
EncodePS1ToBat

Resources