cha*_*rdy 26 setup-project visual-studio-2008 visual-studio
有没有办法在VS2008安装项目中包含版本号作为output.msi文件名的一部分?
我想要一个名为"myinstaller-1.0.13.msi"的输出文件,其中版本部分是根据我在部署项目属性中放置的版本号自动设置的.
小智 18
我不想使用上面的.exe方法,并且有一点闲暇,所以我开始使用diggind.我在Windows 7 64位上使用VS 2008.当我有一个安装项目时,让我们调用它MySetup项目的所有细节都可以在文件$(ProjectDir)MySetup.vdproj中找到.
产品版本将在表单中该文件的单行中找到
ProductVersion="8:1.0.0"
Run Code Online (Sandbox Code Playgroud)
现在,在安装项目上有一个构建后事件.如果选择一个安装项目并点击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"
Run Code Online (Sandbox Code Playgroud)
我会带你了解上面的内容.
datevar是YYYYMMDD格式的当前日期.
findstr行通过MySetup.vdproj,删除PostBuildEvent中的任何行,然后返回带有productVersion的单行,并将其输出到文件.然后我们删除引号,空格,将点转换成下划线.
for行在冒号上拆分剩余的字符串,然后取第二部分,并再次将其输出到文件.
然后,我们将realvar设置为文件中剩余的值,并重命名MySetup.msi以包含日期和版本.
因此,鉴于上面的ProductVersion,如果是2012年3月27日,则文件将重命名为
MySetup-20120327-1_0_0.msi
Run Code Online (Sandbox Code Playgroud)
显然,使用此方法可以获取vdproj文件中的任何变量并将它们包含在输出文件名中,我们不必构建任何额外的.exe程序来执行此操作.
HTH
ant*_*tak 13
与Jim Grimmett的答案相同的概念,但依赖性较小:
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"
Run Code Online (Sandbox Code Playgroud)
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 ...
JPR*_*ddy 12
不确定你是否仍然需要这个,但是想要回答这个,因为我们在postbuild事件中做了类似的操作.就我所做的研究而言,无法通过设置过程在内部设置文件名.
您可以通过在构建后事件中通过外部应用程序命名输出文件以其他方式执行此操作.
这是你可以做的:
在post build事件中 - >
[MsiRenamerAppPath]\MsiRenamer.exe"$(BuildOutputPath)"
创建一个应用程序,它将使用部署项目中的版本号重命名msi文件.以下是用于该应用程序的代码.这应该符合你的要求我猜.
从alteridem文章中获取获取msi属性代码
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;
}
}
Run Code Online (Sandbox Code Playgroud)