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:
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:
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.
Title
Windows:
npc installfails withreplace executable failedwhen executable is already in target directoryEnvironment
windows_amd64_client.tar.gz)Reproduce
Verify that the client works correctly:
Output:
Then install the service:
or use the interactive menu:
Both produce:
The Windows service is never created.
Root cause
I checked the source code in
lib/install/install.go.InstallNpc()calls:copyStaticFile()builds:In this case:
replaceExecutable()then executes:After that it tries:
or falls back to:
Since
srcBinhas already been renamed to.old,copyFile()calls:which returns:
So this appears to be a self-replacement bug when
srcBinanddestBinare the same executable.Suggested fix
Skip replacement when
srcBinanddestBinrefer to the same file, for example:or avoid calling
replaceExecutable()if the executable is already located in the destination directory.