Comment inclure le numéro de version dans le nom de fichier de sortie du projet VS Setup
Existe-t-il un moyen d'inclure le numéro de version dans la sortie.nom de fichier msi dans un projet D'installation VS2008?
Je voudrais par exemple un fichier de sortie appelé: "myinstaller-1.0.13.msi " où la partie version est automatiquement définie en fonction du numéro de version que j'ai mis dans les propriétés du projet de déploiement.
6 réponses
Je ne sais pas si vous avez toujours besoin de ceci ou non, mais je voulais répondre à cela car nous avons fait un type d'opération similaire dans l'événement postbuild. En ce qui concerne la recherche que j'ai faite, il n'est pas possible de définir le nom du fichier comme vous le souhaitez en interne via le processus d'installation.
Vous pouvez le faire autrement en nommant le fichier de sortie via une application externe dans l'événement post build.
Voici ce que vous pouvez faire:
Dans l'événement post build- >
[MsiRenamerAppPath] \ MsiRenamer.exe "$(BuildOutputPath) "
Créez une application qui renommera le fichier msi avec le numéro de version du projet de déploiement. Voici le code utilisé pour l'application. Cela devrait répondre à votre exigence, je suppose.
Obtenir le code des propriétés msi est utilisé à partir de alteridem article
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;
}
}
Je ne voulais pas utiliser le .méthode exe ci-dessus et avait un peu de temps libre alors j'ai commencé à diggind autour. J'utilise VS 2008 sur Windows 7 64 bits. Quand j'ai un projet D'installation, appelons-le MySetup tous les détails du projet peuvent être trouvés dans le fichier $ (ProjectDir)MySetup.vdproj.
La version du produit sera trouvée sur une seule ligne dans ce fichier sous la forme
ProductVersion="8:1.0.0"
Maintenant, il y a un événement post-build sur un projet d'installation. Si vous sélectionnez un projet d'installation et appuyez sur F4 vous obtenez un complètement différent de propriétés lorsque vous faites un clic droit et sélectionnez propriétés. Après avoir frappé F4, vous verrez que L'un des PostBuildEvent est. Encore une fois en supposant que le projet d'installation est appelé MySetup ce qui suit définira le nom de la .msi pour inclure la date et la version
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"
Je vais vous emmener à travers ce qui précède.
Datevar est la date actuelle sous la forme AAAAMMJJ.
La ligne findstr passe par MySetup.VDPROJ, supprime toute ligne avec PostBuildEvent dans, renvoie ensuite la seule ligne laissée avec productVersion et la sort dans un fichier. Nous supprimons ensuite les guillemets, les espaces, transformons les points en traits de soulignement.
La ligne for divise la chaîne restante sur deux-points, et prend la deuxième partie, et la sort à nouveau dans un fichier.
Nous avons ensuite mis realvar à la valeur laissée dans le fichier, et renommer MySetup.msi pour inclure la date et la version.
Donc, étant donné la ProductVersion ci-dessus, si c'était le 27 mars 2012, le fichier serait renommé à
MySetup-20120327-1_0_0.msi
Clairement en utilisant cette méthode, vous pouvez saisir L'une des variables dans le fichier vdproj et les inclure dans votre nom de fichier de sortie et nous n'avons pas besoin de construire un supplément .programmes exe pour le faire.
HTH
Même concept que la réponse de Jim Grimmett, mais avec moins de dépendances:
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"
Quelques points à noter:
MySetupProjectName.vdproj
doit être remplacée par le nom de votre fichier de projet. Oublier de changer cela entraîne une erreur de construction: 'PostBuildEvent' failed with error code '1'
et la fenêtre Output
montre quel fichier FINDSTR
n'a pas pu s'ouvrir.
Description étape par Étape:
FINDSTR /B /R /C:" *\"ProductVersion\"" $(ProjectDir)MySetupProjectName.vdproj
- recherche la ligne
"ProductVersion" = "8:x.y.z.etc"
du fichier de projet.
FOR /F "tokens=2 delims== " %%V IN (...) DO ... %%~nxV ...
- ceci est utilisé pour analysez la partie
x.y.z.etc
à partir du résultat ci-dessus.
$(BuiltOuputPath)
- c'est le chemin de sortie d'origine, selon ce qu'il dit dans les "Macros"de la ligne de commande de L'événement Post-build.
FOR %%I IN (...) DO ... %%~nI-%%~nxV%%~xI
- ceci est utilisé pour convertir la chaîne
foo.msi
enfoo-x.y.z.etc.msi
.
REN "$(BuiltOuputPath)" ...
- cela renomme simplement le chemin de sortie au nouveau nom.
FOR ... DO FOR .. DO REN ...
- Il est écrit sur une ligne comme ceci de sorte qu'une erreur le long du chemin brise proprement la construction.
Si vous utilisez un projet Wix (par opposition à un projet VS Setup & Deployment) alors Cet article explique exactement comment réaliser ce que vous recherchez.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using WindowsInstaller;
// cscript //nologo "$(ProjectDir)WiRunSql.vbs" "$(BuiltOuputPath)" "UPDATE `Property` SET `Property`.`Value`='4.0.0.1' WHERE `Property`='ProductVersion'"
// "SELECT `Property`.`ProductVersion` FROM `Property` WHERE `Property`.`Property` = 'ProductVersion'"
/*
* That's a .NET wrapper generated by tlbimp.exe, wrapping the ActiveX component c:\windows\system32\msi.dll.
* You can let the IDE make one for you with Project + Add Reference, COM tab,
* select "Microsoft Windows Installer Object Library".
*/
namespace PostBuildEventModifyMSI
{
/* Post build event fro Rename MSI file.
* $(SolutionDir)PostBuildEventModifyMSI\bin\Debug\PostBuildEventModifyMSI.exe "$(SolutionDir)TestWebApplicationSetup\Debug\TestWebApplicationSetup.msi"
*/
[System.Runtime.InteropServices.ComImport(), System.Runtime.InteropServices.Guid("000C1090-0000-0000-C000-000000000046")]
class Installer { }
class Program
{
static void Main(string[] args)
{
#region New code.
string msiFilePath = string.Empty;
if (args.Length == 0)
{
Console.WriteLine("Enter MSI file complete path:");
msiFilePath = Console.ReadLine();
}
else
{
Console.WriteLine("Argument Received args[0]: " + args[0]);
msiFilePath = args[0];
}
StringBuilder sb = new StringBuilder();
string[] words = msiFilePath.Split('\\');
foreach (string word in words)
{
sb.Append(word + '\\');
if (word.Contains("Debug"))
{
break;
}
else
{
}
}
// Open a view on the Property table for the Label property
//UPDATE Property set Value = '2.06.36' where Property = 'ProductVersion'
Program p = new Program();
string version = p.GetMsiVersionProperty(msiFilePath, "ProductVersion");
string productName = p.GetMsiVersionProperty(msiFilePath, "ProductName");
string newMSIpath = sb.ToString() + string.Format("{0}_{1}.msi", productName, version);
Console.WriteLine("Original MSI File Path: " + msiFilePath);
Console.WriteLine("New MSI File Path: " + newMSIpath);
System.IO.File.Move(msiFilePath, newMSIpath);
#endregion
//Console.Read();
}
private string GetMsiVersionProperty(string msiFilePath, string property)
{
string retVal = string.Empty;
// Create an Installer instance
WindowsInstaller.Installer installer = (WindowsInstaller.Installer) new Installer();
// Open the msi file for reading
// 0 - Read, 1 - Read/Write
Database db = installer.OpenDatabase(msiFilePath, WindowsInstaller.MsiOpenDatabaseMode.msiOpenDatabaseModeReadOnly); //// Open the MSI database in the input file
// Fetch the requested property
string sql = String.Format(
"SELECT Value FROM Property WHERE Property='{0}'", property);
View view = db.OpenView(sql);
//View vw = db.OpenView(@"SELECT `Value` FROM `Property` WHERE `Property` = 'ProductVersion'");
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(db);
return retVal;
}
}
}
Je l'ai fait avec 2 lignes dans powershell.
$versionText=(Get-Item MyProgram.exe).VersionInfo.FileVersion
(Get-Content MySetup.vdproj.template).replace('${VERSION}', $($versionText)) | Set-Content MySetup.vdproj
Renommez votre existant .vdproj pour être MySetup.vdproj.template et insérez "$ {VERSION} " partout où vous voulez insérer la version de votre fichier exe principal.
VS détectera alors le changement dans le fichier vdproj et vous demandera si vous voulez le recharger.