Как включить номер версии в имя выходного файла проекта установки VS

Есть ли способ включить номер версии как часть имени файла output.msi в проект установки VS2008?

Я хотел бы, например, выходной файл с именем: «myinstaller-1.0.13.msi», в котором часть версии автоматически устанавливается на основе номера версии, которую я ввел в свойствах проекта развертывания.


person chardy    schedule 29.07.2010    source источник


Ответы (5)


Не уверен, требуется ли вам это по-прежнему или нет, но хотел ответить на этот вопрос, поскольку мы проделали аналогичную операцию в событии postbuild. Что касается исследования, которое я провел, невозможно установить имя файла так, как вы хотите, внутри процесса установки.

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

Вот что можно сделать:

В событии сборки сообщения ->

[MsiRenamerAppPath] \ MsiRenamer.exe "$ (BuildOutputPath)"

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

Получение кода свойств msi используется из статьи alteridem

class MsiRenamer
  {
    static void Main(string[] args)
    {
      string inputFile;
      string productName = "[ProductName]";

      if (args.Length == 0)
      {
        Console.WriteLine("Enter MSI file:");
        inputFile = Console.ReadLine();
      }
      else
      {
        inputFile = args[0];
      }

      try
      {
        string version;

        if (inputFile.EndsWith(".msi", StringComparison.OrdinalIgnoreCase))
        {
          // Read the MSI property
          version = GetMsiProperty(inputFile, "ProductVersion");
          productName = GetMsiProperty(inputFile, "ProductName");
        }
        else
        {
          return;
        }
        // Edit: MarkLakata: .msi extension is added back to filename
        File.Copy(inputFile, string.Format("{0} {1}.msi", productName, version));
        File.Delete(inputFile);
      }
      catch (Exception ex)
      {
        Console.WriteLine(ex.Message);
      }
    }

    static string GetMsiProperty(string msiFile, string property)
    {
      string retVal = string.Empty;

      // Create an Installer instance  
      Type classType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
      Object installerObj = Activator.CreateInstance(classType);
      Installer installer = installerObj as Installer;

      // Open the msi file for reading  
      // 0 - Read, 1 - Read/Write  
      Database database = installer.OpenDatabase(msiFile, 0);

      // Fetch the requested property  
      string sql = String.Format(
          "SELECT Value FROM Property WHERE Property='{0}'", property);
      View view = database.OpenView(sql);
      view.Execute(null);

      // Read in the fetched record  
      Record record = view.Fetch();
      if (record != null)
      {
        retVal = record.get_StringData(1);
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(record);
      }
      view.Close();
      System.Runtime.InteropServices.Marshal.FinalReleaseComObject(view);
      System.Runtime.InteropServices.Marshal.FinalReleaseComObject(database);

      return retVal;
    }
  }
person JPReddy    schedule 11.02.2011
comment
У меня не было возможности проверить это, но похоже, что это отличное решение. Спасибо. - person chardy; 19.12.2011
comment
Чтобы использовать это, обязательно добавьте ссылку COM на библиотеку объектов установщика Microsoft Windows и с помощью WindowsInstaller; в этом фрагменте кода. - person Mark Lakata; 13.01.2012
comment
Что вы делаете с setup.exe при использовании предварительных условий? Это не сработает, AFAIK? - person Marcel; 01.03.2012
comment
@MarkLakata Есть вариант после сборки. Однако он не появляется, когда вы щелкаете правой кнопкой мыши и нажимаете свойства. Вы должны щелкнуть проект, затем нажать f4, чтобы открыть панель свойств справа. - person basher; 25.07.2013
comment
Я был как бы скучен, не видя свойства PostBuildEvent. Единственное, что сбивает с толку, это то, что для проекта развертывания есть 2 набора свойств. Щелкните правой кнопкой мыши "Свойства", а затем щелкните левой кнопкой мыши "Свойства" (при условии, что у вас открыто окно "Свойства"). Это свойство, которое можно щелкнуть левой кнопкой мыши. - person Mark Lakata; 25.07.2013

Я не хотел использовать метод .exe, описанный выше, и у меня было немного свободного времени, поэтому я начал копать. Я использую VS 2008 в 64-разрядной версии Windows 7. Когда у меня есть проект установки, давайте назовем его MySetup. Все подробности проекта можно найти в файле $ (ProjectDir) MySetup.vdproj.

Версия продукта будет найдена в отдельной строке этого файла в форме

ProductVersion="8:1.0.0"

Теперь в проекте установки ЕСТЬ событие после сборки. Если вы выберете проект установки и нажмете F4, вы получите совершенно другой набор свойств, чем когда вы щелкаете правой кнопкой мыши и выбираете свойства. После нажатия F4 вы увидите, что одно из событий - PostBuildEvent. Опять же, предполагая, что проект установки называется MySetup, следующее установит имя файла .msi, чтобы включить дату и версию.

set datevar=%DATE:~6,4%%DATE:~3,2%%DATE:~0,2%
findstr /v PostBuildEvent $(ProjectDir)MySetup.vdproj | findstr ProductVersion >$(ProjectDir)version.txt
set /p var=<$(ProjectDir)version.txt
set var=%var:"=%
set var=%var: =%
set var=%var:.=_%
for /f "tokens=1,2 delims=:" %%i in ("%var%") do @echo %%j >$(ProjectDir)version.txt
set /p realvar=<$(ProjectDir)version.txt
rename "$(ProjectDir)$(Configuration)\MySetup.msi" "MySetup-%datevar%-%realvar%.msi"

Я проведу вас через все вышесказанное.

datevar - текущая дата в формате ГГГГММДД.

Строка findstr проходит через MySetup.vdproj, удаляет любую строку с PostBuildEvent в, затем возвращает единственную строку, оставшуюся с productVersion в, и выводит ее в файл. Затем мы удаляем кавычки, пробелы, превращаем точки в подчеркивания.

Строка for разделяет оставшуюся строку на двоеточие, берет вторую часть и снова выводит ее в файл.

Затем мы устанавливаем realvar на значение, оставшееся в файле, и переименовываем MySetup.msi, чтобы включить дату и версию.

Итак, учитывая ProductVersion выше, если бы это было 27 марта 2012 г., файл был бы переименован в

MySetup-20120327-1_0_0.msi

Очевидно, что с помощью этого метода вы можете получить ЛЮБУЮ переменную в файле vdproj и включить их в имя выходного файла, и нам не нужно создавать для этого какие-либо дополнительные программы .exe.

HTH

person Jim Grimmett    schedule 27.03.2012
comment
@MuhammadMubashir В чем ошибка? Какую версию Visual Studio вы используете? - person basher; 25.07.2013
comment
У меня была аналогичная проблема с @MuhammadMubashir. Формат% date% зависит от настроек локализации, и поля не всегда находятся в одном месте. В Win7 US к дате добавлен сокращенный день недели, что мешает извлечению в примере кода, который предполагал только дд / мм / гггг. Это приводит к недопустимым символам имени файла для цели переименования, что приводит к сбою. - person Kevin Thibedeau; 23.05.2014
comment
У меня тоже была проблема. Чтобы извлечь ту же строку даты yyyyMMdd из даты в формате США, вы можете настроить первую строку следующим образом: set datevar =% DATE: ~ 10,4 %% DATE: ~ 4,2 %% DATE: ~ 7,2% - person Robb Sadler; 26.01.2017

Та же концепция, что и ответ Джима Гримметта, но с меньшими зависимостями:

FOR /F "tokens=2 delims== " %%V IN ('FINDSTR /B /R /C:" *\"ProductVersion\"" "$(ProjectDir)MySetupProjectName.vdproj"') DO FOR %%I IN ("$(BuiltOuputPath)") DO REN "$(BuiltOuputPath)" "%%~nI-%%~nxV%%~xI"

Некоторые примечания:

MySetupProjectName.vdproj следует изменить на имя файла вашего проекта. Если вы забудете изменить это, появится ошибка сборки: 'PostBuildEvent' failed with error code '1', а в окне Output показано, какой файл FINDSTR не удалось открыть.

Пошаговое описание:

FINDSTR /B /R /C:" *\"ProductVersion\"" $(ProjectDir)MySetupProjectName.vdproj

  • Будет найдена строка "ProductVersion" = "8:x.y.z.etc" из файла проекта.

FOR /F "tokens=2 delims== " %%V IN (...) DO ... %%~nxV ...

  • Это используется для выделения части x.y.z.etc из приведенного выше результата.

$(BuiltOuputPath)

  • Это исходный путь вывода, как указано в «Макросах» командной строки события после сборки.

FOR %%I IN (...) DO ... %%~nI-%%~nxV%%~xI

  • Используется для преобразования строки foo.msi в foo-x.y.z.etc.msi.

REN "$(BuiltOuputPath)" ...

  • Это просто переименовывает путь вывода на новое имя.

FOR ... DO FOR .. DO REN ...

  • Он написан в одной строке, вот так, чтобы возникшая в процессе ошибка полностью прервала сборку.
person antak    schedule 26.12.2014
comment
Отлично работает с VS2010! Готово! Очень умный способ сделать это. - person MensSana; 25.05.2016

Если вы используете проект WIX (в отличие от проекта установки и развертывания VS), тогда эта статья объясняет, как именно достичь того, что вам нужно.

person prairiehat    schedule 02.11.2010

Я сделал это с помощью двух строк в PowerShell.

$versionText=(Get-Item MyProgram.exe).VersionInfo.FileVersion
(Get-Content MySetup.vdproj.template).replace('${VERSION}', $($versionText)) | Set-Content MySetup.vdproj

Переименуйте существующий .vdproj в MySetup.vdproj.template и вставьте «$ {VERSION}» везде, где вы хотите вставить версию вашего основного exe-файла.

Затем VS обнаружит изменение в файле vdproj и спросит вас, хотите ли вы его перезагрузить.

person Evvo    schedule 01.10.2018