1

I try to write a batch script that, when you drag and drop another file to it, it will do something. If you don't drop anything, just double click it, it will open a file selection dialog window.

For the first part, it's easy:

@echo off
bin\dosomething "%~1"

For the second part, I googled this thread: https://stackoverflow.com/a/15885133/1683264

It also works.

But, I can't combine these two to one. I've tried

if "%~1" == [] goto select

then add :select before the second part, it just don't work. Codes below:

@ECHO OFF
if "%~1" == [] goto select
bin\dosomething "%~1"
goto :EOF

:select

<# : chooser.bat
:: launches a File... Open sort of file chooser and outputs choice(s) to the console
:: https://stackoverflow.com/a/15885133/1683264

@echo off
setlocal

for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0} | out-string)"') do (
    echo You chose %%~I
    bin\dosomething "%%~I"
)
goto :EOF

: end Batch portion / begin PowerShell hybrid chimera #>

Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }

I tried If "%~1"=="", it jumped as purpose, but the dialog windows still don't appear, CMD directly output error lines as:

You chose + iex (${D:\Program Files (x86)\BBB\choose list file.bat} | out-strin ...

Solved

It's solved. Only "%~1" works right.

I paste code here:

<# : chooser.bat

:: drop file to execute, or open a file chooser dialog window to execute.
:: code mostly comes from https://stackoverflow.com/a/15885133/1683264

@ECHO OFF

if "%~1" == "" goto SELECT
bin\dosomething "%~1"
goto :EOF

:SELECT

setlocal
for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0} | out-string)"') do (
    echo You chose %%~I
    bin\dosomething "%%~I"
)
goto :EOF

: end Batch portion / begin PowerShell hybrid chimera #>

Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }
Community
  • 1
  • 1
kaikaiiiiiii
  • 63
  • 1
  • 7
  • 2
    The `IF` syntax is incorrect. It is a string comparison. If you have quotes on one side of the comparison you must have them on the other side of the comparison. Remove the brackets and use quotes to check if the command line argument is empty. – Squashman Aug 28 '18 at 02:03
  • I tried all possibles, "%~1" == "", [%~1] == [], "%~1" == [], [%~1] == "". First two is right. But it still don't works as purpose. The script directly output some lines instead of jump out a dialog window. – kaikaiiiiiii Aug 28 '18 at 02:36
  • Two equal symbols. – Squashman Aug 28 '18 at 02:39
  • You are also not understanding how to use the hybrid. All your batch file code needs to be inside the comments section of the powershell script. – Squashman Aug 28 '18 at 02:42
  • Oh that's why I can't googled the symbols "<# : " . I've thought it some kind of pipes. So the scripts actually is a PS scripts, which means it should pass the %~1 from PS script to the batch ? But how... – kaikaiiiiiii Aug 28 '18 at 02:46
  • No. The batch file code runs first. Then the powershell code runs. – Squashman Aug 28 '18 at 02:50
  • Thanks for explain. I learned. – kaikaiiiiiii Aug 28 '18 at 10:58

1 Answers1

3

The trick with those Hybrid scripts is, to hide the batch code for the Powershell parser and to hide the Powershell code for the batch parser.

For Powershell, the part between <# and #> is a comment. Thanksfully <# : comment does no harm for the batch parser. So your batch code is supposed to be inside that Powershell comment.

On the other hand, the last batch command is goto :EOF, which means, all below ( the "end of comment"-line" for Powershell and the Powershell code itself ) will be ignored by the Batch parser.

So just move up your line <# : chooser.bat as very first line.

Stephan
  • 53,940
  • 10
  • 58
  • 91
  • May I ask a more question. Does `'powershell -noprofile "iex (${%~f0} | out-string)"'` means calling powershell and pass the batch file itself to the powershell to execute? And then PS ignored the "comment" continueing run the rest code? – kaikaiiiiiii Aug 28 '18 at 11:02
  • Exactly. `%~f0` is batch's method to get its own full qualified file name (complete with `drive:\path\name.extension') – Stephan Aug 28 '18 at 16:38