Archive: CopyFiles problem on Win7 x64


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?

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?


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.

Have you tried

CopyFiles "$VC_CL_PATH" "$VC_BIN_FOLDER\cl_backup.exe"

Thanks for the replies. I have now tried adding the extra quotes, that didn't work either.


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...


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


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.

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!


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.


WordReplace?

Stu