Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get the current DateTime from the Precompiler in C#?

In C# 3.0, I have a property which is suppose to contain the version of the class. The version number is simply the date and time of compilation. Right now, I have the following code:

public DateTime Version
{
    get { return DateTime.UtcNow; }
}

Obviously, this is wrong since this property returns me the current date and time. So, is the precompiler can print the DateTime at compile time? In this case, I could do something similar to below.

public DateTime Version
{
    get { return new DateTime("PRECOMPILER DATE"); }
}
like image 440
Martin Avatar asked Jan 07 '09 07:01

Martin


2 Answers

You can retreive it from the dll itself (Source: codinghorror)

   private DateTime RetrieveLinkerTimestamp() {
        string filePath = System.Reflection.Assembly.GetCallingAssembly().Location;
        const int c_PeHeaderOffset = 60;
        const int c_LinkerTimestampOffset = 8;
        byte[] b = new byte[2048];
        System.IO.Stream s = null;

        try {
            s = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);
            s.Read(b, 0, 2048);
        } finally {
            if (s != null) {
                s.Close();
            }
        }

        int i = System.BitConverter.ToInt32(b, c_PeHeaderOffset);
        int secondsSince1970 = System.BitConverter.ToInt32(b, i + c_LinkerTimestampOffset);
        DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0);
        dt = dt.AddSeconds(secondsSince1970);
        dt = dt.AddHours(TimeZone.CurrentTimeZone.GetUtcOffset(dt).Hours);
        return dt;
    }
like image 85
Stormenet Avatar answered Oct 22 '22 21:10

Stormenet


C# doesn't have the concept of macros; however, you can use other tools in your build script (csproj / NANT / etc) to manipulate the source before it compiles. I use this, for example, to set the revision number to the current SVN revision.

A cheap option is a pre-build event (you can do this via the project properties dialog in VS): essentially a bat file that runs before build; you can then script whatever changes you need. A more sophisticated option is build tasks.

For example, the utility library here includes a Time task and a FileUpdate task; it should (in theory) be possible to chain the two together to emulate what you need.

Personally, I'd use the [AssemblyVersion] details rather than the time - if you link this to your source-control system, this makes it very easy to find the offending version; so for my SVN version, I then use (in my build proj):

<!-- See http://msbuildtasks.tigris.org -->
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
...
<SvnInfo LocalPath=".">
  <Output TaskParameter="Revision" PropertyName="BuildRev" />
</SvnInfo>
...
<FileUpdate Files="Path\To\My\AssemblyInfo.cs"
    Regex='(\[\s*assembly:\s*AssemblyVersion\(\s*"[^\.]+\.[^\.]+)\.([^\.]+)(\.)([^\.]+)("\)\s*\])'
    ReplacementText='$1.$2.$(BuildRev)$5' />
<FileUpdate Files="Path\To\My\AssemblyInfo.cs"
    Regex='(\[\s*assembly:\s*AssemblyFileVersion\(\s*"[^\.]+\.[^\.]+)\.([^\.]+)(\.)([^\.]+)("\)\s*\])'
    ReplacementText='$1.$2.$(BuildRev)$5' />

And now my assembly-version is correct, including the file-version that gets reported by the OS.

like image 34
Marc Gravell Avatar answered Oct 22 '22 21:10

Marc Gravell