Java user.dir is not always correct - java

Im making a basic .bat file that runs the application. This is to get auto startup feature.
However for some reason System.getProperty("user.dir") does not always get the correct path to the program.
Basically i am saving this to the .bat file:
protected final String fileSeparator=System.getProperty("file.separator");
out.println("#echo off");
out.println("start " + System.getProperty("user.dir") + fileSeparator +"App.jar");
out.println("exit");
On Windows server it returns the correct path but on Vista it does not.
Any ideas how i could get this to work on all versions of Windows?

You can do this by providing user.dir when you start your Java program like this
java somepackage.Main -Duser.dir=C:/Users/myUser

user.dir = User working directory
[from documentation ]
It is difficult to take decision based on value of this variable. Depending on the program starting the "java", it could have different values. For example, a bat file could have different working directory from invoked from different command-windows.
You could use %~dp0 to get location of the batch script and then put other paths relative to this.
Another option is to use tools like launch4j, which allows an easy way to control program directory : How to get the path to the executable when using launch4j?

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.

Issue of input line is too long while executing bat file

I have created one automated test which is running a bat file. This abc.bat is generated using application assembler plug-in. Inside bat file, class path has been set and Java commands has been executing). On Linux, it's working fine, but on Windows environment, I am getting the error of:
The input line is too long
The path from which batch file is executing is C:\build\work\work1\abc\abc.bat. I have to keep this path, can't reduce it to like C:\build\abc.bat.
I am using process builder to run this abc.bat file.
public Test(Path wp, Path exe) throws IOException {
builder = new ProcessBuilder()
.directory(wp.toFile())
.command(wp.resolve(exe).toAbsolutePath().toString())
.redirectOutput(Redirect.INHERIT)
.redirectError(Redirect.INHERIT);
builder.start();
}
Path wp contains the path of C:\build\work\work1. (I am fetching this path from system environment variables). Path exe contains the path of abc\abc.bat
I have done some research and found out that long path issue can be fixed by changing group policy as shown below:
Hit the Windows key, type gpedit.msc and press Enter.
Navigate to Local Computer Policy > Computer Configuration > Administrative Templates > System > Filesystem
and enable win32 long paths.
This doesn't work for me. I am using Windows 10 enterprise, OS build is 14393.1593.
Another way is using Subst command. Manually I can map the drive using command prompt like:
C:\build> Subst X: “C:\build\work\work1”
X:\>abc\abc.bat
It works fine and there is no issue of "The input line is too long". Is this a good way to overcome this issue? and how to automate this using process builder?
According to Microsoft's docs "Maximum Path Length Limitation" that path is not long enough to hit the windows limit.
"The input line is too long" must include other characters, possibly parameters being passed to the bat file, or parameters being used to call that bat file.
To get a better picture of what is actually being executed, turn on command line process auditing in windows. Command line process auditing
If you are somehow hitting that limit, and parameter passing is happening, I suggest finding a different way to get to that information, possibly by saving to and reading from a file.

Finding program's own location (path) [duplicate]

I've recently searched how I could get the application's directory in Java. I've finally found the answer but I've needed surprisingly long because searching for such a generic term isn't easy. I think it would be a good idea to compile a list of how to achieve this in multiple languages.
Feel free to up/downvote if you (don't) like the idea and please contribute if you like it.
Clarification:
There's a fine distinction between the directory that contains the executable file and the current working directory (given by pwd under Unix). I was originally interested in the former but feel free to post methods for determining the latter as well (clarifying which one you mean).
In Java the calls
System.getProperty("user.dir")
and
new java.io.File(".").getAbsolutePath();
return the current working directory.
The call to
getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
returns the path to the JAR file containing the current class, or the CLASSPATH element (path) that yielded the current class if you're running directly from the filesystem.
Example:
Your application is located at
C:\MyJar.jar
Open the shell (cmd.exe) and cd to C:\test\subdirectory.
Start the application using the command java -jar C:\MyJar.jar.
The first two calls return 'C:\test\subdirectory'; the third call returns 'C:\MyJar.jar'.
When running from a filesystem rather than a JAR file, the result will be the path to the root of the generated class files, for instance
c:\eclipse\workspaces\YourProject\bin\
The path does not include the package directories for the generated class files.
A complete example to get the application directory without .jar file name, or the corresponding path to the class files if running directly from the filesystem (e.g. when debugging):
String applicationDir = getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
if (applicationDir.endsWith(".jar"))
{
applicationDir = new File(applicationDir).getParent();
}
// else we already have the correct answer
In .NET (C#, VB, …), you can query the current Assembly instance for its Location. However, this has the executable's file name appended. The following code sanitizes the path (using System.IO and using System.Reflection):
Directory.GetParent(Assembly.GetExecutingAssembly().Location)
Alternatively, you can use the information provided by AppDomain to search for referenced assemblies:
System.AppDomain.CurrentDomain.BaseDirectory
VB allows another shortcut via the My namespace:
My.Application.Info.DirectoryPath
In Windows, use the WinAPI function GetModuleFileName(). Pass in NULL for the module handle to get the path for the current module.
Python
path = os.path.dirname(__file__)
That gets the path of the current module.
Objective-C Cocoa (Mac OS X, I don't know for iPhone specificities):
NSString * applicationPath = [[NSBundle mainBundle] bundlePath];
In Java, there are two ways to find the application's path. One is to employ System.getProperty:
System.getProperty("user.dir");
Another possibility is the use of java.io.File:
new java.io.File("").getAbsolutePath();
Yet another possibilty uses reflection:
getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
In VB6, you can get the application path using the App.Path property.
Note that this will not have a trailing \ EXCEPT when the application is in the root of the drive.
In the IDE:
?App.Path
C:\Program Files\Microsoft Visual Studio\VB98
In .Net you can use
System.IO.Directory.GetCurrentDirectory
to get the current working directory of the application, and in VB.NET specifically you can use
My.Application.Info.DirectoryPath
to get the directory of the exe.
Delphi
In Windows applications:
Unit Forms;
path := ExtractFilePath(Application.ExeName);
In console applications:
Independent of language, the first command line parameter is the fully qualified executable name:
Unit System;
path := ExtractFilePath(ParamStr(0));
Libc
In *nix type environment (also Cygwin in Windows):
#include <unistd.h>
char *getcwd(char *buf, size_t size);
char *getwd(char *buf); //deprecated
char *get_current_dir_name(void);
See man page
Unix
In unix one can find the path to the executable that was started using the environment variables. It is not necessarily an absolute path, so you would need to combine the current working directory (in the shell: pwd) and/or PATH variable with the value of the 0'th element of the environment.
The value is limited in unix though, as the executable can for example be called through a symbolic link, and only the initial link is used for the environment variable. In general applications on unix are not very robust if they use this for any interesting thing (such as loading resources). On unix, it is common to use hard-coded locations for things, for example a configuration file in /etc where the resource locations are specified.
In bash, the 'pwd' command returns the current working directory.
In PHP :
<?php
echo __DIR__; //same as dirname(__FILE__). will return the directory of the running script
echo $_SERVER["DOCUMENT_ROOT"]; // will return the document root directory under which the current script is executing, as defined in the server's configuration file.
echo getcwd(); //will return the current working directory (it may differ from the current script location).
?>
in Android its
getApplicationInfo().dataDir;
to get SD card, I use
Environment.getExternalStorageDirectory();
Environment.getExternalStoragePublicDirectory(String type);
where the latter is used to store a specific type of file (Audio / Movies etc). You have constants for these strings in Environment class.
Basically, for anything to with app use ApplicationInfo class and for anything to do with data in SD card / External Directory using Environment class.
Docs :
ApplicationInfo ,
Environment
In Tcl
Path of current script:
set path [info script]
Tcl shell path:
set path [info nameofexecutable]
If you need the directory of any of these, do:
set dir [file dirname $path]
Get current (working) directory:
set dir [pwd]
Java:
On all systems (Windows, Linux, Mac OS X) works for me only this:
public static File getApplicationDir()
{
URL url = ClassLoader.getSystemClassLoader().getResource(".");
File applicationDir = null;
try {
applicationDir = new File(url.toURI());
} catch(URISyntaxException e) {
applicationDir = new File(url.getPath());
}
return applicationDir;
}
in Ruby, the following snippet returns the path of the current source file:
path = File.dirname(__FILE__)
In CFML there are two functions for accessing the path of a script:
getBaseTemplatePath()
getCurrentTemplatePath()
Calling getBaseTemplatePath returns the path of the 'base' script - i.e. the one that was requested by the web server.
Calling getCurrentTemplatePath returns the path of the current script - i.e. the one that is currently executing.
Both paths are absolute and contain the full directory+filename of the script.
To determine just the directory, use the function getDirectoryFromPath( ... ) on the results.
So, to determine the directory location of an application, you could do:
<cfset Application.Paths.Root = getDirectoryFromPath( getCurrentTemplatePath() ) />
Inside of the onApplicationStart event for your Application.cfc
To determine the path where the app server running your CFML engine is at, you can access shell commands with cfexecute, so (bearing in mind above discussions on pwd/etc) you can do:
Unix:
<cfexecute name="pwd"/>
for Windows, create a pwd.bat containing text #cd, then:
<cfexecute name="C:\docume~1\myuser\pwd.bat"/>
(Use the variable attribute of cfexecute to store the value instead of outputting to screen.)
In cmd (the Microsoft command line shell)
You can get the name of the script with %* (may be relative to pwd)
This gets directory of script:
set oldpwd=%cd%
cd %0\..
set app_dir=%pwd%
cd %oldpwd%
If you find any bugs, which you will. Then please fix or comment.
I released https://github.com/gpakosz/whereami which solves the problem in C and gives you:
the path to the current executable
the path to the current module (differs from path to executable when calling from a shared library).
It uses GetModuleFileNameW on Windows, parses /proc/self/maps on Linux and Android and uses _NSGetExecutablePath or dladdr on Mac and iOS.
Note to answer "20 above regarding Mac OSX only: If a JAR executable is transformed to an "app" via the OSX JAR BUNDLER, then the getClass().getProtectionDomain().getCodeSource().getLocation(); will NOT return the current directory of the app, but will add the internal directory structure of the app to the response. This internal structure of an app is /theCurrentFolderWhereTheAppReside/Contents/Resources/Java/yourfile
Perhaps this is a little bug in Java. Anyway, one must use method one or two to get the correct answer, and both will deliver the correct answer even if the app is started e.g. via a shortcut located in a different folder or on the desktop.
carl
SoundPimp.com

how programmatically distinguish between Unix and Windows directory

In a java method i am loading a path name into a string variable, not knowing whether it is a Unix or a Windows path name.
How can i programmatically check whether it is a Unix or a Windows path?
if path.contains(":") execute a Windows-related function
else execute a Unix-related function
won't work, because Unix path names can contain a ":" as far as i know. Same with "/" for Unix , because Windows path names can contain a "/" .
So how could i do this best?
EDIT: I am loading directory names for remote machines, so i doubt i can use Use System.getProperty("os.name").
i was thinking about using Regex, but since i have no idea about regex in Java i have not considered that yet.
IMHO, using path names to determine OS platform is not the best idea.
Use System.getProperty("os.name")
and have a look here:
How do I programmatically determine operating system in Java?

Store paths in property files

I have Java app which runs on Linux and Windows and app depends of path of some program ( I need to read two paths in my app, one if I on windows and second if I on Linux, I read which OS in my code ). How to achive this with property file ?
What about simply adding both properties?
org.example.linux.path=...
org.example.windows.path=...
And read the property you need
String path = props.getProperty("org.example." + getOS() + ".path");
EDIT: btw, you can get an idea of different system properties and their respective values from this question
You can read O.S. by
System.getProperty("os.name");
and then conditionally read properties file
you can use
System.getProperty("os.name")
You have a property file for each OS and decide which one to load depending on the operating system you run on. For example linux.properties will contain the Linux paths while windows.properties will contain the windows paths.
just a thought not necessarily correct. Can we try having a property with key as
DS = "\" for one operating system and
DS1 = "/" for another operating system and we select it on the basis of whether i am on windows or mozilla.
and we save paths as
path = "c:".DS."dir1".DS."dir2"

Categories