上一篇博客写了如何在 .Net 项目使用 SVN 作为版本控制工具时生成与代码对应的组件版本号。虽然在公司一直使用 SVN ,但我却对 GIT 情有独钟(可能要归功于那段捣鼓 ROM 的时光),但少有文章提及如何具体在 Windows 平台来获得版本号。这让我有了迫切得到方法的希望。

上篇博客《在VS项目中使用SVN版本号作为编译版本号

经过测试,该方法是可行的,以前验证失败的原因主要是打开了 AssemblyInfo.cs  文件,造成占用不可替换!

本文提供的方法还不完善,写出来的目的是为了得到更多人的关注,也希望有大牛能指点一二。

将 GIT 的 commit 作为 . Net 项目编译后生成dll的文件版本号主要有以下几个困难。

1,GIT 没有一个数字的序号,而是一个SHA散列码;

2,GIT 提供的命令在 linux 十分方便,在 Windows 下需要额外的工具。

第一个问题好解决,我们取当前文件夹 commit 的次数加上截取一段 SHA 码就可以作为文件版本号的最后一位。第二个问题目前想到的方法是调用 msysgit 提供的 Git Bash 来执行命令。

好了,首先我们依旧得找到 msysgit 的安装目录,一查之下头就大了,各个地方的路径都感觉不靠谱,最后还是选用了

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Git_is1的InstallLocation

(本来是想通过 temp 环境变量来取值的,查看 GIT 源代码好像也有写入,后来在自己电脑里却找不到)

注:经验证,与安装选项有关,如果希望简单的话在安装时选择一下可以省很多事情!

然后参照 Git Bash 的快捷方式拼接了下 call 的语句。

然后写了一个 sh 文件来获得版本号,并保存到文件:

 # file name: git_ver.sh
#!/bin/bash
VER_FILE=git_version.tmp
LOCALVER=`git rev-list HEAD | wc -l | awk '{print $1}'`
VER=r$LOCALVER
VER="$VER $(git rev-list HEAD -n 1 | cut -c 1-7)"
GIT_VERSION=$VER
echo $GIT_VERSION>$VER_FILE

在批处理里取出刚保存文件的值,接下来的工作就和使用 SVN 里的差不多了,唯一的区别是我们要自己实现关键字的替换。

上篇博客《在VS项目中使用SVN版本号作为编译版本号

我们建立以一个 AssemblyInfo.tpl 作为替换使用的模板,由于 AssemblyInfo.cs 中除了固定的值外还有类似 GUID 变化的值,所以我们不能全部替换,因此仅将需要修改的部分放在 tpl 中,内容如下:

[assembly: AssemblyVersion("1.0.0.0")]

[assembly: AssemblyFileVersion("1.0.0.GITVERSION")]

自己替换 GITVERSION 字段为前面取到的版本号。

接下来使用批处理替换原来的 AssemblyInfo.cs 文件,为了在每次编译时都自动替换,我们把调用批处理的命令卸载项目生成事件的生成前事件中:

"$(TargetDir)BeforeBuildProject.bat" $(ProjectDir) $(TargetDir)

批处理代码:

 ::-------------------------------------------------
:: <sunmary>
:: 根据指定工作目录信息和模板生成目标文件
:: </sunmary>
:: <param name="WorkDir">工作目录路径</param>
:: <param name="Template">模板文件路径</param>
:: <param name="target">生成目标文件的路径</param>
:: <returns>执行结果</returns>
::================================================= ::-------------------------------------------------
:: * Initialize *
@ECHO OFF
::SetLocal EnableExtensions
setlocal enabledelayedexpansion Rem Initialize Script arguments
SET WorkDir=%
SET target=% Rem Initialize Constants
SET AssemblyInfo=ASSEMBLY_INFO.tmp Rem GoTo Main Entry
GOTO Main
::================================================= ::-------------------------------------------------
:: * Main Entry *
:Main
Rem Check arguments
IF %WorkDir%=="" GOTO ARGUNENT_ERROR
IF %target%=="" GOTO ARGUNENT_ERROR
PushD %WorkDir% Rem Search TSVN Path For /f "tokens=1* delims=_" %% in ('reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Git_is1" /v "InstallLocation"^| findstr /i "InstallLocation"') Do (
For /f "tokens=1*" %% in ("%%~2") Do (
SET GIT_PATH=%%
)
) COPY /y "%target%git_ver" "%WorkDir%git_ver" SET GIT_PATH="%GIT_PATH%bin\sh.exe" --login -i
call %GIT_PATH% %WorkDir%git_ver for /f "delims=" %%i in (%WorkDir%\git_version.tmp) do (set VERSION=%%i)&(goto :next)
:next
DEL /Q "%WorkDir%\git_ver">NUL
DEL /Q "%WorkDir%\git_version.tmp">NUL Rem Generate a template file COPY /y "%WorkDir%\Properties\AssemblyInfo.cs" "%WorkDir%\Properties\AssemblyInfo.cs.bak">NUL
SET FILESTR="%WorkDir%\Properties\AssemblyInfo.cs"
FindStr /v "AssemblyVersion AssemblyFileVersion" %FILESTR%>%AssemblyInfo% For /f "delims=" %%k In (%target%\AssemblyInfo.tpl) do (
set str=%%k
set str=!str:GITVERSION=%VERSION%!
echo !str! >> "%AssemblyInfo%"
) COPY /y "%AssemblyInfo%" "%WorkDir%\Properties\AssemblyInfo.cs"
GOTO SUCCESS
::================================================= ::-------------------------------------------------
:: * Error Handlers *
:ARGUNENT_ERROR
ECHO 传入的参数无效。
GOTO FAIL :UNKNOE_ERROR
ECHO 未知错误。
GOTO FAIL
::================================================= ::-------------------------------------------------
:: * Program Exit *
:FAIL
DEL /Q "%AssemblyInfo%">NUL
::IF EXIST "%WorkDir%Properties\AssemblyInfo.cs.bak" (COPY /y "%WorkDir%Properties\AssemblyInfo.cs.bak" "%WorkDir%Properties\AssemblyInfo.cs"&DEL /q "%WorkDir%Properties\AssemblyInfo.cs.bak")>NUL
ECHO "error"
popd
EXIT :SUCCESS
DEL /Q "%AssemblyInfo%">NUL
ECHO "success"
popd
EXIT
::=================================================

如果一切顺利的话,应该就可以得到想要的结果了,可是……

替换文件竟然发生在生成后,也就是说 VS 在批处理执行结束前就已经编译生成了,这样文件版本号就只能在下次生成才会生效。上篇文章说的每次版本号都会增加的缺陷就无法那样解决了。

当然你也可以为每个 AssemblyInfo.cs 文件生成备份,批处理通过备份文件产生 AssemblyInfo.cs ,这样可以把 AssemblyInfo.cs 排除到项目外。版本号也就不会因此迭代增加了。

对于疑问的一个猜想是:因为我在批处理中调用了 Git Bash ,导致 VS 以为批处理执行结束而继续了生成。

希望大家能提出其它想法或者验证我的猜想,有解决方案那就再好不过了。

惯例附上所有代码:点击下载

本文来自 NewIdea 的博客,作者 Carey Tzou 。

原文地址:http://www.cnblogs.com/NewIdea/p/GITVersion.html

转载请注明出处,否则拒绝转载!

在VS项目中通过GIT生成版本号作为编译版本号的更多相关文章

  1. Android项目中JNI技术生成并调用.so动态库实现详解

    生成 jni方式有两种:一种是通过SWIG从C++代码生成过度的java代码:另一种是通过javah的方式从java代码自动生成过度的C++代码.两种方式下的步骤流程正好相反. 第一种方式:由于需要配 ...

  2. 在VS项目中使用SVN版本号作为编译版本号

    在实际项目中(特别是作为产品的项目),版本号是必不可少的一部分.版本号的规则也有许多种,在此不讨论具体的编码规范.对于迭代的产品,版本繁多,特别是有多个实施项目所使用产品的版本不同(基于定制需求)时, ...

  3. [Android][Android Studio] Gradle项目中加入JNI生成文件(.so文件)

    版权声明:本文作者:Qiujuer https://github.com/qiujuer; 转载请注明出处,盗版必究! ! ! https://blog.csdn.net/qiujuer/articl ...

  4. Java Web项目中使用Freemarker生成Word文档

    Web项目中生成Word文档的操作屡见不鲜.基于Java的解决方式也是非常多的,包含使用Jacob.Apache POI.Java2Word.iText等各种方式,事实上在从Office 2003開始 ...

  5. 开发日记:在VS项目中使用SVN版本号作为编译版本号

    在实际项目中(特别是作为产品的项目),版本号是必不可少的一部分.版本号的规则也有许多种,在此不讨论具体的编码规范.对于迭代的产品,版本繁多,特别是有多个实施项目所使用产品的版本不同(基于定制需求)时, ...

  6. ABP项目中使用Swagger生成动态WebAPI

    本文是根据角落的白板报的<使用ABP实现SwaggerUI,生成动态webapi>一文的学习总结,感谢原文作者角落的白板报. 1 安装Swashbuckle.core 1.1 选择WebA ...

  7. 在Unity项目中使用Git

    (搬运自我在SegmentFault的博客) 本文参考了Unity官网的Mastering Unity Project Folder Structure - Version Control Syste ...

  8. Android项目中独立Git项目分库后的编译调试时Gradle的配置

    基于AS开发项目,对于特定的功能模块,往往抽取成独立的库进行管理,然后上传到Marven库中,通过Gradle依赖的方式进行引用. 其优势体现在: 1,独立的Git项目库,模块功能,及职责界定清晰: ...

  9. 项目中的Git七步精髓

    项目中Git常用的七步操作: 1.git branch -a  查看所有分支 2.git checkout dev_yxq 如果冲突了,操作回退上一个版本, git status git checko ...

随机推荐

  1. css居中学习笔记

    css居中学习笔记 一.水平居中 以下面的代码为例: <body> <div class="parent"> <div class="chi ...

  2. IOS开发UI基础UILabel属性

    UILabel属性 1.text:设置标签显示的文本. 2.attributedText:设置标签属性文本. Ios代码 NSString *text = @"first";  N ...

  3. WinForm公共控件

    公共控件:1.Button:按钮 用户点击时触发事件 行为属性 Enabled -是否启用 Visible -是否隐藏2.CheckBox .CheckListBox - 复选框 复选框组 3.Com ...

  4. sql server索引功能资料

    无论何时对基础数据执行插入.更新或删除操作,SQL Server 数据库引擎都会自动维护索引.随着时间的推移,这些修改可能会导致索引中的信息分散在数据库中(含有碎片).当索引包含的页中的逻辑排序(基于 ...

  5. 【循序渐进学Python】1. Python基础知识

    1. Python安装和配置 首先需要到Python的官方网站(http://www.python.org/getit/) 下载安装包,现在Python的发行版分为兼容之前Python程序的Pytho ...

  6. c#使用aspose.cells 从datatable导出数据到excel

    string json=value.Value; DataTable dt=Utils.JsonDataTableConvert.ToDataTable(json); string fileName ...

  7. 1 初识Orchard

    网上关于Orchard的介绍已经很多了,具体Orchard是干啥的我就不再啰嗦,这个系列的主要目的就是介绍学习和使用orchard的过程,和在此过程中碰到问题的解决方案.下面直接进入正题. 获取orc ...

  8. 【GOF23设计模式】组合模式

    来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_组合模式.树状结构.杀毒软件架构.JUnite底层架构.常见开发场景 package com.test.composite ...

  9. iphone 使用 soap 服务 介绍

    iphone 使用 soap 服务 介绍 目前比较常用的有几个办法: 1. WSDL to Objective C自动根据wsdl文件生成ios可以直接调用的Objective-C (Cocoa) 代 ...

  10. 可怜的js居然没有块级作用域

    js中在一个函数中定义一个for循环:for(var i=0;i<5;i++) 其中的i并不会随着for循环的结束就销毁,i会一直存在该函数中,这就是js和其他语言的区别,也就是js没有块级作用 ...