Задача такова: можете ли вы дата + время компиляции скомпилировать в вашу программу? Предпочтительно в выбранном вами формате, но достаточно любого формата, потому что вы можете переформатировать в «тег» любым удобным вам способом. (Если вы не можете переформатировать его во время компиляции, вы можете переформатировать его до неузнаваемости во время выполнения.)
Ответ таков: прямого пути нет. C # не имеет ничего общего с __DATE__
или __TIME__
. Дата + время компиляции полностью недоступно во время компиляции. Если программа хочет знать дату + время ее компиляции, она может только попытаться подобрать их во время выполнения, , изучив себя . C # создает структуры данных внутри и вокруг скомпилированной программы, но ни одно из полей не доступно во время компиляции, и ни одно из них не гарантирует дату + время компиляции.
Решение 1 (мое любимое на данный момент): VS не безоговорочно записывает дату + время компиляции в поля с соответствующим названием, чтобы предоставить вам эту информацию. Но он условно записывает производную даты + времени компиляции в 2 из 4 полей версии, в качестве хитрого способа поставить автоматически увеличивающийся номер версии в исполняемый файл, если вы скажете это. AssemblyVersion - это структура из 4 полей («Major Version», «Minor Version», «Build Number» и «Revision»), которые обычно представляют собой всего лишь 4 номера UInt16, введенные программистом (или программой контроля версий). Но, Если установить поля AssemblyVersion равными a
, b
, *
и [пустая строка], , и никто не изменит последние 2 , тогда компилятор заменяет последние два на c
и d
, где c == дни и d * 2 == секунды с 1 января 2000 года в 00:00 (по местному времени, но без учета перехода на летнее время) (без -human-decodable timestamp (отображается в разделе «Свойства файла» файла), в данный момент она анализирует AssemblyInfo.cs. К ним легко получить доступ через:
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")]
}
Если вы хотите, чтобы File: Properties (в Internet Explorer) отображала произвольную версию a.b.c.d по вашему выбору, вы можете сделать это тоже. Файл: Свойства показывает AssemblyFileVersion, который по умолчанию равен AssemblyVersion, если не указан. Вы можете указать только AssemblyFileVersion в "AssemblyInfo.cs" (просто добавьте для него новую строку, используя тот же синтаксис, что и AssemblyVersion, за исключением того, что "*" не допускается). Использование [половины] AssemblyVersion для закодированной даты + времени компиляции скрыто от этого представления.
Решение 2: (Мне это не нравится, потому что метаданные легко изменяются, и доступ может быть заблокирован.) Работающая программа находит себя (файл .exe) через файловую систему и считывает свою собственную дату последнего изменения. Но последняя измененная дата - это метаданные, хранящиеся в файловой системе, а не файл программы. Дата последнего изменения может быть легко изменена или утеряна путем переноса между часовыми поясами или изменениями летнего времени через FAT, CDFS или FTP; ленивые FTP-серверы, которые не принимают входящие метаданные дата + время; безумные FTP-серверы, которые округляют старые отметки времени; и файловые утилиты, которые изменяют метаданные по запросу. И иногда права доступа к файлам мешают. И необходимая процедура зависит от операционной системы. (Даже если бы я попробовал этот подход, я бы не вставлял код)
Решение 3: (Я считаю, что это лучше, чем Решение 2, потому что данные не могут измениться, но хуже, чем Решение 2, потому что исполняемый файл открывается и считывает себя как двоичные данные.) "Дастин Алексюк недавно опубликовал умная запись в блоге, описывающая, как извлечь временную метку встроенного компоновщика из раздела IMAGE_FILE_HEADER заголовка Portable Executable "- https://blog.codinghorror.com/determining-build-date-the-hard-way/ (с кодом). Запись в блоге (с 3 марта 2005 г.), на которую он ссылается, исчезла (вместе со всем блогом), но она заархивирована в http://web.archive.org/web/20060615040705/http://blog.signaleleven.com/index.php?itemid=10