CMD runs in terminal but not in .BAT - batch-file

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?

Related

Can't run a Powershell command in a SQL Server Agent Job Step

I tried with "Powershell" option and commands (both don't work):
Get-Item "*.csv" | Out-File "d:\tracking\$(get-date -f yyyyMMdd-hhmmss).txt"
"Get-Item """*.csv""" | Out-File """d:\tracking\$(get-date -f yyyyMMdd-hhmmss).txt""""
And tried with "CmdExec" option and command (it doesn't work):
powershell.exe -Command "Get-Item """*.csv""" | Out-File """d:\tracking\$(get-date -f yyyyMMdd-hhmmss).txt""""
But the last command runs ok on a separate cmd.exe window
and the following also runs ok inside the powershell:
Get-Item "*.csv" | Out-File "d:\tracking\$(get-date -f yyyyMMdd-hhmmss).txt"
They create a text file eg. "20220607-112233.txt" containing the directory listing of CSV files
However I can't get this command to work from within the Job Step
The step finishes with "Unable to run. Syntax error"
Ok, I found a solution:
I created a batch (.bat file) with the code inside block 2:
powershell.exe -Command "Get-Item """*.csv""" | Out-File """d:\tracking\$(get-date -f yyyyMMdd-HHmmss).txt""""
(I only changed the hh for HH, for 24 hours based time)
Then, I configured the Job Step to run the bat file (setting the option "cmdExec")
That's all
I don't know what was going on, directory permissions were ok, the command of code block #2 above even works if I execute it with xp_cmdshell

Bat file for Windows 10 Custom Start Menu

I have a .bat file, (which makes a custom start menu from a custom .xml file), to deploy to a group of machines.
Here is what I got:
PowerShell.exe -Command "&Import-StartLayout –LayoutPath C:\Installs\StartMenu.xml –MountPath $env:SystemDrive\"
When I run the PowerShell command itself it works but for some reason I cannot get it to work from the .bat file.
Here are my comments, put together as an answer:
PowerShell -C "&{Import-StartLayout -LayoutPath C:\Installs\StartMenu.xml -MountPath %SystemDrive%\}"
I had to change my code to:
PowerShell.exe -Command "&{Import-StartLayout -LayoutPath C:\Installs\StartMenu.xml -MountPath $env:%SystemDrive%\}"
The suggestions from Compo seemed to work.

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

Running Powershell command in a command line/batch file

I am creating a batch file which involves converting a SID to local/domain username. Since we can not achieve this using the command prompt I am planning to use powershell and I have the PS command as well. I am able to run it in powershell console without any issue, but not sure how to use it in command prompt as a SINGLE LINE(to use it in batch file). I have already tried the below.
Powershell command which works perfectly in PS console -
([System.Security.Principal.SecurityIdentifier]("S-1-5-32-544")).Translate([System.Security.Principal.NTAccount]).Value
Command lines which I have already tried but with no success -
powershell -command ([System.Security.Principal.SecurityIdentifier]("S-1-5-32-544")).Translate([System.Security.Principal.NTAccount]).Value
powershell -command {([System.Security.Principal.SecurityIdentifier]("S-1-5-32-544")).Translate([System.Security.Principal.NTAccount]).Value}
What am I doing wrong? Is it due to any escape characters or am I missing any powershell command parameters? Any help is greatly appreciated.
powershell -command "([System.Security.Principal.SecurityIdentifier]('S-1-5-32-544')).Translate([System.Security.Principal.NTAccount]).Value"
worked for me. Just a question of changing the innermost double-quotes to singles around the SID.
Alternatively, escape them with a backslash
powershell -command "([System.Security.Principal.SecurityIdentifier](\"S-1-5-32-544\")).Translate([System.Security.Principal.NTAccount]).Value"
Here is a short VBScript script that uses WMI to do the conversion for you:
Dim SID
SID = WScript.Arguments.Item(0)
Dim SWbemServices, SWbemObject
Set SWbemServices = GetObject("winmgmts:root/CIMV2")
Set SWbemObject = SWbemServices.Get("Win32_SID.SID='" & SID & "'")
WScript.Echo SWbemObject.ReferencedDomainName & "\" & SWbemObject.AccountName
You would of course need to capture this script's output from your shell script (batch file).
You're actually really close. What you want to do is this:
powershell -command "& {([System.Security.Principal.SecurityIdentifier]('S-1-5-32-544')).Translate([System.Security.Principal.NTAccount]).Value}"
I tested this using the Get-WmiObject cmdlet. In a standard, but elevated cmd shell I entered:
powershell -command "& {get-wmiobject win32_operatingsystem}"
At that point the wmi object data as returned by powershell was written to the console. You can also load the command into a variable like so:
set wmi=powershell -command "& {get-wmiobject win32_operatingsystem}"
If you call the variable %wmi% there's a delay before it prints. The command itself is in the variable so everytime you call the variable it'll execute the powershell code and return the result.
An alternative answer is to use a base64 encodedcommand switch.
#ECHO OFF
powershell -encodedcommand "KABbAFMAeQBzAHQAZQBtAC4AUwBlAGMAdQByAGkAdAB5AC4AUAByAGkAbgBjAGkAcABhAGwALgBTAGUAYwB1AHIAaQB0AHkASQBkAGUAbgB0AGkAZgBpAGUAcgBdACgAIgBTAC0AMQAtADUALQAzADIALQA1ADQANAAiACkAKQAuAFQAcgBhAG4AcwBsAGEAdABlACgAWwBTAHkAcwB0AGUAbQAuAFMAZQBjAHUAcgBpAHQAeQAuAFAAcgBpAG4AYwBpAHAAYQBsAC4ATgBUAEEAYwBjAG8AdQBuAHQAXQApAC4AVgBhAGwAdQBlAA=="
PAUSE
When decoded, you'll see it's the OP's original snippet (with the double quotes preserved). Maybe overkill for the OP, but useful for dev's with larger scripts. Plus my original answer was identical to someone elses, so I had to edit.
powershell.exe -EncodedCommand
Accepts a base-64-encoded string version of a command. Use this parameter
to submit commands to Windows PowerShell that require complex quotation
marks or curly braces.

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