16

Is there an equivalent of __DATE__ and __TIME__ in C#?

Basically what I'm trying to do is place some build timestamping in a C# application.

One possibility I saw on Microsoft's website was to do the following:

Assembly assem = Assembly.GetExecutingAssembly();
Version vers = assem.GetName().Version;
DateTime buildDate = new DateTime(2000, 1, 1).AddDays(vers.Build).AddSeconds(vers.Revision * 2);
Console.WriteLine(vers.ToString());
Console.WriteLine(buildDate.ToString());

However, this only works if your version in AssemblyInfo.cs is "1.0..", which ours won't be.

Soo Wei Tan
  • 3,262
  • 2
  • 34
  • 36

6 Answers6

4

I recommend customising your build script to write the date time into the file. The MSBuild Community Tasks project has a Time task that can be used for exactly this.

Tim Booker
  • 2,801
  • 1
  • 25
  • 36
  • Thanks, this looks like the most straightforward way to insert the timestamp somewhere. – Soo Wei Tan Aug 21 '09 at 17:17
  • Other than `inserting the timestamp` there is the possibility of extracting an already inserted timestamp. See http://stackoverflow.com/questions/1600962/displaying-the-build-date for code to get what the linker put in. Probably good until the PE and COFF files headers get changed. – Jesse Chisholm Nov 10 '15 at 17:49
  • How does this even work? The documentation shows how to install it, but not how actually run a task in Visual Studio. I did some digging, is this the correct documentation? https://learn.microsoft.com/en-us/visualstudio/msbuild/walkthrough-using-msbuild?view=vs-2019 – user3147973 Nov 07 '19 at 02:33
3

Short answer: NO. There is no equivalent. They left it out. Too bad. Joke's on you.

There are some near-equivalent work-arounds, all based on the program examining itself. None is rational, elegant, or sturdy.

Some solutions pick up the compile date+time from "AssemblyVersion", a structure of four UInt16 fields ("Major Version", "Minor Version", "Build Number", and "Revision") that are not guaranteed to contain the date and time at all, much less in a specific format. If you set AssemblyVersion to "a.b.*" (and no one changes it), then the compiler overrides it to a.b.c.d, where c == days and d*2 == seconds since Jan. 1, 2000 at 00:00 (local time, but disregards daylight saving time), at the moment it parses AssemblyInfo.cs. These get compiled into the program, where they can be accessed via System.Reflection.Assembly.GetExecutingAssembly().GetName().Version .

Other solutions have the executable file reach into the file system to pick up its "last-modified" date+time from its own metadata, which is easily changed or damaged by transfer via FAT, CDFS, or FTP with DST or time-zone changes, lazy FTP servers that discard metadata outright, or file utilities that change metadata on request. Pathetic.

Where is the compile-time constant (or constants), maybe called #NOW (or #YEAR, #MONTH, #DAY, etc.), that can be used in expressions or assigned to a const or a readonly? CodeWarrior C, GCC, MS C, and MS C++ give the standard predefined macros __DATE__ and __TIME__ , which can be used like compile-time string constants. It seems like a glaring omission from C#, driving everyone to waste person-years asking about and setting up work-arounds. New language, new code, pathetic rickety design. C# doesn't have macros. C#'s #define only has "defined" or "undefined". SO WHAT? I see no excuse for deleting significant compile-time constants. How about putting it into C#'s fake pro-processor?

17 years into "Simple Managed C" / "C-like Object Oriented Language", CIL, and CLR, and this is what it is? A million ways to write code that doesn't do what it says (implementation of threading)? Libraries that expose every flaw of "the underlying method"? You have to target one (or both) of two separate virtual machines: a 32-bit VM for 32-bit hardware (or emulator) and a 64-bit VM for 64-bit hardware (only) - what's virtual about that? Java compiles once, for only one virtual machine, which of course has separate implementations for each platform (32 or 64).

A876
  • 471
  • 5
  • 8
2

If you are trying to autogenerate your build and revision numbers, I would look into the following project on CodePlex:

http://autobuildversion.codeplex.com/

jrista
  • 32,447
  • 15
  • 90
  • 130
  • I'm not looking to generate version numbers as we already have a pre-existing convention to stick to. Just would like to embed the compile time somewhere in the app. – Soo Wei Tan Aug 20 '09 at 22:48
  • Out of curiosity, why do you need the build time embedded? – jrista Aug 20 '09 at 23:46
  • No real reason, I've often found it handy to have some kind of build time printed out as our version numbers don't bump with every build we make. – Soo Wei Tan Aug 21 '09 at 17:14
  • 1
    @jrista - re: `why?` In the field, when tracking down an issue, I'd like to know exactly which version of each .exe and .dll is actually being used. There is the compiled in `AssemblyVersion` and related which may or may not change from compile to compile. There is the File System's Creation and Modification date and time, which may or may not be related to when it was actually **compiled**. This _feature_ was trivial back in the C/C++ days, and seems painful, if not impossible, in C#. :-( – Jesse Chisholm Aug 28 '15 at 19:11
  • Yeah, there are indeed issues with moderns enterprise class development systems. Including C/C++. These days, I've moved on from C# development...most of what I do is javascript stack now. Things are pretty flexible in that world...if you want a timestamp in a package.json that's deployed with a project or component, it's easy to do. Just like pretty much everything else. ;) – jrista Sep 02 '15 at 19:21
1

You could look at customizing the projects .csproj file. This is just an ordinary msbuild file and you can hook into the BeforeBuild target to generate or update a file, perhaps storing this value in a custom assembly level attribute.

I'd imagine the msbuild community tasks would be useful here as they have several helpful tasks for things like token replacement within a file.

Chris Chilvers
  • 6,429
  • 3
  • 32
  • 53
1

Ugly, and requires certain permissions, but if this is for internal use:

            // assume the relevant using statements above...
            FileVersionInfo vi = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
            FileInfo fileInfo = new System.IO.FileInfo(vi.FileName);
            DateTime createTime = fileInfo.CreationTime;
Charlie Skilbeck
  • 1,081
  • 2
  • 15
  • 38
-1

DateTime DATE = File.GetLastWriteTime( Application.ExecutablePath );

OneGuyInDc
  • 1,557
  • 2
  • 19
  • 50