tags:

views:

498

answers:

7

I want to include the current time and date in a .net application so I can include it in the start up log to show the user what version they have. Is it possible to retrieve the current time during compilation, or would I have to get the creation/modification time of the executable?

E.g.

Welcome to ApplicationX. This was built day-month-year at time.

+2  A: 

There's nothing built into the language to do this.

You could write a pre-build step to write out the current date and time to a source file though (in a string literal, for example, or as source code to generate a DateTime), and then compile that as part of your build.

I would suggest you make this source file as simple as possible, containing nothing but this information. Alternatively it could edit an existing file.

For an example of this, see the build file for MiscUtil which embeds the current SVN revision into the AssemblyFileVersion attribute. Some assorted bits of the build file:

<!-- See http://msbuildtasks.tigris.org -->
<Import 
 Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>

<!-- Find out what the latest version is -->
<SvnInfo RepositoryPath="$(SvnUrl)">
  <Output TaskParameter="LastChangedRevision" PropertyName="Revision" />
</SvnInfo>

<!-- Update the AssemblyInfo with the revision number -->
<FileUpdate Files="$(OutputDirectory)\MiscUtil\MiscUtil\Properties\AssemblyInfo.cs"
            Regex='(\[\s*assembly:\s*AssemblyFileVersion\(\s*"[^\.]+\.[^\.]+)\.([^\.]+)(\.)([^\.]+)("\)\s*\])'
            ReplacementText='$1.$2.$(Revision)$5' />
Jon Skeet
Thanks for the suggestion about the assemblies but that was just a little more complex than I needed. Dumping info into a source file is just fine.
Nick
+3  A: 

The only way I know of doing this is somewhat convoluted -

You can have a pre-build event that runs a small application which generates the source code on the fly. An easy way to do this is to just overwrite a very small file that includes a class (or partial class) with the day/month/year hardcoded as a string constant.

If you set this to run as a pre-build event, it will rewrite that file before every build.

Reed Copsey
Thanks, this is what I ended up doing. I wrote a little C# app that can be run as a pre-build step.
Nick
+2  A: 

You could use PostSharp to weave in the date immediately post-build. PostSharp comes with a lightweight aspect-oriented programming library, but it can be extended to weave in anything you need in a wide variety of ways. It works at the IL level, but the API abstracts you a bit from that.

http://www.postsharp.org/

jrista
A: 

You could update the Assembly version in AssemblyInfo.cs as part of your build. Then you could do something like this

FileVersionInfo lvar = FileVersionInfo.GetVersionInfo(FileName);

FileVersionInfo has the information (build/version,etc) that you looking for. See if this works out for you.

Vasu Balakrishnan
JeffH
+4  A: 

If you're using reflection for your build number you can use that to figure out when a build was compiled.

Version information for an assembly consists of the following four values:

  1. Major Version
  2. Minor Version
  3. Build Number
  4. Revision

You can specify all the values or you can accept the default build number, revision number, or both by using an asterisk (*). Build number and revision are based off Jan 1, 2000 by default.

The following attribute will set Major and minor, but then increment build number and revision.

[assembly: AssemblyVersion("5.129.*")]

Then you can use something like this:

public static DateTime CompileTime
{
   get
   {
      System.Version MyVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
      // MyVersion.Build = days after 2000-01-01
      // MyVersion.Revision*2 = seconds after 0-hour  (NEVER daylight saving time)
      DateTime compileTime = new DateTime(2000, 1, 1).AddDays(MyVersion.Build).AddSeconds(MyVersion.Revision * 2);                
      return compileTime;
   }
}
Sam T.
I think the date returned is UTC.
Nick
+1  A: 

In makefiles for C programs, it is common to see something like this:

echo char * gBuildSig ="%DATE% %TIME%"; > BuildTimestamp.c

And then the resulting C source file is compiled into the image. The above works on Windows because the %date% and %time% variables are known in cmd.exe, but a similar thing would work on Unix using cat.

You can do the same thing using C#. Once again, this is how it would look if you are using a makefile. You need a class, and a public static property.

BuildTimestamp.cs: 
    echo public static class Build { public static string Timestamp = "%DATE% %TIME%";} > BuildTimestamp.cs

And then for the thing you are building, a dependency and a delete:

MyApp.exe: BuildTimestamp.cs MyApp.cs
    $(_CSC)  /target:exe /debug+ /optimize- /r:System.dll /out:MyApp.exe MyApp.cs BuildTimestamp.cs
    -del  BuildTimestamp.cs

Be sure to delete the BuildTimestamp.cs file after you compile it; you don't want to re-use it. Then, in your app, just reference Build.Timestamp.

Using MSBuild or Visual Studio, it is more complicated. I couldn't get %date% or %time% to resolve. Those things are pseudo environment variables, I guess that is why. So I resorted to an indirect way to get a timestamp, using the Touch task with AlwaysCreate = true. That creates an empty file. The next step writes source code into the same file, referencing the timestamp of the file. One twist - I had to escape the semicolon.

Your pre-build step should build the target "BuildTimestamp". And be sure to include that file into the compile. And delete it afterwards, in the post-build step.

<ItemGroup>
  <StampFile   Include="BuildTimestamp.cs"/>
</ItemGroup>

<Target Name="BuildTimestamp" 
        Outputs="@(StampFile)">
  <Message Text="Building timestamp..." />

  <Touch
        AlwaysCreate="true"
        Files="@(StampFile)" />

  <WriteLinesToFile
        File="@(StampFile)"
        Lines='public static class Build { public static string Timestamp = "%(StampFile.CreatedTime)" %3B }'
        Overwrite="true" />

</Target>
Cheeso
A: 

Hi I used following method for the same...

private DateTime ExecutableInfo()
{
  System.IO.FileInfo fi = new System.IO.FileInfo(Application.ExecutablePath.Trim());
  try
  {
    return fi.CreationTime;
  }
  catch (Exception ex)
  {
    throw ex;
  }
  finally
  {
    fi = null;
  }
}
Still Learning