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

Я пытаюсь использовать пакетный файл при предварительной сборке, который выглядит как

@echo off
set TARGETDIRECTORY=%1
set OUTPUTFILE=%2
set PROJDIR=%3
echo Starting Dependency check...
echo ^<?xml version="1.0" encoding="UTF-8"?^> > %OUTPUTFILE%
echo ^<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"^> >> %OUTPUTFILE%
echo   ^<Fragment^> >> %OUTPUTFILE%
echo     ^<ComponentGroup Id="MyWebApiBinaries" Directory="INSTALLFOLDER"^> >> %OUTPUTFILE%

for %%F in (%TARGETDIRECTORY%\*.dll) do (
    echo "-- Adding %%~nxF" 
    echo "-- Calling %PROJDIR%Uuidgen.Exe"
    %PROJDIR%Uuidgen.Exe> %PROJDIR%temp.txt
    set /p aGUID=<%PROJDIR%temp.txt
    del %PROJDIR%temp.txt
    echo "-- Adding %aGUID%"
    echo       ^<Component Id="%%~nxF" Guid="%aGUID%"^> >> %OUTPUTFILE%
    echo                     ^<File  Id="%%~nxF" Name="%%~nxF" Source="%%~dpnxF" Vital="yes" KeyPath="yes" DiskId="1"/^> >> %OUTPUTFILE%
    echo       ^</Component^> >> %OUTPUTFILE%
)

echo     ^</ComponentGroup^> >> %OUTPUTFILE%
echo   ^</Fragment^> >> %OUTPUTFILE%
echo ^</Wix^> >> %OUTPUTFILE%
echo Dependency check done.

Получил эту идею из этого ответа, за исключением того, что мне нужно было добавить GUID, потому что я устанавливаю в inetpub вместо программных файлов. Поэтому я включил uuidgen.exe в проект для создания GUID. Я вызываю exe и переключаю guid во временный файл, который позже пытался прочитать, за исключением того, что он его не читает. Я пробовал этот подход в другом командном файле и вручную его вызываю, и он его читает, поэтому я не знаю, почему он здесь не работает. В основном я говорю об этих двух строчках:

%PROJDIR%Uuidgen.Exe> %PROJDIR%temp.txt
set /p aGUID=<%PROJDIR%temp.txt

Я удалил удаление, чтобы убедиться, что файл генерирует guid и создается, и он там, поэтому я знаю, что это должна быть вторая строка.

Я также пробовал бегать

for /f %%i in ('"%PROJDIR%\Uuidgen.Exe"') do set GUID=%%i

Вместо двух других строк, но я не получаю руководство по переменной

Я знаю, что этого не происходит, потому что я добавил эхо с переменной, а также %OUTPUTFILE% генерируется с Guid = "" (просто пустой строкой / переменной). Есть идеи, почему он не получает руководство по переменной?

0
CPay 5 Янв 2017 в 02:11
Delayed expansion проблема. Я включил ответ о том, как решить эту проблему, не включая его. Но вы должны уделять пристальное внимание другим сообщениям, поскольку delayed expansion или variable expansion within a block спрашивали множество раз. Надеюсь, это поможет.
 – 
elzooilogico
5 Янв 2017 в 15:10
Почему нельзя просто использовать автоматически сгенерированные идентификаторы GUID, опуская атрибут guid или используя Guid="*"? Если вы когда-нибудь снова автоматически создадите файл wxs для тех же компонентов, вы можете столкнуться с проблемами при обновлении в зависимости от того, где вы запланировали удаление существующих продуктов.
 – 
Brian Sutherland
5 Янв 2017 в 17:55
Сазерленд, потому что внешне это приведет к ошибке, я думаю, что автоматически сгенерированные руководства работают только с папкой программных файлов. Но ваше беспокойство также справедливо, я не думал об этом сценарии
 – 
CPay
5 Янв 2017 в 20:51

1 ответ

Лучший ответ

Это проблема нашего старого друга delayed expansion.

Есть масса вопросов о расширении переменных внутри блоков.

Когда командный процессор находит блок (что-либо в скобках), он полностью анализирует его и расширяет переменные до значения, которое они имеют при оценке блока. Если вы обновляете значение переменной в блоке, вам необходимо включить отложенное расширение для переменной, чтобы отразить внесенные изменения. Также вы должны изменить синтаксис var с %var% на !var!.

В вашем коде aGUID var создается в блоке for, поэтому он расширяется до значения, которое он содержит, когда начинается блок (в вашем случае empty или undefined). Чтобы обновлять значение на каждой итерации блока for, вам необходимо включить отложенное расширение.

Другой обходной путь - использовать новый цикл for для получения выходных данных uuidgen.exe, поскольку переменные for всегда раскрываются в строке. Такой подход дает вам еще одно преимущество: вам не понадобится временный файл.

ПРИМЕЧАНИЕ: Кроме того, вы пишете несколько строк в файл, обратите внимание, что

>"%output%" (
   for ... do (
     echo(...
     echo(...
   )
)  

Открывает файл только один раз, тогда как

   for ... do (
     echo(...>>"%output%"
     echo(...>>"%output%"
   )

Открывает и закрывает файл каждый раз, когда >> используется перенаправление "% output%", поэтому сначала ускоряется блок.

КСТАТИ

>"%output%" (
   for ... do (
     ...
   )
)  

Такой же как

(
   for ... do (
     ...
   )
)>"%output%"  

Наконец, рекомендуется заключать в кавычки как var name, так и var content, как в

set "TARGETDIRECTORY=%~1"

Чтобы избавиться от нежелательных конечных пробелов, также %~1 означает первый аргумент без кавычек.

Не испытано. Возможный рабочий код

@echo off
SetLocal

set "TARGETDIRECTORY=%~1"
set "OUTPUTFILE=%~2"
set "PROJDIR=%~3"

if not "%TARGETDIRECTORY%" EQU "" if not "%OUTPUTFILE%" EQU "" echo Missing argument/s.& exit/B
if not exist "%PROJDIR%Uuidgen.Exe" echo Uuidgen.exe not found or missing argument.& exit/B

echo Starting Dependency check...

>"%OUTPUTFILE%" (
  echo ^<?xml version="1.0" encoding="UTF-8"?^>
  echo ^<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"^>
  echo   ^<Fragment^>
  echo     ^<ComponentGroup Id="MyWebApiBinaries" Directory="INSTALLFOLDER"^>

  for %%F in (%TARGETDIRECTORY%\*.dll) do (
      for /F %%U in ('"%PROJDIR%Uuidgen.Exe"') do (
         echo "-- Adding %%~nxF - GUID %%U" >CON
         echo       ^<Component Id="%%~nxF" Guid="%%U"^>
         echo                     ^<File  Id="%%~nxF" Name="%%~nxF" Source="%%~dpnxF" Vital="yes" KeyPath="yes" DiskId="1"/^>
         echo       ^</Component^>
      )   
  )

  echo     ^</ComponentGroup^>
  echo   ^</Fragment^>
  echo ^</Wix^>
)

echo Dependency check done.
EndLocal
exit /B

Поскольку весь вывод перенаправляется на OUTPUTFILE, любое сообщение, которое вы хотите отобразить, должно быть затем перенаправлено на стандартный вывод >CON, поэтому echo "-- Adding %%~nxF - GUID %%U" >CON

1
elzooilogico 5 Янв 2017 в 15:08