when running a Java application as service with the user 'LocalService', the temp directory ("java.io.tmpdir") points to 'c:/windows/temp' (for example).
Running a Java application normally gives 'c:/documents and settings/user/local settings/temp' instead.
How can I determine the user independent temp folder 'c:/windows/temp' when my application runs normally?
Thanks and greetings,
GHad
You could:
as suggested by St Shadow, rely on some environment variable such as %WINDIR% or %SYSTEMROOT%, append "\temp" on the end, and use this.
or pass in this value to your app as a variable using a commandline argument to the JVM, e.g.
-Dmytempdir=%WINDIR%\temp
As you mention, the user could change the values of either of these
variables using System -> Environment Variables, but I don't think they'd have any affect on the system until a reboot anyway (...?).
Or...
try and read the value from the registry using some nasty use of java.util.prefs.Preferences or something -- On my machine it looks like the value you're after is held in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\TEMP.
This would likely have to be quite messy and I don't know if the Preferences class will get you access to the key you'd need to read. Again, there's not much you could do about the user changing the registry value either, if they really wanted to, but again I doubt it would have any affect until after a reboot, and would probably have an impact on more than just your app.
Cheers,
--J
I'm not sure there is a 'clean' way of doing this.
In this situation, I would probably create a directory specifically for the Java app and refer to it in a properties file.
Java system property java.io.tmpdir just point to system variable %TMP%.
For normal user %TMP% points to %HOMEPATH%\temp, for other account - can be another path.
You can try to use %SYSTEMROOT%\temp instead of java.io.tmpdir - %SYSTEMROOT% points to directory, where windows is installed.
You can simply create your own temporary folder, add use the deleteOnExit() method to ensure this folder will be removed at the exit of your application.
Related
I need to create a persistent storage in my Java app so all users can access it. So I was studying about java.util.prefs.Preferences and using systemRoot() works fine to me on Windows, saving data at Register.
But I'm really facing some problems on Linux (Ubuntu). I want to use a directory that other of our apps already uses: /usr/share/.
So, I'm trying to redirect systemRoot default directory to /usr/share at runtime. Here's my code:
System.setProperty("java -Djava.util.prefs.systemRoot", "/usr/share/myfolder");
Preferences pref = Preferences.systemRoot().node("/usr/share/myfolder");
According to this site, I have to create .systemPrefs folder before execute this command line and its implicit that systemRoot() will use it.
When I execute my program, I get the following WARNING:
java.util.prefs.FileSystemPreferences syncWorld
WARNING Couldn't flush system prefs: java.util.prefs.BackingStoreException: /etc/.java/.systemPrefs/usr create failed.
So I'm assuming that System.setProperty isn't working. Any suggestion?
Thanks in advance!
This is a really pesky issue Java running on *nix based servers.
I was able to solve it by using the following vm args:
-Djava.util.prefs.userRoot=/opt/apache-tomcat-7.0.50/uprefs -Djava.util.prefs.systemRoot=/opt/apache-tomcat-7.0.50/sprefs
One important note though on the systemRoot path is to create a sub-folder within it named .systemPrefs or it will not work.
Also, don't forget to chown -R these directories to the user running the java application (in my case it was tomcat).
Bimalesh suggested that instead of
System.setProperty("java -Djava.util.prefs.systemRoot", "/usr/share/myfolder"), that you say
System.setProperty("-Djava.util.prefs.systemRoot", "/usr/share/myfolder").
But the name of the property that you are trying to set is java.util.prefs.systemRoot, and not -Djava.util.prefs.systemRoot, so you should do
System.setProperty("java.util.prefs.systemRoot", "/usr/share/myfolder");
If that doesn't work, try adding the "-D" switch to the command line that starts your program. That is where
java -D... should go. The command would start with
java -Djava.util.prefs.systemRoot=/usr/share/myfolder
In a Linux system, the System root preference node will be under /etc. This is due to history, and is a standard that is regulated by the Linux Standard Base. Any non-system preferences can go in other locations, but it is a violation of the design of the operating system to have system preference go elsewhere.
Odds are your define is ineffective in a Linux system because it fails to start at /etc. Apparently something in the Java code defers to the specification of the operating system over your decision to re-base the preference root.
Typically such files are protected against modification by not being world (or even most user) writeable. This means that for users to have access to Preferences, they should go under
Preferences.userRoot()
Which will place them in hidden directories just off their home directory (where they will have modification privileges).
If your want any user to read any other user's preferences (the description sounds like you might) then you will need to have an installer that runs as a sufficiently authorized user (typically root) to make the required directory under /etc and change it's permissions to be world writeable.
Typically files under /etc are not world writable as users changing other's user's setting is then possible, and considered a type of security breach of the user's expected environment. For example, a careless employee (or a disgruntled one) could wipe out all other user's preferences in one stroke.
In Linux, I'll usually put user configuration files in $HOME/.myapp and in Windows I'll use APPDATA. So far so good.
What about non-user specific configuration? In linux, I'd put it into /etc. Is there an equivalent in Windows? Please note I would like to have the service running before any user logs in. Also, in case it plays a role, I'm developing in Java.
Alternatively: I approaching this the wrong way?
You could use ALLUSERPROFILES as a base directory. This environment variable resolves to the C:\PROGRAMDATA folder in Windows7. Of course you need to add a specific folder for your applications
In summary, you should use the known folder: ProgramData.
To avoid hard coding of paths (and hence why I'm not providing them here) you should always retrieve the value via one of the following methods:
The %PROGRAMDATA% environment variable (you can also use %ALLUSERSPROFILE% but I consider %PROGRAMDATA% more meaningful)
For unmanaged code use SHGetKnownFolderPath, passing the FOLDERID_ProgramData.
For managed code use System.Environment.GetFolderPath, passing CommonApplicationData.
This folder is not writeable by non-admins, so depending on your requirements you'll want to create a directory for your program and set the ACLs you need at install time.
Some good information on this topic is provided in the blog post: "Where Should I Write Program Data Instead of Program Files".
For those interested in using other Known Folders, MSDN provides extensive documentation.
In Windows most "program files" for an app go in C:\Program Files\MyApp. The environment variable would be %ProgramFiles%\MyApp.
I would like to use the Users\Public directory to write some files to share between accounts easily, is there a way to get this as a system variable in Java?
The way to find the public directory is
System.getenv("PUBLIC");
This should get something like C:\Users\Public, or if your main drive is D:, D:\Users\Public.
This Wikipedia article is a good reference for Windows environment variables.
I don't have a Windows 7 around to check, but if that public directory is stored in an environment variable (e.g. like %APPHOME% or %USERPROFILE%) you can get retrieve its value using System.getenv()
http://docs.oracle.com/javase/6/docs/api/java/lang/System.html#getenv(java.lang.String)
You need to use System object
System.getProperty("user.home");
should get you what you need.
I'm trying to make my program save its state in the location set by %APPDATA% when the user is using Windows. However, System.getProperty("temp.dir"); does not return that. How do I get the value of the %APPDATA% variable in Windows, for the purpose of state saving?
Use System.getenv()
System.getenv("APPDATA")
But I think
System.getProperty("user.home")
should be preferred even though it's not exactly the same thing because it is more portable.
APPDATA is a Windows specific environment variable that gives you the location where application specific data is stored, so if you are not looking to write platform independent code, you can just do System.getenv("APPDATA");
I wish to place a file named as myFile.file in
C:/Windows/System32/ location.
Here is use java code to place my file. while I execute my program it throws "Access Denied:C:/Windows/System32/myFile.file".
why is it happening? Is it possible to place in that location?
That (and many other) system locations are restricted for admin users/elevated applications.
Application data should be stored in the user application data files in the user profile (or the common application data).
If you really must write into the system folder, then you will need to ask the user for permission via UAC, either by using ShellExecute() with the runas verb to run another program, or COM elevation (if that's possible in Java)
Update
See Andrew's answer for a method to get the correct path in Java.
Put myFile.file in a sub-directory of user.home.
The sub-directory could be the package name of the class saving the file. E.G. if your main class is our.com.Main, store the file at ${user.home}/our/com/myFile.file. The reason to use a sub-directory is to help prevent another apps. myFile.file from overwriting or interfering with your own version.
To get the location of user.home, see:
System.getProperty("user.home");
The value of user.home here, is:
Name Value
user.home C:\Users\Andrew
This technique will work reliably for Mac. & *nix, as well as Windows.