模仿NSIS SetOverwrite

时间:2019-02-04 23:12:47

标签: nsis archive robocopy

我的软件中有一些用户可修改的文件,如果被修改,我不想在重新安装期间覆盖。

我决定使用存档位来指示用户是否修改了目标文件。在全新安装期间,所有相关文件的所有存档位都将设置为OFF。

存档关闭:表示此文件未修改,因此可以替换为最新版本 存档打开:表示该文件是由用户修改的,即使有较新的版本,也不应被安装程序覆盖。

注意:众所周知,根据设计,编辑和保存文件会将存档位设置为“开”。

我什至认为在NSIS脚本中使用robocopy,但是据我所知,robocopy的排除参数与源文件有关,而与目标文件无关。我使用下面的代码:

    robocopy c:\source c:\target /XA:A

能否请您提供实现此类功能的线索。

1 个答案:

答案 0 :(得分:0)

我认为无法通过File /r来做到这一点。

当您手动提取每个文件时,您可以执行以下操作:

!include LogicLib.nsh

!define /IfNDef FILE_ATTRIBUTE_ARCHIVE 0x20
!define /IfNDef INVALID_FILE_ATTRIBUTES 0xffffffff
!define File_NoArchiveOverwrite "!insertmacro File_NoArchiveOverwrite "
!macro File_NoArchiveOverwrite sourcefile destinationfile
    Push $1
    System::Call 'KERNEL32::GetFileAttributes(ts)i.r1' "${destinationfile}"
    ${IfThen} $1 = ${INVALID_FILE_ATTRIBUTES} ${|} StrCpy $1 0 ${|} ; File does not exist? Make sure "it" has no attributes.
    IntOp $1 $1 & ${FILE_ATTRIBUTE_ARCHIVE}
    ${If} $1 = 0 ; Archive not set?
        SetOverwrite on
        File "/oname=${destinationfile}" "${sourcefile}"
        SetOverwrite lastused
    ${EndIf}
    Pop $1
!macroend


Section "Example preparation"
InitPluginsDir 
StrCpy $InstDir $PluginsDir ; Just a hack for this example

; Prepare some test files for this example:
File "/oname=$InstDir\test1.ini" "${__FILE__}"
SetFileAttributes "$InstDir\test1.ini" ARCHIVE
File "/oname=$InstDir\test2.ini" "${__FILE__}"
SetFileAttributes "$InstDir\test2.ini" NORMAL
SectionEnd

Section "Real code"
SetOutPath $InstDir
#File /r /x "*.ini" c:\myfiles\*.* ; Exclude .ini files because we handle them manually

${File_NoArchiveOverwrite} "${__FILE__}" "$InstDir\test1.ini" ; Not extracted because the dummy test1.ini file has ARCHIVE set
${File_NoArchiveOverwrite} "${__FILE__}" "$InstDir\test2.ini" ; This will overwrite the test2.ini dummy file.
${File_NoArchiveOverwrite} "${__FILE__}" "$InstDir\test3.ini" ; This file does not exist so we will extract a new file

SectionEnd

如果文件太多,无法手动创建${File_NoArchiveOverwrite}调用,则可以使用!system来调用批处理文件(或任何其他脚本或应用程序),该批处理文件会与{ {1}}个呼叫,然后您可以${File_NoArchiveOverwrite}这个文件:

!include

这假设Section SetOutPath $InstDir !tempfile FILELIST !system 'generatefilecommands.cmd "${FILELIST}"' !include "${FILELIST}" !delfile "${FILELIST}" !undef FILELIST SectionEnd 是您编写的文件,并且可能看起来像这样:

generatefilecommands.cmd