As gknicker and I commented above, this is the way it should be done. If you used an installer (like NSIS or similar) to deploy the .jar
file and .bat
script, have the installer write the registry value, and a search or file browse may never be needed. If the .jar
file is moved after installation, pop up a GUI file chooser and let the user browse to the location he saved MyFile.jar
. Save the updated location to the registry. Re-prompt if the file is moved again.
@echo off
setlocal enabledelayedexpansion
set "jarfile=MyFile.jar"
set "regkey=HKLM\Software\Company Name"
set "regvalue=jarfile"
set jarpath=
for /f "tokens=2*" %%I in ('reg query "%regkey%" /v "%regvalue%" 2^>NUL') do (
set "jarpath=%%~J"
)
if not exist "%jarpath%" (
call :chooser jarpath "%jarfile%" "%jarfile% (*.jar)|*.jar"
)
if exist "%jarpath%" (
reg add "%regkey%" /v "%regvalue%" /t REG_SZ /d "%jarpath%" /f 2>&1>NUL
) else (
<NUL set /P "=Unable to locate %jarfile%. This thread will self-destruct in 5 seconds... "
ping -n 6 0.0.0.0 >NUL
echo bang.
exit /b 1
)
java -jar "%jarpath%"
goto :EOF
:chooser <var_to_set> <filename> <filter>
:: based on https://stackoverflow.com/questions/15885132
setlocal enabledelayedexpansion
:: Does powershell.exe exist within %PATH%?
for %%I in (powershell.exe) do if "%%~$PATH:I" neq "" (
set chooser=powershell "Add-Type -AssemblyName System.windows.forms|Out-Null;$f=New-Object System.Windows.Forms.OpenFileDialog;$f.InitialDirectory='%cd%';$f.Filter='%~3';$f.showHelp=$true;$f.Title='Locate %~2';$f.ShowDialog()|Out-Null;$f.FileName"
) else (
rem :: If not, compose and link C# application to open file browser dialog
set chooser=%temp%\chooser.exe
>"%temp%\c.cs" echo using System;using System.Windows.Forms;
>>"%temp%\c.cs" echo class dummy{
>>"%temp%\c.cs" echo public static void Main^(^){
>>"%temp%\c.cs" echo OpenFileDialog f=new OpenFileDialog^(^);
>>"%temp%\c.cs" echo f.InitialDirectory=Environment.CurrentDirectory;
>>"%temp%\c.cs" echo f.Filter="%~3";
>>"%temp%\c.cs" echo f.ShowHelp=true;
>>"%temp%\c.cs" echo f.Title="Locate %~2";
>>"%temp%\c.cs" echo f.ShowDialog^(^);
>>"%temp%\c.cs" echo Console.Write^(f.FileName^);}}
for /f "delims=" %%I in ('dir /b /s "%windir%\microsoft.net\*csc.exe"') do (
if not exist "!chooser!" "%%I" /nologo /out:"!chooser!" "%temp%\c.cs" 2>NUL
)
del "%temp%\c.cs"
if not exist "!chooser!" (
echo Error: Please install .NET 2.0 or newer, or install PowerShell.
goto :EOF
)
)
:: capture choice to a variable
endlocal && for /f "delims=" %%I in ('%chooser%') do set "%~1=%%I"
:: Clean up the mess
del "%temp%\chooser.exe" 2>NUL
goto :EOF
If you insist on searching all local drives for MyFile.jar
, you can query a drive list with wmic logicaldisk
. Exclude network drives by adding where "not drivetype=4"
. You should still save the result to the registry to prevent a several minute delay on every run.
@echo off
setlocal
set "jarfile=MyFile.jar"
set "regkey=HKLM\Software\Company Name"
set "regvalue=jarfile"
set jarpath=
for /f "tokens=2*" %%I in ('reg query "%regkey%" /v "%regvalue%" 2^>NUL') do (
set "jarpath=%%~J"
)
if not exist "%jarpath%" (
call :finder jarpath "%jarfile%"
)
if exist "%jarpath%" (
reg add "%regkey%" /v "%regvalue%" /t REG_SZ /d "%jarpath%" /f 2>&1>NUL
) else (
<NUL set /P "=Unable to locate %jarfile%. This thread will self-destruct in 5 seconds... "
ping -n 6 0.0.0.0 >NUL
echo bang.
exit /b 1
)
java -jar "%jarpath%"
goto :EOF
:finder <var_to_set> <file_to_find>
setlocal
:: in wmic, drivetype=4 is network drive
for /f "tokens=2 delims=:=" %%I in (
'wmic logicaldisk where "not drivetype=4" get DeviceID /format:list ^| find "="'
) do (
<NUL set /P "=Searching %%I: for %~2... "
for /f "delims=" %%a in ('dir /s /b "%%I:\*%~2"') do (
echo %%~dpa
endlocal & set "%~1=%%a"
goto :EOF
)
echo Not found.
)
goto :EOF