বিল্ডের তারিখ প্রদর্শন করা হচ্ছে


260

আমার কাছে বর্তমানে একটি অ্যাপ রয়েছে যার শিরোনাম উইন্ডোটিতে বিল্ড নম্বরটি প্রদর্শন করছে। এটি বেশ ভাল এবং ব্যতীত এর বেশিরভাগ ব্যবহারকারীর কাছে কিছুই বোঝা যায় না, যারা সর্বশেষ বিল্ডটি রয়েছে কিনা তা জানতে চান - তারা এটিকে "গত বৃহস্পতিবারের" হিসাবে উল্লেখ করেছেন 1.0.8.4321 নির্মাণের পরিবর্তে।

পরিবর্তে সেখানে বিল্ডের তারিখ রাখার পরিকল্পনা রয়েছে - সুতরাং "21/10/2009 এ নির্মিত অ্যাপ" উদাহরণস্বরূপ।

আমি এর মতো ব্যবহারের জন্য পাঠ্য স্ট্রিং হিসাবে বিল্ডের তারিখটি টানানোর জন্য একটি প্রোগ্রাম্যাটিক উপায় খুঁজতে লড়াই করছি।

বিল্ড নম্বরটির জন্য, আমি ব্যবহার করেছি:

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

কীভাবে সেগুলি এসেছিল তা নির্ধারণ করার পরে।

আমি সংকলনের তারিখ (এবং সময়, বোনাস পয়েন্ট জন্য) এর মত কিছু চাই।

পয়েন্টারগুলি এখানে অনেক প্রশংসা করেছে (উপযুক্ত হলে ক্ষমা করার শঙ্কা), বা আরও সুন্দর সমাধান ...


2
আমি সাধারণ পরিস্থিতিতে দৃশ্যে কাজ করে এমন সমাবেশগুলির বিল্ড ডেটা পাওয়ার জন্য সরবরাহিত উপায়গুলি চেষ্টা করেছিলাম তবে দুটি সভা যদি একত্রিত হয় তবে আমি সঠিকভাবে নির্মাণের সময়টি পাই না, এটি ভবিষ্যতে এক ঘন্টা আছে .. কোনও পরামর্শ?

উত্তর:


356

কঠিন উপায় নির্ধারণের তারিখ নির্ধারণে জেফ অ্যাটউডের এই সমস্যাটি সম্পর্কে কিছু বলতে হবে ।

এক্সিকিউটেবল ফাইলে এম্বেড করা পিই হেডার থেকে লিঙ্কার টাইমস্ট্যাম্পটি পুনরুদ্ধার করার জন্য সবচেয়ে নির্ভরযোগ্য পদ্ধতিটি দেখা গেছে - এর জন্য জেফের নিবন্ধের মন্তব্যগুলি থেকে কিছু সি # কোড (জো স্পাইভে লিখেছেন):

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;
}

ব্যবহারের উদাহরণ:

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

আপডেট: পদ্ধতিটি নেট কোর 1.0 এর জন্য কাজ করছিল, তবে নেট কোর 1.1 প্রকাশের পরে কাজ করা বন্ধ করে দিয়েছে (1900-2020 পরিসরে এলোমেলো বছর দেয়)


8
আমি এই সম্পর্কে আমার স্বর কিছুটা বদলেছি, আকিউটাল পিই হেডারটি খনন করার সময় আমি এখনও খুব সতর্ক থাকব। তবে যতদূর আমি বলতে পারি, এই পিই স্টাফটি সংস্করণ নম্বরগুলি ব্যবহার করার চেয়ে অনেক বেশি নির্ভরযোগ্য, তাছাড়া আমি বিল্ডের তারিখ থেকে পৃথক সংস্করণ নম্বরগুলিও নির্ধারণ করতে চাই না।
জন লেইডগ্রেন

6
আমি এটি পছন্দ করি এবং এটি ব্যবহার করছি, তবে দ্বিতীয়টির সাথে দ্বিতীয়টি শেষ লাইনের .AddHours()পরিবর্তে হ্যাকিশ এবং (আমি মনে করি) ডিএসটি আমলে নেবে না। আপনি যদি স্থানীয় সময়ে এটি চান তবে আপনার dt.ToLocalTime();পরিবর্তে ক্লিনারটি ব্যবহার করা উচিত । মাঝের অংশটি একটি using()ব্লক দিয়ে ব্যাপকভাবে সরল করা যেতে পারে ।
জেএলআরিশ

6
হ্যাঁ, এটি আমার জন্য নেট কোর (1940, 1960, ইত্যাদি)
শ্রুতিমধুর

7
যদিও আজ পিই শিরোলেখার ব্যবহার সম্ভবত একটি ভাল বিকল্প বলে মনে হচ্ছে, তবে এটি লক্ষণীয় যে এমএস নির্ধারিত বিল্ডগুলির সাথে পরীক্ষা করছে (যা এই শিরোনামকে অকেজো করে দেবে) এবং সম্ভবত এটি সি # এর ভবিষ্যতের সংকলক সংস্করণগুলিতে ডিফল্টও বানাচ্ছে (ভাল কারণে)। ভাল পড়ুন: ব্লগ.প্যারানয়েডকোডিং ডটকম / ২০১/0/০৪/২০১৫/২ এবং এখানে নেট নেট সম্পর্কিত টিএলডিআর সম্পর্কিত উত্তর রয়েছে (টিএলডিআর: "এটি ডিজাইনের দ্বারা"): ডেভেলপারকোমিউনিটি.ভিজুয়ালস্টুডিও
পাওয়ে বুলওয়ান

13
যারা এটিকে আর কাজ করে না বলে মনে হয় তাদের জন্য সমস্যাটি কোনও নেট নেট সমস্যা নয়। ভিজুয়াল স্টুডিও 15.4 দিয়ে শুরু হওয়া নতুন বিল্ড প্যারামিটার ডিফল্টগুলি সম্পর্কে আমার উত্তরটি দেখুন।
টম

107

প্রাক-বিল্ড ইভেন্ট কমান্ড লাইনে নীচে যুক্ত করুন:

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

এই ফাইলটিকে উত্স হিসাবে যুক্ত করুন, এখন আপনার সংস্থানগুলিতে আপনার 'বিল্ডডেট' স্ট্রিং রয়েছে।

সংস্থান তৈরি করতে ,। নেট এ সংস্থানগুলি কীভাবে তৈরি করতে এবং ব্যবহার করতে হয় তা দেখুন ।


4
আমার কাছ থেকে +1, সহজ এবং কার্যকর। এমনকি আমি এই জাতীয় কোডের একটি লাইন দিয়ে ফাইলটি থেকে মানটি পরিচালনা করতে পেরেছি: স্ট্রিং বিল্ডডেট = <মাইক্র্লাসলিবারিয়ান নেম> .প্রাপ্তি.সংশ্লিষ্ট.বিল্ড তারিখ
ডেভিডফ্রান্সিস

11
অন্য বিকল্পটি একটি শ্রেণি তৈরি করা হয়েছে: (আপনি প্রথম বার এটি সংকলন করার পরে প্রকল্পে অন্তর্ভুক্ত করতে হবে) -> প্রতিধ্বনি নেমস্পেস My.app.namespace {পাবলিক স্ট্যাটিক ক্লাস বিল্ড {পাবলিক স্ট্যাটিক স্ট্রিং টাইমস্ট্যাম্প = "% DATE%% TIME%" .সুবস্ট্রিং (0,16);}}> "$ (প্রজেক্টডির) \ বিল্ডটাইমস্ট্যাম্প.cs" - - -> তারপরে এটি বিল্ডের সাথে কল করতে পারেন
ime

9
এটি একটি দুর্দান্ত সমাধান। একমাত্র সমস্যা হ'ল% তারিখ% এবং% সময়% কমান্ড লাইন ভেরিয়েবলগুলি স্থানীয়করণ করা হয়, সুতরাং আউটপুটটি ব্যবহারকারীর উইন্ডোজ ভাষার উপর নির্ভর করে পরিবর্তিত হবে।
ভিএস

2
+1, পিই শিরোনামগুলি পড়ার চেয়ে এটি একটি ভাল পদ্ধতি - কারণ এমন অনেকগুলি পরিস্থিতি রয়েছে যেখানে এটি
ম্যাট হুইটফিল্ড

17
চালাক। আপনি ফর্ম্যাটটিতে আরও সুনির্দিষ্ট নিয়ন্ত্রণ পেতে পাওয়ারশেল ব্যবহার করতে পারেন, যেমন একটি ইউটিসি তারিখের সময়টি ISO8601: পাওয়ারশেল -কম্যান্ড "((গেট-ডেট)) হিসাবে রূপান্তর করুন o টু ইউনিভার্সালটাইম () To টু স্ট্রিং (s" s \ ") | আউট-ফাইল 'Project (প্রজেক্টডির) রিসোর্সগুলি D বিল্ডডেট.টেক্সট' "
২২ অক্টোবর'১২ এ 22

90

রাস্তা

হিসাবে @ c00000fd দ্বারা নির্দিষ্ট মন্তব্য । মাইক্রোসফ্ট এটি পরিবর্তন করছে। এবং যখন অনেকে তাদের সংকলকটির সর্বশেষতম সংস্করণ ব্যবহার করেন না তখন আমার সন্দেহ হয় যে এই পরিবর্তনটি এই পদ্ধতির সন্দেহাতীত খারাপ করেছে। এবং এটি একটি মজাদার অনুশীলনের সময় আমি বাইনারি নিজেই তৈরির তারিখটি ট্র্যাক করা যদি গুরুত্বপূর্ণ হয় তবে অন্য যে কোনও উপায়ের মাধ্যমে লোকদের কেবল বাইনারিতে কোনও বিল্ড ডেট এম্বেড করার জন্য সুপারিশ করব।

এটি কিছু তুচ্ছ কোড উত্পাদন সহ করা যেতে পারে যা সম্ভবত আপনার বিল্ড স্ক্রিপ্টের ইতিমধ্যে ইতিমধ্যে প্রথম পদক্ষেপ। এটি এবং এএলএম / বিল্ড / ডিভোপস সরঞ্জামগুলি এর সাথে অনেক সহায়তা করে এবং অন্য যে কোনও কিছুর চেয়ে অগ্রাধিকার দেওয়া উচিত।

আমি এই উত্তরটি এখানে কেবল historicalতিহাসিক উদ্দেশ্যে ছেড়ে চলেছি।

নতুন উপায়

আমি এই সম্পর্কে আমার মতামত পরিবর্তন করেছি, এবং বর্তমানে সঠিক কৌশলটির তারিখ পেতে এই কৌশলটি ব্যবহার করছি।

#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

পুরানো উপায়

আচ্ছা, আপনি কীভাবে বিল্ড নম্বর তৈরি করবেন? ভিজ্যুয়াল স্টুডিও (বা সি # সংকলক) আসলে আপনি স্বয়ংক্রিয় বিল্ড এবং সংশোধন নম্বরগুলি সরবরাহ করে যদি আপনি অ্যাসেম্বলিভিশন বৈশিষ্ট্যটিকে উদাহরণস্বরূপ পরিবর্তন করেন1.0.*

যা ঘটবে তা হ'ল বিল্ডটি স্থানীয় সময় অনুসারে জানুয়ারী 1, 2000 সাল থেকে দিনের সংখ্যার সমান এবং সংশোধন করার জন্য স্থানীয় সময় মধ্যরাত থেকে সেকেন্ডের সংখ্যার সমান হবে, 2 দ্বারা বিভক্ত।

সম্প্রদায় সামগ্রী, স্বয়ংক্রিয় বিল্ড এবং সংশোধন নম্বর দেখুন

যেমন এসেম্বলিআইএনফো

[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)

3
আমি কেবল এক ঘন্টা যোগ করেছি যদিTimeZone.CurrentTimeZone.IsDaylightSavingTime(buildDateTime) == true
e4rthdog

2
দুর্ভাগ্যক্রমে আমি এই পদ্ধতিটি ভালভাবে পরীক্ষা না করে ব্যবহার করেছি এবং এটি আমাদের উত্পাদনতে কামড় দিচ্ছে। সমস্যাটি হ'ল জেআইটি সংকলক যখন পিই শিরোনামের তথ্যটিতে কিক দেয়। সুতরাং ডাউনভোট। কেন আমরা ইনস্টলড তারিখটি বিল্ডের তারিখ হিসাবে দেখি তা বোঝাতে এখন আমি অনিবদ্ধ 'গবেষণা' করতে চলেছি।
জেসন ডি

8
@ জেসনডি কোন মহাবিশ্বে আপনার সমস্যাটি কোনওভাবে আমার সমস্যা হয়ে উঠবে? আপনি কীভাবে একটি ডাউনওয়েটকে ন্যায়সঙ্গত করবেন তা কেবল আপনি এই কারণেছিলেন যে আপনি এমন একটি সমস্যা নিয়ে এসেছিলেন যা এই বাস্তবায়ন বিবেচনায় নেই। আপনি এটি নিখরচায় পেয়েছেন এবং আপনি এটির খারাপ পরীক্ষা করেছেন। এছাড়াও আপনি কী বিশ্বাস করতে পারেন যে শিরোনামটি JIT সংকলক দ্বারা পুনরায় লেখা হচ্ছে? আপনি কি প্রক্রিয়া মেমরি থেকে বা ফাইল থেকে এই তথ্যটি পড়ছেন?
জন লিডেগ্রেন

6
আমি লক্ষ্য করেছি যে আপনি যদি কোনও ওয়েব অ্যাপ্লিকেশনটিতে চলমান থাকেন তবে। কোড কোড বেসটি কোনও ইউআরএল হিসাবে উপস্থিত হবে (ফাইল: // সি: /path/to/binary.dll)। এটি ফাইলের কারণ হয় E কোডবেস সম্পত্তির পরিবর্তে "এসেম্বলি.লোকেশন" ব্যবহার করা আমার জন্য সমস্যাটি সমাধান করেছে।
mdryden

2
@ জনলিডগ্রেন: তার জন্য উইন্ডোজ পিই হেডারের উপর নির্ভর করবেন না। উইন্ডোজ 10 এবং পুনরুত্পাদনযোগ্য বিল্ড হওয়ায় IMAGE_FILE_HEADER::TimeDateStampক্ষেত্রটি এলোমেলো সংখ্যায় সেট করা আছে এবং এটি আর টাইম স্ট্যাম্পের নয়।
c00000fd

51

প্রাক-বিল্ড ইভেন্ট কমান্ড লাইনে নীচে যুক্ত করুন:

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

এই ফাইলটিকে উত্স হিসাবে যুক্ত করুন, এখন আপনার সংস্থানগুলিতে আপনার 'বিল্ডডেট' স্ট্রিং রয়েছে।

রিসোর্সে ফাইলটি publicোকানোর পরে (সর্বজনীন পাঠ্য ফাইল হিসাবে), এর মাধ্যমে আমি এটি অ্যাক্সেস করেছি

string strCompTime = Properties.Resources.BuildDate;

সংস্থান তৈরি করতে ,। নেট এ সংস্থানগুলি কীভাবে তৈরি করতে এবং ব্যবহার করতে হয় তা দেখুন ।


1
@ ডেভিডগর্সলাইন - মন্তব্য উত্তরসূচিটি সঠিক ছিল কারণ এটি এই অন্য উত্তরটির উদ্ধৃতি দিচ্ছে । আপনার পরিবর্তনটি রোলব্যাক করার জন্য আমার অপর্যাপ্ত খ্যাতি আছে, অন্যথায় আমি নিজেই এটি করে ফেলতাম।
ওয়াই হা লি

1
@ ওয়াই হা লি - ক) আপনি যে উত্তরটি উদ্ধৃত করেছেন তা সংকলনের তারিখ / সময়টি পুনরুদ্ধার করার জন্য কোড দেয় না। খ) সেই সময়টিতে আমার উত্তরটির পক্ষে মন্তব্য করার মতো যথেষ্ট খ্যাতি ছিল না (যা আমি করতাম) কেবল পোস্ট করার জন্য। তাই গ) আমি পুরো উত্তর দিয়ে পোস্ট করেছি যাতে লোকেরা একটি বিষয়ে সমস্ত বিবরণ পেতে পারে ..
ব্রিউম্যান্জ

যদি আপনি% তারিখ% এর পরিবর্তে %te% দেখেন তবে এখানে চেক করুন: developercommune.visualstudio.com/content/problem/237752/… সংক্ষেপে, এটি করুন: প্রতিধ্বনিত% 25%% 25% 25%% 25
কোডেক্স

41

আমি যে অবাক হয়েছি এমন একটি পদ্ধতির মধ্যে এখনও কেউ উল্লেখ করেনি তা হল কোড জেনারেশনের জন্য টি 4 টেক্সট টেম্পলেট ব্যবহার করা।

<#@ 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); } }
    }
}

পেশাদাররা:

  • লোকেল স্বাধীন
  • সংকলনের সময় ছাড়াও অনেক কিছু মঞ্জুরি দেয়

কনস:


1
সুতরাং, এটি এখন সেরা উত্তর। এটি শীর্ষ ভোটের উত্তর হয়ে যাওয়ার আগে 324 পয়েন্ট যেতে হবে :)। স্ট্যাকওভারফ্লো দ্রুততম লতা দেখানোর জন্য একটি উপায় প্রয়োজন।
পলডেন্ডুল্ক

1
@ পলডেন্ডুলক, খুব বেশি উপকারে আসবে না, কারণ সর্বাধিক উত্সাহিত উত্তর এবং গৃহীত উত্তর প্রায় সর্বদা দ্রুততম ভোট গ্রহণ করে। আমি এই উত্তরটি পোস্ট করার পরে এই প্রশ্নের গৃহীত উত্তরের + 60 / -2 রয়েছে।
পিটার টেলর

আমি বিশ্বাস করি আপনার টিক্সে আপনাকে একটি .ToString () যুক্ত করতে হবে (অন্যথায় আমি সংকলনের ত্রুটি পেয়েছি)। বলেছিল, আমি এখানে খাড়া শেখার বক্ররেখা চালাচ্ছি, আপনি কীভাবে মূল প্রোগ্রামটিতে এটি ব্যবহার করবেন তা দেখাতে পারেন?
অ্যান্ডি

@ অ্যান্ডি, আপনি তোস্ট্রস্ট্রিং সম্পর্কে ঠিক বলেছেন ()। ব্যবহার ঠিক Constants.CompilationTimestampUtc। যদি ভিএস ক্লাসের সাথে কোনও সি # ফাইল তৈরি করে না থাকে তবে এটি কীভাবে করা যায় তা আপনাকে খুঁজে বের করতে হবে, তবে উত্তরটি (খুব কমপক্ষে) ভিএস এর সংস্করণ এবং সিএসপোজ ফাইলের ধরণের উপর নির্ভর করে, তাই এটি এই পোস্টের জন্য খুব বিস্তারিত।
পিটার টেলর

1
অন্যেরা যদি ভাবতে থাকে যে, ভিএস 2017 এ এটি কাজ করার জন্য এটি কী নিয়েছিল: আমাকে এটি একটি ডিজাইনের সময় টি 4 টেমপ্লেট তৈরি করতে হয়েছিল (আমি প্রথমে একটি প্রিপ্রসেসর টেম্পলেট যুক্ত করেছি)। প্রকল্পটির একটি রেফারেন্স হিসাবে আমাকে এই সমাবেশটিও অন্তর্ভুক্ত করতে হয়েছিল: মাইক্রোসফ্ট.ভিজুয়াল স্টুডিও.সেক্সটটেম্প্লেটিং.আইনটারফেসস.১০.০ অবশেষে আমার টেমপ্লেটে "সিস্টেম ব্যবহার করে" অন্তর্ভুক্ত করতে হয়েছিল; নেমস্পেসের আগে, বা অন্যথায় ডেটটাইমের রেফারেন্স ব্যর্থ হয়েছিল।
অ্যান্ডি

20

কোনও সমাবেশের পিই শিরোনামের বাইটগুলি থেকে বিল্ডের তারিখ / সংস্করণ তথ্য টানানোর কৌশল সম্পর্কে, মাইক্রোসফ্ট ভিজ্যুয়াল স্টুডিও 15.4 দিয়ে শুরু করে ডিফল্ট বিল্ড প্যারামিটারগুলি পরিবর্তন করেছে। নতুন ডিফল্টে ডিটারিনিস্টিক সংকলন অন্তর্ভুক্ত রয়েছে, যা একটি বৈধ টাইমস্ট্যাম্প এবং স্বয়ংক্রিয়ভাবে বর্ধিত সংস্করণ সংখ্যাকে অতীতের একটি বিষয় করে। টাইমস্ট্যাম্প ক্ষেত্রটি এখনও বিদ্যমান তবে এটি স্থায়ী মানের সাথে পূর্ণ হয়ে যায় যা কোনও কিছু বা অন্য কোনও হ্যাশ, তবে বিল্ড টাইমের কোনও ইঙ্গিত দেয় না।

কিছু বিশদ পটভূমি এখানে

যারা ডেসটিনিস্টিক সংকলনের চেয়ে দরকারী টাইমস্ট্যাম্পকে অগ্রাধিকার দেন তাদের জন্য নতুন ডিফল্টকে ওভাররাইড করার একটি উপায় রয়েছে। আপনি আগ্রহের সমাবেশের .csproj ফাইলে একটি ট্যাগ অন্তর্ভুক্ত করতে পারেন:

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

আপডেট: আমি এখানে অন্য উত্তরে বর্ণিত টি 4 পাঠ্য টেম্পলেট সমাধানটিকে সমর্থন করি। আমি নির্ধারিত সংকলনের সুবিধাটি না হারিয়ে আমার সমস্যাটি পরিষ্কারভাবে সমাধান করার জন্য এটি ব্যবহার করেছি। এটি সম্পর্কে একটি সতর্কতা হ'ল .tl ফাইলটি সংরক্ষণের সময় ভিজুয়াল স্টুডিও কেবলমাত্র T4 সংকলকটি চালায়, বিল্ড টাইমে নয়। যদি আপনি উত্স নিয়ন্ত্রণ থেকে .cs ফলাফল বাদ দেন (যেহেতু আপনি এটি উত্পন্ন হওয়ার প্রত্যাশা করছেন) এবং অন্য বিকাশকারী কোডটি পরীক্ষা করে দেখেন তবে এটি বিশ্রী হতে পারে। পুনঃনির্মাণ ছাড়া তাদের কাছে .cs ফাইল থাকবে না। নুগেটে একটি প্যাকেজ রয়েছে (আমি মনে করি অটোটি 4 নামে পরিচিত) যা প্রতিটি বিল্ডের টি 4 সংকলন অংশ করে। উত্পাদন স্থাপনার সময় আমি এখনও এর সমাধানটির মুখোমুখি হইনি, তবে এটি সঠিক করার জন্য আমি অনুরূপ কিছু প্রত্যাশা করি।


এটি আমার সমস্যার সমাধান একটি স্ল্যানে করে যা সবচেয়ে পুরানো উত্তর ব্যবহার করে in
পলডেন্ডুল্ক

টি 4 সম্পর্কে আপনার সতর্কতা পুরোপুরি ন্যায্য, তবে মনে রাখবেন যে এটি আমার উত্তরটিতে ইতিমধ্যে উপস্থিত।
পিটার টেলর

15

আমি কেবল সি # নবাগত তাই সম্ভবত আমার উত্তরটি নির্বাক শোনায় - এক্সিকিউটেবল ফাইলটি সর্বশেষে লেখা হওয়ার তারিখ থেকে আমি বিল্ডের তারিখটি প্রদর্শন করি:

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());

আমি ফাইল.গেটক্রিয়েশনটাইম পদ্ধতিটি ব্যবহার করার চেষ্টা করেছি কিন্তু অদ্ভুত ফলাফল পেয়েছি: কমান্ডের তারিখটি ছিল 2012-05-29, তবে উইন্ডো এক্সপ্লোরারের তারিখটি 2012-05-23 দেখিয়েছে। এই তাত্পর্যটি অনুসন্ধানের পরে আমি দেখতে পেলাম যে ফাইলটি সম্ভবত 2012-05-23-এ তৈরি হয়েছিল (উইন্ডোজ এক্সপ্লোরার দ্বারা দেখানো হয়েছে), তবে বর্তমান ফোল্ডারে অনুলিপি করা হয়েছে 2012-05-29-এ (ফাইল.গেটক্রাইটিটাইম কমান্ড দ্বারা প্রদর্শিত) - সুতরাং নিরাপদ দিকে থাকতে আমি ফাইল.গেটলাস্টওয়্যারটাইম কমান্ডটি ব্যবহার করছি।

Zalek


4
আমি নিশ্চিত না যে ড্রাইভ / কম্পিউটার / নেটওয়ার্ক জুড়ে এক্সিকিউটেবলের অনুলিপি করা থেকে এটি বুলেট প্রুফ কিনা।
স্টিলথ রাব্বি

এটি প্রথম জিনিসটি মাথায় আসে তবে আপনি জানেন এটি নির্ভরযোগ্য নয় এমন অনেক সফ্টওয়্যার রয়েছে যা নেটওয়ার্কের মাধ্যমে ফাইলগুলি সরানোর জন্য ব্যবহৃত হয় যা ডাউনলোডের পরে বৈশিষ্ট্যগুলি আপডেট করে না, আমি @ আবদুর রহমানের উত্তরটি দিয়ে যাব।
মুবাশার

আমি জানি এটি পুরানো, তবে আমি সবেমাত্র কিছু অনুরূপ কোডের সাথে সন্ধান করেছি যা ইনস্টল প্রক্রিয়া (কমপক্ষে ক্লিকওনেস ব্যবহার করার সময়) সমাবেশ ফাইলের সময় আপডেট করে। খুব দরকারী নয়। যদিও এটি এই সমাধানটিতে প্রযোজ্য তা নিশ্চিত নয়।
bobwki

আপনি সম্ভবত সত্যই এটি চান LastWriteTime, যেহেতু এটি কার্যকরভাবে কার্যকর ফাইলটি আপডেট হওয়ার সময়টি সঠিকভাবে প্রতিফলিত করে।
ডেভিড আর ট্রাইবল

দুঃখিত তবে একটি নির্বাহযোগ্য ফাইল লেখার সময়টি বিল্ড টাইমের নির্ভরযোগ্য ইঙ্গিত নয়। আপনার প্রভাবের ক্ষেত্রের বাইরে থাকা সমস্ত ধরণের জিনিসগুলির কারণে ফাইল টাইম স্ট্যাম্প পুনরায় লেখা যেতে পারে।
টম

15

এখানে প্রচুর দুর্দান্ত উত্তর রয়েছে তবে আমি মনে করি যে সরলতা, পারফরম্যান্স (রিসোর্স-সম্পর্কিত সমাধানগুলির সাথে তুলনা করা) ক্রস প্ল্যাটফর্ম (নেট কোরের সাথেও কাজ করে) এবং কোনও তৃতীয় পক্ষের সরঞ্জাম এড়ানোর কারণে আমি নিজের নিজস্ব যুক্ত করতে পারি। কেবল এই এমএসবিল্ড লক্ষ্যটিকে সিএসপিজে যুক্ত করুন।

<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>

এবং এখন আপনার কাছে Builtin.CompileTimeবা new DateTime(Builtin.CompileTime, DateTimeKind.Utc)যদি আপনার এটির প্রয়োজন হয়।

রিশার্পার এটি পছন্দ করে না। আপনি তাকে উপেক্ষা করতে পারেন বা প্রকল্পে একটি আংশিক বর্গ যোগ করতে পারেন তবে এটি যাইহোক কাজ করে।


আমি এটি দিয়ে তৈরি করতে পারি এবং স্থানীয়ভাবে (ওয়েবসাইট চালাও) এএসপি.নেট কোর ২.১ এ বিকাশ করতে পারি তবে ভিএস 2017 থেকে ওয়েব প্রকাশের ত্রুটি "ব্যাল্টিন" বর্তমান প্রসঙ্গে নেই "এ ব্যর্থ হয়ে যায়। যোগ করুন: আমি যদি Builtin.CompileTimeএকটি রেজার ভিউ থেকে অ্যাক্সেস করছি ।
জেরেমি কুক

এই ক্ষেত্রে আমি মনে করি আপনার কেবল প্রয়োজন BeforeTargets="RazorCoreCompile"তবে কেবল এটি একই প্রকল্পে রয়েছে
দিমিত্রি গুসরভ

দুর্দান্ত, তবে আমরা উত্পন্ন বস্তুকে কীভাবে উল্লেখ করব? আমার কাছে মনে হচ্ছে উত্তরের একটি মূল অংশ অনুপস্থিত ...
মাত্তিও

1
@ মাত্তিও, উত্তরে উল্লিখিত হিসাবে আপনি "বিল্টিন.কম্পাইলটাইম" বা "নতুন ডেটটাইম (বিল্টিন.কমপাইলটাইম, ডেটটাইমকিন্ড.ইউটিসি)" ব্যবহার করতে পারেন। ভিজ্যুয়াল স্টুডিও ইন্টেলিজেন্স এখনই এটি দেখতে সক্ষম। একটি পুরানো রিসার্পার ডিজাইনের সময় অভিযোগ করতে পারে, তবে দেখে মনে হচ্ছে তারা এটি নতুন সংস্করণে স্থির করেছে। clip2net.com/s/46rgaaO
দিমিত্রি

আমি এই সংস্করণটি ব্যবহার করেছি তাই তারিখ পাওয়ার জন্য অতিরিক্ত কোডের প্রয়োজন নেই। এছাড়াও পুনঃভাগটি তার সর্বশেষতম সংস্করণে অভিযোগ করে না। <WritLinesToFile ফাইল = "$ (ইন্টারমিডিয়েটআউটপুটপথ) বিল্ডইনফোকস" লাইনস = "সিস্টেম% 3 বি অভ্যন্তরীণ স্থিতিশীল আংশিক বর্গ বিল্ডইনফো {পাবলিক স্ট্যাটিক লম্বা তারিখবিল্টিক্স = $ ([সিস্টেম.ডেটটাইম] :: অবটনো.টিক্স)% 3 বি পাবলিক স্ট্যাটিক ডেটটাইম টাইম বিল্ট => নতুন ডেটটাইম (ডেটবিল্টটিক্স, ডেটটাইমকাইন্ড.ইউটিসি)% 3B} "ওভাররাইট =" সত্য "/>
সফটলিয়ন

12

। নেট কোর প্রকল্পগুলির জন্য, আমি বিল্ডিং তারিখের সাথে অ্যাসেম্বলি কপিরাইট ক্ষেত্রটি আপডেট করার জন্য পোস্টলগার্কার্টের উত্তরটি অভিযোজিত করেছি।

সরাসরি সিএসপোজ সম্পাদনা করুন

নিম্নলিখিতটি সরাসরি PropertyGroupসিএসপিজে প্রথম যুক্ত করা যেতে পারে :

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

বিকল্প: ভিজ্যুয়াল স্টুডিও প্রকল্পের বৈশিষ্ট্য

বা ভিজ্যুয়াল স্টুডিওতে প্রকল্পের বৈশিষ্ট্যগুলির প্যাকেজ বিভাগে কপিরাইট ক্ষেত্রে সরাসরি অভ্যন্তরীণ অভিব্যক্তিটি পেস্ট করুন:

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

এটি কিছুটা বিভ্রান্তিকর হতে পারে, কারণ ভিজ্যুয়াল স্টুডিওটি এক্সপ্রেশনটি মূল্যায়ন করবে এবং উইন্ডোতে বর্তমান মানটি প্রদর্শন করবে, তবে এটি প্রকল্পের ফাইলটিকে দৃশ্যের পিছনে যথাযথভাবে আপডেট করবে।

ডিরেক্টরি. বিল্ড.প্রেসগুলির মাধ্যমে সমাধান-বিস্তৃত

আপনি আপনার সমাধানের মূলের <Copyright>একটি Directory.Build.propsফাইলের উপরের উপাদানটি প্লপ করতে পারেন এবং এটি প্রতিটি প্রকল্পের নিজস্ব কপিরাইট মান সরবরাহ করে না বলে ধরে নিয়ে ডিরেক্টরিতে সমস্ত প্রকল্পে এটি স্বয়ংক্রিয়ভাবে প্রয়োগ করে।

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

ডিরেক্টরি। বিল্ড.প্রপস : আপনার বিল্ডটি কাস্টমাইজ করুন

আউটপুট

উদাহরণ প্রকাশটি আপনাকে এর মতো একটি কপিরাইট দেবে:

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

উদ্ধার

আপনি উইন্ডোজ ফাইলের বৈশিষ্ট্যগুলি থেকে কপিরাইটের তথ্য দেখতে পারেন, বা রানটাইমে এটি দখল করতে পারেন:

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

Console.WriteLine(version.LegalCopyright);

11

উপরের পদ্ধতিটি ইতিমধ্যে প্রক্রিয়াটির মধ্যে মেশিনে ফাইলের চিত্র ব্যবহার করে (স্টোরেজ থেকে এটি পুনরায় পড়ার বিরোধিতা করে) প্রক্রিয়াটির মধ্যে লোড করা অ্যাসেমব্লিশগুলির জন্য টুইঙ্ক করা যেতে পারে :

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;
    }
}

এই এক কাজ করে মহান, এমনকি ফ্রেমওয়ার্ক 4.7 ব্যবহারের জন্য: Utils.GetLinkerDateTime (Assembly.GetExecutingAssembly (), নাল))
real_yggdrasil

দুর্দান্ত কাজ! ধন্যবাদ!
bobwki

10

উইন্ডোজ 8 / উইন্ডোজ ফোন 8-তে সংকলনের সময় পাওয়ার জন্য যে কেউ প্রয়োজন:

    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);
            }
        }
    }

উইন্ডোজ ফোন 7 এ সংকলনের সময় পাওয়ার জন্য যে কারও জন্য:

    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;
    }

দ্রষ্টব্য: সমস্ত ক্ষেত্রে আপনি একটি স্যান্ডবক্সে চলছেন, সুতরাং আপনি কেবল আপনার অ্যাপ্লিকেশন দিয়ে স্থাপন করা সমাবেশগুলির সংকলনের সময় পেতে সক্ষম হবেন। (যেমন এটি জিএসি-তে কোনও কিছুতেই কাজ করবে না)।


আপনি এখানে ডাব্লুপি 8.1 এ কীভাবে বিধানসভা পাবেন:var assembly = typeof (AnyTypeInYourAssembly).GetTypeInfo().Assembly;
আন্দ্রে ফ্রেডলার

আপনি যদি উভয় সিস্টেমে আপনার কোডটি চালাতে চান তবে? - উভয় প্ল্যাটফর্মের জন্য এই পদ্ধতিগুলির মধ্যে একটি প্রযোজ্য?
বিভিডিবি

10

2018 সালে উপরের সমাধানগুলির কয়েকটি আর কাজ করে না বা। নেট কোর দিয়ে কাজ করে না।

আমি নিম্নলিখিত পদ্ধতির ব্যবহার করি যা সহজ এবং আমার .NET কোর 2.0 প্রকল্পের জন্য কাজ করে।

প্রোপার্টি গ্রুপের ভিতরে আপনার .csproj এ নিম্নলিখিতগুলি যুক্ত করুন:

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

এটি একটি প্রপার্টি ফাংশন সংজ্ঞায়িত করে যা আপনি আপনার প্রাক বিল্ড কমান্ডটিতে অ্যাক্সেস করতে পারেন।

আপনার প্রাক-বিল্ডটি দেখতে এমন দেখাচ্ছে

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

বিল্ডটাইমস্ট্যাম্প.টেক্সট এর সম্পত্তি এম্বেডড রিসোর্সে সেট করুন।

এখন আপনি টাইম স্ট্যাম্পটি এভাবে পড়তে পারেন

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();
            }
        }
    }

ব্যাচ স্ক্রিপ্ট কমান্ড ব্যবহার করে প্রাক-বিল্ড ইভেন্টগুলি থেকে কেবল বিল্ডটাইমস্ট্যাম্প.টিএসটি উত্পাদন করাও কাজ করে। মনে রাখবেন যে আপনি সেখানে ভুল করেছেন: আপনার লক্ষ্যটি উদ্ধৃতিতে (যেমন "$(ProjectDir)BuildTimeStamp.txt") ঘিরে রাখা উচিত বা ফোল্ডারের নামগুলিতে শূন্যস্থান থাকলে তা ভেঙে যাবে।
নাইয়ারগডস

সংস্কৃতি আক্রমণকারী সময় ফর্ম্যাটটি ব্যবহার করে তা বোধগম্য হতে পারে। এটি পছন্দ করুন: এর $([System.DateTime]::Now.tostring("MM/dd/yyyy HH:mm:ss"))পরিবর্তে$([System.DateTime]::Now)
ইভান কোচুরকিন

9

এখানে আলোচিত বিকল্পটি হ'ল এসেম্বলিআইএনফো-সি-তে আপনার নিজস্ব ডেটা toোকানো, "এসেম্বলি ইনফরমেশনাল ভার্শন" ক্ষেত্রটি যথাযথ বলে মনে হচ্ছে - আমাদের বেশ কয়েকটি প্রকল্প রয়েছে যেখানে আমরা বিল্ড স্টেপ হিসাবে অনুরূপ কিছু করছিলাম (তবে আমি সম্পূর্ণরূপে সন্তুষ্ট নই যেভাবে কাজ করে তা সত্যিই আমরা যা পেয়েছি তা পুনরুত্পাদন করতে চাই না)।

কোডেপ্রজেক্ট সম্পর্কিত বিষয়ে একটি নিবন্ধ রয়েছে: http://www.codeproject.com/KB/dotnet/Customizing_csproj_files.aspx


6

আমার একটি সার্বজনীন সমাধানের দরকার ছিল যা কোনও প্ল্যাটফর্মের (আইওএস, অ্যান্ড্রয়েড এবং উইন্ডোজ।) নেটস স্ট্যান্ডার্ড প্রকল্পের সাথে কাজ করে, এটি সম্পাদন করার জন্য, আমি পাওয়ারশেল স্ক্রিপ্টের মাধ্যমে স্বয়ংক্রিয়ভাবে একটি সিএস ফাইল তৈরি করার সিদ্ধান্ত নিয়েছি। এখানে পাওয়ারশেল লিপিটি রয়েছে:

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

জেনবিল্ডডেট.পিএস 1 হিসাবে পাওয়ারস্ক্রিপ্ট ফাইলটি সংরক্ষণ করুন এবং এটি আপনার প্রকল্প যুক্ত করুন। অবশেষে, আপনার প্রাক-বিল্ড ইভেন্টে নিম্নলিখিত লাইনটি যুক্ত করুন:

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

আপনার প্রকল্পে বিল্ডডেট.সি.গুলি অন্তর্ভুক্ত রয়েছে তা নিশ্চিত করুন। কোনও ওএসে চ্যাম্পের মতো কাজ করে!


1
আপনি এসভিএন কমান্ড লাইন সরঞ্জামটি ব্যবহার করে এসভিএন সংশোধন নম্বর পেতে এটি ব্যবহার করতে পারেন। আমি এর সাথে এরকম কিছু করেছি।
ব্যবহারকারী169771

5

আমি শুধু করি:

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

1
মজার বিষয় হল, যদি ডিবাগ থেকে চালানো হয় তবে 'সত্য' তারিখটি গেটলাস্টঅ্যাক্সেসটাইম ()
14 ই

4

আপনি এই প্রকল্পটি ব্যবহার করতে পারেন: https://github.com/dwcullop/BuildInfo

এটি বিল্ড ডেটের টাইমস্ট্যাম্পটি স্বয়ংক্রিয় করতে টি 4 -কে সহায়তা দেয়। আপনি যদি এই ধরণের জিনিসটিতে থাকেন তবে এমন একাধিক সংস্করণ (বিভিন্ন শাখা) রয়েছে যা আপনাকে বর্তমানে পরীক্ষিত শাখার গিট হ্যাশ সরবরাহ করে।

প্রকাশ: আমি মডিউলটি লিখেছি।


3

আলাদা, পিসিএল-বন্ধুত্বপূর্ণ পদ্ধতিটি হ'ল এমএসবিল্ড ইনলাইন টাস্কটি বিল্ড সময়কে স্ট্রিংয়ের পরিবর্তে প্রয়োগ করতে হবে যা অ্যাপ্লিকেশনটিতে কোনও সম্পত্তি দ্বারা ফিরে আসে। আমরা এই অ্যাপ্লিকেশনটি সফলভাবে একটি অ্যাপে ব্যবহার করছি যা Xamarin.forms, Xamarin.Android এবং Xamarin.iOS প্রকল্প রয়েছে।

সম্পাদনা করুন:

সমস্ত লজিককে SetBuildDate.targetsফাইলে সরানো এবং Regexসরল স্ট্রিংয়ের পরিবর্তে রিপ্লেসমেন্ট ব্যবহার করে সরলীকৃত করা যাতে ফাইলটি "রিসেট" ছাড়াই প্রতিটি বিল্ডের মাধ্যমে সংশোধন করা যায়।

এমএসবিল্ড ইনলাইন টাস্ক সংজ্ঞা (উদাহরণস্বরূপ জ্যামারিন.ফর্মের প্রকল্পে স্থানীয় একটি সেটবিল্ডডেট.টরজেটস ফাইলটিতে সংরক্ষিত):

<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>

জ্যামারিনে উপরের ইনলাইন টাস্কটি প্রবর্তন করা হচ্ছে Before

  <!-- 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>

FilePathসম্পত্তি একটি সেট করা হয় BuildMetadata.csXamarin.Forms প্রকল্পের যে একটি স্ট্রিং সম্পত্তি সঙ্গে একটি সহজ বর্গ থাকে ফাইল BuildDate, যা বিল্ড সময় প্রতিস্থাপিত হবে:

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

BuildMetadata.csপ্রকল্পে এই ফাইল যুক্ত করুন । এটি প্রতিটি বিল্ড দ্বারা সংশোধন করা হবে, তবে এমন পদ্ধতিতে যা পুনরাবৃত্ত বিল্ডগুলির (পুনরাবৃত্তি প্রতিস্থাপন) অনুমতি দেয়, যাতে আপনি এটি পছন্দসই হিসাবে উত্স নিয়ন্ত্রণে অন্তর্ভুক্ত বা বাদ দিতে পারেন।


2

আপনি বর্তমান তারিখের সময় সহ আপনার টার্গেট ডিরেক্টরিতে একটি পাঠ্য ফাইল লিখতে একটি প্রকল্প পোস্ট-বিল্ড ইভেন্ট ব্যবহার করতে পারেন। তারপরে আপনি রান-টাইমে মানটি পড়তে পারেন। এটি একটু হ্যাকি, তবে এটি কাজ করা উচিত।



2

ঝনের কাছ থেকে "নতুন উপায়" উত্তর সম্পর্কে একটি ছোট আপডেট।

ASP.NET/MVC এর সাথে কাজ করার সময় আপনাকে কোডবেস স্ট্রিংটি ব্যবহার না করে পাথ তৈরি করতে হবে

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

1

আপনি বিল্ড প্রক্রিয়াতে একটি অতিরিক্ত পদক্ষেপ চালু করতে পারেন যা কোনও ফাইলের জন্য একটি তারিখ স্ট্যাম্প লেখায় যা প্রদর্শিত হতে পারে।

প্রকল্পের বৈশিষ্ট্য ট্যাবে বিল্ড ইভেন্ট ট্যাবটি দেখুন। একটি প্রাক বা পোস্ট বিল্ড কমান্ড কার্যকর করতে একটি বিকল্প রয়েছে।


1

আমি আবদুর রহিমের পরামর্শ ব্যবহার করেছি। যাইহোক, এটি একটি অদ্ভুত সময় বিন্যাস বলে মনে হয়েছিল এবং বিল্ডের তারিখের অংশ হিসাবে দিনের জন্য সংক্ষিপ্তসারও যুক্ত করেছে; উদাহরণ: সান 12/24/2017 13: 21: 05.43। আমার কেবলমাত্র তারিখের দরকার ছিল তাই আমাকে স্ট্রিং ব্যবহার করে বাকীটি দূর করতে হবে।

echo %date% %time% > "$(ProjectDir)\Resources\BuildDate.txt"প্রাক-বিল্ড ইভেন্টে যোগ করার পরে , আমি কেবল নিম্নলিখিতটি করেছি:

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

এখানে সুসংবাদটি এটি কাজ করেছিল it


খুব সহজ সমাধান। আমি এটা পছন্দ করি. এবং যদি ফর্ম্যাটটি বিরক্ত হয় তবে কমান্ড লাইন থেকে আরও ভাল ফর্ম্যাট পাওয়ার উপায় রয়েছে ।
নাইয়ারগডস

0

যদি এটি একটি উইন্ডোজ অ্যাপ হয় তবে আপনি কেবল অ্যাপ্লিকেশন সম্পাদনযোগ্য পাথ ব্যবহার করতে পারেন: নতুন System.IO.FileInfo (অ্যাপ্লিকেশন। এক্সেক্সিউটেবলপথ) ast


2
ইতিমধ্যে এবং এটি ব্যবহার করে উত্তর দিন, এবং ঠিক বুলেটপ্রুফও নয়।
ক্র্যাশমাস্টার

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.