Frage

Im Moment habe ich eine App die Build-Nummer in seinem Titelfenster angezeigt wird. Das ist schön und gut, außer es nichts meisten Nutzer bedeutet, die wollen wissen, ob sie die neueste Version haben -. Sie neigen dazu, es als „letzten Donnerstag“ zu beziehen, anstatt 1.0.8.4321 zu bauen

Der Plan ist, das Erstellungsdatum setzen dort statt -. So zum Beispiel „App am 21.10.2009 gebaut“

Ich kämpfe einen programmatischen Weg zu finden, das Erstellungsdatum als Textzeichenfolge für die Verwendung so ziehen.

Für die Build-Nummer, habe ich:

Assembly.GetExecutingAssembly().GetName().Version.ToString()

nach der Definition, wie diejenigen aufkommen.

ich so etwas für die Kompilierung Datum möchte (und Zeit für Bonuspunkte).

Pointers hier sehr geschätzt (Entschuldigung pun wenn zutreffend) oder sauberere Lösungen ...

War es hilfreich?

Lösung

Jeff Atwood hatte ein paar Dinge über dieses Thema in Bestimmung Herstellungsdatum auf die harte Weise .

Die zuverlässigste Methode stellt sich heraus, den Linker-Zeitstempel aus der PE-Header in der ausführbaren Datei eingebettet - einig C # -Code (von Joe Spivey) für den aus den Kommentaren zu Jeffs Artikeln:

public static DateTime GetLinkerTime(this Assembly assembly, TimeZoneInfo target = null)
{
    var filePath = assembly.Location;
    const int c_PeHeaderOffset = 60;
    const int c_LinkerTimestampOffset = 8;

    var buffer = new byte[2048];

    using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        stream.Read(buffer, 0, 2048);

    var offset = BitConverter.ToInt32(buffer, c_PeHeaderOffset);
    var secondsSince1970 = BitConverter.ToInt32(buffer, offset + c_LinkerTimestampOffset);
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    var linkTimeUtc = epoch.AddSeconds(secondsSince1970);

    var tz = target ?? TimeZoneInfo.Local;
    var localTime = TimeZoneInfo.ConvertTimeFromUtc(linkTimeUtc, tz);

    return localTime;
}

Anwendungsbeispiel:

var linkTimeLocal = Assembly.GetExecutingAssembly().GetLinkerTime();

UPDATE: Die Methode funktioniert für .Net-Core 1.0, aber funktioniert nicht nach dem .Net-Core 1.1 Release (random Jahren 1900-2020 Bereich gibt)

Andere Tipps

unten In der Pre-Build-Ereignisse Befehlszeile:

echo %date% %time% > "$(ProjectDir)\Resources\BuildDate.txt"

Fügen Sie diese Datei als Ressource, Jetzt Sie 'Builddate' string in Ihren Ressourcen haben.

Ressourcen zu erstellen, finden Sie unter Wie erstellen und verwenden, um Ressourcen in. NET .

Die Art und Weise

Wie @ C00000FD in der Kommentare . Microsoft ändert sich dies. Und während viele Menschen nutzen nicht die neueste Version ihres Compiler vermute ich diese Änderung dieser Ansatz zweifellos schlecht macht. Und während es eine Spaß Übung ist würde ich die Leute empfehlen, einfach ein Build-Datum in ihre binären einbetten durch andere Mittel notwendig, wenn es wichtig ist das Erstellungsdatum der binären selbst zu verfolgen.

Dies kann mit trivialer Codegenerierung durchgeführt werden, die wahrscheinlich den ersten Schritt in Ihrem Build-Skript ohnehin schon ist. Das, und die Tatsache, dass ALM / Bauen / DevOps Tools viel dabei helfen und sollten etwas anderes bevorzugt werden.

Ich lasse den Rest dieser Antwort hier aus historischen Gründen nur.

Die neue Art und Weise

Ich änderte meine Meinung über das, und zur Zeit diesen Trick verwenden, um das richtige Build-Datum zu erhalten.

#region Gets the build date and time (by reading the COFF header)

// http://msdn.microsoft.com/en-us/library/ms680313

struct _IMAGE_FILE_HEADER
{
    public ushort Machine;
    public ushort NumberOfSections;
    public uint TimeDateStamp;
    public uint PointerToSymbolTable;
    public uint NumberOfSymbols;
    public ushort SizeOfOptionalHeader;
    public ushort Characteristics;
};

static DateTime GetBuildDateTime(Assembly assembly)
{
    var path = assembly.GetName().CodeBase;
    if (File.Exists(path))
    {
        var buffer = new byte[Math.Max(Marshal.SizeOf(typeof(_IMAGE_FILE_HEADER)), 4)];
        using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
        {
            fileStream.Position = 0x3C;
            fileStream.Read(buffer, 0, 4);
            fileStream.Position = BitConverter.ToUInt32(buffer, 0); // COFF header offset
            fileStream.Read(buffer, 0, 4); // "PE\0\0"
            fileStream.Read(buffer, 0, buffer.Length);
        }
        var pinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        try
        {
            var coffHeader = (_IMAGE_FILE_HEADER)Marshal.PtrToStructure(pinnedBuffer.AddrOfPinnedObject(), typeof(_IMAGE_FILE_HEADER));

            return TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1) + new TimeSpan(coffHeader.TimeDateStamp * TimeSpan.TicksPerSecond));
        }
        finally
        {
            pinnedBuffer.Free();
        }
    }
    return new DateTime();
}

#endregion

Der alte Weg

Nun, wie Sie generieren Zahlen bauen? Visual Studio (oder der C # -Compiler) bietet tatsächlich automatische Build und Versionsnummern, wenn Sie das Attribut Assemblyversion ändern, um z 1.0.*

Was passiert, ist, dass es, dass die Build auf die Anzahl der Tage seit dem 1. Januar 2000 Ortszeit gleich sein, und für die Revision auf die Anzahl der Sekunden seit Mitternacht Ortszeit gleich sein, geteilt durch 2.

siehe Community-Inhalt, Automatische Build- und Revisionsnummern

z. AssemblyInfo.cs

[assembly: AssemblyVersion("1.0.*")] // important: use wildcard for build and revision numbers!

SampleCode.cs

var version = Assembly.GetEntryAssembly().GetName().Version;
var buildDateTime = new DateTime(2000, 1, 1).Add(new TimeSpan(
TimeSpan.TicksPerDay * version.Build + // days since 1 January 2000
TimeSpan.TicksPerSecond * 2 * version.Revision)); // seconds since midnight, (multiply by 2 to get original)

unten In der Pre-Build-Ereignisse Befehlszeile:

echo %date% %time% > "$(ProjectDir)\Resources\BuildDate.txt"

Fügen Sie diese Datei als Ressource, jetzt String ‚Builddate‘ haben in Ihrer Ressourcen.

, um die Datei in die Ressource Nach dem Einfügen (als öffentliche Textdatei), zugegriffen ich es über

string strCompTime = Properties.Resources.BuildDate;

Ressourcen zu erstellen, finden Sie unter Wie erstellen und verwenden, um Ressourcen in. NET .

Ein Ansatz, den ich bin erstaunt, niemand erwähnt hat noch zu verwenden ist T4 Textvorlagen für die Codegenerierung.

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System" #>
<#@ output extension=".g.cs" #>
using System;
namespace Foo.Bar
{
    public static partial class Constants
    {
        public static DateTime CompilationTimestampUtc { get { return new DateTime(<# Write(DateTime.UtcNow.Ticks.ToString()); #>L, DateTimeKind.Utc); } }
    }
}

Vorteile:

  • Locale unabhängige
  • Ermöglicht viel mehr als nur die Zeit der Kompilation

Nachteile:

In Bezug auf die Technik des Ziehens Datum / Versionsinformationen aus der Bytes einer Baugruppe PE-Header bauen, hat Microsoft die Standard-Build-Parameter, beginnend mit Visual Studio 15.4 geändert. Der neue Standard enthält determinis Kompilation, die einen gültigen Zeitstempel und automatisch erhöht Versionsnummern eine Sache der Vergangenheit macht. Das Zeitstempel-Feld ist immer noch vorhanden, aber es wird mit einem permanenten Wert gefüllt, die ein Hash von etwas oder andere, aber nicht irgendein Anzeichen der Build-Zeit.

Einige detaillierte Hintergrund hier

Für diejenigen, die einen nützlichen Zeitstempel über determinis Kompilation priorisieren, gibt es eine Möglichkeit, den neuen Standard außer Kraft zu setzen. Sie können einen Tag in der CSPROJ Datei der Montage in der Nähe sind wie folgt:

  <PropertyGroup>
      ...
      <Deterministic>false</Deterministic>
  </PropertyGroup>

Update: Ich unterstütze die T4 Textvorlage Lösung hier in einer anderen Antwort beschrieben. Ich habe es mein Problem sauber zu lösen, ohne den Vorteil der deterministischen Zusammenstellung zu verlieren. Eine Warnung darüber ist, dass Visual Studio läuft nur den T4-Compiler, wenn die .tt Datei gespeichert wird, nicht zum Zeitpunkt der Erstellung. Dies kann umständlich sein, wenn Sie die CS- aus der Quellcodeverwaltung ausschließen führen und ein anderer Entwickler checkt die Code (da Sie es erzeugt werden erwartet). Ohne resaving, werden sie die CS-Datei nicht haben. Es ist ein Paket auf nuget (ich glaube AutoT4 genannt), die T4-Kompilierung Teil jeder Build macht. Ich habe noch nicht die Lösung dieses Problems während der Produktion Einsatz konfrontiert, aber ich erwarte etwas ähnliches, um es richtig zu machen.

Ich bin gerade # Neuling C so vielleicht meine Antwort dumm klingen - ich zeige das Build-Datum ab dem Datum der ausführbare Datei wurde zuletzt geschrieben:

string w_file = "MyProgram.exe"; 
string w_directory = Directory.GetCurrentDirectory();

DateTime c3 =  File.GetLastWriteTime(System.IO.Path.Combine(w_directory, w_file));
RTB_info.AppendText("Program created at: " + c3.ToString());

Ich habe versucht, File.GetCreationTime Methode zu verwenden, bekam aber seltsame Ergebnisse: das Datum, von dem Befehl war 2012-05-29, aber das Datum aus dem Fenster Explorer 2012-05-23 zeigte. Nachdem für diese Diskrepanz der Suche fand ich, dass die Datei wahrscheinlich auf 2012-05-23 erstellt wurde (wie von Windows Explorer angezeigt), aber auf 2012.05.29 in den aktuellen Ordner kopiert (wie durch File.GetCreationTime Befehl gezeigt) - so auf der sicheren Seite zu sein, ich File.GetLastWriteTime Befehl verwenden.

Zalek

Für alle, die die Kompilierung in Windows 8 / Windows Phone 8 erhalten muss:

    public static async Task<DateTimeOffset?> RetrieveLinkerTimestamp(Assembly assembly)
    {
        var pkg = Windows.ApplicationModel.Package.Current;
        if (null == pkg)
        {
            return null;
        }

        var assemblyFile = await pkg.InstalledLocation.GetFileAsync(assembly.ManifestModule.Name);
        if (null == assemblyFile)
        {
            return null;
        }

        using (var stream = await assemblyFile.OpenSequentialReadAsync())
        {
            using (var reader = new DataReader(stream))
            {
                const int PeHeaderOffset = 60;
                const int LinkerTimestampOffset = 8;

                //read first 2048 bytes from the assembly file.
                byte[] b = new byte[2048];
                await reader.LoadAsync((uint)b.Length);
                reader.ReadBytes(b);
                reader.DetachStream();

                //get the pe header offset
                int i = System.BitConverter.ToInt32(b, PeHeaderOffset);

                //read the linker timestamp from the PE header
                int secondsSince1970 = System.BitConverter.ToInt32(b, i + LinkerTimestampOffset);

                var dt = new DateTimeOffset(1970, 1, 1, 0, 0, 0, DateTimeOffset.Now.Offset) + DateTimeOffset.Now.Offset;
                return dt.AddSeconds(secondsSince1970);
            }
        }
    }

Für alle, die die Kompilierung in Windows Phone 7 bekommen muss:

    public static async Task<DateTimeOffset?> RetrieveLinkerTimestampAsync(Assembly assembly)
    {
        const int PeHeaderOffset = 60;
        const int LinkerTimestampOffset = 8;            
        byte[] b = new byte[2048];

        try
        {
            var rs = Application.GetResourceStream(new Uri(assembly.ManifestModule.Name, UriKind.Relative));
            using (var s = rs.Stream)
            {
                var asyncResult = s.BeginRead(b, 0, b.Length, null, null);
                int bytesRead = await Task.Factory.FromAsync<int>(asyncResult, s.EndRead);
            }
        }
        catch (System.IO.IOException)
        {
            return null;
        }

        int i = System.BitConverter.ToInt32(b, PeHeaderOffset);
        int secondsSince1970 = System.BitConverter.ToInt32(b, i + LinkerTimestampOffset);
        var dt = new DateTimeOffset(1970, 1, 1, 0, 0, 0, DateTimeOffset.Now.Offset) + DateTimeOffset.Now.Offset;
        dt = dt.AddSeconds(secondsSince1970);
        return dt;
    }

Hinweis: In allen Fällen Sie in einer Sandbox laufen lassen, so dass Sie nur in der Lage sein, um die Kompilierung von Baugruppen zu erhalten, die Sie mit Ihrer App bereitstellen. (Das heißt das wird nicht im GAC auf etwas arbeiten).

Das obige Verfahren kann für Baugruppen gezwickt wird bereits innerhalb des Prozesses geladen durch die Datei des Bildes in einem Speicher unter Verwendung von (im Gegensatz zu Wieder liest aus dem Speicher):

using System;
using System.Runtime.InteropServices;
using Assembly = System.Reflection.Assembly;

static class Utils
{
    public static DateTime GetLinkerDateTime(this Assembly assembly, TimeZoneInfo tzi = null)
    {
        // Constants related to the Windows PE file format.
        const int PE_HEADER_OFFSET = 60;
        const int LINKER_TIMESTAMP_OFFSET = 8;

        // Discover the base memory address where our assembly is loaded
        var entryModule = assembly.ManifestModule;
        var hMod = Marshal.GetHINSTANCE(entryModule);
        if (hMod == IntPtr.Zero - 1) throw new Exception("Failed to get HINSTANCE.");

        // Read the linker timestamp
        var offset = Marshal.ReadInt32(hMod, PE_HEADER_OFFSET);
        var secondsSince1970 = Marshal.ReadInt32(hMod, offset + LINKER_TIMESTAMP_OFFSET);

        // Convert the timestamp to a DateTime
        var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        var linkTimeUtc = epoch.AddSeconds(secondsSince1970);
        var dt = TimeZoneInfo.ConvertTimeFromUtc(linkTimeUtc, tzi ?? TimeZoneInfo.Local);
        return dt;
    }
}

Die Option hier nicht eingegangen ist Ihre eigenen Daten in AssemblyInfo.cs einzufügen, scheint das „AssemblyInformationalVersion“ Feld angemessen - wir ein paar Projekte, wo wir etwas ähnliches tun, als Build Schritt (aber ich bin nicht ganz zufrieden mit der Art und Weise, also nicht wirklich will, funktioniert zu reproduzieren, was wir haben).

Es gibt einen Artikel über das Thema auf Codeproject: http://www.codeproject.com /KB/dotnet/Customizing_csproj_files.aspx

Für .NET Core-Projekte, ich Postlagerkarte Antwort angepasst ist, das Montag Urheberrecht Feld mit dem Build-Datum zu aktualisieren.

direkt bearbeiten csproj

Das Folgende kann direkt mit dem ersten PropertyGroup im csproj hinzugefügt werden:

<Copyright>Copyright © $([System.DateTime]::UtcNow.Year) Travis Troyer ($([System.DateTime]::UtcNow.ToString("s")))</Copyright>

Alternative: Visual Studio Projekteigenschaften

oder den inneren Ausdruck direkt in das Urheberrecht Feld im Paket-Abschnitt der Projekteigenschaften in Visual Studio einfügen:

Copyright © $([System.DateTime]::UtcNow.Year) Travis Troyer ($([System.DateTime]::UtcNow.ToString("s")))

Dies kann ein wenig verwirrend sein, weil Visual Studio wird den Ausdruck auswerten und den aktuellen Wert in dem Fenster angezeigt werden, sondern es wird auch die Projektdatei in geeignete Weise hinter den Kulissen aktualisieren.

Lösung weit über Directory.Build.props

Sie können das <Copyright> Element plop oben in eine Directory.Build.props Datei in Ihrer Lösung Wurzel, und haben es für alle Projekte innerhalb des Verzeichnisses automatisch angelegt, jedes Projekt unter der Annahme keinen eigenen Urheberrecht Wert liefern.

<Project>
 <PropertyGroup>
   <Copyright>Copyright © $([System.DateTime]::UtcNow.Year) Travis Troyer ($([System.DateTime]::UtcNow.ToString("s")))</Copyright>
 </PropertyGroup>
</Project>

Directory.Build.props: Passen Sie Ihre build

Ausgabe

Das Beispiel Ausdruck geben Ihnen einen Urheberrecht wie folgt aus:

Copyright © 2018 Travis Troyer (2018-05-30T14:46:23)

Retrieval

Sie können die Copyright-Informationen aus den Dateieigenschaften in Windows anzuzeigen, oder es zur Laufzeit greifen:

var version = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location);

Console.WriteLine(version.LegalCopyright);

Es gibt viele gute Antworten hier, aber ich fühle mich wie ich wegen der Einfachheit meines eigenen hinzufügen, die Leistung (im Vergleich zu aufwandsbezogene Lösungen) Cross-Plattform (funktioniert mit Net-Core auch) und Vermeidung jegliche 3rd-Party-Tool. Fügen Sie einfach dieses msbuild Ziel des csproj.

<Target Name="Date" BeforeTargets="CoreCompile">
    <WriteLinesToFile File="$(IntermediateOutputPath)gen.cs" Lines="static partial class Builtin { public static long CompileTime = $([System.DateTime]::UtcNow.Ticks) %3B }" Overwrite="true" />
    <ItemGroup>
        <Compile Include="$(IntermediateOutputPath)gen.cs" />
    </ItemGroup>
</Target>

und jetzt haben Sie Builtin.CompileTime oder new DateTime(Builtin.CompileTime, DateTimeKind.Utc), wenn Sie es auf diese Weise benötigen.

ReSharper ist wie es nicht gonna. Sie können ihn eine partielle Klasse für das Projekt ignorieren oder auch, aber es funktioniert trotzdem.

Im Jahr 2018 einige der oben genannten Lösungen nicht mehr funktionieren oder nicht funktionieren mit .NET-Core.

Ich verwende den folgenden Ansatz, die einfach ist und arbeitet für mein .NET Core 2.0-Projekt.

Fügen Sie den folgenden Code zu Ihrem CSPROJ innerhalb des Property:

    <Today>$([System.DateTime]::Now)</Today>

Dies definiert eine PropertyFunction , die Sie zugreifen können in Ihrem Pre Build-Befehl.

Ihre Pre-Build sieht wie folgt aus

echo $(today) > $(ProjectDir)BuildTimeStamp.txt

Legen Sie die Eigenschaft des BuildTimeStamp.txt auf Eingebettete Ressource.

Jetzt können Sie den Zeitstempel wie das lesen

public static class BuildTimeStamp
    {
        public static string GetTimestamp()
        {
            var assembly = Assembly.GetEntryAssembly(); 

            var stream = assembly.GetManifestResourceStream("NamespaceGoesHere.BuildTimeStamp.txt");

            using (var reader = new StreamReader(stream))
            {
                return reader.ReadToEnd();
            }
        }
    }

ich eine universelle Lösung benötigt, die mit einem NETStandard Projekt auf jeder Plattform gearbeitet (iOS, Android und Windows.) Um dies zu erreichen, habe ich beschlossen, eine CS-Datei über einen Powershell-Skript automatisch zu generieren. Hier ist der Powershell-Skript:

param($outputFile="BuildDate.cs")

$buildDate = Get-Date -date (Get-Date).ToUniversalTime() -Format o
$class = 
"using System;
using System.Globalization;

namespace MyNamespace
{
    public static class BuildDate
    {
        public const string BuildDateString = `"$buildDate`";
        public static readonly DateTime BuildDateUtc = DateTime.Parse(BuildDateString, null, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
    }
}"

Set-Content -Path $outputFile -Value $class

Speichern Sie die Datei als Powerscript GenBuildDate.ps1 und es Ihr Projekt hinzufügen. Schließlich fügen Sie die folgende Zeile in der Pre-Build-Ereignisse:

powershell -File $(ProjectDir)GenBuildDate.ps1 -outputFile $(ProjectDir)BuildDate.cs

Stellen Sie sicher, BuildDate.cs ist in Ihrem Projekt enthalten. Funktioniert wie ein Champion auf jedem Betriebssystem!

ich gerade tun:

File.GetCreationTime(GetType().Assembly.Location)

Sie können dieses Projekt verwenden: https://github.com/dwcullop/BuildInfo

Es nutzt T4 das Erstellungsdatum Zeitstempel zu automatisieren. Es gibt mehrere Versionen (verschiedene Zweige) mit ein, dass Sie die Git Hash des aktuell ausgecheckt Zweig gibt, wenn Sie in diese Art der Sache sind.

Disclosure:. Ich schrieb das Modul

Sie können ein Projekt Post-Build-Ereignis verwenden, um eine Textdatei zu Ihrem Zielverzeichnis mit dem aktuellen Datetime zu schreiben. Sie könnten dann den Wert zur Laufzeit gelesen. Es ist ein wenig hacky, aber es sollte funktionieren.

Ich bin nicht sicher, aber vielleicht das bauen Incrementer hilft.

Ein anderer, PCL freundlicher Ansatz wäre eine MSBuild Inline-Aufgabe zu verwenden, um die Build-Zeit in einen String zu ersetzen, die von einem Objekt auf der App zurückgegeben. Wir verwenden diesen Ansatz erfolgreich in einer App, die Xamarin.Forms, Xamarin.Android und Xamarin.iOS Projekte hat.

EDIT:

Vereinfachte durch die gesamte Logik in die SetBuildDate.targets Datei und mit Regex statt einfacher Saitenverrutschen ersetzen, so dass die Datei von jedem geändert werden kann, ohne einen „Reset“ zu bauen.

Die MSBuild Inline Aufgabendefinition (in einem SetBuildDate.targets gespeichert Datei lokal auf das Xamarin.Forms Projekt für dieses Beispiel):

<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' ToolsVersion="12.0">

  <UsingTask TaskName="SetBuildDate" TaskFactory="CodeTaskFactory" 
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
    <ParameterGroup>
      <FilePath ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Code Type="Fragment" Language="cs"><![CDATA[

        DateTime now = DateTime.UtcNow;
        string buildDate = now.ToString("F");
        string replacement = string.Format("BuildDate => \"{0}\"", buildDate);
        string pattern = @"BuildDate => ""([^""]*)""";
        string content = File.ReadAllText(FilePath);
        System.Text.RegularExpressions.Regex rgx = new System.Text.RegularExpressions.Regex(pattern);
        content = rgx.Replace(content, replacement);
        File.WriteAllText(FilePath, content);
        File.SetLastWriteTimeUtc(FilePath, now);

   ]]></Code>
    </Task>
  </UsingTask>

</Project>

die oben Inline-Aufgabe in der Xamarin.Forms csproj Datei in Zielbefore aufrufen:

  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.  -->
  <Import Project="SetBuildDate.targets" />
  <Target Name="BeforeBuild">
    <SetBuildDate FilePath="$(MSBuildProjectDirectory)\BuildMetadata.cs" />
  </Target>

Die FilePath Eigenschaft wird auf eine BuildMetadata.cs Datei im Xamarin.Forms Projekt festgelegt, die eine einfache Klasse mit einer String-Eigenschaft BuildDate enthält, in denen die Erstellungszeit ersetzt werden:

public class BuildMetadata
{
    public static string BuildDate => "This can be any arbitrary string";
}

Fügen Sie diese Datei BuildMetadata.cs zu projizieren. Es wird von jedem Build geändert werden, aber in einer Weise, die baut wiederholt ermöglicht (wiederholte Ersatz), so dass Sie enthalten können oder es in der Quellcodeverwaltung unterlassen, wie gewünscht.

Ein kleines Update auf der "New Way" Antwort von Jhon.

Sie müssen den Pfad bauen, anstatt die Code-Basis Zeichenfolge verwenden, wenn sie mit ASP.NET/MVC

Arbeits
    var codeBase = assembly.GetName().CodeBase;
    UriBuilder uri = new UriBuilder(codeBase);
    string path = Uri.UnescapeDataString(uri.Path);

Sie können einen zusätzlichen Schritt in dem Build-Prozess starten, der einen Datumsstempel in eine Datei schreibt, die dann angezeigt werden können.

Auf der Projekte Register Eigenschaften Blick auf die Registerkarte Build-Ereignisse. Es gibt eine Option, um einen Pre- oder Post-Build-Befehl auszuführen.

Ich habe Abdurrahim Vorschlag. Aber es schien eine seltsame Zeitformat zu geben und auch die Abkürzung für den Tag als Teil des Build-Datum hinzugefügt; Beispiel: Sun 2017.12.24 13: 21: 05,43. Ich brauchte nur gerade das Datum so dass ich den Rest mit Teilzeichenfolge zu beseitigen hatte.

echo %date% %time% > "$(ProjectDir)\Resources\BuildDate.txt"to das Pre-Build-Ereignis Nach dem Hinzufügen, ich habe nur die folgende:

string strBuildDate = YourNamespace.Properties.Resources.BuildDate;
string strTrimBuildDate = strBuildDate.Substring(4).Remove(10);

Die gute Nachricht dabei ist, dass es geklappt hat.

Wenn dies eine Windows-Anwendung ist, können Sie die Anwendung ausführbaren Pfad benutzen Sie einfach: neue System.IO.FileInfo (Application.ExecutablePath) .LastWriteTime.ToString ( "YYYY.MM.DD")

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top