يرتبط العمل في فريق إدارة التهيئة بضمان وظائف عمليات الإنشاء - تجميع منتجات الشركة ، والتحقق الأولي من التعليمات البرمجية ، والتحليل الإحصائي ، والتوثيق والمزيد. بالإضافة إلى ذلك ، نحن نعمل باستمرار على تحسين العمليات المختلفة ، وما هو رائع ، نحن عمليًا أحرارًا في اختيار أدوات لهذا العمل المثير للاهتمام. بعد ذلك ، سأتحدث بالتفصيل عن الكيفية التي ، من خلال امتلاك مستوى مختلف فقط من المعرفة في C # و C ++ ، قمت بتقديم خدمة WCF وظيفية للعمل مع قوائم انتظار الإصلاح. ولماذا قررت أنه مهم للغاية.

الأتمتة مرة واحدة أو 117 صفحة تعليمات مرارا وتكرارا
انحراف صغير حتى تفهم لماذا أنا قلق جدًا بشأن أتمتة العمليات وتحسينها.
قبل شركة Veeam ، عملت لدى شركة دولية كبيرة - كنت رئيس فريق فريق إدارة التهيئة ، وشاركت في بناء التطبيق ونشره لاختبار البيئات. تم تطوير البرنامج بنجاح ، وأضيفت وظائف جديدة ، وكتبت الوثائق ، وتناولت الدعم أيضًا. لكنني كنت متفاجئًا دائمًا من السبب في أن مثل هذا البرنامج الجاد لا يحتوي على نظام تكوين معلمات عادي ، حيث كان هناك العديد من العشرات ، إن لم يكن المئات.
لقد تحدثت مع المطورين حول هذا الموضوع وتلقيت إجابة - لم يدفع العميل مقابل هذه الميزة ، ولم يوافق على تكلفتها ، لذلك لم يتم تنفيذ الميزة. ولكن في الواقع ، عانت وكالة ضمان الجودة ، وقد تأثرنا بشكل مباشر ، نحن فريق SM. تم تنفيذ تكوين البرنامج وتكوينه الأولي من خلال العديد من ملفات التكوين ، كل منها يحتوي على عشرات المعلمات.
كل بناء جديد ، قام كل إصدار جديد بتغييراته على التكوين. تعذر استخدام ملفات التكوين القديمة ، لأنها غالبًا ما تكون غير متوافقة مع الإصدار الجديد. ونتيجة لذلك ، في كل مرة قبل نشر البنية للاختبار أو على آلات عمل المختبرين ، كان عليك قضاء الكثير من الوقت في تكوين البرنامج ، وإصلاح أخطاء التكوين ، والاستشارات المستمرة مع المطورين حول موضوع "لماذا لا يعمل مثل هذا الآن؟" بشكل عام ، كانت العملية غير محسنة للغاية.
للمساعدة في الإعداد ، كان لدينا تعليمات من 117 صفحة بحجم الخط Arial 9. كان علينا أن نقرأ بعناية فائقة. في بعض الأحيان بدا أنه كان من الأسهل بناء نواة لينكس بعيون مغلقة على جهاز كمبيوتر مغلق.
أصبح من الواضح أنه لا يمكن تجنب التحسين هنا. لقد بدأت في كتابة أداة التكوين الخاصة بي لبرنامج يدعم الملفات الشخصية والقدرة على تغيير المعلمات في بضع ثوانٍ ، لكن المشروع وصل إلى مرحلته الأخيرة ، وتحولت إلى العمل في مشروع آخر. في ذلك ، قمنا بتحليل العديد من السجلات لنظام فوترة واحد للأخطاء المحتملة في جانب الخادم. إن أتمتة العديد من الإجراءات باستخدام لغة Python أنقذني من الكم الهائل من العمل اليدوي. لقد أحببت حقًا لغة البرمجة النصية هذه ، وبمساعدتها قمنا بعمل مجموعة من نصوص التحليل لجميع المناسبات. تلك المهام التي تتطلب عدة أيام من التحليل المدروس وفقًا لـ "ملف القطط 123 | grep something_special "، استغرق الأمر بضع دقائق. كل شئ كان رائعا ... وممل.
إدارة التكوين - مغامرات جديدة
جئت إلى Veeam كفريق لفريق CM صغير. تتطلب العديد من العمليات الأتمتة والتحسين وإعادة التفكير. ولكن كانت هناك حرية كاملة في اختيار الأدوات! يجب على المطور استخدام لغة برمجة محددة ، ونمط التعليمات البرمجية ، ومجموعة محددة من المكتبات. SM ، من ناحية أخرى ، قد لا يستخدم أي شيء على الإطلاق لحل المهمة ، إذا كان لديه ما يكفي من الوقت والشجاعة والصبر لذلك.
تقوم Veeam ، مثل العديد من الشركات الأخرى ، بمهمة تجميع تحديثات المنتجات. تضمن التحديث مئات الملفات ، وكان من الضروري تغيير الملفات التي تغيرت فقط ، مع مراعاة عدد من الشروط الهامة. للقيام بذلك ، أنشأنا برنامجًا نصيًا قويًا يمكن أن يتسلق إلى TFS ، حدد الملفات ، وفرزها في المجلدات الضرورية. تم استكمال وظيفة البرنامج النصي ، وأصبح ضخمًا بشكل تدريجي ، واستغرق الأمر الكثير من الوقت لتصحيحه واستمرار بعض العكازات للتشغيل. كان من الملح القيام بشيء ما.
ماذا أراد المطورون
فيما يلي الشكاوى الرئيسية:
- غير قادر على انتظار إصلاحات قائمة الانتظار. يجب عليك التحقق باستمرار من صفحة الويب لمعرفة متى ينتهي تجميع الإصلاح الخاص ويمكنك البدء في بناء الخاصة بك.
- لا توجد إشعارات حول الأخطاء - لرؤية الأخطاء في واجهة المستخدم الرسومية لتطبيق التجميع ، عليك الذهاب إلى الخادم ومشاهدة الكثير من السجلات الضخمة.
- لا يوجد تاريخ بناء للإصلاحات الخاصة.
كان من الضروري التعامل مع هذه المهام وإضافة أشياء صغيرة ممتعة لن يرفضها المطورون.
ما هي الإصلاحات الخاصة
إصلاح خاص في سياق تطويرنا هو مجموعة معينة من التصحيحات في التعليمات البرمجية ، والتي يتم تخزينها في رفوف خادم Foundation Team لفرع الإصدار. توضيح قليل لأولئك الذين ليسوا على دراية كبيرة بمصطلحات TFS:
- الاختيار - مجموعة من التغييرات المحلية في التعليمات البرمجية المصدر ، والتي يتم إجراؤها على التعليمات البرمجية المخزنة في TFS. يمكن التحقق من هذا الاختيار باستخدام عمليات التكامل المستمر / عمليات تسجيل الدخول المسورة التي تسمح لك بتخطي الرمز الصحيح فقط ورفض جميع عمليات التحقق التي تنتهك جمع المشروع النهائي.
- shelveset - مجموعة من التغييرات المحلية في شفرة المصدر لا يتم إجراؤها مباشرة على شفرة المصدر الموجودة في TFS ، ولكن يمكن الوصول إليها باسمها. يمكن نشر shellset على الجهاز المحلي للمطور أو نظام البناء للعمل مع التعليمات البرمجية المعدلة التي لم يتم تضمينها في TFS. أيضا ، يمكن إضافة القشرة إلى TFS كاختبار بعد النشر ، عند اكتمال جميع العمل معها. على سبيل المثال ، يعمل مدقق البوابة بهذه الطريقة. أولاً ، يتم فحص القشرة الموجودة في الباني. إذا نجح الفحص ، تتحول shellset إلى شيك!
إليك ما يفعله منشئ الإصلاح الخاص:
- الحصول على اسم (رقم) مجموعة القشرة ونشرها في أداة إنشاء الإصلاحات الخاصة. ونتيجة لذلك ، نحصل على الكود المصدري لمنتج الإصدار بالإضافة إلى التغييرات / الإصلاحات من shellset. فرع الإصدار يبقى دون تغيير.
- في منشئ إصلاح خاص ، يتم تنفيذ مشروع أو سلسلة من المشاريع التي تم إجراء إصلاح خاص لها.
- يتم نسخ مجموعة الملفات الثنائية المترجمة إلى دليل شبكة الإصلاح الخاص. يحتوي الكتالوج على اسم shellset ، وهو عبارة عن سلسلة من الأرقام.
- يتم استعادة التعليمات البرمجية المصدر في منشئ الإصلاح الخاص إلى شكلها الأصلي.
من أجل راحة المطورين ، يتم استخدام واجهة الويب حيث يمكنك تحديد المنتج الذي تريد جمع إصلاح خاص له ، وتحديد رقم shell ، وتحديد المشاريع التي تريد جمع إصلاح خاص لها ، وإضافة تجميع الإصلاح إلى قائمة الانتظار. تعرض لقطة الشاشة أدناه إصدار العمل النهائي من تطبيق الويب ، والذي يعرض الحالة الحالية للإنشاء ، وقائمة الإصلاحات الخاصة وتاريخ تجميعها. في مثالنا ، يتم النظر فقط في قائمة الانتظار لتجميع الإصلاحات الخاصة.
ما كان لي
- أداة إنشاء إصلاح خاصة جمعت إصلاحات خاصة من قذيفة TFS من خلال تشغيل تطبيق وحدة تحكم بمعلمات سطر الأوامر المعطاة.
- Veeam.Builder.Agent - خدمة WCF مكتوبة بواسطة Veeam تقوم بتشغيل التطبيق مع المعلمات في وضع وحدة التحكم تحت المستخدم الحالي وإرجاع الحالة الحالية للتطبيق.
- خدمة ويب IIS هو تطبيق في نماذج Windows يسمح لك بإدخال اسم shellset والمعلمات المحددة وبدء عملية بناء إصلاح خاص.
- معرفة البرمجة الضحلة جدًا هي C ++ ، القليل من C # في الجامعة ، وكتابة تطبيقات صغيرة للأتمتة ، وإضافة وظائف جديدة لعمليات البناء الحالية وكهواية.
- الزملاء من ذوي الخبرة و Google ومقالات MSDN الهندية هي مصادر إجابات لجميع الأسئلة.
ماذا سنفعل
في هذه المقالة ، سأخبرنا كيف نفذت قائمة انتظار تجميع الإصلاحات وإطلاقها المتسلسل في أداة الإنشاء. فيما يلي أجزاء الحل:
- QBuilder.AppQueue هي خدمة WCF الخاصة بي التي توفر العمل مع قائمة انتظار البناء وتستدعي خدمة Veeam.Builder.Agent لتشغيل برنامج الإنشاء.
- dummybuild.exe هو برنامج كعب يستخدم للتصحيح وكمساعدة بصرية. مطلوب لتصور المعلمات المحولة.
- QBuilder.AppLauncher - خدمة WCF التي تقوم بتشغيل التطبيقات في وحدة تحكم المستخدم الحالي وتعمل في الوضع التفاعلي. هذا هو نظير مبسط بشكل كبير من Veeam.Builder.Agent برنامج مكتوب خصيصًا لهذه المقالة. يمكن أن تعمل الخدمة الأصلية كخدمة windows وتشغيل التطبيقات في وحدة التحكم ، الأمر الذي يتطلب عملًا إضافيًا مع Windows API. لوصف جميع الحيل ، ستكون هناك حاجة إلى مقال منفصل. يعمل المثال الخاص بي كخدمة وحدة تحكم تفاعلية بسيطة ويستخدم وظيفتين - بدء عملية باستخدام المعلمات والتحقق من حالتها.
بالإضافة إلى ذلك ، قمنا بإنشاء تطبيق ويب ملائم جديد يمكنه العمل مع العديد من المنشئين والاحتفاظ بسجلات الأحداث. حتى لا نفرط في تحميل المقالة ، لن نتحدث عنها بالتفصيل أيضًا. بالإضافة إلى ذلك ، لا تصف هذه المقالة العمل مع TFS ، مع تاريخ التخزين للإصلاحات الخاصة التي تم جمعها والعديد من الفئات والوظائف المساعدة.

إنشاء خدمات WCF
هناك العديد من المقالات التفصيلية التي تصف إنشاء خدمات WCF. أحببت
المواد من موقع Microsoft أكثر من أي شيء آخر. أخذتها كأساس للتنمية. لتسهيل معرفتي بالمشروع ، قمت أيضًا بتحديد
الثنائيات . دعنا نبدأ!
قم بإنشاء خدمة QBuilder.AppLauncher
هنا سيكون لدينا فقط القرص الأساسي للخدمة. في هذه المرحلة ، نحتاج إلى التأكد من أن الخدمة تبدأ وتعمل. بالإضافة إلى ذلك ، فإن الرمز مطابق لكل من QBuilder.AppLauncher و QBuilder.AppQueue ، لذا يجب تكرار هذه العملية مرتين.
- قم بإنشاء تطبيق وحدة تحكم جديد يسمى QBuilder.AppLauncher
- إعادة تسمية Program.cs إلى Service.cs
- إعادة تسمية مساحة الاسم إلى QBuilder.AppLauncher
- أضف المراجع التالية إلى المشروع:
أ. System.ServiceModel.dll
ب. System.ServiceProcess.dll
ج. System.Configuration.Install.dll
- أضف التعريفات التالية إلى Service.cs
using System.ComponentModel; using System.ServiceModel; using System.ServiceProcess; using System.Configuration; using System.Configuration.Install;
في عملية مزيد من التجميع ، ستكون هناك حاجة أيضًا إلى التعاريف التالية:
using System.Reflection; using System.Xml.Linq; using System.Xml.XPath;
- نحدد واجهة IAppLauncher ونضيف وظائف للعمل مع قائمة الانتظار:
- في فئة AppLauncherService ، نقوم بتطبيق الواجهة ووظيفة الاختبار TestConnection:
public class AppLauncherService : IAppLauncher { public bool TestConnection() { return true; } }
- إنشاء فئة AppLauncherWindowsService جديدة ترث فئة ServiceBase. إضافة serviceHost المتغير المحلي - رابط إلى ServiceHost. نحدد الأسلوب الرئيسي ، الذي يستدعي ServiceBase.Run (AppLauncherWindowsService () الجديد):
public class AppLauncherWindowsService : ServiceBase { public ServiceHost serviceHost = null; public AppLauncherWindowsService() {
- تجاوز دالة OnStart () التي تنشئ مثيل ServiceHost الجديد:
protected override void OnStart(string[] args) { if (serviceHost != null) { serviceHost.Close(); }
- تجاوز وظيفة onStop التي تغلق مثيل ServiceHost:
protected override void OnStop() { if (serviceHost != null) { serviceHost.Close(); serviceHost = null; } } }
- قم بإنشاء فئة ProjectInstaller جديدة ، موروثة من Installer وتم تمييزها بـ RunInstallerAttribute ، والتي تم تعيينها على True. يسمح لك هذا بتثبيت خدمة Windows باستخدام برنامج installutil.exe:
[RunInstaller(true)] public class ProjectInstaller : Installer { private ServiceProcessInstaller process; private ServiceInstaller service; public ProjectInstaller() { process = new ServiceProcessInstaller(); process.Account = ServiceAccount.LocalSystem; service = new ServiceInstaller(); service.ServiceName = "QBuilder App Launcher"; Installers.Add(process); Installers.Add(service); } }
- قم بتغيير محتويات ملف app.config:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="QBuilder.AppLauncher.AppLauncherService" behaviorConfiguration="AppLauncherServiceBehavior"> <host> <baseAddresses> <add baseAddress="http://localhost:8000/QBuilderAppLauncher/service"/> </baseAddresses> </host> <endpoint address="" binding="wsHttpBinding" contract="QBuilder.AppLauncher.IAppLauncher" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <behaviors> <serviceBehaviors> <behavior name="AppLauncherServiceBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="False"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
التحقق من صلاحية الخدمة
- نقوم بتجميع الخدمة.
- قم بتثبيته باستخدام الأمر installutil.exe
1) انتقل إلى المجلد حيث يوجد ملف الخدمة المترجمة
2) قم بتشغيل أمر التثبيت:
C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ InstallUtil.exe - ننتقل إلى الأداة الإضافية services.msc ، ونتحقق من توفر خدمة QBuilder App Launcher وتشغيلها.
- نتحقق من صلاحية الخدمة باستخدام برنامج WcfTestClient.exe ، المضمن في VisualStudio:
1) قم بتشغيل WcfTestClient
2) أضف عنوان الخدمة: http: // localhost: 8000 / QBuilderAppLauncher / service
3) تفتح واجهة الخدمة:

4) نسمي وظيفة الاختبار TestConnection ، وتحقق من أن كل شيء يعمل وأن الوظيفة ترجع قيمة:

الآن بعد أن أصبح لدينا قرص عمل للخدمة ، نضيف الوظائف التي نحتاجها.
لماذا أحتاج إلى وظيفة اختبار لا تفعل شيئًا
عندما بدأت في تعلم كيفية كتابة خدمة WCF من الصفر ، قرأت مجموعة من المقالات حول هذا الموضوع. على الطاولة كان لدي عشرات أو ورقتان مطبوعتان يمكنني معرفة ماذا وكيف. أعترف ، لم أتمكن من بدء الخدمة على الفور. لقد قضيت الكثير من الوقت واستنتجت أنه من المهم حقًا إنشاء قرص خدمة. مع ذلك سوف تتأكد من أن كل شيء يعمل ويمكنك البدء في تنفيذ الوظائف الضرورية. قد يبدو هذا النهج مسرفًا ، لكنه سيجعل الحياة أسهل إذا لم تعمل مجموعة من التعليمات البرمجية المكتوبة كما يجب.
أضف القدرة على التشغيل من وحدة التحكم
العودة إلى التطبيق. في مرحلة التصحيح وفي عدد من الحالات الأخرى ، من الضروري بدء الخدمة في شكل تطبيق وحدة تحكم دون التسجيل كخدمة. هذه ميزة مفيدة للغاية تسمح لك بالاستغناء عن الاستخدام المضجر للمصححات. في هذا الوضع تعمل خدمة QBuilder.AppLauncher. إليك كيفية تنفيذها:
- أضف الإجراء RunInteractive إلى فئة AppLauncherWindowsService ، التي توفر الخدمة في وضع وحدة التحكم:
static void RunInteractive(ServiceBase[] services) { Console.WriteLine("Service is running in interactive mode."); Console.WriteLine(); var start = typeof(ServiceBase).GetMethod("OnStart", BindingFlags.Instance | BindingFlags.NonPublic); foreach (var service in services) { Console.Write("Starting {0}...", service.ServiceName); start.Invoke(service, new object[] { new string[] { } }); Console.Write("Started {0}", service.ServiceName); } Console.WriteLine(); Console.WriteLine("Press any key to stop the services and end the process..."); Console.ReadKey(); Console.WriteLine(); var stop = typeof(ServiceBase).GetMethod("OnStop", BindingFlags.Instance | BindingFlags.NonPublic); foreach (var service in services) { Console.Write("Stopping {0}...", service.ServiceName); stop.Invoke(service, null); Console.WriteLine("Stopped {0}", service.ServiceName); } Console.WriteLine("All services stopped."); }
- نقوم بإجراء تغييرات على الإجراء الرئيسي - إضافة معالجة معلمات سطر الأوامر. مع خيار / console وجلسة مستخدم نشطة مفتوحة ، نطلق البرنامج في الوضع التفاعلي. خلاف ذلك ، نطلقه كخدمة.
public static void Main(string[] args) { var services = new ServiceBase[] { new AppLauncherWindowsService() };
أضف وظائف لتشغيل التطبيق والتحقق من حالته
الخدمة بسيطة للغاية ، ولا توجد فحوصات إضافية. يمكنه تشغيل التطبيقات فقط في إصدار وحدة التحكم وباسم المسؤول. يمكنه أيضًا إطلاقها كخدمة - ولكنك لن تراها ، وستدور في الخلفية ولا يمكنك رؤيتها إلا من خلال إدارة المهام. يمكن تنفيذ كل هذا ، ولكن هذا موضوع لمقال منفصل. الشيء الرئيسي بالنسبة لنا هنا هو مثال عملي واضح.
- أولاً ، أضف appProcess للمتغير العام ، الذي يخزن العملية الجارية حاليًا.
public class AppLauncherService : IAppLauncher
:
public class AppLauncherService : IAppLauncher { Process appProcess;
- قم بإضافة دالة إلى نفس الفئة التي تتحقق من حالة العملية الجارية:
public bool IsStarted() { if (appProcess!=null) { if (appProcess.HasExited) { return false; } else { return true; } } else { return false; } }
تعرض الدالة خطأ إذا كانت العملية غير موجودة أو لم تكن قيد التشغيل بالفعل ، وصحيح إذا كانت العملية نشطة.
- أضف الوظيفة لإطلاق التطبيق:
public bool Start(string fileName, string arguments, string workingDirectory, string domain, string userName, int timeoutInMinutes) { ProcessStartInfo processStartInfo = new ProcessStartInfo(); processStartInfo.FileName = fileName; processStartInfo.Arguments = arguments; processStartInfo.Domain = domain; processStartInfo.UserName = userName; processStartInfo.CreateNoWindow = false; processStartInfo.UseShellExecute = false; try { if (appProcess!=null) { if (!appProcess.HasExited) { Console.WriteLine("Process is still running. Waiting..."); return false; } } } catch (Exception ex) { Console.WriteLine("Error while checking process: {0}", ex); } try { appProcess = new Process(); appProcess.StartInfo = processStartInfo; appProcess.Start(); } catch (Exception ex) { Console.WriteLine("Error while starting process: {0}",ex); } return true; }
تقوم الوظيفة بتشغيل أي تطبيق يحتوي على معلمات. لا يتم استخدام معلمات المجال واسم المستخدم في هذا السياق وقد تكون فارغة ، نظرًا لأن الخدمة تبدأ التطبيق من جلسة وحدة التحكم بحقوق المسؤول.
إطلاق خدمة QBuilder.AppLauncher
كما هو موضح سابقًا ، تعمل هذه الخدمة بشكل تفاعلي وتسمح لك بتشغيل التطبيقات في الجلسة الحالية للمستخدم ، والتحقق مما إذا كانت العملية قيد التشغيل أو مكتملة بالفعل.
- للعمل ، تحتاج إلى ملفات QBuilder.AppLauncher.exe و QBuilder.AppLauncher.exe.config ، الموجودة في الأرشيف على الرابط أعلاه. يوجد أيضًا رمز المصدر لهذا التطبيق للتجميع الذاتي.
- نبدأ الخدمة مع حقوق المسؤول.
- سيتم فتح نافذة وحدة التحكم الخاصة بالخدمة:

عند إغلاق أي ضغطة مفتاح في وحدة التحكم بالخدمة ، كن حذرًا.
- للاختبارات ، قم بتشغيل wcftestclient.exe ، والذي تم تضمينه في Visual Studio. نتحقق من توفر الخدمة على http: // localhost: 8000 / QBuilderAppLauncher / service أو نفتح الرابط في Internet Explorer.
إذا كان كل شيء يعمل ، فانتقل إلى الخطوة التالية.
إنشاء خدمة QBuilder.AppQueue
والآن دعنا ننتقل إلى أهم خدمة ، والتي تمت كتابة المقالة بأكملها من أجلها! نكرر تسلسل الإجراءات في الفصل "إنشاء خدمة QBuilder.AppLauncher" وفي الفصل "إضافة التشغيل من وحدة التحكم" ، واستبدال AppLauncher بـ AppQueue في التعليمات البرمجية.
قم بإضافة ارتباط لخدمة QBuilder.AppLauncher للاستخدام في خدمة قائمة الانتظار
- في مستكشف الحلول لمشروعنا ، حدد إضافة مرجع خدمة وحدد العنوان: localhost : 8000 / QBuilderAppLauncher / service
- حدد مساحة الاسم: AppLauncherService.
الآن يمكننا الوصول إلى واجهة الخدمة من برنامجنا.
إنشاء هيكل لتخزين عناصر قائمة الانتظار
في مساحة اسم QBuilder.AppQueue ، أضف فئة QBuildRecord:
تنفيذ فئة قائمة انتظار CXmlQueue
نضيف فئة CXmlQueue.cs إلى مشروعنا ، حيث سيتم تحديد عدد من الإجراءات للعمل مع ملف XML:
- CXmlQueue منشئ - يعين الاسم الأولي للملف حيث يتم تخزين قائمة الانتظار.
- SetCurrentBuild - يكتب معلومات حول البناء الحالي إلى ملف XML لقائمة الانتظار. هذا عنصر غير موجود في قائمة الانتظار ؛ فهو يخزن معلومات حول العملية الجارية حاليًا. قد تكون فارغة.
- GetCurrentBuild - احصل على معلمات عملية قيد التشغيل من ملف XML في قائمة الانتظار. قد تكون فارغة.
- ClearCurrentBuild - يؤدي هذا إلى مسح عنصر buildbuild في ملف XML الخاص بقائمة الانتظار إذا تم إنهاء العملية.
- OpenXmlQueue - وظيفة لفتح ملف XML حيث يتم تخزين قائمة الانتظار. إذا كان الملف مفقودًا ، يتم إنشاء ملف جديد.
- GetLastQueueBuildNumber - لكل بناء في قائمة الانتظار الرقم التسلسلي الفريد الخاص به. تُرجع هذه الدالة قيمتها ، التي يتم تخزينها في السمة الجذر.
- IncrementLastQueueBuildNumber - يزيد من قيمة رقم البناء عند وضع بناء جديد في قائمة الانتظار.
- GetCurrentQueue - إرجاع قائمة بعناصر QBuildRecord من ملف XML لقائمة الانتظار.
في الكود الأصلي ، تم وضع كل هذه الإجراءات في الفصل الرئيسي ، ولكن للتوضيح ، قمت بعمل فئة منفصلة CXmlQueue. يتم إنشاء الفئة في مساحة الاسم QBuilder.AppQueue ، تحقق من تحديد جميع التعريفات اللازمة:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml.Linq; using System.Xml.XPath; using System.IO; namespace QBuilder.AppQueue { . . . }
لذا ، نحن ننفذ. فئة CXmlQueue نفسها:
قائمة الانتظار في ملف XML هي كما يلي:
<?xml version="1.0" encoding="utf-8"?> <BuildsQueue BuildNumber="23"> <build BuildId="14" IssueId="26086" IssueName="TestIssueName" StartDate="2018-06-13T16:49:50.515238+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="15" IssueId="59559" IssueName="TestIssueName" StartDate="2018-06-13T16:49:50.6880927+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="16" IssueId="45275" IssueName="TestIssueName" StartDate="2018-06-13T16:49:50.859937+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="17" IssueId="30990" IssueName="TestIssueName" StartDate="2018-06-13T16:49:51.0321322+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="18" IssueId="16706" IssueName="TestIssueName" StartDate="2018-06-13T16:49:51.2009904+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="19" IssueId="66540" IssueName="TestIssueName" StartDate="2018-06-13T16:49:51.3581274+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="20" IssueId="68618" IssueName="TestIssueName" StartDate="2018-06-13T16:49:51.5087854+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="21" IssueId="18453" IssueName="TestIssueName" StartDate="2018-06-13T16:49:51.6713477+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="22" IssueId="68288" IssueName="TestIssueName" StartDate="2018-06-13T16:49:51.8277942+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="23" IssueId="89884" IssueName="TestIssueName" StartDate="2018-06-13T16:49:52.0151294+02:00" Build_CSharp="true" Build_Cpp="true" /> <currentbuild BuildId="13" IssueId="4491" StartDate="13.06.2018 16:53:16" /> </BuildsQueue>
قم بإنشاء ملف BuildQueue.xml بهذا المحتوى ووضعه في الدليل بالملف القابل للتنفيذ. سيتم استخدام هذا الملف في تصحيح الاختبار لمطابقة نتائج الاختبار.
إضافة فئة AuxFunctions
في هذه الفئة ، أضع وظائف المساعد. يوجد الآن وظيفة واحدة فقط ، FormatParameters ، والتي تقوم بتنسيق المعلمات لتمريرها إلى تطبيق وحدة التحكم لبدء التشغيل. قائمة ملف AuxFunctions.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace QBuilder.AppQueue { class AuxFunctions {
أضف ميزات جديدة إلى واجهة الخدمة
يمكن حذف وظيفة الاختبار TestConnection في هذه المرحلة. لتنفيذ عمل قائمة الانتظار ، كنت بحاجة إلى مجموعة الوظائف التالية:
- PushBuild (QBuildRecord): باطل. هذه وظيفة تضيف قيمة جديدة لملف XML لقائمة الانتظار مع معلمات QBuildRecord
- TestPushBuild (): باطل. هذه وظيفة اختبار تضيف بيانات الاختبار إلى قائمة انتظار في ملف XML.
- PullBuild: QBuildRecord. هذه وظيفة تقوم باسترجاع قيمة QBuildRecord من ملف XML لقائمة الانتظار. قد تكون فارغة.
ستكون الواجهة على النحو التالي:
public interface IAppQueue {
نقوم بتطبيق الدالات في فئة AppQueueService: IAppQueue:
انقر لتوسيع المفسد برمز public class AppQueueService : IAppQueue {
إجراء تغييرات على فئة AppQueueWindowsService: ServiceBase
أضف متغيرات جديدة إلى نص الفصل:
في مُنشئ AppQueueWindowsService () ، قم بإضافة وظائف لقراءة ملف التكوين ، وتهيئة الخدمات وفئات قائمة الانتظار:
AgentTimeout - تردد استجابة المؤقت. المشار إليها بالمللي ثانية. وضعنا هنا أنه يجب تشغيل المؤقت كل 30 ثانية. في الأصل ، هذه المعلمة في ملف التكوين. بالنسبة للمقالة ، قررت تعيينها في التعليمات البرمجية.
أضف الوظيفة للتحقق من عملية البناء الجارية للفصل الدراسي:
أضف الإجراء للعمل مع المؤقت:
private void TimerTick(object sender, System.Timers.ElapsedEventArgs e) { try {
نجري تغييرات على وظيفة OnStart ، نضيف وظيفة العمل مع المؤقت:
تحقق من قائمة التعريفات المستخدمة
إليك ما يجب أن يبدو عليه الآن: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.ServiceModel; using System.ServiceProcess; using System.Configuration; using System.Configuration.Install; using System.Reflection; using System.Xml.Linq; using System.Xml.XPath; using QBuilder.AppQueue.AppLauncherService;
أضف قسم التكوين إلى App.config
أضف مجموعة المعلمات التالية إلى القسم: <appSettings> <add key="QueueFileName" value="BuildQueue.xml"/> <add key="BuildToolPath" value="c:\temp\dummybuild.exe"/> <add key="BuildToolWorkDir" value="c:\temp\"/> <add key="LocalDomain" value="."/> <add key="UserName" value="username"/> <add key="ScriptPath" value="C:\Temp\BuildSample.bld"/> </appSettings>
فحص الخدمة
- قم بفك ضغط أرشيف QBuilder.AppLauncher.zip. هو والملفات الضرورية الأخرى متوفرة هنا .
- انسخ ملف dummybuild.exe من الدليل داخل أرشيف الثنائيات إلى الدليل ، على سبيل المثال ، في c: \ temp. هذا البرنامج هو كعب اختبار ويعرض ببساطة معلمات سطر الأوامر التي تمر بها الخدمة إلى التطبيق الذي يتم تشغيله. إذا كنت تستخدم دليلًا مختلفًا ، فتأكد من تغيير معلمات BuildToolPath و BuildToolWorkDir في ملف التكوين.
- انتقل إلى الدليل \ QBuilder.AppLauncher \ binaries \ QBuilder.AppLauncher \ وقم بتشغيل ملف QBuilder.AppLauncher.exe في وضع المسؤول. يمكنك أيضا تجميع هذه الخدمة من المصدر.
- أطلقنا إصدار وحدة التحكم للخدمة المترجمة باستخدام أمر / وحدة التحكم QBuilder.AppQueue.exe مع حقوق المسؤول.
- تحقق من أن الخدمة قد بدأت وأنها تعمل:

- نبدأ وننتظر. إذا نجح كل شيء ، فستظهر النافذة التالية بعد 30 ثانية:

- افتح ملف BuildQueue.xml ولاحظ كيفية تناقص قائمة الانتظار وقيمة تغييرات Currentbuild:
<?xml version="1.0" encoding="utf-8"?> <BuildsQueue BuildNumber="23"> <build BuildId="19" IssueId="66540" IssueName="TestIssueName" StartDate="2018-06-13T16:49:51.3581274+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="20" IssueId="68618" IssueName="TestIssueName" StartDate="2018-06-13T16:49:51.5087854+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="21" IssueId="18453" IssueName="TestIssueName" StartDate="2018-06-13T16:49:51.6713477+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="22" IssueId="68288" IssueName="TestIssueName" StartDate="2018-06-13T16:49:51.8277942+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="23" IssueId="89884" IssueName="TestIssueName" StartDate="2018-06-13T16:49:52.0151294+02:00" Build_CSharp="true" Build_Cpp="true" /> <currentbuild BuildId="18" IssueId="16706" StartDate="13.06.2018 23:20:06" /> </BuildsQueue>
- بعد كل إغلاق للبرنامج الوهمي ، تتم محاكاة نهاية العملية ، وبعد ذلك يتم إطلاق العنصر التالي في قائمة الانتظار:
<?xml version="1.0" encoding="utf-8"?> <BuildsQueue BuildNumber="23"> <build BuildId="21" IssueId="18453" IssueName="TestIssueName" StartDate="2018-06-13T16:49:51.6713477+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="22" IssueId="68288" IssueName="TestIssueName" StartDate="2018-06-13T16:49:51.8277942+02:00" Build_CSharp="true" Build_Cpp="true" /> <build BuildId="23" IssueId="89884" IssueName="TestIssueName" StartDate="2018-06-13T16:49:52.0151294+02:00" Build_CSharp="true" Build_Cpp="true" /> <currentbuild BuildId="20" IssueId="68618" StartDate="13.06.2018 23:24:25" /> </BuildsQueue>
الخط يعمل!النتائج
تم إرسال نص Powerhell حسن التصرف إلى مكب النفايات. تمت كتابة التطبيق الجديد بالكامل في C #. لدينا الآن الفرصة لاستخدام مجموعات القواعد - القواعد التي تحدد الملفات وفقًا لمعايير خاصة وإدراجها فقط في أماكن معينة في برنامج الإعداد النصي. بسبب نظام التجزئة الجديد ، قاموا بحل مشكلة اختيار الملفات فقط بالاسم والحجم - نشأ عندما اختلفت الملفات التي تحمل نفس الاسم والحجم في المحتوى. لا يعتبر برنامج بناء التحديث الجديد الملفات كملفات - فهو يعتبرها تجزئات MD5 وينشئ جدول تجزئة حيث تحتوي كل مجموعة من الملفات في دليل معين على تجزئة فريدة خاصة بها.
لقطة شاشة للحل النهائي الذي نستخدمه في عملنايتم إدخال تحسينات طفيفة باستمرار على الحل ، لكننا قمنا بالفعل بحل المشكلة الأكثر أهمية - سمح لنا النهج الجديد بإزالة العامل البشري تمامًا وإنقاذ أنفسنا من مجموعة من العكازات. اتضح أن النظام عالمي جدًا بحيث سيتم استخدامه في المستقبل القريب لبناء الإصلاحات العاجلة ، حيث تتغير العديد من الملفات. كل هذا سيعمل من خلال واجهة ويب باستخدام تطبيق آخر.خلال المشروع ، اكتشفت كيفية العمل مع XML ، مع ملفات التكوين ، مع نظام الملفات. الآن لدي أفكاري الخاصة ، والتي أستخدمها بنجاح في مشاريع أخرى. من أجل الوضوح ، قمت بإزالة كمية كبيرة من التعليمات البرمجية ، والتي يمكن أن تشتت الانتباه عن الجوهر ، وقمت بإعادة هيكلة جدية.آمل أن تساعدك هذه المقالة في العمل مع خدمات WCF ، مع أجهزة ضبط الوقت في نص الخدمات ، وتنفيذ قوائم الانتظار من خلال ملفات XML. يمكنك مشاهدة تشغيل التطبيقات وقائمة الانتظار في الفيديو:PS أريد أن أعبر عن امتناني لفيكتور بوروديتش ، الذي ساعدت نصيحته كثيرًا على جعل هذا النظام في نموذج العمل. يثبت فيكتور أنه إذا جمعت بين المطورين والخبراء ذوي الخبرة ، فستزداد جودة الرمز بالتأكيد في الأخير.