While there are some techniques that allows you to create the perfect (and not so perfect) batch file hybrids with some 'native' windows script languages.
What a 'perfect' hybrid should look like:
The embedded code must be usable as it is and you should be capable
to copy-pasted it in any other editor/IDE you want. There should be
no endless echoes to temp files and weird escape sequences.(rather
possible for every language that support multi-line comments).
No 'poisonous' prints of error messages (e.g. /* will print an error
in command prompt despite the execution of the batch will continue
on the next line)
No temporary files.With the exception of compiled binary files which
is unavoidable for the languages that does not have an interpreter.
Is it possible to create the 'perfect' java/batch hybrid?
解决方案
The answer is almost.
The main impediment is that the all compilers I know are very strict about the file extensions and will refuse to compile any file that has no .java extension.
As any command in batch files starting with @ will be not displayed we can use the java annotations to silence the error message that comes from the java comment (should be saved with .bat extension):
@Deprecated /* >nul 2>&1
:: self compiled java/.bat hybrid
::
:: deprecated is the only one annotation that can be used outside the class definition
:: and is needed for 'mute' start of multi-line java comment
:: that will be not printed by the batch file.
:: though it still creates two files - the .class and the .java
:: it still allows you to embed both batch and java code into one file
@echo off
setlocal
java -version >nul 2>&1 || (
echo java not found
exit /b 1
)
::find class name
::can be different than the script name
for /f "usebackq tokens=3 delims=} " %%c in (`type %~f0 ^|find /i "public class"^|findstr /v "for /f"`) do (
set "javaFile=%%c"
goto :skip
)
:skip
copy "%~f0" "%javaFile%.java" >nul 2>&1
javac "%javaFile%.java"
java "%javaFile%"
::optional
::del %javaFile%.* >nul 2>&1
end local
exit /b 0
*******/
public class TestClass
{
public static void main(String args[])
{
System.out.println("selfcompiled .bat/.java hybrid");
}
}
The example above covers points 1. and 2. but of course there's still need of creation of .java file.Still copying is faster than echoing java content line by line.
One step further (or half step) - making a .java extension to act like .bat (or almost)
Lets say you don't the like the part in the code that finds the java class name and the self-copy code.
You can make the .java extension to act like .bat file.Or almost - the %0 will be lost and the file name will be stored in %1.
For that purpose you need to call this batch file with admin permissions:
@echo off
:: requires Admin permissions
:: allows a files with .JAVA (in this case ) extension to act like .bat/.cmd files.
:: Will create a 'caller.bat' asociated with the extension
:: which will create a temp .bat file on each call (you can consider this as cheating)
:: and will call it.
:: Have on mind that the %0 argument will be lost.
rem :: "installing" a caller.
if not exist "c:\javaCaller.bat" (
echo @echo off
echo copy "%%~nx1" "%%temp%%\%%~nx1.bat" /Y ^>nul
echo "%%temp%%\%%~nx1.bat" %%*
) > c:\javaCaller.bat
rem :: associating file extension
assoc .java=javafile
ftype javafile=c:\javaCaller "%%1" %%*
Then the self-compiled .java file will look like this (should be saved with .java extension):
@Deprecated /* >nul 2>&1
:: requires ran javaExtInstaller.bat
:: https://github.com/npocmaka/batch.scripts/blob/master/Java/javaExtInstaller.bat
::
:: self compiled java/.bat hybrid
::
:: deprecated is the only one annotation that can be used outside the class definition
:: and is needed for 'mute' start of multi-line java comment
:: that will be not printed by the batch file.
:: allows you to embed both batch and java code into one file
@echo off
setlocal
java -version >nul 2>&1 || (
echo java not found
exit /b 1
)
if not exist "%~n1.class" javac "%~nx1"
:: to compile the class every time use:
:: javac "%~nx1"
java "%~n1"
endlocal
exit /b 0
*******/
public class TestClass
{
public static void main(String args[])
{
System.out.println("selfcompiled .bat/.java hybrid");
}
}
there still will have a creation of temp .bat file by the javaCaller.bat but it will be not 'visible' and batch part is much shorter.
In the examples there are no packages as the only single java file is used .Packages will make only the example harder to understand.