Running Powershell command in a command line/batch file - 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.

Related

how to concatenate two variables when one has spaces in it in AzureDevops batch file

I have this input in my ps script. I am passing $(Build.ArtifactStagingDirectory) system variable to get the path in the input %1. The path has spaces i.e. E:\Build Agents\Agent2\_work\15\a. I need to concatenate this with other path but I am not able to do so.
set BuildDrop=%1
set Directory=%BuildDrop% + "\adapters\bin"
This is my output, which is incorrect as Directory should be something like E:\Build Agents\Agent2\_work\15\a\adapters\bin. How to solve this?
set BuildDrop="E:\Build Agents\Agent2\_work\15\a"
set Directory="E:\Build Agents\Agent2\_work\15\a" + "\adapters\bin"
My task is like this in my build pipeline
Task : Batch script
Description : Run a Windows command or batch script and optionally allow it to change the environment
Version : 1.1.10
I found the solution for this. Since my %1 had space I needed to remove apostrohphe before assigning. I did it using ~ variable. working code looks like this.
set "BuildDrop=%~1"
set "Directory=%BuildDrop%\adapters\bin"
You could try this :
set BuildDrop=%1
set Directory= %BuildDrop%\adapters\bin
echo %Directory%
Sample Output
This is the concatenation code.
%BuildDrop%\adapters\bin
In my above sample I am trying to concatenate C:\Users\svijay\Desktop & \adapters\bin using the batch script
And the output : C:\Users\svijay\Desktop\adapters\bin
UPDATE :
#echo off
set BuildDrop=%1
set Directory= %BuildDrop%\adapters\bin
set Directory= %Directory:"=%
echo %Directory%
If you have space, you could provide the "" to provide input.
In your code you could remove the double quotes.
%Directory:"=% - Removes the Double quotes from the string literal.
Sample output :
You may use this to create Azure DevOps variable containing your path
powershell: |
$directory = $(Build.ArtifactStagingDirectory)
$newDirectory = $directory + "\adapters\bin"
Write-Host "##vso[task.setvariable variable=testvar]$newDirectory "
and if you need set variable in powershell script
$BuildDrop=$args[0]
$Directory=$BuildDrop + "\adapters\bin"
Here you have an article how to use parameters in powershell.
We can use powershell task in the Azure DevOps to concatenate two variables.
Sample:
Write-Host "Build.ArtifactStagingDirectory is $(Build.ArtifactStagingDirectory)"
Write-Host "Build.ArtifactStagingDirectory is $(Build.ArtifactStagingDirectory)\adapters\bin"
Result:
In addition, I found a similar issue, please also check it.
Update1
Use power shell script in the Azure DevOps pipeline
$testpath1 = "E:\Build Agents\Agent2\_work\15\a"
$testpath2 = "\adapters\bin"
Write-Host "path is $($testpath1)$($testpath2)"
Result:
Use local power shell
Result:
Update2
.bat file
set testpath1=E:\Build Agents\Agent2\_work\15\a
set testpath2=\adapters\bin
set newpath=%testpath1%%testpath2%
echo %newpath%
Pipeline result:

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.

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?

How can I use nested quotes when calling a powershell script within a batch file?

I have a DOS batch file that has a line that executes a powershell script. First I tried a very simple script with this line in the batch file:
powershell -command "get-date" < nul
That worked great. But the script has nested double-quote characters, which can sometimes be escaped with a backtick (`) character. So then I tried this:
powershell -command "Write-Host `"hello world`"" < nul
That also worked great. However, the script I need to run is pretty complicated and has more than one level of nested double-quote characters. I have taken the complicated script and simplified it to an example that has the same principles here:
[string]$Source = " `"hello world`" ";
Write-Host $Source;
If I save this script inside a PS script file and run it, it works fine, printing out “hello world” including the double quotes, but I need to embed it in the line in the batch file. So I take the script and put it all on one line, and try to insert it into the batch file line, but it doesn’t work. I try to escape the double-quotes, but it still doesn’t work, like this:
powershell -command "[string]$Source = `" `"hello world`" `";Write-Host $Source;" < nul
Is there a way to do what I want? You might ask why I am doing this, but it’s a long story, so I won’t go into the details.
thanks
You'll have to use a combination of batch's escape character and PowerShell's escape character.
In batch, when escaping quotes, you use the common shell backslash (\) to escape those quotes. In Powershell, you use the backtick `.
So if you wanted to use batch to print out a quoted string with Powershell, you need to first batch escape the quote to declare the variable in Powershell, then to ensure the string is quoted you need batch and Powershell escape another quote, and then your add your desired string, ensuring you batch escape first.
For your example, this will work:
powershell -command "[string]$Source = \"`\"hello world`\"\"; Write-Host $Source;"
Here's a break down of the declaration of the $Source variable:
"[string]$Source = # open quote to begin -command parameter declaration
\" # batch escape to begin the string portion
`\" # Powershell+Batch escape
hello world # Your content
`\" # Posh+Batch again
\"; # Close out the batch and continue
more commands " # Close quote on -command parameter
This renders the string like this in batch:
`"hello world`"
One note, you don't need to explicitly cast $Source as a string since you are building it as a literal string from scratch.
$Source = "string stuff" will work as intended.

Hide empty console window in a all GUI Powershell script?

I have made a very simple Powershell script with WinForms GUI.
Everything works as intended but, when I run the .ps1 script with PowerShell a black empty console window appears at first and then the GUI shows.
Anyway to make the console window dissapear?
Best regards
I wrote a small article on this subject (sorry in french) one year ago.
Here is the common solution using a small VBS script to start PowerShell hidding his window (the trick is in the last ,0).
Set Args = Wscript.Arguments
'MsgBox "Chemin LDAP: " & Args(0)
'MsgBox "Classe: " & Args(1)
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "c:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -nologo -Noninteractive -file c:\SlxRH\RhModif.ps1 " & chr(34) & Args(0) & chr(34) , 0
I also embeded PowerShell in an executable with no console called slxPShell2.EXE.
I found the above didn't work for me. I used this:
Set objShell = CreateObject("WScript.Shell")
objShell.Run "CMD /C START /B " & objShell.ExpandEnvironmentStrings("%SystemRoot%") & "\System32\WindowsPowerShell\v1.0\powershell.exe -file " & "YourScript.ps1", 0, False
Set objShell = Nothing
Hope that helps.
This solution Minimizes Powershell window after it starts. Powershell window opens, then disapears, without using any outside code. Put at beginning of your script.
$t = '[DllImport("user32.dll")] public static extern bool ShowWindow(int handle, int state);'
add-type -name win -member $t -namespace native
[native.win]::ShowWindow(([System.Diagnostics.Process]::GetCurrentProcess() | Get-Process).MainWindowHandle, 0)
This is how I got this working:
Have the Winforms GUI script in one ScriptOne.ps1 file
Create another LaunchScriptOne.ps1 file with the content:
powershell.exe -WindowStyle Hidden -File "C:\path\to\ScriptOne.ps1".
The solution was provided in another thread on the same topic: Hide or Minimize the powershell prompt after Winform Launch
I hope someone will find a way to put this into one single script as well. The answers above in this thread did not help me, but maybe I did something wrong, idk.
I'm nube so no rep so can't comment inline... though wrt #Ipse's solution which I'm a fan of, I also make sure to close the hidden window when the script is done... not sure if PS gets around to this sort of auto-garbage collection, but suspect it's good best practice.
eg. at end of your script I'd suggest doing:
stop-process -Id $PID
(which should terminate that hidden window v. just leave it lurking around and tying up those resources).

Resources