成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

深究.NET中程序的編譯時間

開發 后端
今天我們將詳細研究編寫.NET程序時,經常會在該程序的“關于本軟件”對話框中給出這個程序的編譯時間。

我們在編寫.NET程序時,經常會在該程序的“關于本軟件”對話框中給出這個程序的編譯時間,如下圖所示:

上圖中的編譯時間是如果得到的呢?其實是在其 C# 源程序中有這么一句:

  1. [assembly: AssemblyVersion("1.3.*")] 

上述語句使用了 System.Reflection.AssemblyVersionAttribute 類,該類用于指定正在特性化的程序集的版本。在 MSDN 文檔中有以下描述:

  1. 程序集版本號是程序集標識的一部分,在綁定到程序集時以及在版本策略中扮演著關鍵的角色。  
  2. 版本號包含以下四部分:<主版本(Major)>.<次版本(Minor)>.<內部版本號(Build)>.<修訂號(Revision)> 
  3. 您可以指定所有這些值,也可使用星號 (*) 表示接受默認的內部版本號、修訂號,或者接受二者。 例如,  
  4. [assembly:AssemblyVersion("2.3.25.1")] 指示主版本為 2,次版本為 3,內部版本號為 25,修訂號為 1。 
  5. 版本號 [assembly:AssemblyVersion("1.2.*")] 指定主版本為 1,次版本為 2,并接受默認的內部版本號和修訂號。 
  6. 版本號 [assembly:AssemblyVersion("1.2.15.*")] 指定主版本為 1,次版本為 2,內部版本號為 15,并接受默認的修訂號。  
  7. 默認的內部版本號每日增加。 默認修訂號是隨機的。  

具體來說,默認的內部版本號表示自2000年1月1日以來的天數,而默認修訂號也不是隨機的,表示自該天午夜零時以來的秒數的一半。于是就可以使用下面的表達式獲得 .NET 程序的編譯時間:

  1. new DateTime(2000, 1, 1).AddDays(version.Build).AddSeconds(version.Revision * 2) 

但是,還有很多 .NET 程序的程序集版本號沒有使用星號來接受默認的內部版本號、修訂號,就不能使用這個方法了。我們知道,.NET 程序也是一個標準的32位或64位的 Microsoft Windows 可執行體(PE32,Portable Executable)文件。而PE文件頭中包含一個時間標記來指出文件的生成時間,請參見:“Microsoft可移植可執行文件和通用目標文件格式文件規范v8.1修訂版”和“Microsoft Portable Executable and Common Object File Format Specification”。具體來說就是:

PE文件頭由Microsoft MS-DOS®占位程序、PE文件簽名、COFF文件頭以及可選文件頭組成,COFF目標文件頭由COFF文件頭和可選文件頭組成。在這兩種情況下,文件頭后面緊跟著的都是節頭。
MS-DOS占位程序是一個運行于MS‑DOS下的合法應用程序,它被放在EXE映像的最前面。在位置0x3C處,這個占位程序包含PE文件簽名的偏移地址。
在MS-DOS占位程序后面、在偏移0x3C指定的文件偏移處,是一個4字節的簽名,它用來標識文件為一個PE格式的映像文件。這個簽名是“PE\0\0”(字母“P”和“E”后跟著兩個空字節)。
緊跟著映像文件簽名之后,是一個標準COFF文件頭。在這個COFF文件頭的偏移為4開始的4個字節就是從UTC時間1970年1月1日00:00起的總秒數(一個C運行時time_t類型的值)的低32位,它指出文件何時被創建。

一個PE文件的例子如下圖所示:

使用 DumpBin.exe 可得到如下信息:

  1. Microsoft (R) COFF/PE Dumper Version 10.00.30319.01  
  2. Copyright (C) Microsoft Corporation.  All rights reserved.  
  3.  
  4. Dump of file PowerWord2Snb.exe  
  5.  
  6. PE signature found  
  7.  
  8. File Type: EXECUTABLE IMAGE  
  9.  
  10. FILE HEADER VALUES  
  11.              14C machine (x86)  
  12.                3 number of sections  
  13.         4D0165D7 time date stamp Fri Dec 10 07:27:19 2010  
  14.                0 file pointer to symbol table  
  15.                0 number of symbols  
  16.               E0 size of optional header  
  17.              102 characteristics  
  18.                    Executable  
  19.                    32 bit word machine 

此外,在操作系統的文件系統中,也記錄了每個文件(不要求是PE文件)的創建和修改時間,如下圖所示:

我們寫一個 C# 程序來獲取這三個時間吧:

  1. using System;  
  2. using System.IO;  
  3.  using System.Reflection;  
  4. [assembly: AssemblyVersion("1.0.*")]  
  5. namespace Skyiv.BuildTime  
  6.  {  
  7.    sealed class Program  
  8.    {  
  9.      delegate DateTime GetTime(string fileName);  
  10.     TextWriter writer;  
  11.      Program(TextWriter writer)  
  12.     {  
  13.       this.writer = writer;  
  14.     }  
  15.     static void Main(string[] args)  
  16.   {  
  17.      Console.WriteLine("OS  Version: " + Environment.OSVersion);  
  18.       Console.WriteLine("CLR Version: " + Environment.Version);  
  19.       Console.WriteLine();  
  20. var fileName = (args.Length > 0) ? args[0] : Assembly.GetExecutingAssembly().Location;  
  21.      new Program(Console.Out).Write(fileName);  
  22.     }  
  23.     void Write(string fileName)  
  24.     {  
  25.       writer.WriteLine(fileName);  
  26.       Write("文件系統  ", GetFileCreationTime, fileName);  
  27.        Write("PE32      ", GetPe32Time, fileName);  
  28. rite("裝配件版本", GetAssemblyVersionTime, fileName);  
  29.     }  
  30.  void Write(string msg, GetTime getTime, string fileName)  
  31.     {  
  32.      string time;  
  33.       try 
  34.       {  
  35.          time = getTime(fileName).ToString("yyyy-MM-dd HH:mm:ss");  
  36.     }  
  37.       catch (Exception ex)  
  38.       {  
  39.        time = ex.Message;  
  40.      }  
  41.      writer.WriteLine("{0}: {1}", msg, time);  
  42.      }  
  43.   DateTime GetFileCreationTime(string fileName)  
  44.     {  
  45.       return new FileInfo(fileName).CreationTime;  
  46.   }  
  47.   DateTime GetAssemblyVersionTime(string fileName)  
  48.   {  
  49.      var version = Assembly.LoadFrom(fileName).GetName().Version;  
  50. return new DateTime(2000, 1, 1).AddDays(version.Build).AddSeconds(version.Revision * 2);  
  51.     }  
  52.    DateTime GetPe32Time(string fileName)  
  53.    {  
  54.        int seconds;  
  55. using (var br = new BinaryReader(new FileStream(fileName, FileMode.Open, FileAccess.Read)))  
  56.        {  
  57.          var bs = br.ReadBytes(2);  
  58.        var msg = "非法的PE32文件";  
  59.   if (bs.Length != 2) throw new Exception(msg);  
  60.   if (bs[0] != 'M' || bs[1] != 'Z'throw new Exception(msg);  
  61.        br.BaseStream.Seek(0x3c, SeekOrigin.Begin);  
  62.         var offset = br.ReadByte();  
  63.          br.BaseStream.Seek(offset, SeekOrigin.Begin);  
  64.          bs = br.ReadBytes(4);  
  65.    if (bs.Length != 4) throw new Exception(msg);  
  66.  if (bs[0] != 'P' || bs[1] != 'E' || bs[2] != 0 || bs[3] != 0) throw new Exception(msg);  
  67.         bs = br.ReadBytes(4);  
  68.         if (bs.Length != 4) throw new Exception(msg);  
  69.         seconds = br.ReadInt32();  
  70.      }  
  71.     return DateTime.SpecifyKind(new DateTime(1970, 1, 1), DateTimeKind.Utc).  
  72.         AddSeconds(seconds).ToLocalTime();  
  73.     }  
  74.   }  
  75.  } 

這個程序的運行結果如下所示:

  1. E:\work> BuildTime PowerWord2Snb.exe  
  2. OS  Version: Microsoft Windows NT 6.0.6002 Service Pack 2  
  3. CLR Version: 2.0.50727.4206  
  4.  
  5. PowerWord2Snb.exe  
  6. 文件系統  : 2010-12-10 07:32:14  
  7. PE32      : 2010-12-10 07:27:19  
  8. 裝配件版本: 2010-12-10 07:27:18  
  9.  
  10. E:\work> BuildTime  
  11. OS  Version: Microsoft Windows NT 6.0.6002 Service Pack 2  
  12. CLR Version: 2.0.50727.4206  
  13.  
  14. E:\work\BuildTime.exe  
  15. 文件系統  : 2010-12-18 20:26:24  
  16. PE32      : 2010-12-18 19:56:41  
  17. 裝配件版本: 2010-12-18 19:56:40 

我們來看看著名的 .NET Reflector 的信息吧:

  1. E:\work> BuildTime d:\bin\reflector\reflector.exe  
  2. OS  Version: Microsoft Windows NT 6.0.6002 Service Pack 2  
  3. CLR Version: 2.0.50727.4206  
  4.  
  5. d:\bin\reflector\reflector.exe  
  6. 文件系統  : 2008-07-10 19:36:45  
  7. PE32      : 2010-07-15 00:42:36  
  8. 裝配件版本: 2000-01-01 00:00:00  
  9.  
  10. E:\work> 

再來更多的例子:

  1. E:\work> BuildTime C:\windows\regedit.exe  
  2. OS  Version: Microsoft Windows NT 6.0.6002 Service Pack 2  
  3. CLR Version: 2.0.50727.4206  
  4.  
  5. C:\windows\regedit.exe  
  6. 文件系統  : 2008-04-23 19:35:29  
  7. PE32      : 2008-01-19 13:30:16  
  8. 裝配件版本: 未能加載文件或程序集“file:///C:\windows\regedit.exe”  
  9. 或它的某一個依賴項。該模塊應包含一個程序集清單。  
  10.  
  11. E:\work> BuildTime BuildTime.cs  
  12. OS  Version: Microsoft Windows NT 6.0.6002 Service Pack 2  
  13. CLR Version: 2.0.50727.4206  
  14.  
  15. BuildTime.cs  
  16. 文件系統  : 2010-12-18 20:50:03  
  17. PE32      : 非法的PE32文件  
  18. 裝配件版本: 未能加載文件或程序集“file:///E:\work\BuildTime.cs”  
  19. 或它的某一個依賴項。該模塊應包含一個程序集清單。  
  20.  
  21. E:\work> 

我們再看看在 Linux 操作系統中的情況(openSUSE 11.3, mono 2.8.1):

  1. ben@ben1520:~/work> dmcs BuildTime.cs  
  2. ben@ben1520:~/work> mono BuildTime.exe  
  3. OS  Version: Unix 2.6.34.7  
  4. CLR Version: 4.0.30319.1  
  5.  
  6. /home/ben/work/BuildTime.exe  
  7. 文件系統  : 2010-12-18 21:29:14  
  8. PE32      : 2010-12-18 21:29:14  
  9. 裝配件版本: 2000-01-01 00:00:00  
  10. ben@ben1520:~/work> mono BuildTime.exe /usr/lib/mono/4.0/dmcs.exe  
  11. OS  Version: Unix 2.6.34.7  
  12. CLR Version: 4.0.30319.1  
  13.  
  14. /usr/lib/mono/4.0/dmcs.exe  
  15. 文件系統  : 2010-11-12 22:52:48  
  16. PE32      : 2010-11-12 22:44:24  
  17. 裝配件版本: 2000-01-02 00:00:00  
  18. ben@ben1520:~/work> mono BuildTime.exe /usr/bin/gcc-4.5  
  19. OS  Version: Unix 2.6.34.7  
  20. CLR Version: 4.0.30319.1  
  21.  
  22. /usr/bin/gcc-4.5  
  23. 文件系統  : 2010-07-02 02:29:53  
  24. PE32      : 非法的PE32文件  
  25. 裝配件版本: Could not load file or assembly '/usr/bin/gcc-4.5' or one of its dependencies.  
  26.  An attempt was made to load a program with an incorrect format.  
  27. ben@ben1520:~/work>  

由上可見,在 Linux 操作系統中 mono 對 System.Reflection.AssemblyVersionAttribute 類的支持很成問題。在 Microsoft 的 MSDN 文檔中說可以用星號表示接受默認的內部版本號、修訂號,默認的內部版本號每日增加。 默認修訂號是隨機的。而 mono 的 C# 編譯器直接將默認的內部版本號和默認的修訂號都設置為零了。

綜上所述,要得到 .NET 程序的編譯時間,還是去讀該程序的PE文件頭中的文件創建時間最靠譜。

原文鏈接:http://www.cnblogs.com/skyivben/archive/2010/12/18/1910180.html

【編輯推薦】

  1. .NET Framework字符串相關操作細節介紹
  2. 詳解.NET字符串解析的具體過程
  3. 漫談.NET開發中的字符串編碼
  4. .NET Lambda表達式的語義:字符串列表范例
  5. 解釋.NET之匿名對象(AnonymousObject)

 

責任編輯:彭凡 來源: 博客園
相關推薦

2016-03-07 09:09:35

blockios開發實踐

2009-07-21 15:14:32

預編譯應用程序ASP.NET

2010-09-13 08:48:04

Visual Stud

2010-04-16 15:05:10

Oracle數據庫

2009-07-21 15:23:55

預編譯Web應用程序ASP.NET

2022-11-11 10:56:37

2013-04-08 10:08:22

開源虛擬化KVM

2013-05-29 15:33:01

開源虛擬化KVM

2011-07-27 09:52:38

軟件項目

2012-11-27 09:34:10

.NET版本

2013-04-07 09:33:31

開源虛擬化KVM

2009-08-04 18:05:37

動態編譯ASP.NET

2024-05-22 09:36:42

開源NET

2011-03-25 16:59:07

編譯Nagios

2012-09-06 16:17:09

Ubuntu 12.0Windows 7

2012-11-27 10:14:01

.net條件編譯

2019-06-11 14:52:46

2010-01-07 14:31:59

Ubuntu編譯

2011-04-20 10:32:44

java反編譯

2011-05-31 14:18:17

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 天天综合网天天综合色 | 日韩精品视频在线播放 | 国产99久久精品一区二区永久免费 | 亚洲成人毛片 | 国产精品久久久久久久久大全 | 男人天堂999| 欧美精品1区2区3区 精品国产欧美一区二区 | 亚洲精品免费观看 | 中文字幕一区二区三区不卡 | 国产中文字幕在线观看 | 亚洲精品久久久久久一区二区 | 一级a性色生活片久久毛片波多野 | 欧美日韩高清在线观看 | 国产一区三区在线 | 欧美日韩在线电影 | 91高清视频在线 | 伊人超碰在线 | 欧美亚洲视频 | 精品国产乱码久久久久久中文 | 欧美视频日韩 | 日韩精品在线一区 | 欧美成人高清 | 欧美性生活免费 | 极品粉嫩国产48尤物在线播放 | 超碰免费在线观看 | 日本福利在线观看 | 欧美日韩一区二区三区四区五区 | 天天曰天天干 | 日韩欧美久久精品 | 亚洲国产成人精品久久久国产成人一区 | 精品国产一区二区在线 | 日韩精品在线一区二区 | 久久精品一级 | 国产精品视频免费观看 | 国产精品久久国产精品 | 欧美三级电影在线播放 | 中国av在线免费观看 | 福利网址 | 亚洲国产aⅴ精品 | a级片在线观看 | 国产精品毛片久久久久久 |