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;
}
}
}
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"
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。
7条答案
按热度按时间g6ll5ycj1#
如果您使用WIX项目(与VS Setup & Deployment项目相反),那么this article将准确地解释如何实现您所追求的目标。
rkkpypqq2#
我用powershell中的2行代码完成了它。
将现有的.vdproj重命名为MySetup.vdproj.template,并在要插入主exe文件版本的位置插入“${VERSION}”。
VS将检测vdproj文件中的更改,并询问您是否要重新加载它。
g0czyy6m3#
5fjcxozz4#
我对@JPreddy提交做了一些修改,使其具有用于重命名的输入和输出文件夹以及一些日志记录。
使用.net framework 4.8创建和新建控制台项目下载here
下面是如何安装和使用。转到您的安装程序项目下,然后单击“PostBuildEvents”。在参数中,您将需要调用.exe,然后添加变量/宏,如下所示:
EXE输入文件夹输出文件夹
下面是应用程序的app.config代码
下面是该应用程序的C#代码:
ftf50wuq5#
我不想使用上面的.exe方法,并且有一点空闲时间,所以我开始挖掘。我在Windows 7 64位上使用VS 2008。当我有一个安装项目时,让我们称之为MySetup,项目的所有细节都可以在文件$(ProjectDir)MySetup. vdproj中找到。
产品版本将显示在该文件的一行中,格式为
现在,安装项目上有一个生成后事件。如果选择安装项目并按F4,则在右键单击并选择属性时,会得到一组与完全不同的属性。按F4后,您将看到其中一个是PostBuildEvent。再次假设安装项目名为MySetup,则以下内容将设置.msi的名称以包括日期和版本
我将带你通过以上。
datevar是当前日期,格式为YYYYMMDD。
findstr行遍历MySetup.vdproj,删除任何包含PostBuildEvent的行,然后返回包含productVersion的单行,并将其输出到一个文件中,然后删除引号、空格,将点变为下划线。
for行拆分冒号上的剩余字符串,并获取第二部分,然后再次将其输出到一个文件。
然后将realvar设置为文件中的值,并重命名MySetup.msi以包含日期和版本。
因此,根据上述产品版本,如果日期为2012年3月27日,则该文件将重命名为
显然,使用此方法,您可以获取vdproj文件中的任何变量,并将它们包含在输出文件名中,而且我们不必构建任何额外的.exe程序来完成此操作。
高温加热
fnvucqvd6#
与Jim Grimmett的答案概念相同,但依赖性更小:
一些注意事项:
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 ...
xghobddn7#
不确定您是否仍然需要此问题,但希望回答此问题,因为我们在生成后事件中执行了类似的操作。就我所做的研究而言,这是不可能通过安装过程在内部设置您想要的文件名的。
您也可以通过其他方式完成此操作,方法是在生成后事件中通过外部应用程序命名输出文件。
以下是您可以执行的操作:
在生成后事件中-〉
[MsiRenamer应用程序路径]\MsiRenamer. exe "$(生成输出路径)"
创建一个应用程序,该应用程序将使用部署项目中的版本号重命名msi文件。以下是用于该应用程序的代码。我猜这应该能满足您的要求。
从alteridem article使用获取msi属性代码