设置Windows服务的工作目录

问题描述 投票:0回答:3

我正在使用 Apache Commons Daemon 的 procrun 将 Java 应用程序包装为 Windows 服务。我遇到的问题与服务的工作目录

C:\Windows\system32
有关。服务所需的配置文件是相对于应用程序引用的(在
.\conf
目录中)。

我尝试了

--StartPath
参数到
procrun
,但它并没有影响服务的工作目录。 (更新:我现在看到该参数仅在启动 exe 时有效。)我试图保持应用程序跨平台,因此除非绝对必要,否则我不想修改配置文件路径。

有没有办法设置Windows服务的工作目录?

windows-services apache-commons-daemon
3个回答
0
投票

--StartPath
jvm
结合使用(而不是
exe
--StartMode
)对我来说很有效,并使用几个小时前下载的 Apache Commons Daemon 1.1。

如果没有

--StartPath
,即使使用
prunsrv
在 shell 上使用正确的目录启动
pushd
,我的守护进程也找不到它的配置文件。 Process Monitor 显示存储
prunsrv
的目录被用作当前工作目录。有了
--StartPath
,只有对我之前的内容进行补充,我的守护进程现在发现它自己的配置文件,并且 Logback 也正确初始化,在其
logback.xml
中使用相对路径仅在当前工作目录正确的情况下才有意义.

因此,无论您过去做了什么,都可能是错误的,或者该功能可能是从那时起添加的。看源代码,我不觉得

--StartPath
也只依赖或影响Exes:

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

希望这不是未定义的行为,因为文档实际上读起来不同:

启动映像可执行文件的工作路径。

OTOH,很长一段时间以来都是这样:

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


0
投票

这可能不是同一个问题。然而,我发现 procrun 对

--StartPath
参数路径周围双引号的解释存在问题。我的安装批处理文件如下所示:

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

如果没有引号,路径将在

%ROOTDIR%
中的第一个空格处结束。为了处理空格,我在路径两边加了双引号。然后,当我查看注册表时,我可以看到
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Apache Software Foundation\Procrun 2.0\MyServiceName\Parameters\Start\WorkingPath
的值已删除起始引号,但未删除终止引号,并且该值包含以下所有参数。因此,其他注册表项丢失。

可怕的解决方法是:

  • --StartPath
    移至最后一个参数,
  • 使用开场报价但不使用结束报价

所以批处理文件现在看起来像:

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

0
投票
void changeWorkingDirectory()
{
    // get exe file's path
    wchar_t exeFileFullPath[MAX_PATH];
    if (GetModuleFileName(NULL, exeFileFullPath, MAX_PATH) == 0)
    {
        std::exit(EXIT_FAILURE);
    }

    // split file path
    std::filesystem::path path(exeFileFullPath);
    std::wstring currentWorkingDirectory = path.parent_path().wstring();

    // change current working directory
    int ret = SetCurrentDirectory(currentWorkingDirectory.c_str());
    if (ret == 0)
    {
        std::exit(EXIT_FAILURE);
    }
}

它对我有用。

© www.soinside.com 2019 - 2024. All rights reserved.