之前有一个winfrom项目,想要通过获取SVN版本号作为程序的内部编译版本号。网上也有各种方法,但没有一篇行得通的方法。于是我经过一系列研究,得出了一些经验,特总结成一篇博客。

方法一:通过SVN命令获取版本号

类似地,我在项目中添加了一个名为"Version_inf.bat"的用于生成版本号的批处理文件,把他放在启动项目的目录中。批处理文件中写下如下脚本:

    svn info>bin\Debug\SVN_Version.dll
findstr “Revision” bin\Debug\SVN_Version.dll

这段脚本的意思是通过“svn info”命令获取“Revision”版本信息到Debug的输出目录的“SVN_Version.dll”文件中。(前提是电脑上必须安装了svn软件才能正常使用此命令。)

在程序的Program主入口中,写上类似的代码:

     string str_PathResult = null;
Microsoft.Win32.RegistryKey regKey = null;//表示 Windows 注册表中的项级节点(注册表对象?)
Microsoft.Win32.RegistryKey regSubKey = null;
try
{
regKey = Microsoft.Win32.Registry.LocalMachine;//读取HKEY_LOCAL_MACHINE项 if (regKey != null)
{
string keyPath = @"SOFTWARE\TortoiseSVN";
regSubKey = regKey.OpenSubKey(keyPath, false);
}
//得到SVN安装路径
if (regSubKey != null)
{
if (regSubKey.GetValue("Directory") != null)
{
str_PathResult = regSubKey.GetValue("Directory").ToString();
}
} //如果存在SVN安装信息,则通过调用批处理获取版本号
if (str_PathResult != null)
{
string path = System.Environment.CurrentDirectory;
////删除已经存在的版本信息,避免出现串号
//if (File.Exists(path + "\\SVN_Version.dll"))
//{
// File.Delete(path + "\\SVN_Version.dll");
//} int pathNum = path.LastIndexOf("\\") - ;
ProcessStartInfo psi = new ProcessStartInfo(); string pathStr = path.Substring(, pathNum) + "Version_inf.bat";
//string newPathStr = (pathStr.Substring(0, pathStr.LastIndexOf("."))) + ".bat"; psi.FileName = pathStr;
//psi.FileName = path.Substring(0, pathNum) + "Version_inf.bat";
psi.UseShellExecute = false;
psi.WorkingDirectory = path.Substring(, pathNum).Substring(, path.Substring(, pathNum).Length - );
psi.CreateNoWindow = true;
Process.Start(psi);
}
}
catch (Exception ex)
{
//MessageBox.Show("检测SVN信息出错," + ex.ToString(), "提示信息");
//LogUtil.WriteException(ex, "Program.Main()");
}
finally
{
if (regKey != null)
{
regKey.Close();
regKey = null;
} if (regSubKey != null)
{
regSubKey.Close();
regSubKey = null;
}
}

这样每次程序编译的时候就会生成一个新的“SVN_Version.dll”文件,里面记录了最后一次更新的记录版本号。

然后在主窗口读取“SVN_Version.dll”文件中的版本信息显示到程序的主界面上,代码如下:

     AssemblyName name = Assembly.GetExecutingAssembly().GetName();
String version = name.Version.ToString().Substring(, name.Version.ToString().LastIndexOf("."));
//SVN版本号文件保存路径
String svnVersionPath = System.AppDomain.CurrentDomain.BaseDirectory + "SVN_Version.dll";
if (File.Exists(svnVersionPath))
{
//StreamReader svnSteamReader = new StreamReader(svnVersionPath);
string[] lines = File.ReadAllLines(svnVersionPath);
if (lines.Length > )
{
for (int i = ; i < lines.Length; i++)
{
if (lines[i].Contains("Revision"))
{
String[] temps = lines[i].Split(':');
if (temps.Length > )
{
version += String.Format(".{0}", temps[].Trim());
break;
}
}
}
tssVersion.Text += version;
}
else
{
tssVersion.Text += "获取出错";
}
}
else
{
tssVersion.Text += "未知的版本";
}

这样就完成了SVN版本号的获取和内部编译号的显示了。如下图:

但是这种的方法的问题是:

1)svn命令在程序没有变化或者没有获取最新版本时会无法生成版本号;

2)只是在主界面显示了版本号,但是并没有真正改变项目生成文件的版本号;

3)如果电脑中没有安装svn程序,则极有可能会出现错误;

所以我又研究了方法二。

方法二:通过项目预处理事件获取SVN版本号

先在项目的Properties目录下新建一个“AssemblyInfo.template.cs”的模板类文件,并把“AssemblyInfo.cs”文件从SVN版本号中忽略。在模板文件中写下类似的代码:

 using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; // 有关程序集的常规信息通过以下
// 特性集控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("程序名")]
[assembly: AssemblyDescription("更新时间:$WCDATE$")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("程序名")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] // 将 ComVisible 设置为 false 使此程序集中的类型
// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
// 则将该类型上的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("18501865-f051-43be-ab03-59a2d9e76fcf")] // 程序集的版本信息由下面四个值组成:
//
// 主版本
// 次版本
// 内部版本号
// 修订号
//
// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值,
// 方法是按如下所示使用“*”:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.1.$WCREV$")]
[assembly: AssemblyFileVersion("1.1.1.$WCREV$")]

然后在项目属性的生成事件中编写如下预先生成事件执行的命令:

 $(SolutionDir)Lib\SubWCRev.exe $(SolutionDir) $(ProjectDir)Properties\AssemblyInfo.template.cs $(ProjectDir)Properties\AssemblyInfo.cs -f

这段话的意思就是找到SVN的SubWCRev.exe文件,获取到版本信息后通过模板将数据写入到“AssemblyInfo.cs”文件中。

这样每次生成之后版本号就写入到了项目输出的文件中。将每个项目都按照如上方法添加模板和预生成事件,那么程序文件就会都带有版本信息。

实际效果如下图所示:

程序在显示的时候,可以通过封装一个公共属性让其他人可以调用到版本号信息:

   /// <summary>
/// 版本号
/// </summary>
public static string AppVersion
{
set { AppDomain.CurrentDomain.SetData("AppVersion", value); }
get { return AppDomain.CurrentDomain.GetData("AppVersion") == null ? "" : AppDomain.CurrentDomain.GetData("AppVersion").ToString(); }
}

这样就大功告成啦!!!

当然如果想获取项目生成的文件或者想获取某个指定文件的版本号属性,可以使用如下方法:

 /// <summary>
/// 获取文件的版本号
/// </summary>
/// <param name="filePath">文件的完整路径</param>
/// <returns>文件的版本号</returns>
public static string GetFileVersion(string filePath)
{
string FileVersions = ""; try
{
System.Diagnostics.FileVersionInfo file1 = System.Diagnostics.FileVersionInfo.GetVersionInfo(filePath);
FileVersions = file1.FileVersion;
if (FileVersions != "")
{
string[] strVer = FileVersions.Split('.');
if (strVer.Length == )
{
FileVersions = strVer[] + ".00.0000";
} }
}
catch (Exception ex)
{
FileVersions = "";
}
return FileVersions;
}

特别说明:本文章为本人Healer007 原创! 署名:小萝卜  转载请注明出处,谢谢!

C#:通过Visual Studio项目预生成命令获取SVN版本号的更多相关文章

  1. Visual Studio项目的生成事件代码

    我们打开vs的项目属性可以看到有生成事件,如下图: 可以看到有两块空白区域,这个空白区域可以让我们写代码或脚本来处理编译生成前后的时候,处理一些事情,今天就简单的来说说这两块. 生成前事件命令行 我想 ...

  2. 怎么将visual studio项目打包生成dll文件

    1.打开电脑再打开visual studio软件,在软件里面新建一个项目,文件---->新建---->项目,打开新建项目窗口. 2.选择C#类工程,并为项目命名. 3.将类库文件class ...

  3. 因GIT默认忽略.dll文件导致的Visual Studio项目通过Bamboo编译失败

    背景 由GIT管理的Visual Studio项目,使用Stash管理远端代码库,通过与Stash集成的Bamboo生成项目并发布 现象 Visual Studio项目本地生成成功,用SourceTr ...

  4. 在Visual Studio中新增生成项目

    在Visual Studio中新增生成项目 选择适配器类型 选择WCF-SQL适配器 创建连接选项 选择相应的存储过程 生成相应的消息架构

  5. 【译】Visual Studio 15 预览版更新说明

    序:恰逢Build2016大会召开,微软发布了VS2015的update2更新包和VS2016预览版.本人正在提升英文水平中,于是在这里对VS2016预览版的官方文档进行了部分翻译.因为VS有些功能使 ...

  6. Visual Studio 2019预览,净生产力

    本文章为机器翻译. https://blogs.msdn.microsoft.com/dotnet/2018/12/13/visual-studio-2019-net-productivity/ 该文 ...

  7. 关于在Visual Studio 2019预览版中的用户体验和界面的变化

    原文地址:https://blogs.msdn.microsoft.com/visualstudio/2018/11/12/a-preview-of-ux-and-ui-changes-in-visu ...

  8. Visual Studio 2022 预览版3 最新功能解说

    我们很高兴地宣布Visual Studio 2022 的第三个预览版问世啦!预览版3 提供了更多关于个人和团队生产力.现代开发和持续创新等主题的新功能.在本文中,我们将重点介绍Visual Studi ...

  9. 创建用于自定义SharePoint解决方案部署的Visual Studio项目

    转:http://soft.zdnet.com.cn/software_zone/2007/0903/488083.shtml 在基于SharePoint的开发中,我们通常会在WSS的TEMPLATE ...

随机推荐

  1. java.lang.ClassCastException: android.widget.RelativeLayout cannot be cast to android.widget.TextView

    最近在学习drawerLayout时,遇到这个bug.如下示: java.lang.ClassCastException: android.widget.RelativeLayout cannot b ...

  2. search--搜索引擎的使用笔记

    重度使用 完全匹配搜索 “”把搜索词放在双引号中 搜索不包含该词 减号- 常用的通配符 星号* 站内搜索site docker site:http://blog.daocloud.io/ 扩大范围搜索 ...

  3. js判断用户是否禁用了cookie

    function CookieEnable() { var result = false; if (navigator.cookiesEnabled) return true; document.co ...

  4. zlib快速编译脚本

    zlib允许使用IDE编译生成dll以及静态库,高版本写一个脚本就能轻松的一键编译生成静态/动态lib以及dll文件 以下是一句话编译批处理脚本 nmake -f win32\Makefile.msc ...

  5. 第九章 springboot + mybatis + 多数据源 (AOP实现)

    在第八章 springboot + mybatis + 多数据源代码的基础上,做两点修改 1.ShopDao package com.xxx.firstboot.dao; import org.spr ...

  6. Hadoop中HDFS的管理

    本文讲述怎么在Linux Shell中对HDFS进行操作. 三种命令格式: hadoop fs适用于任何不同的文件系统,比如本地文件系统和HDFS文件系统 hadoop dfs只能适用于HDFS文件系 ...

  7. 基本套接字编程(3) -- select篇

    1. I/O复用 我们学习了I/o复用的基本知识,了解到目前支持I/O复用的系统调用有select.pselect.poll.epoll.而epoll技术以其独特的优势被越来越多的应用到各大企业服务器 ...

  8. EditText的hint不显示

    EditText的hint不显示可能的原因: 1.字体颜色与EditText的背景色一样; 2.使用了android:inputType = phone; 3.如果加上android:ellipsiz ...

  9. Mysql --分区表(2)

    分区类型 RANGE分区 range分区的表是利用取值范围将数据分成分区,区间要连续并且不能互相重叠,使用values less than操作符进行分区定义 LIST分区 LIST分区是建立离散的值列 ...

  10. linux环境变量查看及修改

    例如用命令 echo $PATH 则可以查看该环境变量为/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 添加环境定义一个变量 ...