Files
Common-VS2019/SacsStandardBase/Base/Utils/AssemblyUtil.cs
T

85 lines
2.4 KiB
C#

using System;
using System.IO;
using System.Reflection;
namespace Sarand.Net.Standard.Base.Utils
{
public static class AssemblyUtil
{
// --- Definitions ---
private const Int32 DosHeaderPeOffsetPosition = 0x3c;
private const UInt32 PeSignature = 0x00004550;
private const Int32 CoffTimeDateStampPosition = 8;
// --- Build Information ---
/// <summary>
/// Gets the UTC date and time represented by the assembly's PE/COFF timestamp.
/// </summary>
/// <remarks>
/// Deterministic builds may not store the physical build time in this field.
/// Use <see cref="TryGetBuildDateTime(Assembly, out DateTime)"/> when the caller
/// needs to distinguish an unavailable timestamp from <see cref="DateTime.MinValue"/>.
/// </remarks>
public static DateTime GetBuildDateTime(this Assembly assembly)
{
return TryGetBuildDateTime(assembly, out DateTime buildDateTime)
? buildDateTime
: DateTime.MinValue;
}
/// <summary>
/// Tries to get the UTC date and time represented by the assembly's PE/COFF timestamp.
/// </summary>
public static Boolean TryGetBuildDateTime(this Assembly assembly, out DateTime buildDateTime)
{
ArgumentNullException.ThrowIfNull(assembly);
if (String.IsNullOrEmpty(assembly.Location))
{
buildDateTime = DateTime.MinValue;
return false;
}
return TryGetBuildDateTime(assembly.Location, out buildDateTime);
}
// --- PE Header Parsing ---
internal static Boolean TryGetBuildDateTime(String assemblyPath, out DateTime buildDateTime)
{
buildDateTime = DateTime.MinValue;
try
{
using FileStream fileStream = new FileStream(assemblyPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using BinaryReader reader = new BinaryReader(fileStream);
fileStream.Position = DosHeaderPeOffsetPosition;
UInt32 coffHeaderOffset = reader.ReadUInt32();
fileStream.Position = coffHeaderOffset;
if (reader.ReadUInt32() != PeSignature)
{
return false;
}
fileStream.Position = coffHeaderOffset + CoffTimeDateStampPosition;
UInt32 timeDateStamp = reader.ReadUInt32();
buildDateTime = DateTime.UnixEpoch.AddSeconds(timeDateStamp);
return true;
}
catch (Exception exception) when (exception is IOException
or UnauthorizedAccessException
or ArgumentException
or NotSupportedException)
{
return false;
}
}
// --- The End ---
}
}