Bat file for Windows 10 Custom Start Menu - batch-file

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.

Related

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?

C system function returns sh: Invoke-Item command not found

I want to run a powershell command from c (gcc) and I was told to use the system() function and I get that output. The exact same thing happens in a vacuum as well (nothing else in the program). I am using windows. What I want to do is use Invoke-Item. What should I do?
To run PowerShell commands using system() function, you need to do something like this:
system("powershell -Command \"<your-command-here>\"");
AFAIK, the default shell on Windows is Command Prompt. PowerShell is another shell and you need to invoke it first to run commands in it.
Example (run dir command):
Using Command Prompt:
> PowerShell.exe -Command "dir"
Using Linux Terminal:
$ powershell -Command "dir"
So, the above command format should work for your case also i.e.:
system("PowerShell.exe -Command \"Invoke-Item ...\"");

Creating a cmd line shortcut

I am completely new to Windows, as i am an OSX user.
I am having to run a task in the cmd line every day, is there any way i can create a shortcut on my desktop which automates this?
Task example, open cmd, then execute:
atomInstaller npm -view -Xmx8g -Xms3g
Thanks
You could just make a shortcut to cmd.exe and add command line switches:
https://superuser.com/questions/358565/adding-command-line-switches-to-windows-shortcuts
Or you can put commands into a batch file using notepad ( or a better text editor ):
#echo off
atomInstaller npm -view -Xmx8g -Xms3g
save it as npm.bat then double-click it..
You can use shortcutjs.bat:
call shortcutjs.bat -linkfile "%userprofile%\desktop\atominstaller.lnk" -target "C:\atomInstaller.bat" -adminpermissions yes -iconlocation "C:\Windows\System32\compstui.dll,3" -hotkey "Ctrl+Shift+M"
Here's the usage:
shortcutjs.bat -linkfile link -target target [-linkarguments linkarguments] [-description description] [-iconlocation iconlocation] [-hotkey hotkey] [-windowstyle 1|3|7] [-workingdirectory workingdirectory] [-adminpermissions yes|no]
You can add additional parameter with -linkarguments or start location with -workingdirectory

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.

Programmatically send key strokes to a window program in Groovy or bat script

Backstory: I need to programmatically find the differences between two files. I want to use WinMerge to generate a report (Tools -> Generate Report) that I can parse to get the differences between two files. I need this done using either a Groovy script or a bat script.
I was hoping that WinMerge would offer command line options to generate the report and then I could just use a Groovy Process object to execute WinMergeU.exe with the arguments. No such luck according to the command options I've found for WinMerge.
Next, I was hoping to be able to start WinMerge and send keystrokes to step through the menus to generate the report(Alt+T, R, Diff.html, [Enter]). I don't see a way to do that from a Groovy Process and I haven't found a way to do this in a bat script. I'm looking for something similar to WshShell.Sendkeys in VB. Is this a wild-goose chase?
UPDATE/Answer with PowerShell in a bat file:
I was intrigued by Knuckle-Dragger's comment about using a PowerShell script in a bat file.
$folder = "C:\DevTools\WinMerge\WinMergeU.exe"
ii $folder
Start-Sleep -m 1000
[void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
[Microsoft.VisualBasic.Interaction]::AppActivate("WinMerge")
Start-Sleep -m 100
[void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
Start-Sleep -m 100
[System.Windows.Forms.SendKeys]::SendWait("%F")
[System.Windows.Forms.SendKeys]::SendWait("o")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
[System.Windows.Forms.SendKeys]::SendWait("%T")
[System.Windows.Forms.SendKeys]::SendWait("r")
Start-Sleep -m 1000
[Microsoft.VisualBasic.Interaction]::AppActivate("Save As")
Start-Sleep -m 1000
[System.Windows.Forms.SendKeys]::SendWait("Diff.txt")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
To encapsulate this in a command window, save it to a file PowerShellScript.ps1:
start /b /wait powershell.exe -nologo -WindowStyle Hidden -sta *PowerShellScript.ps1*
Here is a powershell example to activate winmerge and send some keys.
EDIT: Reduced copy pasta with some .NET variables. $SK = Sendkeys $AA = AppActivate $LRA = Reflect .NET.
$startapp = "C:\DevTools\WinMerge\WinMergeU.exe"
ii $startapp
$SK = "[System.Windows.Forms.SendKeys]::SendWait"
$AA = "[Microsoft.VisualBasic.Interaction]::AppActivate"
$LRA = "[void][System.Reflection.Assembly]::LoadWithPartialName"
Start-Sleep 1
$LRA+'("Microsoft.VisualBasic")'
$AA+'("WinMerge")'
Start-Sleep -m 100
$LRA+'("System.Windows.Forms")'
Start-Sleep -m 100
$SK+'("%F")'
$SK+'("o")'
$SK+'("{ENTER}")'
$SK+'("%T")'
$SK+'("r")'
Start-Sleep 1
$AA+'("Save As")'
Start-Sleep 1
$SK+'("Diff.txt")'
$SK+'("{ENTER}")'
To encapsulate this in a command window, save it to a file PowerShellScript.ps1: Note, changed the command syntax a bit, should work if you use the & {.\dot\source\path}
start /b /wait powershell.exe -nologo -WindowStyle Hidden -sta -Command "& {.\PowerShellScript.ps1}"
This is something that I threw together without testing, and I don't have WinMerge so testing isn't really an option.
RunMe.bat
start "" "C:\Path\WinMerge.exe" "file1" "file2"
GenerateDiffFile.vbs
GenerateDiffFile.vbs
Set s = CreateObject("WScript.Shell")
wscript.sleep(1000) ' Sleep for 1 second to allow time for WinMerge to finish loading and merge the files
s.SendKeys("%tr")
wscript.sleep(250) ' Give time for dialog box to appear
s.SendKeys("Diff.html{Enter}")
This is completely untested, but I think it is very close to what you need... You can see that the batch-file runs WinMerge, passing the two files to merge on the command line. Then it launches the VBS script, which pauses long enough to allow the launched WinMerge to be able to accept keyboard input. I used this page from Microsoft to know what keys to send.
I've been sending keys to programs for years. It works very reliably, as long as the program you want to send keys to keeps focus.
All I do is this:
echo y | "Batchfile needing the keystroke"

Resources