如何创建批处理文件以运行位于系统任何位置的 jar 文件

How to create a batch file to run a jar file that is in any location of the system

我有一个 MyFile.jar 文件。我需要一个批处理文件来搜索 jar 文件并触发它。

我找到了以下解决方案。但是对于那个批处理文件和jar文件必须在同一个文件夹中。

java -jar %~dp0MyFile.jar %*

我们不知道客户会将 jar 文件放在他们系统中的什么位置。但是他们会将批处理文件放在启动文件夹中。

编辑:我现在设法写了这个批处理文件。

`ECHO
 ECHO Locating the Jar

 IF EXIST java -jar MyFile.jar  ELSE (GOTO 

 SearchJar)

:SearchJar
SET the_path=D: & CD\
DIR /S/B File.jar > installer_location.txt
SET /P the_path=< installer_location.txt
if defined the_path goto :FoundIt

E: & CD\
DIR /S/B MyFile.jar > installer_location.txt
SET /P the_path=< installer_location.txt
if defined the_path goto :FoundIt

C: & CD\
DIR /S/B MyFile.jar > installer_location.txt
SET /P the_path=< installer_location.txt
if defined the_path goto :FoundIt

G: & CD\
DIR /S/B MyFile.jar > installer_location.txt
SET /P the_path=< installer_location.txt
if defined the_path goto :FoundIt

H: & CD\
DIR /S/B MyFile.jar > installer_location.txt
SET /P the_path=< installer_location.txt
if defined the_path goto :FoundIt

I: & CD\
DIR /S/B MyFile.jar > installer_location.txt
SET /P the_path=< installer_location.txt
if defined the_path goto :FoundIt
ECHO Jar not found.

:FoundIt
ECHO Jar file found at %the_path%

CALL java -jar %the_path%`

这在我的系统中正在运行。但我不确定是否有更简单的方法来一次检查所有驱动器。

首先找到文件并为其路径设置一个变量,然后将该变量用作您想要的路径。从你对 %~dp0 的使用来看,我假设你只在 windows 上工作,所以下面的例子是针对 windows

echo off
for /r C:\search_folder_root %%a in (*) do if "%%~nxa"=="MyFile.jar" set jarLoc=%%~dpa
java -jar %jarLoc%MyFile.jar %*

请注意 - 搜索可能需要相当长的时间,例如如果您搜索整个驱动​​器...

编辑:

为了响应 OP 的评论,请求一个脚本来搜索系统上的任何驱动器,就在这里。请注意——我不认为使用这对用户体验来说是个好主意——它会非常低效,而且可能需要很长时间……在一个非常简单的案例上进行了测试,在早期出现的路径上有一个虚拟罐子在我的机器上搜索。注意 - 如果用户知道 jar 在哪个驱动器上,或者更好的路径,您可以始终提示他们输入该驱动器/路径而不是循环。

echo off
setlocal
set jarName=MyFile.jar

rem -- loop through each drive on system --
for /F "usebackq skip=1" %%i in (`wmic logicaldisk get caption 2^>NUL`) do (
  echo Checking drive %%i for %jarName%

  rem -- temporarily change to the drive --
  pushd %%i\

  rem -- recursively loop through every file of every subdirectory on that drive --
  for /r %%a in (*) do (
    if "%%~nxa"=="%jarName%" set jarLoc=%%~dpa
    if defined jarLoc goto :Found
  )
  popd
)

rem -- if we get to here, the jar has not been found --

echo %jarName% not found on any drive in this system
goto :eof

:Found
echo Jar found at %jarLoc%
popd
java -jar %jarLoc%%jarName% %*

正如 gknicker 和我在上面评论的那样,这是应该完成的方式。如果您使用安装程序(如 NSIS 或类似程序)来部署 .jar 文件和 .bat 脚本,请让安装程序写入注册表值,并且可能永远不需要搜索或文件浏览。如果安装后移动了.jar文件,弹出一个GUI file chooser让用户浏览到他保存的位置MyFile.jar。将更新后的位置保存到注册表中。再次移动文件时重新提示

@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 

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

如果您坚持要在所有本地驱动器中搜索 MyFile.jar,您可以使用 wmic logicaldisk 查询驱动器列表。通过添加 where "not drivetype=4" 排除网络驱动器。您仍应将结果保存到注册表中,以防止每 运行.

出现几分钟的延迟
@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