2010-02-11 62 views
47

比方說,我想創建一個靜態文本文件附帶的每個版本。我想要的文件與釋放(如AssemblyInfo.cs指定)的版本號更新,但我不希望有手動執行此操作。確定組件版本

我希望我可以用一個生成後事件和飼料的版本號這樣一個批處理文件:

call foo.bat $(AssemblyVersion) 

但是我無法找到任何合適的變量或宏來使用。

有沒有辦法實現這一點,我已經錯過了?

+0

讀取一個最最適合你所有的答案。 'PostBuildEventDependsOn'是最高投票和最簡單的。 (注意粘貼' – OzBob 2015-09-21 07:43:36

回答

15

如果你喜歡這些腳本方法也可能會爲你工作:

如果您使用的是生成後事件,您可以使用Filever.exe工具搶出來的已建成總成:

for /F "tokens=4" %%F in ('filever.exe /B /A /D bin\debug\myapp.exe') do (
    set VERSION=%%F 
) 
echo The version is %VERSION% 

獲取filever.exe從這裏:http://support.microsoft.com/kb/913111

如果您使用的是預生成事件,你可以把它拿出來AssemblyInfo.cs文件作爲跟隨S:

set ASMINFO=Properties\AssemblyInfo.cs 
FINDSTR /C:"[assembly: AssemblyVersion(" %ASMINFO% | sed.exe "s/\[assembly: AssemblyVersion(\"/SET CURRENT_VERSION=/g;s/\")\]//g;s/\.\*//g" >SetCurrVer.cmd 
CALL SetCurrVer.cmd 
DEL SetCurrVer.cmd 
echo Current version is %CURRENT_VERSION% 

它使用sed的UNIX命令行工具,你可以從很多地方,比如在這裏下載:http://unxutils.sourceforge.net/ - IIRC一個好的工作。

+0

我使用Pre-Build事件。現在,我有了Properties \ AssemblyInfo。cs或鏈接到%SolutionDir%\ GlobalAssemblyInfo.cs。如何檢測AssemblyVersion是否位於Properties \ AssemblyInfo.cs或%SolutionDir%\ GlobalAssemblyInfo.cs中,然後獲取版本......? – Kiquenet 2011-11-11 08:54:39

+0

也許你可以使用「IF [NOT] EXIST filename命令」功能?鍵入「if /?」在文檔和一些示例的命令提示符下。 – Tuinstoelen 2011-11-11 13:24:10

1

我認爲你能做的最好的事情是看看的MSBuild和MsBuild Extension Pack,使得後生成事件發生,並寫入到您的測試文件,你應該能夠編輯你的解決方案文件。

如果這太複雜了,那麼您可以簡單地創建一個小程序來檢查您輸出目錄中的所有程序集,並在後期構建中執行它,您可以使用變量名稱傳遞輸出目錄...例如後生成事件...

AssemblyInspector.exe 「$(TARGETPATH)」

class Program 
{ 
    static void Main(string[] args) 
    { 
     var assemblyFilename = args.FirstOrDefault(); 
     if(assemblyFilename != null && File.Exists(assemblyFilename)) 
     { 
      try 
      { 
       var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyFilename); 
       var name = assembly.GetName(); 

       using(var file = File.AppendText("C:\\AssemblyInfo.txt")) 
       { 
        file.WriteLine("{0} - {1}", name.FullName, name.Version); 
       } 
      } 
      catch (Exception ex) 
      { 
       throw; 
      } 
     } 
    } 
} 

你也可以通過在文本文件中的位置......

11

作爲一種變通方法我已經寫了一個管理控制檯應用程序,它採取目標作爲參數,並返回版本號。

我仍然有興趣聽到一個簡單的解決方案 - 但我張貼這種的情況下,任何人發現它是有用的。

using System; 
using System.IO; 
using System.Diagnostics; 
using System.Reflection; 

namespace Version 
{ 
    class GetVersion 
    { 
     static void Main(string[] args) 
     { 
      if (args.Length == 0 || args.Length > 1) ShowUsage(); 

      string target = args[0]; 

      string path = Path.IsPathRooted(target) 
           ? target 
           : Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName) + Path.DirectorySeparatorChar + target; 

      Console.Write(Assembly.LoadFile(path).GetName().Version.ToString(2)); 
     } 

     static void ShowUsage() 
     { 
      Console.WriteLine("Usage: version.exe <target>"); 
     } 
    } 
} 
+0

時特殊的'25'Unicode技巧是的,我確實發現這個很有用,謝謝。我不想使用unix工具,也不想使用MSBuild,所以我使用類似於這是由Winston和Rohan在這裏提供的在一個項目的postbuild事件中,我使用2個參數調用這段代碼,程序集的TargetPath以及程序集打包的安裝項目的路徑在安裝程序的後期構建事件中,我調用msiinfo將版本數據移動到MSI,以便消費者可以看到他們正在加載的版本。謝謝。 – TonyG 2011-08-06 00:53:35

+0

這應該是可以接受的解決方案,因爲filever似乎獲取文件版本而不是內部程序集版本。我爲我的應用程序使用匯編版本,因爲它很容易自動增加。 – transistor1 2012-10-17 19:46:42

+0

這個命令行非常方便,我可以用它來更新安裝程序的版本號,以匹配它正在安裝的應用程序的版本。一行可以將版本號放入環境變量 – 2013-09-05 16:45:35

1

我已經開始增加一個獨立的項目,最後建立並添加後生成事件到運行本身的項目。然後,我只是在那裏以編程方式執行我的構建後步驟。

它使人們更方便做這樣的東西。然後你可以檢查你想要的組件的組件屬性。到目前爲止它的工作非常棒。

1

從那我所瞭解的...

你需要一個發電機後建立事件。

1步:寫一個發電機

/* 
* Author: Amen RA 
* # Timestamp: 2013.01.24_02:08:03-UTC-ANKH 
* Licence: General Public License 
*/ 
using System; 
using System.IO; 

namespace AppCast 
{ 
    class Program 
    { 
     public static void Main(string[] args) 
     { 
      // We are using two parameters. 

      // The first one is the path of a build exe, i.e.: C:\pathto\nin\release\myapp.exe 
      string exePath = args[0]; 

      // The second one is for a file we are going to generate with that information 
      string castPath = args[1]; 

      // Now we use the methods below 
      WriteAppCastFile(castPath, VersionInfo(exePath)); 
     } 


     public static string VersionInfo(string filePath) 
     { 
      System.Diagnostics.FileVersionInfo myFileVersionInfo = System.Diagnostics.FileVersionInfo.GetVersionInfo(filePath); 
      return myFileVersionInfo.FileVersion; 
     } 


     public static void WriteAppCastFile(string castPath, string exeVersion) 
     { 
      TextWriter tw = new StreamWriter(castPath); 
      tw.WriteLine(@"<?xml version=""1.0"" encoding=""utf-8""?>"); 
      tw.WriteLine(@"<item>"); 
      tw.WriteLine(@"<title>MyApp - New version! Release " + exeVersion + " is available.</title>"); 
      tw.WriteLine(@"<version>" + exeVersion + "</version>"); 
      tw.WriteLine(@"<url>http://www.example.com/pathto/updates/MyApp.exe</url>"); 
      tw.WriteLine(@"<changelog>http://www.example.com/pathto/updates/MyApp_release_notes.html</changelog>"); 
      tw.WriteLine(@"</item>"); 
      tw.Close(); 
     } 
    } 
} 

第2步:在我們的IDE

使用它作爲一個後生成命令的申請後爲您令人滿意的運行:

在您的開發IDE中,對於構建後事件使用以下命令行。

C:\Projects\pathto\bin\Release\AppCast.exe "C:\Projects\pathto\bin\Release\MyApp.exe" "c:\pathto\www.example.com\root\pathto\updates\AppCast.xml" 
71

如果(1)你不想下載或創建檢索程序集的版本和(2)你不介意編輯Visual Studio項目文件,然後有一個簡單的解決方案定製的可執行文件它允許你使用宏,看起來像這樣:

@(目標 - > '%(版)')

@(VersionNumber) 

要做到這一點,卸載你的項目。如果某處的項目定義了<PostBuildEvent>屬性,請將其從項目中剪下並暫時保存在其他位置(記事本?)。然後,在項目的最後,剛剛結束標記之前,把這個:

<Target Name="PostBuildMacros"> 
    <GetAssemblyIdentity AssemblyFiles="$(TargetPath)"> 
    <Output TaskParameter="Assemblies" ItemName="Targets" /> 
    </GetAssemblyIdentity> 
    <ItemGroup> 
    <VersionNumber Include="@(Targets->'%(Version)')"/> 
    </ItemGroup> 
</Target> 
<PropertyGroup> 
    <PostBuildEventDependsOn> 
    $(PostBuildEventDependsOn); 
    PostBuildMacros; 
    </PostBuildEventDependsOn>  
    <PostBuildEvent>echo HELLO, THE ASSEMBLY VERSION IS: @(VersionNumber)</PostBuildEvent> 
</PropertyGroup> 

這段代碼有一個例子<PostBuildEvent>已經在它。不用擔心,重新加載項目後,您可以將其重置爲真正的構建後事件。

如今如許,大會版本可與此宏您後生成事件:

@(VersionNumber) 

完成!

+1

它輸出的組裝版本是:(版本)對我來說 – 2013-10-23 14:32:52

+1

它也適用於我。問題在於'25'通過Visual Studio中的後期編輯編輯器潛入,如果你編輯csproj @(目標 - >'%25(版本)'),你會看到它。當25被刪除時,它就像一個魅力... – jmelhus 2013-12-03 18:25:24

+0

優秀的,找到了25偷偷摸摸(WTH是這樣呢?)我有一個很好的自動化包構建。現在我只需要在釋放模式下構建時有條件地觸發,而且我們是金手指。謝謝! – 2014-01-28 19:23:49

0

我需要這個自動將數字自動放入輸出文件夾中的自述文件。最後,正如溫斯頓史密斯所表明的那樣,一個小型的外部工具是非常好的解決方案,而且它具有可以根據需要進行格式化的優點。

此應用程序將格式化的版本輸出到控制檯。我在後期構建事件中使用它來構建自述文件,方法是使用>>將其自動輸出重定向到自述文件。

public class GetVerNum 
{ 
    static void Main(String[] args) 
    { 
     if (args.Length == 0) 
      return; 
     try 
     { 
      FileVersionInfo ver = FileVersionInfo.GetVersionInfo(args[0]); 
      String version = "v" + ver.FileMajorPart.ToString() + "." + ver.FileMinorPart; 
      if (ver.FileBuildPart > 0 || ver.FilePrivatePart > 0) 
       version += "." + ver.FileBuildPart; 
      if (ver.FilePrivatePart > 0) 
       version += "." + ver.FilePrivatePart; 
      Console.Write(version); 
     } 
     catch { } 
    } 
} 

我生成後事件:

<nul set /p dummyset=My Application > "$(ProjectDir)\Readme\readme-header.txt" 
"$(ProjectDir)\Readme\GetVersionNumber.exe" "$(TargetPath)" >>"$(ProjectDir)\Readme\readme-header.txt" 
echo by Nyerguds>>"$(ProjectDir)\Readme\readme-header.txt" 
echo Build date: %date% %time% >> "$(ProjectDir)\Readme\readme-header.txt" 
echo.>>"$(ProjectDir)\Readme\readme-header.txt" 
copy /b "$(ProjectDir)\Readme\readme-header.txt" + "$(ProjectDir)\Readme\readme-body.txt" "$(TargetDir)\$(ProjectName).txt" 

我把所有的自述在我的項目的\自述\文件夾中生成相關的東西;包含上述代碼的應用程序以及包含實際自述文件的「readme-body.txt」。

  • 第一行:在我的項目的\ Readme \文件夾中創建「readme-header.txt」文件,並將其中的程序名稱。 (<nul set /p dummyset=是我在這裏找到的技巧:Windows batch: echo without new line)。您也可以將此字符串存儲在另一個文本文件中,然後將其複製到「readme-header.txt」中。
  • 第二行:使用新生成的exe文件作爲參數運行版本號檢索應用程序,並將其輸出添加到頭文件。
  • 第三行:在頭文件中添加任何其他的東西(在這種情況下,信用)。這也增加了一個換行符到最後。

這三者一起給你一個「readme-header.txt」文件,裏面有「My Application v1.2.3 by Nyerguds」,後面跟着一個換行符。然後添加生成日期和另一個打開的行,並將頭文件和自述文件正文文件一起復制到最終生成文件夾中的一個文件中。請注意,我特別使用二進制副本,否則會產生奇怪的結果。您必須確保主體文件在開始時不包含UTF-8字節順序標記,否則在最終文件中會出現奇怪的字節。

4

這個答案是布倫特阿里亞斯答案的一個小修改。他的PostBuildMacro爲我工作得非常好,直到Nuget.exe的版本更新。

在最近發佈的版本中,Nuget修剪軟件包版本號的非重要部分,以獲得像「1.2.3」這樣的語義版本。例如,程序集版本「1.2.3.0」由Nuget.exe「1.2.3」格式化。按照預期將「1.2.3.1」格式化爲「1.2.3.1」。

正如我需要推斷由Nuget.exe產生的確切包文件名,我現在用這個adaptated宏(在VS2015測試):

<Target Name="PostBuildMacros"> 
    <GetAssemblyIdentity AssemblyFiles="$(TargetPath)"> 
    <Output TaskParameter="Assemblies" ItemName="Targets" /> 
    </GetAssemblyIdentity> 
    <ItemGroup> 
    <VersionNumber Include="$([System.Text.RegularExpressions.Regex]::Replace(&quot;%(Targets.Version)&quot;, &quot;^(.+?)(\.0+)$&quot;, &quot;$1&quot;))" /> 
    </ItemGroup> 
</Target> 
<PropertyGroup> 
    <PostBuildEventDependsOn> 
    $(PostBuildEventDependsOn); 
    PostBuildMacros; 
    </PostBuildEventDependsOn>  
    <PostBuildEvent>echo HELLO, THE ASSEMBLY VERSION IS: @(VersionNumber)</PostBuildEvent> 
</PropertyGroup> 

UPDATE 2017年5月24日:我糾正了正則表達式:「1.2.0.0」將被翻譯爲「1.2.0」,而不是「1.2」,如前所述。


而要回答Ehryk Apr的評論,您可以修改正則表達式以僅保留版本號的某些部分。舉個例子,以保持「MAJOR.MINOR」,替換:

<VersionNumber Include="$([System.Text.RegularExpressions.Regex]::Replace(&quot;%(Targets.Version)&quot;, &quot;^(.+?)(\.0+)$&quot;, &quot;$1&quot;))" /> 

通過

<VersionNumber Include="$([System.Text.RegularExpressions.Regex]::Replace(&quot;%(Targets.Version)&quot;, &quot;^([^\.]+)\.([^\.]+)(.*)$&quot;, &quot;$1.$2&quot;))" />