Как я могу изменить текущий каталог программы - установив его в ярлык exe?
У меня есть исполняемый процесс, который работает с ярлыком.
В свойстве ярлыка "Начать с" я установил его в папку, где находятся все ресурсы приложения. Процесс по-прежнему ищет файлы в расположении исполняемого файла, а не в месте, указанном в ярлыке.
Я также могу видеть это в Process Explorer - "текущий каталог" - это местоположение исполняемого файла.
Есть ли способ изменить это?
(Если я не был достаточно ясен - я хочу поместить свое приложение в центральном сетевом расположении, а не в каждой папке пользователя - но я хочу, чтобы оно запускалось - над каждой папкой пользователя, поместив ярлык в каждую папку пользователя.)
Кстати: почему я не решаю это с помощью написания кода? Из-за сторонних банок у меня есть в exe (я использую exe4j, чтобы сделать exe)
4 ответа
Из документации exe4-j.., кажется, это можно настроить в проекте exe4j.
Working directory
For some applications (especially GUI applications) you might want to change the working directory
to a specific directory relative to the executable, for example to read config files that are in a fixed
location. To do so, please select the Change working directory to: checkbox and enter a
directory relative to the executable in the adjacent text field. To change the current directory to the
same directory where the executable is located, please enter a single dot.
Одна из альтернатив - использовать системное свойство. Просто создайте ярлык вот так:
java -Dmyproperty="\\myserver\myfolder" -jar yourjar.jar
И получите это свойство в вашей программе:
System.getProperty("myproperty");
Вы также можете установить несколько свойств системы.
Вы можете взломать classpath программно, что позволит вам указать конкретную папку или серию папок для доступа к данным.
import java.io.IOException;
import java.io.File;
import java.net.URLClassLoader;
import java.net.URL;
import java.lang.reflect.Method;
public class ClassPathHacker {
private static final Class[] parameters = new Class[]{URL.class};
public static void addFile(String s) throws IOException {
File f = new File(s);
addFile(f);
}//end method
public static void addFile(File f) throws IOException {
addURL(f.toURI().toURL());
}//end method
public static void addURL(URL u) throws IOException {
URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class sysclass = URLClassLoader.class;
try {
Method method = sysclass.getDeclaredMethod("addURL", parameters);
method.setAccessible(true);
method.invoke(sysloader, new Object[]{u});
} catch (Throwable t) {
t.printStackTrace();
throw new IOException("Error, could not add URL to system classloader");
}//end try catch
}//end method
}//end class
с файлом загрузчика свойств
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Properties;
import java.util.ResourceBundle;
public abstract class PropertyLoader
{
/**
* Looks up a resource named 'name' in the classpath. The resource must map
* to a file with .properties extention. The name is assumed to be absolute
* and can use either "/" or "." for package segment separation with an
* optional leading "/" and optional ".properties" suffix. Thus, the
* following names refer to the same resource:
* <pre>
* some.pkg.Resource
* some.pkg.Resource.properties
* some/pkg/Resource
* some/pkg/Resource.properties
* /some/pkg/Resource
* /some/pkg/Resource.properties
* </pre>
*
* @param name classpath resource name [may not be null]
* @param loader classloader through which to load the resource [null
* is equivalent to the application loader]
*
* @return resource converted to java.util.Properties [may be null if the
* resource was not found and THROW_ON_LOAD_FAILURE is false]
* @throws IllegalArgumentException if the resource was not found and
* THROW_ON_LOAD_FAILURE is true
*/
public static Properties loadProperties (String name, ClassLoader loader)
{
if (name == null)
throw new IllegalArgumentException ("null input: name");
if (name.startsWith ("/"))
name = name.substring (1);
if (name.endsWith (SUFFIX))
name = name.substring (0, name.length () - SUFFIX.length ());
Properties result = null;
InputStream in = null;
try
{
if (loader == null) loader = ClassLoader.getSystemClassLoader ();
if (LOAD_AS_RESOURCE_BUNDLE)
{
name = name.replace ('/', '.');
// Throws MissingResourceException on lookup failures:
final ResourceBundle rb = ResourceBundle.getBundle (name,
Locale.getDefault (), loader);
result = new Properties ();
for (Enumeration keys = rb.getKeys (); keys.hasMoreElements ();)
{
final String key = (String) keys.nextElement ();
final String value = rb.getString (key);
result.put (key, value);
}
}
else
{
name = name.replace ('.', '/');
if (! name.endsWith (SUFFIX))
name = name.concat (SUFFIX);
// Returns null on lookup failures:
in = loader.getResourceAsStream(name);
if (in != null)
{
result = new Properties ();
result.load (in); // Can throw IOException
}
}
}
catch (Exception e)
{
result = null;
}
finally
{
if (in != null) try { in.close (); } catch (Throwable ignore) {}
}
if (THROW_ON_LOAD_FAILURE && (result == null))
{
throw new IllegalArgumentException ("could not load [" + name + "]"+
" as " + (LOAD_AS_RESOURCE_BUNDLE
? "a resource bundle"
: "a classloader resource"));
}
return result;
}
/**
* A convenience overload of {@link #loadProperties(String, ClassLoader)}
* that uses the current thread's context classloader.
*/
public static Properties loadProperties (final String name)
{
return loadProperties (name,
Thread.currentThread ().getContextClassLoader ());
}
private static final boolean THROW_ON_LOAD_FAILURE = true;
private static final boolean LOAD_AS_RESOURCE_BUNDLE = false;
private static final String SUFFIX = ".properties";
} // End of class
тогда вы можете добавить путь следующим образом
try {
//First Load up the properties and populate the config
ClassPathHacker.addFile("/pathtomyapp");
} catch (IOException ex) {
ex.printStackTrace();
}
properties = PropertyLoader.loadProperties("myapp");
или вы также можете использовать getResourceBundle для получения ваших ресурсов, это всего лишь один пример взлома classpath, чтобы позволить файлам быть доступными, вы всегда можете просто добавить classpath программно и позволить jar-файлам, которые вам нужны, находиться там, поэтому если вы всегда гарантируете, что сетевой путь приложения равен Q: вы можете добавить Q:\ к пути к классам.
Я бы запустил Java-приложение с помощью cmd или bat-файла, а затем переключился на рабочий каталог, прежде чем вызывать javaw. Если вы не делаете ничего особенного в своем коде Java-приложения, все пути в нем будут относительно места, где вы начали Java.
Джесс