I have a .net 2.0 C# application in Visual Studio 2005 for which I'd like to automatically generate the correct version build number which should contain a number that allows me to guess the build date of the application.
I tried to use the 'AssemblyInfo Task' tool from Microsoft but by default this tool doesn't work. For today it would generate a build number '090227' which exceeds the maximum of 65535 and thus geneartes an error.
I could also live with a build number which contains the year and the day in the year, like 09001 for January 1 2009...
Do you know any solution for this problem?
Do I have to update the source code for this 'AssemblyInfo Task' or would this be possible to achieve in VS2008 or so?
Thanks for your help.
You'll want to look at msbuildtasks. It is an open source set of msbuild tasks. The module has a task to increment/modify/etc a build number. It's also super easy to use and super easy to extend.
The default automatic build number generated by VS/C#/msbuild is the number of days since 1.1.2000 and the release number is the number of two second increments since midnight, so that you can compute the date and time of the build backwards like this:
new DateTime(2000, 1, 1).AddDays(assemblyName.Version.Build).AddSeconds(assemblyName.Version.Revision*2)
msbuildtasks didn't solve my problem. As explained in the description I need a special format. Also the documentation for msbuildtasks is well... go find it.
I've modified the source code for AssemblyInfo Task by adding a new increment type 'YearAndDay' with my needs:
case IncrementMethod.YearAndDay:
{
DateTime dDate = DateTime.Now;
long buildNumber = dDate.Year % 2000 * 1000;
buildNumber += dDate.DayOfYear;
string newVersionNumber = buildNumber.ToString();
Log.LogMessage(MessageImportance.Low, logMessage, newVersionNumber);
return newVersionNumber;
}
Seemed to be the simplest solution.
Related
In C# on Windows Vista - 7 with dot net 4.0 or less
I am trying to compare the values of login time, current time, and the modified time of a file to see which is the greater and which is least. I have found ways to declare and cast these three values but not as the same type. I figured unix epoch made the most since and I seem to be stuck with converting the long format of
File.GetLastWriteTime("time.cs" )
Apparently overflows are a problem, who would have guessed, not my esp. Such a superior os & language. Anyway. Can someone please give me a full example of how to cast return and output the modified time of a file to int32 unix epoch. Or, can some one show me, in full example how to compare the above three values without trolling a log file or the use of jQuery or defining functions or languages beyond the scope of what I have requested. Speed is key and the parameters are required not optional.
The csharp crowd doesn't have the answer? there is a surprise. Well this is about as exact as there being 365 days in a year but for my purpose it will work. Because two forms of builtin not traversal date time isn't enough. For the pleasure of all that is prime and dec ten. A solution:
DateTime dt = File.GetLastWriteTime("time.cs");
var sec = ( ( dt.Year - 1970 )*31536000) + (dt.Month*2592000) + (dt.Day*86400) + (dt.Hour*3600) + (dt.Minute*60) + (dt.Second * 1) - 2592000 - 86400;
I guess for windows this is actually considered efficient. Can anyone tell my why DateTime isn't just considered a string? is base24 replacing base 16 or some thing? Did we add a register to our processor just for msns inefficiencies. Im going with the ladder. Front end convenience is no excuse for back end ugliness. Ill be posting a pure assembly answer next on how to convert gregorian to epoch via means of base 2 and 127 bit addressing... crazy.
The actual version number of my solution is placed in Properties/AssemblyInfo.cs:
[assembly: AssemblyVersion("1.0.0.*")]
The last part of that number is an askerisk. It will be replaced by an revision number. By the following code in my controller, I am able to get that full version number, including the revision number:
ViewBag.VersionNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
Where does MVC3 save the revision number?
When using the * in the revision number, then the 3rd digit will increment each day, and the 4th will be generated based on time-of-day.
What you're seeing is the 4th digit generated based on time-of-day. You'll notice that after midnight it will reset close to 0.
If you use a version such as "1.0.*", then the 3rd and 4th digits will generate automatically.
The Revision number isn't "Saved" anywhere instead it is just generated each time you build your project (it is written into the assembly as part of the version number but not saved for future builds).
As an aside I noted a behaviour that doesn't seem to be documented anywhere (and caught me out). The Revision number seems to be generated based on the time (and not always date)!
I.e. you have v1.0.0.1234 on Day 1 at 11:00
This changes to v1.0.0.1257 on Day 1 at 11:30
But, on Day 2 at 10:00 you re-build thinking it will change to v1.0.0.1279 or similar but it actually changes to v1.0.0.0950 so producing a "lower" version number that the last build (on Day 1)?!
This doesn't always seem to happen but I would warn against using Revision as a guaranteed value to increment.
I have been trying to use TimeZoneInfo.GetSystemTimeZones in .net4 to replace our old method which uses COM to call into some MFC code. However, I've had to revert to the COM method because GetSystemTimeZones doesn't return all time zones. Being based in the UK and not including GMT Standard Time in our list of options is a problem.
When I look in the registry, I find that GMT Standard Time has a Dynamic DST subkey with no rules defined. I downloaded the .net4 source code and, in TimeZoneInfo.cs, GetSystemTimeZones eventually calls TryCreateAdjustmentRules which appears to return false if the Dynamic DST key has no FirstEntry or LastEntry defined.
//
// loop over all of the "<time_zone_name>\Dynamic DST" hive entries
//
// read FirstEntry {MinValue - (year1, 12, 31)}
// read MiddleEntry {(yearN, 1, 1) - (yearN, 12, 31)}
// read LastEntry {(yearN, 1, 1) - MaxValue }
// read the FirstEntry and LastEntry key values (ex: "1980", "2038")
Int32 first = (Int32)dynamicKey.GetValue(c_firstEntryValue, -1, RegistryValueOptions.None);
Int32 last = (Int32)dynamicKey.GetValue(c_lastEntryValue, -1, RegistryValueOptions.None);
if (first == -1 || last == -1 || first > last) {
rules = null;
return false;
}
As TryCreateAdjustmentRules returns false, TryGetTimeZoneByRegistryKey throws an InvalidTimeZoneException which means GMT Standard Time doesn't get added into the time zone collection. I've tried deleting the empty Dynamic DST subkeys but something adds them back in again (probably Windows Update).
I've done alot of searching but haven't seen anyone else report this problem. I'm not sure whether there is a GetSystemTimeZones fix or whether I can stop the empty Dynamic DST subkey appearing in the first place. Any ideas?
I'm guessing this is just a registry issue.
Something similar is outlined here for WinXP / Server 2003 SP1.
Please see if the following helps:
http://blogs.technet.com/b/dst2007/archive/2007/03/06/missing-time-zones-in-registry.aspx
My guess is you could export the entire registry Key from another machine, and apply it to your problematic box(es).
It turns out that the problem is with our COM object and not with the .NET code. The code to read the registry should only be reading but it mistakenly calls RegCreateKey to optimise multiple calls to the same registry branch.
When the COM object is registered (with admin rights) because of a new version, it loads the time zones and creates Dynamic DST for the local time zone which in my case is GMT/UTC.
Administrators, I guess this question should be marked for deletion.
After looking it over your problem and even running the code you provided in the comments to print out a list of Time Zones I am not able to get GMT to show up on my system. I am running Windows 7 Professional and selecting GMT is just not an option. I know that doesn't solve your problem and you - like a lot of other people - sound like you really need to get this to work with GMT.
However if at all possible, if you see a way to use UTC then I would check out these links:
Windows 7 Lack of Support for GMT
Converting UTC to GMT
Just another possible answer to your problem, is there anyway you can create a wrapper around the UTC values to display GMT? I ask because this problem doesn't seem like it is going to go away anytime soon. Even if you get it to work now - in the future it might break again. If I come up with a method for this I will update my answer.
Is there an alternative to a revision number (incremented int)? I'd like to create a revision tag (or identifier if you like) from date+time (and later convert the tag back to a date time object).
Preferably the revision is as small as possible. CouchDB uses a format like this for revision: 765B7D1C - but I'm uncertain how they made this and if it's even a time stamp.
Any suggestions?
You could use something like this:
DateTime.Now.Subtract(new DateTime(2000, 1, 1)).Days
This returns the number of days since 2000-01-01 (as of today, this would be 3566).
This is similar to what is used in .NET if you specify the assembly version (in AssemblyInfo.cs) as "1.0.*". Of course you could also use another start date, such as the start of your project.
I recently went through the same thought process. I couldn't find a good way to fit it into the signed int that your allowed. Instead I went with Maj.{Year-2000}.{MMdd}.{svn revision}. You could still try and cram the date... here is the issue:
1 year = 365 days = 8760 hours = 525600 minutes. As you can see given a max of 32k the best you can do for the current year is hours. That can record the next 3.5 years worth, so you could do:
int revision = (int) (DateTime.Now - new DateTime(2009, 1, 1)).TotalHours;
... and this will then blow up around Aug, 2012. Or if you use days you be able to store apx 88 years, so you could go with Martin's suggestion safely.
Take a look at VSVersion Manager which is a set of macros for setting version numbers in AssemblyInfo based on date.
The macro is fired on each build.
You can set up a rules for setting revision fields to any of the date elements (month, day, year in different formats), have them increment by one or leave them untouched.
The site includes detailed instructions for installing the macros.
The challenge is: Can you get the date+time of compilation compiled into your program? Preferably in the format you choose, but any format is sufficient, because you can re-format into a "tag" any way you like. (If you cannot re-format it at compile time, you can re-format it beyond recognition at run-time.)
The answer is: There is no direct way. C# has nothing like __DATE__ or __TIME__. The date+time of compilation are completely unavailable at compile-time. If a program wants to know the date+time of its compilation, it can only try to pick them up at run-time, by examining itself. C# creates data structure(s) in and around the compiled program, but none of the fields is available at compile-time, and none is guaranteed to have the date+time of compilation.
Solution 1 (my favorite so far): VS doesn't unconditionally write the compilation date+time into suitably named fields, for the purpose of giving you that information. But it does conditionally write a derivative of the compilation date+time into 2 of the 4 version fields, as a klugey way of putting an automatic incrementing version number on the executable file, if you tell it to. "AssemblyVersion" is a structure of 4 fields ("Major Version", "Minor Version", "Build Number", and "Revision"), which are normally just 4 UInt16 numbers typed in by the programmer (or version control software). But, If you set the fields of AssemblyVersion to a, b, *, and [empty string], and no one changes the last 2, then the compiler overrides the last two to c and d, where c == days and d*2 == seconds since Jan. 1, 2000 at 00:00 (local time, but disregarding daylight saving time) (making a non-human-decodable timestamp, which is visible under File Properties of the file), at the moment it parses AssemblyInfo.cs. These are easily accessed via:
private string DateCompiled()
{
System.Version v = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
// v.Build == days and v.Revision*2 == seconds since Jan. 1, 2000 at 00:00 (midnight, 12:00am). (Local time, but disregards daylight saving time.)
return new DateTime(2000, 1, 1).AddDays(v.Build).AddSeconds(v.Revision * 2).ToString("yyyyMMdd-HHmm (local no DST)");
// "Assembly version" has four UInt16 fields: "Major Version", "Minor Version", "Build Number", and "Revision".
// When Build is "*" and Revision is empty, the compiler overrides them with the encoded date and time.
// AssemblyVersion can be specified in the solution Properties window, Application tab, "Assembly Information..." button and dialog box: Assembly version.
// AssemblyVersion can also be specified in "AssemblyInfo.cs". Example:
// [assembly: AssemblyVersion("2016.11.*")]
// AssemblyFileVersion is optional, defaulting to AssemblyVersion if not specified. (Build is NOT allowed to be "*".)
// Properties of the file (in Windows Explorer) displays AssemblyFileVersion.
// AssemblyVersion can be specified in the solution Properties window, Application tab, "Assembly Information..." button and dialog box: File version.
// AssemblyVersion can also be specified in "AssemblyInfo.cs". Example:
// [assembly: AssemblyFileVersion("1.2.3.4")]
}
If you want File:Properties (in Internet Explorer) to show an arbitrary a.b.c.d version of your choice, you can do that too. File:Properties shows AssemblyFileVersion, which defaults to AssemblyVersion if not specified. You can only specify AssemblyFileVersion in "AssemblyInfo.cs" (just add a new line for it, using the same syntax as AssemblyVersion, except "*" is not allowed). The use of [half of] AssemblyVersion for the encoded date+time of compilation is hidden from that view.
Solution 2: (I don't like it because metadata changes easily and access could be blocked.) The running program finds itself (the .exe file) through the file system and reads its own last-modified date. But the last-modified date is metadata stored in the file system, not the program file. The last-modified date can easily be changed or lost by transfer across time-zones or DST changes via FAT, CDFS, or FTP; lazy FTP servers that do not accept incoming date+time metadata; insane FTP servers that round older timestamps; and file utilities that change metadata on request. And sometimes file permissions get in the way. And the needed procedure varies by operating system. (Even if I had tried this approach, I wouldn't paste code)
Solution 3: (I find it better than Solution 2 because the data cannot change, but worse than Solution 2 because the executable file opens and reads itself as binary data.) "Dustin Aleksiuk recently posted a clever blog entry describing how to retrieve the embedded linker timestamp from the IMAGE_FILE_HEADER section of the Portable Executable header" --https://blog.codinghorror.com/determining-build-date-the-hard-way/ (with code). The blog entry (from March 3, 2005) that it cites is gone (along with the entire blog), but it is archived at http://web.archive.org/web/20060615040705/http://blog.signaleleven.com/index.php?itemid=10
If you are asking about formatting a date, the answers vary according to the data type, the precision (resolution) that you want, the time span that you want to cover, how human-readable or machine-readable it should be and how to address time zone.
Imagine the date and time are 2016-11-08 14:08:12. That is already a string encoding of 19 characters (19 bytes if string, not wstring).
String: I like yyyyMMdd-HHmmss: 20161108-140812. 15 characters. I think it is more human readable without the dashes and colons.
BCD: Int64 stores 16 decimal digits in only 8 bytes, preserving human readability (if viewed as hexadecimal). Choices:
0x0020161108140812 (years 0-799,999; resolution 1s)
0x0201611081408120 (years 0-79,999; resolution 0.1s)
0x2016110814081200 (years 0-7999; resolution 0.01s)
(First digit is limited to 0..7 because Int64 is signed; its maximum value is 0x7fffffffffffffff.)
Decimal: Int64 stores 18.96 decimal digits in only 8 bytes.
0000020161108140812 (years 0-922,337,203; resolution 1s)
0020161108140812000 (years 0-922,337; resolution 0.001s)
(maximum value is 9,223,372,036,854,775,807.)
UInt32 can store the date (8 digits) as BCD or decimal.
0x20161108 (years 0-9999 or 15,999)
0020161108 (years 0-429,496)
Int32 can store the date as BCD or decimal.
0x20161108 (years 0-7999)
0020161108 (years 0-214,748)
There are nearly endless possibilities (if you don't look to a standard).
These are just some of the more human-readable variations.
Can anyone find a constant in the .NET framework that defines the number of days in a week (7)?
DateTime.DaysInAWeek // Something like this???
Of course I can define my own, but I'd rather not if it's somewhere in there already.
Update:
I am looking for this because I need to allow the user to select a week (by date, rather than week number) from a list in a DropDownList.
You could probably use System.Globalization.DateTimeFormatInfo.CurrentInfo.DayNames.Length.
I think it's ok to harcode this one. I don't think it will change any soon.
Edit: I depends where you want to use this constant. Inside the some calendar related algorithm it is obvious what 7 means. On the other hand sometimes named constant make code much more readable.
Try this:
Enum.GetNames(System.DayOfWeek).Length
If you look at the IL code for Calendar.AddWeeks you will see that Microsoft itself uses a hardcoded 7 in the code.
Also the rotor source uses a hardcoded 7.
Still, I would suggest to use a const.
I used this:
public static readonly int WeekNumberOfDays = Enum.GetNames(typeof(DayOfWeek)).Length;
I don't believe there is one. TimeSpan defines constants for the number of ticks per milli/second/minute/hour/day, but nothing at the level of a week.
I ran a query across the standard libraries for symbols (methods/constants/fields/etc) containing the word 'Week'. Nothing came back. FYI, I ran this query using ReSharper.
I'm not sure what exactly you're looking for, but you can try DateHelper (CODE.MSDN). It's a library I put together for typical date needs. You might be able to use the week methods or the List methods. method list
Edit - no more MSDN code, not on GitHub as part of lib: https://github.com/tbasallo/toolshed
Do you mean calendar weeks or just common weeks?
Obviously, there are calendar weeks that might be shortrer than seven days. The last calendar week of the year is usually shorter, and depending on your definition of calendar week, the first week might be shorter as well.
In that case, I'm afraid you will have to roll out your own week length function. It's not really hard to do with the DateTime class, I did it before, if you need more help let me know.
GregorianCalendar has AddWeeks(1) which will add 7 days to a date.