To expand upon Santiago's great answer, and with a real world example, my goal was to take an input from SendTo
and then pass that input to PowerShell for additional processing. I don't need to see anything on the console so I wanted this to be hidden.
I want this for Beyond Compare, as I like the app a lot, but I really dislike how applications pollute our right-click context menu's with endless commands. I might only use Beyond Compare a couple of times per week, so I don't need it polluting my context menu for the 1,000+ other times per week that I right-click on something. I do this for all of my tools so that I have a very minimal and clean right-click context menu. The below would also apply to almost any other app that you would want a customised tooling in SendTo
, and also almost unchanged for WinMerge if you prefer that tool (but Beyond Compare can also compare folders which can be very useful). For WinMerge, just break out of the script if a folder is selected at the first step as it cannot handle folders.
As I required two inputs, one from the initial SendTo, and the second from the OpenFileDialog or FolderBrowerDialog, this meant that I had to also pass the Argument given to the VBScript part of the solution. The syntax for that was a bit tricky to work out (it's 10+ years since I've had to use VBScript!), but is:
""" & path & """ """ & arg & """"
The solution then requires a .vbs
launcher plus the .ps1
script and finally the shortcut in shell:sendto
to call the scripts:
D:\MyPortableApps\ShortcutLauncher.vbs
Set oShell = CreateObject("WScript.Shell")
path = WScript.Arguments(0)
arg = WScript.Arguments(1)
PSCommand = "powershell -NoProfile -ExecutionPolicy ByPass -File """ & path & """ """ & arg & """"
oShell.run PScommand,0
D:\MyPortableApps\Compare with (Files or Folders, Beyond Compare).ps1
# Selected item in SendTo is the left side, then use OpenFileDialog or FolderBrowserDialog to pick the right side
$MyPrograms = "D:\MyPortableApps" # Location of my portable apps
$left_side = (Get-Item $args[0]).FullName # In case path contains '.' or '..'
$parent = Split-Path $left_side # Use this as InitialDirectory
$IsFolder = $false; if ((Get-Item $left_side) -is [System.IO.DirectoryInfo]) { $IsFolder = $true }
Add-Type -AssemblyName System.Windows.Forms # Required to access the OpenFileDialog object
if ($IsFolder) {
$FolderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog # -Property @{ InitialDirectory = $parent }
$FolderBrowser.RootFolder = $parent
$FolderBrowser.Description = "Select Folder to compare to '$left_side':"
$Show = $FolderBrowser.ShowDialog()
if ($Show -eq "OK") {
$right_side = $FolderBrowser.SelectedPath
} else {
break
}
} else {
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ InitialDirectory = $parent } # [Environment]::GetFolderPath('Desktop')
$FileBrowser.Title = "Select File to compare to '$left_side':"
$null = $FileBrowser.ShowDialog() # Assign to null as $FileBrowser does not return useful information by itself
$right_side = $FileBrowser.FileName
}
# $ButtonClicked = [System.Windows.Forms.MessageBox]::Show("Beyond Compare will be opened with the following panes:`n`nLeft side: '$left_side'`n`nRight side: '$right_side'", 'Open Beyond Compare?', 'OKCancel')
$appexe_pf = "C:\Program Files\Beyond Compare 4\BCompare.exe"
$appexe_sb = "$MyPrograms\Beyond Compare 4\BCompare.exe"
if ( (!(Test-Path $appexe_sb)) -and (!(Test-Path $appexe_pf))) { choco install beyondcompare -y }
if (Test-Path $appexe_pf) {
& $appexe_pf "$left_side" "$right_side"
} else {
& $appexe_sb "$left_side" "$right_side"
}
Snippet to create a shortcut in SendTo
function New-Shortcut ($mylnk, $mytgt, $myarg, $mywrk, $myico) {
$lnk = $WScriptShell.CreateShortcut($mylnk)
$lnk.TargetPath = $mytgt
if ($myarg -ne "") { $lnk.Arguments = $myarg }
if ($mywrk -ne "") { $lnk.WorkingDirectory = $mywrk }
if ($myico -ne "") { $lnk.IconLocation = $myico }
$lnk.Save()
}
$SendTo = "$Env:AppData\Microsoft\Windows\SendTo"
$lnkName = "Compare with (Files or Folders, Beyond Compare)"
$SendToLnk = "$SendTo\$lnkName.lnk"
$wscript = "C:\Windows\system32\wscript.exe"
New-Shortcut $SendToLnk $wscript "`"D:\MyPortableApps\ShortcutLauncher.vbs`" `"D:\MyPortableApps\$lnkName.ps1`"" "" ""