Имитировать несуществующую опцию "ifNotModified" в NSIS SetOverwrite - PullRequest
0 голосов
/ 05 февраля 2019

В моем программном обеспечении есть некоторые изменяемые пользователем файлы, которые я не хочу перезаписывать при переустановке в случае изменения.

Я решил использовать архивный бит, чтобы сигнализировать о том, что файл назначения изменен пользователем или нет, пользователем,Во время новой установки весь бит архива всех связанных файлов будет установлен в OFF.

архива OFF: означает, что этот файл не изменен, поэтому может быть заменен на новую версию архива ON: означает, что этот файл измененпользователь и не должен быть перезаписан установщиком, даже если есть более новая версия.

Примечание: как вы знаете, при разработке, редактировании и сохранении файла устанавливается бит архива ON.

Iдаже предполагалось использовать robocopy в скрипте NSIS, однако параметры исключения robocopy связаны с исходными файлами, а не с файлами назначения, насколько я могу видеть.Я использовал код ниже:

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

Не могли бы вы дать подсказки для реализации такой функции.

1 Ответ

0 голосов
/ 06 февраля 2019

Я не думаю, что это можно сделать с помощью 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 для вызова пакетного файла (или любого другого скрипта или приложения), который генерирует файл .NSH с вызовами ${File_NoArchiveOverwrite}, а затем вы можете !include этот файл:

Section
SetOutPath $InstDir
!tempfile FILELIST
!system 'generatefilecommands.cmd "${FILELIST}"'
!include "${FILELIST}"
!delfile "${FILELIST}"
!undef FILELIST
SectionEnd

Предполагается, что generatefilecommands.cmd - это файл, который вы пишете, и он может выглядеть примерно так:

@ECHO OFF&SETLOCAL ENABLEEXTENSIONS DISABLEDELAYEDEXPANSION
FOR %%A IN (*.ini) DO (
    ECHO >> "%~1" ${File_NoArchiveOverwrite} "%%~fA" "$InstDir\%%~A"
)
...