Skip to content

Windows 安装服务时自覆盖 Bug:srcBin 与 destBin 相同导致 install 失败 #338

Description

@forwads

Title

Windows: npc install fails with replace executable failed when executable is already in target directory

Environment

  • OS: Windows 11 x64
  • Version: v0.26.36
  • Download: Official Release (windows_amd64_client.tar.gz)

Reproduce

Verify that the client works correctly:

npc.exe -server=example.com:8024 -vkey=REDACTED_VKEY -type=tcp

Output:

Successful connection with server example.com:8024

Then install the service:

npc.exe install -server=example.com:8024 -vkey=REDACTED_VKEY -type=tcp

or use the interactive menu:

1 -> Register system service

Both produce:

替换可执行文件失败:
open C:\windows_amd64_client_npc\npc.exe:
The system cannot find the file specified.

The Windows service is never created.

Root cause

I checked the source code in lib/install/install.go.

InstallNpc() calls:

copyStaticFile(common.GetAppPath(), "npc")

copyStaticFile() builds:

srcBin := filepath.Join(common.GetAppPath(), "npc.exe")
destBin := filepath.Join(common.GetAppPath(), "npc.exe")

In this case:

srcBin == destBin

replaceExecutable() then executes:

os.Rename(destBin, destBin+".old")

After that it tries:

os.Rename(srcBin, destBin)

or falls back to:

copyFile(srcBin, destBin)

Since srcBin has already been renamed to .old, copyFile() calls:

os.Open(srcBin)

which returns:

The system cannot find the file specified

So this appears to be a self-replacement bug when srcBin and destBin are the same executable.

Suggested fix

Skip replacement when srcBin and destBin refer to the same file, for example:

absSrc, _ := filepath.Abs(srcBin)
absDst, _ := filepath.Abs(destBin)

if strings.EqualFold(absSrc, absDst) {
    return nil
}

or avoid calling replaceExecutable() if the executable is already located in the destination directory.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions