Behavior of %~dp0 on Windows 2008 Server when used from Java - java

Issue Environment : Windows Server 2008 R2 Build 7601
I have a batch file SomeBatchFile.bat which uses %~dp0 to get the script location. But when it's executed on Windows Server 2008 R2 Build 7601 from a java program, its showing a buggy behavior.
Here is the behavior,
1) When executed like this
Process proc= Runtime.getRuntime().exec("c:\\full\\path\\SomeBatchFile.bat");
Keeping the SomeBatchFile.bat file in C:\full\path (essentially giving the actual full path), its returning the expected result c:\full\path\
2) But when executed like this
Process proc= Runtime.getRuntime().exec("SomeBatchFile.bat");
Keeping the SomeBatchFile.bat file in C:\Windows (essentially a location that is a part of environment variable PATH).This returns a wrong value instead of the BAT script location, its returning the java program location from where this script is called.
This is the script file I am using,
REM Just prints the script location to a file
set MY_HOME=%~dp0
echo %MY_HOME% >> test_out.txt
REM And some other business logic here ...
On Windows Server 2003, this is working absolutely fine.
Any idea why this happens like this ? Is this Java/Windows Bug ? And how to resolve this ?

If you are trying to launch script in a relative path, you should also give a try for these syntaxes:
Process proc= Runtime.getRuntime().exec(".\\SomeBatchFile.bat");
or
Process proc= Runtime.getRuntime().exec(".\SomeBatchFile.bat");
or
Process proc= Runtime.getRuntime().exec("./SomeBatchFile.bat");
One of the three should work.

I've tried to replicate your problem, and the only way I get to do it is if the batch file is executed quoted, that is, if when the java program invokes the cmd instance to handle the batch file execution, the batch file name is "SomeBatchFile.bat". You can try to execute your batch file from command line calling it with quotes to see the problem.
That is, a simple batch file as
#echo %~dp0
placed somewhere in the path (by example, c:\windows\test.bat), when called from command line, from any folder, without including the path to it, without quotes (just type test.bat), you will retrieve the correct folder. But, if the same test is done calling the file as "test.bat" you will retrieve the current folder
D:\>type c:\windows\test.bat
#echo %~dp0
D:\>
D:\>test.bat
C:\Windows\
D:\>"test.bat"
D:\
D:\>cd temp
D:\temp>test.bat
C:\Windows\
D:\temp>"test.bat"
D:\temp\
I don't have access to neither 2003 not 2008 to check, but "probably" the configuration on batch file invocation was changed.
Here (in this case the problem raised from c# and the reference is to the full batch file name, but it is the same problem) you will find why this happens.
If the batch file name does not contain spaces or special characters you can simply use something like
Runtime.getRuntime().exec("cmd.exe /c SomeBatchFile.bat")
Or, if you can not avoid the quotes in the file name, you can change the batch file to use a subroutine to obtain the required information
#echo off
setlocal enableextensions disabledelayedexpansion
call :getBatchFolder MY_HOME
echo %MY_HOME%
goto :eof
:getBatchFolder returnVar
set "%~1=%~dp0"
goto :eof

Related

How to run jlink-generated Java runtime image without CMD window?

I've created Java runtime image for a simple OpenJFX application. In order to run this app, jlink auto-generated two lauch scripts under %image_path%/bin directory. This how it looks like (the one for Windows):
#echo off
set JLINK_VM_OPTIONS=
set DIR=%~dp0
"%DIR%\java" %JLINK_VM_OPTIONS% -m app/com.package.Launcher %*
Obviously, when I run this batch file it opens new shell window, which is not what I want to. I've tried all common approaches: use javaw instead of java, run script via start command etc. Nothing works.
Is it possible to avoid shell window or somehow create native launcher?
Ok, I've figured out it's not posiible to eliminite shell window completely. In the best scenario it's just flickers for ~1sec. This is how it can be achieved:
#echo off
set JLINK_VM_OPTIONS=
set DIR=%~dp0
start "" "%DIR%\javaw" %JLINK_VM_OPTIONS% -m app/com.package.Launcher %* && exit 0
There is a feature request about native laucher implementation but it's not discussed actively.
Nonetheless I've solved the problem. There is "Batch to EXE Converter" tool. It can generate executable (basically the same batch file) which can run your app silently.
This looks to be possible using vbscript. If you put the following script into a .vbs file next to the launcher.bat file (or whatever the name of the batch file is):
CreateObject("Wscript.Shell").Run CreateObject("Scripting.FileSystemObject").GetParentFolderName(WScript.ScriptFullName) & "\launcher.bat " & WScript.Arguments(0) & " > " & CreateObject("Scripting.FileSystemObject").GetParentFolderName(WScript.ScriptFullName) & "\launch-log.log", 0, False
This runs the batch file in the same directory, and also redirects stdout to a log file.
What you´d like to achieve is very well possible. It is actually even quite easy and I use this every day. There already is an early access build of jpackage available here: http://jdk.java.net/jpackage/ Creating executables works already
nicely (I use it on Mac and Windows). Only creating installers is still a bit problematic.
It's very easy to run a bat file without showing the cmd window.
you just need to create VBS file to run bat file with the following cmd
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & ".\bin\launcher.bat" & Chr(34), 0
Set WshShell = Nothing
Save cmd in the file out of the bin folder with any name like
Launcher.vbs.

Why does my batch file give an error if it has spaces in path?

I am trying to run a .jar file using a .bat file. But my Batch file gives an error when I have spaces in my path.
For e.g.
#echo off
java -jar %~dp0\..\new\myFile.jar %*
This are the contents of my batch file. I know that %~dp0 will give the current drive letter and path to my batch file and then \..\ will go back to it's parent directory and then it will open the new directory and run the jar file from it.
But the problem here is if my path contains a space in it the batch file gives an error:
Error: Unable to access jarfile C:\Users\Vatsal
Assuming my path for .jar file is:
C:\Users\Vatsal Sura\myFolder\new\myFile.jar
and path for my .bat file is:
C:\Users\Vatsal Sura\myFolder\batch\batchFile.bat
Now if I move myFolder directly in C:\, which doesn't contain any spaces in it, then it won't give any error and the .jar file would run as expected.
I want to know why this is happening and what should I do to make spaces count in my path?
Put the offending part in double quotes: java -jar "%~dp0\..\new\myFile.jar" %*
If the expansion is C:\Users\Vatsal Sura\myFolder\new\myFile.jar, then without quotes, -jar is only seeing up to the first space as it's argument (i.e. -jar C:\Users\Vatsal) and the remainder (Sura\myFolder\new\myFile.jar) is a completely different argument not related to the -jar
You need to make the shell/cmd see all of that as one argument. Double quotes will still allow any expansion to happen but everything within the quotes will be seen as a single item (the quotes won't be there when java sees it).
The reason for your problem is simple
Batch Is Simple Too,
Windows needed to create command Line, powershell, blah blah, and with its awesome features. However, Batch only runs on one programmed line of code, yes its confusing lol but when you write the code it is nothing compared to the binary. Batch is not too advanced and therefore does not process spaces when its in the "heart" of the command, like it i do this it literally has the same error however batch can tell the difference:
ec ho
(supposed to be echo)
anyways, a simple solution to your problem can be changing the encoding that your batch file is working on or just simply taking out the spaces on you directory.
Plus, don't use
%~dp0\
(it suKs)
Instead, to simplify this just do
#echo off
java -jar %CD%\new\myFile.jar %*
you don't have to even set %CD% to be anything it just automatically used the current directory.
*even with all this, your initial problem will not be solved. It may if you change the encoding (use notepad++ for that) but i hope you found this answer at least a little helpful to explain how this is working.

Running Eclipse from usb

I have put the necessary files on my USB pen drive, the Java Development Kit and the Eclipse files. I have created a .bat file which reads
#echo off
set Path=\32 Bit\jdk32\bin;%Path%
cd "32 Bit\Eclipse"
start eclipse.exe
exit
However when I run the batch, Eclipse launches and brings the error
As far as I can tell this is trying to use my old path variable for the JNI Shared Library. Could someone help me with this problem please.
It turns out there is a really simple solution to this.
Amended .bat file
#echo off
set Path=%~dp032 Bit\jdk32\bin;%Path%
cd "32 Bit\Eclipse"
start eclipse.exe
exit
Explanation
This works by getting the path of an executing batch file using the command %~dp0.
Where
d is the drive (in this case N:\)
p is the path (Code\Java\Eclipse Mars\)
0 is the name of the executing batch file
This path N:\Code\Java\Eclipse Mars\32 Bit\jdk32\bin which sets the Java version correctly and removes the error I had above
you don't need the batch script you can just change the -vm config directive and it will build the virtual machine from the exe for java you give it.
ex. -vm C:\jdk1.7.0_21\bin\javaw.exe. https://wiki.eclipse.org/Eclipse.ini#-vm_value:_Linux_Example

Executing a batch file from Java does not give access to full PATH

I am writing a Java utility that executes a batch file to generate a PDF using the DITA toolkit and Apache FOP. It finishes by using pdftk to watermark the front page. If I execute the batch file in Windows using Start>CMD, this line in the batch file works:
pdftk "%DITA_OUTPUT%book.pdf" multibackground C:\doc_build_system\watermark.pdf output "%DITA_OUTPUT%external.pdf" compress verbose
When I execute the batch file by Runtime.exec() the same line fails.
The cause of the failure is that the PATH variable is incomplete when executed through Java. It should have an entry like:
C:\Program Files (x86)\PDFtk Server\bin\
...but it does not. I tried to force execution through CMD by invoking runtime.exec("cmd /c batchfile.bat") (rather than just directly invoking the batchfile) but this also had no effect.
Any ideas?
You can try to set the path manualy before your start your java in cmd:
start cmd.exe. Then type:
SET PATH=%PATH%;C:\Program Files (x86)\PDFtk Server\bin
java MyProgram
If that is working you have to check if edited the right PATH variable. In Windows you can have different PATH environment variables for each user, plus there is one system-wide PATH variable (see screenshot) that will always be applied and combined with the user variables.
e.g. if you did set the path for your user and then use administrator for elevated rights to execute java, the PATH won't be set properly.
Make sure to use the system variable.
Also make sure to restart windows after you did edit the variable, because open applications and consoles will usually only fetch environment variables once at start up.
Just take pathman from the Windows Server 2003 Resource Kit:
USAGE:
/as path[;path[;path ...]]
Adds the semicolon-separated paths to the system path.
/au path[;path[;path ...]]
Adds the semicolon-separated paths to the user path.
/rs path[;path[;path ...]]
Removes the semicolon-separated paths from the system path.
/ru path[;path[;path ...]]
Removes the semicolon-separated paths from the user path.

Is there anyway to execute a jar file with a single word (or phrase) in Terminal?

I'm building a server in Java. I want to setup a single word option that will start and stop the server. "start" to start the server. "stop" to stop the server. I tried to use an executable file that launched the jar, but even using that strategy, I still have to type "./start". The punctuation is a little ugly.
I wanted something similar to "git". If you type "git" in Terminal, you are immediately using git's tools. I'm guessing this is because of a symlink? If so, how did the symlink for "git" get setup? I didn't have to manually set it up from what I remember.
If you would like to avoid sh or ./ while executing you may use alias, add following at the end in ~/.bashrc file:
alias sayhello="./sayhello.sh"
And then run the .bashrc file using following command:
source .bashrc
Finally, you should be able to execute your command using just:
sayhello
What OS are you working on? In windows you just have to add the location of start.exe to your PATH, then typing "start" in the command prompt will launch the executable and the jar

Categories