Bekerja di tim Manajemen Konfigurasi dikaitkan dengan memastikan fungsionalitas proses pembuatan - merakit produk perusahaan, verifikasi kode awal, analisis statistik, dokumentasi, dan banyak lagi. Selain itu, kami terus berupaya mengoptimalkan berbagai proses, dan, yang luar biasa, kami praktis bebas memilih alat untuk pekerjaan yang menarik ini. Selanjutnya, saya akan berbicara secara rinci tentang bagaimana, karena hanya memiliki tingkat pengetahuan yang berbeda dalam C # dan C ++, saya membuat layanan WCF fungsional untuk bekerja dengan memperbaiki antrian. Dan mengapa saya memutuskan bahwa ini sangat penting.

Otomatis sekali atau 117 halaman instruksi berulang-ulang
Penyimpangan kecil sehingga Anda mengerti mengapa saya sangat khawatir tentang otomatisasi dan optimalisasi proses.
Sebelum Veeam, saya bekerja untuk sebuah perusahaan internasional besar - saya adalah pemimpin tim dari tim Manajemen Konfigurasi, terlibat dalam membangun aplikasi dan menggunakannya untuk menguji lingkungan. Program ini berhasil dikembangkan, fungsi-fungsi baru ditambahkan, dokumentasi ditulis, dukungan yang juga saya tangani. Tetapi saya selalu terkejut mengapa program yang begitu serius tidak memiliki sistem konfigurasi parameter normal, yang jumlahnya banyak, bahkan ratusan.
Saya berbicara dengan pengembang tentang topik ini dan menerima jawaban - pelanggan tidak membayar untuk fitur ini, tidak setuju dengan biayanya, jadi fitur itu tidak diterapkan. Tetapi pada kenyataannya, QA menderita, dan kami, tim SM, secara langsung terpengaruh. Konfigurasi program dan konfigurasi awal dilakukan melalui banyak file konfigurasi, yang masing-masing memiliki lusinan parameter.
Setiap versi baru, setiap versi baru membuat perubahan pada konfigurasi. File konfigurasi lama tidak dapat digunakan, karena mereka sering tidak kompatibel dengan versi baru. Akibatnya, setiap kali sebelum memasang build untuk pengujian atau pada mesin penguji yang bekerja, Anda harus menghabiskan banyak waktu untuk mengonfigurasi program, memperbaiki kesalahan konfigurasi, konsultasi terus-menerus dengan pengembang pada topik "mengapa tidak bekerja seperti itu sekarang?" Secara umum, proses itu sangat tidak dioptimalkan.
Untuk membantu dengan pengaturan, kami memiliki instruksi 117 halaman dalam font Arial ukuran 9. Kami harus membaca dengan sangat hati-hati. Terkadang sepertinya lebih mudah untuk membangun kernel Linux dengan mata tertutup pada komputer yang mati.
Menjadi jelas bahwa optimasi tidak dapat dihindari di sini. Saya mulai menulis konfigurator untuk sebuah program dengan dukungan untuk profil dan kemampuan untuk mengubah parameter dalam beberapa detik, tetapi proyek tersebut sampai pada tahap akhir, dan saya beralih untuk bekerja di proyek lain. Di dalamnya, kami menganalisis banyak log dari satu sistem penagihan untuk kemungkinan bug di sisi server. Otomatisasi banyak tindakan menggunakan bahasa Python menyelamatkan saya dari sejumlah besar pekerjaan manual. Saya sangat menyukai bahasa skrip ini, dan dengan bantuannya kami membuat satu set skrip analisis untuk semua kesempatan. Tugas-tugas yang memerlukan beberapa hari analisis yang bijaksana menurut "cat logfile123 | grep something_special ”, perlu waktu beberapa menit. Semuanya hebat ... dan membosankan.
Manajemen Konfigurasi - Petualangan Baru
Saya datang ke Veeam sebagai pemimpin tim untuk tim CM kecil. Banyak proses yang memerlukan otomatisasi, optimisasi, dan pemikiran ulang. Tetapi ada kebebasan penuh dalam memilih alat! Pengembang harus menggunakan bahasa pemrograman tertentu, gaya kode, kumpulan perpustakaan tertentu. SM, di sisi lain, mungkin tidak menggunakan apa pun untuk menyelesaikan tugas, jika dia memiliki cukup waktu, keberanian dan kesabaran untuk ini.
Veeam, seperti banyak perusahaan lain, memiliki tugas mengumpulkan pembaruan produk. Pembaruan termasuk ratusan file, dan itu perlu untuk mengubah hanya yang berubah, dengan mempertimbangkan sejumlah kondisi penting. Untuk melakukan ini, kami membuat skrip PowerShell tebal yang bisa naik ke TFS, pilih file, mengurutkannya ke folder yang diperlukan. Fungsionalitas skrip ditambahkan, secara bertahap menjadi besar, butuh banyak waktu untuk debug dan terus-menerus beberapa kruk untuk boot. Sangat mendesak untuk melakukan sesuatu.
Apa yang diinginkan para pengembang
Berikut keluhan utama:
- Tidak dapat melakukan perbaikan antrian. Anda harus terus-menerus memeriksa halaman web untuk melihat kapan perakitan perbaikan pribadi selesai dan Anda dapat mulai membangun sendiri.
- Tidak ada pemberitahuan tentang kesalahan - untuk melihat kesalahan dalam GUI aplikasi perakitan, Anda harus pergi ke server dan menonton banyak log yang banyak.
- Tidak ada riwayat pembangunan untuk perbaikan pribadi.
Itu perlu untuk menangani tugas-tugas ini dan menambahkan hal-hal kecil yang menyenangkan yang tidak akan ditolak oleh pengembang.
Apa itu perbaikan pribadi
Perbaikan pribadi dalam konteks pengembangan kami adalah serangkaian koreksi dalam kode, yang disimpan di rak-rak Server Tim Foundation untuk cabang rilis. Sedikit klarifikasi untuk mereka yang tidak terlalu mengenal terminologi TFS:
- check-in - satu set perubahan lokal dalam kode sumber, yang dibuat untuk kode yang disimpan di TFS. Pemeriksaan ini dapat diperiksa menggunakan proses Integrasi Berkelanjutan / Gated Check-in yang memungkinkan Anda hanya melewati kode yang benar dan menolak semua pemeriksaan yang melanggar koleksi proyek akhir.
- shelveset - satu set perubahan lokal dalam kode sumber yang tidak secara langsung dibuat ke kode sumber yang terletak di TFS, tetapi dapat diakses dengan namanya. Shellset dapat digunakan pada mesin lokal pengembang atau membangun sistem untuk bekerja dengan kode yang dimodifikasi yang tidak termasuk dalam TFS. Juga, shellset dapat ditambahkan ke TFS sebagai cek setelah penyebaran, ketika semua pekerjaan dengan itu selesai. Misalnya, pemeriksa gerbang bekerja dengan cara ini. Pertama, shellset pada builder diperiksa. Jika cek berhasil, shellset berubah menjadi cek!
Inilah yang dilakukan pembangun perbaikan pribadi:
- Mendapat nama (nomor) dari shellset dan menyebarkannya pada build fix pribadi. Hasilnya, kami mendapatkan kode sumber produk rilis plus perubahan / perbaikan dari shellset. Cabang rilis tetap tidak berubah.
- Pada pembangun perbaikan pribadi, sebuah proyek atau serangkaian proyek akan dilakukan untuk mana perbaikan pribadi telah dilakukan.
- Set file biner yang dikompilasi disalin ke direktori jaringan perbaikan pribadi. Katalog berisi nama shellset, yang merupakan urutan angka.
- Kode sumber pada pembangun perbaikan pribadi dikembalikan ke bentuk aslinya.
Untuk kenyamanan pengembang, antarmuka web digunakan di mana Anda dapat menentukan produk yang ingin Anda kumpulkan perbaikan pribadi, tentukan nomor shellset, pilih proyek yang ingin Anda kumpulkan perbaikan pribadi, dan tambahkan unit perbaikan ke antrian. Tangkapan layar di bawah ini menunjukkan versi terakhir aplikasi web yang berfungsi, yang menampilkan status build saat ini, antrian perbaikan pribadi, dan riwayat perakitannya. Dalam contoh kami, kami hanya mempertimbangkan antrian perakitan perbaikan pribadi.
Apa milikku
- Pembangun perbaikan pribadi yang mengumpulkan perbaikan pribadi dari TFS shellset dengan meluncurkan aplikasi konsol dengan parameter baris perintah yang diberikan.
- Veeam.Builder.Agent - layanan WCF yang ditulis oleh Veeam yang meluncurkan aplikasi dengan parameter dalam mode konsol di bawah pengguna saat ini dan mengembalikan status aplikasi saat ini.
- Layanan web IIS adalah aplikasi pada Formulir Windows yang memungkinkan Anda untuk memasukkan nama shellset, parameter yang ditentukan dan memulai proses membangun perbaikan pribadi.
- Pengetahuan pemrograman yang sangat dangkal adalah C ++, sedikit C # di universitas, dan menulis aplikasi kecil untuk otomatisasi, menambahkan fungsi baru ke proses pembuatan saat ini dan sebagai hobi.
- Rekan kerja yang berpengalaman, Google, dan artikel MSDN India adalah sumber jawaban untuk semua pertanyaan.
Apa yang akan kita lakukan
Pada artikel ini saya akan menceritakan bagaimana saya menerapkan antrian perakitan perbaikan dan peluncuran berurutan mereka pada pembangun. Inilah bagian dari solusinya:
- QBuilder.AppQueue adalah layanan WCF saya yang menyediakan pekerjaan dengan antrian build dan memanggil layanan Veeam.Builder.Agent untuk menjalankan program build.
- dummybuild.exe adalah program rintisan yang digunakan untuk debugging dan sebagai alat bantu visual. Diperlukan untuk memvisualisasikan parameter yang ditransfer.
- QBuilder.AppLauncher - Layanan WCF yang menjalankan aplikasi di konsol pengguna saat ini dan bekerja dalam mode interaktif. Ini adalah analog yang disederhanakan secara signifikan dari program Veeam.Builder.Agent yang ditulis khusus untuk artikel ini. Layanan asli dapat berfungsi sebagai layanan windows dan menjalankan aplikasi di konsol, yang membutuhkan kerja tambahan dengan Windows API. Untuk menggambarkan semua trik, diperlukan artikel terpisah. Contoh saya berfungsi sebagai layanan konsol interaktif sederhana dan menggunakan dua fungsi - memulai proses dengan parameter dan memeriksa statusnya.
Selain itu, kami membuat aplikasi web baru yang nyaman yang dapat bekerja dengan beberapa pembangun dan menyimpan log peristiwa. Agar tidak memuat artikel terlalu banyak, kami tidak akan membicarakannya secara mendetail. Selain itu, artikel ini tidak menjelaskan pekerjaan dengan TFS, dengan riwayat penyimpanan perbaikan pribadi yang dikumpulkan dan berbagai kelas dan fungsi bantu.

Membuat Layanan WCF
Ada banyak artikel terperinci yang menggambarkan penciptaan layanan WCF. Saya sangat menyukai
materi dari situs Microsoft . Saya menganggapnya sebagai dasar untuk pengembangan. Untuk memfasilitasi perkenalan saya dengan proyek, saya juga meletakkan
binari . Ayo mulai!
Buat layanan QBuilder.AppLauncher
Di sini kita hanya akan memiliki cakram utama layanan. Pada tahap ini, kita perlu memastikan bahwa layanan dimulai dan berfungsi. Selain itu, kode ini sama untuk QBuilder.AppLauncher dan QBuilder.AppQueue, jadi proses ini perlu diulang dua kali.
- Buat aplikasi konsol baru bernama QBuilder.AppLauncher
- Ganti nama Program.cs ke Service.cs
- Ganti nama namespace menjadi QBuilder.AppLauncher
- Tambahkan referensi berikut ke proyek:
a. System.ServiceModel.dll
b. System.ServiceProcess.dll
c. System.Configuration.Install.dll
- Tambahkan definisi berikut ke Service.cs
using System.ComponentModel; using System.ServiceModel; using System.ServiceProcess; using System.Configuration; using System.Configuration.Install;
Dalam proses perakitan lebih lanjut, definisi berikut juga akan dibutuhkan:
using System.Reflection; using System.Xml.Linq; using System.Xml.XPath;
- Kami mendefinisikan antarmuka IAppLauncher dan menambahkan fungsi untuk bekerja dengan antrian:
- Di kelas AppLauncherService, kami mengimplementasikan antarmuka dan fungsi pengujian TestConnection:
public class AppLauncherService : IAppLauncher { public bool TestConnection() { return true; } }
- Buat kelas AppLauncherWindowsService baru yang mewarisi kelas ServiceBase. Tambahkan serviceHost variabel lokal - tautan ke ServiceHost. Kami mendefinisikan metode Utama, yang memanggil ServiceBase.Run (AppLauncherWindowsService ()) baru:
public class AppLauncherWindowsService : ServiceBase { public ServiceHost serviceHost = null; public AppLauncherWindowsService() {
- Override fungsi OnStart () yang membuat instance ServiceHost baru:
protected override void OnStart(string[] args) { if (serviceHost != null) { serviceHost.Close(); }
- Mengganti fungsi onStop yang menutup contoh ServiceHost:
protected override void OnStop() { if (serviceHost != null) { serviceHost.Close(); serviceHost = null; } } }
- Buat kelas ProjectInstaller baru, yang diwarisi dari Installer dan ditandai dengan RunInstallerAttribute, yang disetel ke True. Ini memungkinkan Anda untuk menginstal layanan Windows menggunakan program 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); } }
- Ubah konten file 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>
Memeriksa kemudahan servis dari layanan
- Kami mengkompilasi layanan.
- Instal dengan perintah installutil.exe
1) Buka folder tempat file layanan terkompilasi berada
2) Jalankan perintah instalasi:
C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ InstallUtil.exe - Kami masuk ke snap-in services.msc, memeriksa ketersediaan layanan QBuilder App Launcher dan menjalankannya.
- Kami memeriksa kemudahan layanan menggunakan program WcfTestClient.exe, yang disertakan dengan VisualStudio:
1) Jalankan WcfTestClient
2) Tambahkan alamat layanan: http: // localhost: 8000 / QBuilderAppLauncher / service
3) Antarmuka layanan terbuka:

4) Kami memanggil fungsi tes TestConnection, periksa apakah semuanya berfungsi dan fungsi mengembalikan nilai:

Sekarang kami memiliki disk layanan yang berfungsi, kami menambahkan fungsi yang kami butuhkan.
Mengapa saya memerlukan fungsi tes yang tidak melakukan apa-apa
Ketika saya mulai belajar cara menulis layanan WCF dari awal, saya membaca banyak artikel tentang topik ini. Di atas meja saya memiliki selusin atau dua lembar cetak di mana saya bisa mencari tahu apa dan bagaimana. Saya akui, saya tidak berhasil segera memulai layanan. Saya menghabiskan banyak waktu dan sampai pada kesimpulan bahwa sangat penting untuk membuat disc layanan. Dengan itu Anda akan yakin bahwa semuanya berfungsi dan Anda dapat mulai mengimplementasikan fungsi yang diperlukan. Pendekatan ini mungkin tampak boros, tetapi akan membuat hidup lebih mudah jika banyak kode tertulis tidak berfungsi sebagaimana mestinya.
Tambahkan kemampuan untuk lari dari konsol
Kembali ke aplikasi. Pada tahap debugging dan dalam beberapa kasus lain, perlu untuk memulai layanan dalam bentuk aplikasi konsol tanpa mendaftar sebagai layanan. Ini adalah fitur yang sangat berguna yang memungkinkan Anda untuk melakukannya tanpa menggunakan debuggers yang membosankan. Dalam mode ini layanan QBuilder.AppLauncher berfungsi. Berikut ini cara mengimplementasikannya:
- Tambahkan prosedur RunInteractive ke kelas AppLauncherWindowsService, yang menyediakan layanan dalam mode konsol:
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."); }
- Kami membuat perubahan pada prosedur Utama - menambahkan pemrosesan parameter baris perintah. Dengan opsi / konsol dan sesi pengguna aktif yang terbuka, kami meluncurkan program dalam mode interaktif. Kalau tidak, kami meluncurkannya sebagai layanan.
public static void Main(string[] args) { var services = new ServiceBase[] { new AppLauncherWindowsService() };
Tambahkan fungsi untuk meluncurkan aplikasi dan periksa statusnya
Layanan ini dibuat sangat sederhana, tidak ada pemeriksaan tambahan. Ia dapat menjalankan aplikasi hanya dalam versi konsol dan atas nama administrator. Itu juga dapat meluncurkan mereka sebagai layanan - tetapi Anda tidak akan melihatnya, mereka akan berputar di latar belakang dan Anda hanya dapat melihatnya melalui Task Manager. Semua ini dapat diimplementasikan, tetapi ini adalah topik untuk artikel terpisah. Hal utama bagi kami di sini adalah contoh kerja yang jelas.
- Pertama, tambahkan appProcess variabel global, yang menyimpan proses yang sedang berjalan.
Tambahkan ke public class AppLauncherService : IAppLauncher
:
public class AppLauncherService : IAppLauncher { Process appProcess;
- Tambahkan fungsi ke kelas yang sama yang memeriksa status proses yang berjalan:
public bool IsStarted() { if (appProcess!=null) { if (appProcess.HasExited) { return false; } else { return true; } } else { return false; } }
Fungsi mengembalikan false jika proses tidak ada atau belum berjalan, dan benar jika proses aktif.
- Tambahkan fungsi untuk meluncurkan aplikasi:
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; }
Fungsi meluncurkan aplikasi apa pun dengan parameter. Parameter Domain dan Nama Pengguna tidak digunakan dalam konteks ini dan mungkin kosong, karena layanan memulai aplikasi dari sesi konsol dengan hak administrator.
Meluncurkan Layanan QBuilder.AppLauncher
Seperti dijelaskan sebelumnya, layanan ini bekerja secara interaktif dan memungkinkan Anda untuk menjalankan aplikasi di sesi pengguna saat ini, memeriksa apakah proses sedang berjalan atau sudah selesai.
- Agar berfungsi, Anda memerlukan file QBuilder.AppLauncher.exe dan QBuilder.AppLauncher.exe.config, yang ada di arsip di tautan di atas. Kode sumber aplikasi ini untuk perakitan mandiri juga terdapat di sana.
- Kami memulai layanan dengan hak administrator.
- Jendela konsol layanan akan terbuka:

Keystroke apa pun di konsol layanan menutupnya, hati-hati.
- Untuk tes, jalankan wcftestclient.exe, yang disertakan dengan Visual Studio. Kami memeriksa ketersediaan layanan di http: // localhost: 8000 / QBuilderAppLauncher / service atau membuka tautan di Internet Explorer.
Jika semuanya berfungsi, lanjutkan ke langkah berikutnya.
Menciptakan Layanan QBuilder.AppQueue
Dan sekarang mari kita beralih ke layanan yang paling penting, di mana seluruh artikel ditulis! Kami mengulangi urutan tindakan dalam bab "Membuat Layanan QBuilder.AppLauncher" dan dalam bab "Menambahkan Peluncuran dari Konsol", menggantikan AppLauncher dengan AppQueue dalam kode.
Tambahkan tautan ke layanan QBuilder.AppLauncher untuk digunakan dalam layanan antrian
- Dalam Solution Explorer untuk proyek kami, pilih Tambahkan Referensi Layanan dan tentukan alamat: localhost : 8000 / QBuilderAppLauncher / service
- Pilih namespace nama: AppLauncherService.
Sekarang kita dapat mengakses antarmuka layanan dari program kita.
Buat struktur untuk menyimpan elemen antrian
Di namespace QBuilder.AppQueue, tambahkan kelas QBuildRecord:
Menerapkan Kelas Antrian CXmlQueue
Kami menambahkan kelas CXmlQueue.cs ke proyek kami, di mana sejumlah prosedur untuk bekerja dengan file XML akan ditemukan:
- CXmlQueue constructor - menetapkan nama awal file tempat antrian disimpan.
- SetCurrentBuild - menulis informasi tentang build saat ini ke file XML antrian. Ini adalah elemen yang tidak ada dalam antrian, ia menyimpan informasi tentang proses yang sedang berjalan. Mungkin kosong.
- GetCurrentBuild - Dapatkan parameter proses yang berjalan dari file XML antrian. Mungkin kosong.
- ClearCurrentBuild - Ini membersihkan elemen currentbuild dalam file XML antrian jika proses berakhir.
- OpenXmlQueue - berfungsi untuk membuka file XML tempat antrian disimpan. Jika file hilang, yang baru dibuat.
- GetLastQueueBuildNumber - setiap build dalam antrian memiliki nomor seri yang unik. Fungsi ini mengembalikan nilainya, yang disimpan dalam atribut root.
- IncrementLastQueueBuildNumber - meningkatkan nilai build number saat mengantri build baru.
- GetCurrentQueue - Mengembalikan daftar elemen QBuildRecord dari file XML antrian.
Dalam kode asli, semua prosedur ini ditempatkan di kelas utama, tetapi untuk kejelasan, saya membuat kelas CXmlQueue yang terpisah. Kelas dibuat di namespace QBuilder.AppQueue namespace, verifikasi bahwa semua definisi yang diperlukan ditentukan:
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 { . . . }
Jadi, kami sedang mengimplementasikan. Kelas CXmlQueue sendiri:
Klik untuk membuka spoiler dengan kode Antrian dalam file XML adalah sebagai berikut:
<?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>
Buat file BuildQueue.xml dengan konten ini dan letakkan di direktori dengan file yang dapat dieksekusi. File ini akan digunakan dalam uji debug untuk mencocokkan hasil pengujian.
Tambahkan Kelas AuxFunctions
Di kelas ini, saya menempatkan fungsi pembantu. Saat ini hanya ada satu fungsi, FormatParameters, yang melakukan pemformatan parameter untuk meneruskannya ke aplikasi konsol untuk diluncurkan. Daftar file AuxFunctions.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace QBuilder.AppQueue { class AuxFunctions {
Tambahkan fitur baru ke antarmuka layanan
Fungsi uji, TestConnection dapat dihapus pada tahap ini. Untuk mengimplementasikan pekerjaan antrian, saya memerlukan serangkaian fungsi berikut:
- PushBuild (QBuildRecord): batal. Ini adalah fungsi yang menambahkan nilai baru ke file XML antrian dengan parameter QBuildRecord
- TestPushBuild (): void. Ini adalah fungsi tes yang menambahkan data uji ke antrian dalam file XML.
- PullBuild: QBuildRecord. Ini adalah fungsi yang mengambil nilai QBuildRecord dari file XML antrian. Mungkin kosong.
Antarmuka akan seperti ini:
public interface IAppQueue {
Kami menerapkan fungsi di kelas AppQueueService: IAppQueue:
Klik untuk membuka spoiler dengan kode public class AppQueueService : IAppQueue {
Membuat perubahan pada AppQueueWindowsService: kelas ServiceBase
Tambahkan variabel baru ke badan kelas:
Di konstruktor AppQueueWindowsService (), tambahkan fungsi untuk membaca file konfigurasi, inisialisasi layanan dan kelas antrian:
AgentTimeout - frekuensi respons timer. Diindikasikan dalam milidetik. Di sini kita menetapkan bahwa timer harus menyala setiap 30 detik. Dalam dokumen asli, parameter ini ada di file konfigurasi. Untuk artikel itu, saya memutuskan untuk membuatnya dalam kode.
Tambahkan fungsi untuk memeriksa proses build yang sedang berjalan ke kelas:
Tambahkan prosedur untuk bekerja dengan timer:
private void TimerTick(object sender, System.Timers.ElapsedEventArgs e) { try {
Kami membuat perubahan pada fungsi OnStart, menambahkan fungsi bekerja dengan timer:
Periksa daftar definisi yang digunakan
Begini tampilannya sekarang: 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;
Tambahkan bagian konfigurasi ke App.config
Tambahkan set parameter berikut ke bagian: <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>
Memeriksa layanan
- Buka paket arsip QBuilder.AppLauncher.zip. Dia dan file-file lain yang diperlukan tersedia di sini .
- Salin file dummybuild.exe dari direktori di dalam arsip binari ke direktori, misalnya, di c: \ temp. Program ini adalah rintisan pengujian dan hanya menampilkan parameter baris perintah yang dilewatkan oleh layanan ke aplikasi yang diluncurkan. Jika Anda menggunakan direktori yang berbeda, pastikan untuk mengubah parameter BuildToolPath dan BuildToolWorkDir dalam file konfigurasi.
- \QBuilder.AppLauncher\binaries\QBuilder.AppLauncher\ QBuilder.AppLauncher.exe . .
- QBuilder.AppQueue.exe /console .
- , :

- . , 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>
- dummy , :
<?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>
!
powershell- . C#. rulesets — , setup-. — , . — MD5- -, .
,, — . , , . - .
, XML, , . , . , , .
, WCF-, XML-. :
PS , . , , .