Now it's time to pick it back up. What you will see in here isn't all that new, but it is however very useful. Also, at the bottom I have listed a few blogs I know of that cover the same topic. Two of which are far more interesting than mine so be sure to have a look.
Recently at work an issue came up where the QA team did not know if the test environment had the correct build applied (TDS package). I decided to use some old code from a version page I created for the same issue with an Asp.net applications.
The following is a list of files that we will create to make the magic happen.
- ReflectionUtil.cs : Generic reflection code to extract version details from the loaded assembly.
- ApplicationDetails.cs : Pipeline to extract version information.
- Sitecore.SharedSource.Version.config : Pipeline configuration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, | |
// INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. | |
using System.Text; | |
using Sitecore.SharedSource.Reflection; | |
using Sitecore.Pipelines.GetAboutInformation; | |
namespace Sitecore.SharedSource.Pipelines | |
{ | |
public class ApplicationDetails | |
{ | |
public void Process(GetAboutInformationArgs args) | |
{ | |
var text = new StringBuilder(); | |
text.Append("<span>Build</span></br><span>"); | |
text.Append(ReflectionUtil.GetExecutingAssemblyDetail(ReflectionUtil.AssemblyDetailType.Date)); | |
text.Append("</span></br><span>"); | |
text.Append(ReflectionUtil.GetExecutingAssemblyDetail(ReflectionUtil.AssemblyDetailType.Version)); | |
text.Append("</span>"); | |
args.LoginPageText = text.ToString(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, | |
// INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. | |
using System; | |
using System.IO; | |
using System.Reflection; | |
namespace Sitecore.SharedSource.Reflection | |
{ | |
public sealed class ReflectionUtil | |
{ | |
/// <summary> | |
/// Represents the type of detail to retrive from the assembly. The data is formatted and therefore will | |
/// not appear exactly is seen through Microsoft Windows Explorer. | |
/// </summary> | |
public enum AssemblyDetailType | |
{ | |
/// <summary> | |
/// Indicates that no detail type is indicated. | |
/// </summary> | |
NotSpecified = 0, | |
/// <summary> | |
/// Indicates that the detail type is the name of the assembly. | |
/// </summary> | |
Name = 1, | |
/// <summary> | |
/// Indicates that the detail type is the version of the assembly. | |
/// </summary> | |
Version = 2, | |
/// <summary> | |
/// Indicates that the detail type is the date the assembly was compiled. | |
/// </summary> | |
Date = 3 | |
} | |
#region Assembly | |
/// <summary> | |
/// Returns the details of the executing assembly specified by the <see cref="AssemblyDetailType"/>. | |
/// </summary> | |
public static string GetExecutingAssemblyDetail(AssemblyDetailType detail) | |
{ | |
return AssemblyDetailHelper(detail, Assembly.GetExecutingAssembly()); | |
} | |
/// <summary> | |
/// Returns the details of the calling assembly specified by the <see cref="AssemblyDetailType"/>. | |
/// </summary> | |
/// <param name="detail">The type of information to extract from the assembly.</param> | |
/// <returns></returns> | |
public static string GetAssemblyDetail(AssemblyDetailType detail) | |
{ | |
return AssemblyDetailHelper(detail, Assembly.GetCallingAssembly()); | |
} | |
#region Helper | |
private static string AssemblyDetailHelper(AssemblyDetailType detail, Assembly assembly) | |
{ | |
switch (detail) | |
{ | |
case AssemblyDetailType.Date: | |
return GetAssemblyDate(assembly); | |
case AssemblyDetailType.Name: | |
return GetAssemblyName(assembly); | |
case AssemblyDetailType.Version: | |
return GetAssemblyVersion(assembly); | |
case AssemblyDetailType.NotSpecified: | |
default: | |
return "No method implemented to return the requested details."; | |
} | |
} | |
private static string GetAssemblyName(Assembly assembly) | |
{ | |
var filepath = assembly.Location; | |
var info = new FileInfo(filepath); | |
var name = String.Format("Assembly: {0}", info.Name); | |
return name; | |
} | |
private static string GetAssemblyVersion(Assembly assembly) | |
{ | |
var version = assembly.GetName().Version; | |
var versionMessage = String.Format("Version: {0}.{1}.{2}.{3}", | |
version.Major, version.Minor, version.Build, version.MinorRevision); | |
return versionMessage; | |
} | |
private static string GetAssemblyDate(Assembly assembly) | |
{ | |
var date = RetrieveLinkerTimestamp(assembly); | |
var dateMessage = String.Format("Date: {0}", date.ToString()); | |
return dateMessage; | |
} | |
private static DateTime RetrieveLinkerTimestamp(Assembly assembly) | |
{ | |
var filePath = assembly.Location; | |
const int cPeHeaderOffset = 60; | |
const int cLinkerTimestampOffset = 8; | |
var b = new byte[2048]; | |
Stream s = null; | |
try | |
{ | |
s = new FileStream(filePath, FileMode.Open, FileAccess.Read); | |
s.Read(b, 0, 2048); | |
} | |
finally | |
{ | |
if (s != null) | |
{ | |
s.Close(); | |
} | |
} | |
var i = BitConverter.ToInt32(b, cPeHeaderOffset); | |
var secondsSince1970 = BitConverter.ToInt32(b, i + cLinkerTimestampOffset); | |
var dt = new DateTime(1970, 1, 1, 0, 0, 0).AddSeconds(secondsSince1970); | |
dt = dt.AddHours(TimeZone.CurrentTimeZone.GetUtcOffset(dt).Hours); | |
return dt; | |
} | |
#endregion Helper | |
#endregion Assembly | |
} | |
} |
The final results are clean and simple.