ngildea
11th March 2010 14:39 UTC
CopyFiles problem on Win7 x64
I'm have a problem with CopyFiles on Windows 7 x64. I use CopyFiles to firstly back up an existing file from another program's installation, then to copy another file from my installation into the directory to replace the backed-up file.
Under Windows XP, Vista and Windows 7 32-bit this all works correctly. Under Windows 7 x64 both the CopyFile operations fail. Initially, I thought it may be a permissions issue but running as administrator makes no difference. I then considered that there may be some problem with the underlying operation so I replaced the use of CopyFiles with direct calls to CopyFileA in kernel32.dll, and still the problem persisted. I made a small test app which perfoms the same operations using CopyFileA from kernel32 which does work, even without Admin privilidges.
Does anyone have any idea why this is the case?
Edit:
I have built a plugin DLL with the following function (just a wrapper around CopyFileA) which does work.
void __declspec(dllexport) copy(
HWND hWndParent, int string_size, char* variables, stack_t** stacktop, extra_parameters* extraParams)
{
char srcPath[1024], dstPath[1024];
DWORD error;
g_hwndParent = hWndParent;
EXDLL_INIT();
memset(srcPath, 0, 1024);
memset(dstPath, 0, 1024);
if (popstringn(srcPath, 1023) || popstringn(dstPath, 1023))
{
return;
}
if (!CopyFileA(srcPath, dstPath, FALSE))
{
char buffer[1024];
memset(buffer, 0, 1024);
error = GetLastError();
sprintf(buffer, "error: %d\n", error);
MessageBoxA(hWndParent, buffer, "CopyFile failed.", MB_OK);
}
}
I can't imagine why this works, but the builtin CopyFiles command itself fails. Surely CopyFiles just does this, along with some other book keeping and error checking?
pengyou
11th March 2010 20:38 UTC
CopyFiles works OK on my Windows 7 x64 system when I use it to copy single files silently.
It would help if you showed the code that fails. How does it fail? (do you get an error, what appears in the installer log)
Which version of NSIS are you using?
ngildea
12th March 2010 12:43 UTC
Here's a cut down version of the script that shows the problem:
Name "CopyFilesError"
OutFile "copyfiles.exe"
InstallDir $PROGRAMFILES\CopyFilesError
RequestExecutionLevel admin
Page directory
Page instfiles
Var VC_BIN_FOLDER
Var VC_CL_PATH
Function InstallFile
ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\${VISUAL_STUDIO_VERSION}\Setup\VC" "ProductDir"
StrCpy $VC_BIN_FOLDER "$0\bin"
StrCpy $VC_CL_PATH "$VC_BIN_FOLDER\cl.exe"
CopyFiles $VC_CL_PATH "$VC_BIN_FOLDER\cl_backup.exe" ; will fail
CopyFiles /SILENT $VC_CL_PATH "$VC_BIN_FOLDER\cl_backup_silent.exe" ; will fail
CopyFiles /FILESONLY $VC_CL_PATH "$VC_BIN_FOLDER\cl_backup_filesonly.exe" ; will fail
exdll::copy $VC_CL_PATH "$VC_BIN_FOLDER\cl_backup_dll.exe" ; will succeed
FunctionEnd
Section ""
SetOutPath $INSTDIR
Call InstallFile
SectionEnd
The installer log says "Copy failed.". Is there any way to get better error information?
I'm using version 2.46.
pengyou
12th March 2010 12:51 UTC
Have you tried
CopyFiles "$VC_CL_PATH" "$VC_BIN_FOLDER\cl_backup.exe"
ngildea
12th March 2010 16:27 UTC
Thanks for the replies. I have now tried adding the extra quotes, that didn't work either.
pengyou
12th March 2010 18:13 UTC
I don't have Visual Studio or your special plugin so I had to make some changes to your sample script ... and it also failed for me.
Edit:
Oops! My idea was rubbish! I should have commented out your plugin call instead of deleting it.
I had found that to access the uninstall entry for the 32-bit version of the Visual C++ 2008 redistributable I had to use SetRegView 64 before reading from the registry. So I jumped to the wrong conclusion...
thek
12th March 2010 22:20 UTC
I'm currently not able to check it myself but try removing
"RequestExecutionLevel admin"
If this is not set, Win7 does some *magic* compatibility stuff
pengyou
13th March 2010 17:37 UTC
Have you checked the value of $0 to see what is being read from the registry?
In your CopyFilesError script try changing
ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\${VISUAL_STUDIO_VERSION}\Setup\VC" "ProductDir"
StrCpy $VC_BIN_FOLDER "$0\bin"
StrCpy $VC_CL_PATH "$VC_BIN_FOLDER\cl.exe"
to
ReadRegStr $0 HKLM "Software\Microsoft\VisualStudio\${VISUAL_STUDIO_VERSION}\Setup\VC" "ProductDir"
StrCpy $VC_BIN_FOLDER "$0\bin"
StrCpy $VC_CL_PATH "$VC_BIN_FOLDER\cl.exe"
DetailPrint "$$0=$0"
DetailPrint "$$VC_BIN_FOLDER=$VC_BIN_FOLDER"
DetailPrint "$$VC_CL_PATH=$VC_CL_PATH"
and check the log to see the values which are being used.
ngildea
15th March 2010 16:16 UTC
I have discovered the problem, the CopyFiles instruction will fail when there are multiple directory separators in a row. My code was building the path "c:\Program Files (x86)\Microsoft Visual Studio 8\VC\\bin" which works correctly in the direct API calls, but for some reason NSIS chokes on this.
Thanks for the help!
onurk
24th August 2010 17:02 UTC
ngildea, thanks a lot for sharing your ideas on this issue. you have been really helpful. I wonder if you could send me the DLL you built as a workaround. I am not familiar with C++ development so even if you posted your code here, I could not make use of it.
I also wonder whether you have a way of fixing the file path (multiple directory separators) so that CopyFiles would work fine.
I appreciate any kind of help.
Afrow UK
24th August 2010 17:17 UTC
WordReplace?
Stu