How can I embed java code into batch script?Is it

2020-07-26 13:44发布

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:

  1. 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).
  2. 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)
  3. 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?

2条回答
We Are One
2楼-- · 2020-07-26 14:21

Didn't you saw my DosTips post on Alternate Data Streams? This method have all the advantages you want for perfect hybrid scripts because the non-Batch code is stored in its own space (alternate stream), so it don't requires a single additional character! The code can be edited with Windows Notepad. The "only" problem is if the java compiler was designed to recognize the Alternate Data Stream. I successully tested this method with VBS, JScript and PowerShell, but unfortunately I have not a java compiler installed...

However, the test to check if this method work with your java compiler is very simple. Copy the code below and create BatchJavaTest.bat file with it:

@echo off

rem Compile the java code stored in this file as an ADS with name "TestClass.java"
javac "%~F0:TestClass.java"
java "TestClass"

Now we need to create the ADS with the java code. To do that, enter the following in the command-line:

notepad BatchJavaTest.bat:TestClass.java

When Notepad open, paste the following on it:

public class TestClass
{
    public static void main(String args[])
    {
       System.out.println("selfcompiled .bat/.java hybrid from an ADS!");
    }
}

Save this file and test the Batch one. That is it!

Please, report the result!

PS - This program must be tested in a NTFS disk in order for it to work...

查看更多
ら.Afraid
3楼-- · 2020-07-26 14:42

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.

查看更多
登录 后发表回答