2

I'm using Apache Commons Daemon's procrun to wrap a Java application as a Windows service. The issue I am having is related to the working directory of the service which is C:\Windows\system32. The configuration files needed by the service are referenced relative to the application (in a .\conf directory).

I tried the --StartPath argument to procrun but it did not affect the service's working directory. (Update: I see now that parameter only works when starting an exe.) I am trying to keep the application cross-platform so I do not want to modify the config file paths unless absolutely necessary.

Is there a way to set a Windows service's working directory?

jzonthemtn
  • 3,344
  • 1
  • 21
  • 30
  • That would be the wrong solution. It should be possible in Java to find the location of the application, and you should be calculating your paths relative to that location, not relative to the current directory. This isn't just a Windows issue, the same is true in Linux and MacOSX - you should never just assume that the current directory is the same as the application directory. – Harry Johnston Jun 27 '17 at 21:17
  • The Java application thinks its location is system32 because it is being run as a service. Hence the question. :) – jzonthemtn Jun 28 '17 at 12:25
  • No. In a service, system32 is the current directory, aka working directory; it is not the application directory. Windows does not lie to applications about where they are located. Having done some research, it seems this is harder to do in Java than I expected and plenty of other people are just confused about the distinction between the current directory and the application directory as you are, but I did find [this answer](https://stackoverflow.com/a/43971405/886887) which should be what you need. – Harry Johnston Jun 28 '17 at 21:41
  • Depending on your needs, a simpler option might be to use the `++Environment` option to `prunsrv` to provide the path to the configuration files in an environment variable. – Harry Johnston Jun 28 '17 at 21:55
  • Relying on the current working directory is not a wrong solution and that's why one can set it during process creation, tools like Upstart or systemd can set it etc. Sometimes it's even necessary to properly integrate with 3rd party libs, like providing configuration files itself containing paths to Logback is a lot easier this way. – Thorsten Schöning Sep 26 '18 at 17:43

2 Answers2

0

Using --StartPath works for me in combination with jvm instead of exe as --StartMode and using Apache Commons Daemon 1.1 downloaded just some hours ago.

Without --StartPath, my daemon couldn't find it's config file even if prunsrv was started on the shell using pushd with the correct dir. Process Monitor showed that the dir where prunsrv was stored in was used as current working dir instead. With --StartPath, and only that addition to what I had before, my daemon finds it's own config file now AND Logback is properly initializing as well, using relative paths in its logback.xml only making sense in case of the proper current working dir.

So whatever you did in the past, it might have been wrong or that feature might have been added since then. Looking at the source code, I don't have the feeling that --StartPath depends or influences Exes only as well:

if (_jni_startup) {
    if (IS_EMPTY_STRING(SO_STARTPATH))
        SO_STARTPATH = gStartPath;
    if (IS_VALID_STRING(SO_STARTPATH)) {
        /* If the Working path is specified change the current directory */
        SetCurrentDirectoryW(SO_STARTPATH);
    }

https://github.com/apache/commons-daemon/blob/trunk/src/native/windows/apps/prunsrv/prunsrv.c#L1201

Let's hope this is not undefined behaviour, because the docs in deed read different:

Working path for the start image executable.

OTOH, it is the way it is for a very long time already:

https://github.com/apache/commons-daemon/commit/4664a01b6dfc8f5e34596f6b327d4498783c2a18#diff-880a104d7fb49226503af45f7d72593eR850

Thorsten Schöning
  • 3,501
  • 2
  • 25
  • 46
0

This may not be the same issue. However I'm finding an issue with procrun's interpretation of double quotes around the path given to the --StartPath argument. My installation batch file looks like:

SET ROOTDIR=%~dp0
"%ROOTDIR%prunsrv.exe" install MyServiceName ... --StartPath="%ROOTDIR%" ...

Without quotes the path ends at the first space in %ROOTDIR%. To cope with spaces I put double quotes around the path. Then when I look at the registry I can see that the value for Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Apache Software Foundation\Procrun 2.0\MyServiceName\Parameters\Start\WorkingPath has removed the starting quote, but not the terminating one and the value includes all the following parameters. Consequently other registry entries are missing.

The horrible workaround is to:

  • move --StartPath to be the last argument,
  • use an opening quote but no closing one.

So the batch file now looks like:

SET ROOTDIR=%~dp0
"%ROOTDIR%prunsrv.exe" install MyServiceName ... ... --StartPath="%ROOTDIR%
Reg Whitton
  • 655
  • 8
  • 9