Daftar pembaruan Windows yang diinstal yang sulit dipahami

Pernahkah Anda bertanya-tanya mengapa daftar pembaruan Windows yang diinstal dibuat? Dan melalui API mana untuk mendapatkannya? Saya akan mencoba memberikan jawaban untuk ini dan pertanyaan lain yang muncul dalam studi kecil saya.



Latar belakang atau bagaimana semuanya dimulai.


Setiap tahun sebuah konferensi spesialis muda diadakan di perusahaan kami , di mana setiap peserta dapat menyelesaikan masalah departemen (daftar topik diusulkan sebelumnya). Dan departemen SPAS (dukungan perangkat lunak dan perangkat keras) memiliki tugas berikut, yang menarik minat saya, ditambah lagi memungkinkan untuk kembali ke pemrograman lagi (sayangnya, saat ini saya bekerja di perusahaan ini sebagai operator sederhana NPPS).

Sebelumnya, untuk setiap "TO" dengan bantuan WSUS, semua pembaruan yang dirilis ditarik dan didistribusikan ke semua mesin. TSB (buletin layanan teknis) juga muncul secara berkala, yang mengindikasikan bahwa diperlukan untuk menginstal pembaruan yang diperlukan dalam bentuk paket terisolasi. Akibatnya, kami mengumpulkan pembaruan yang tidak dapat dilacak di WSUS, tetapi hanya dapat dilihat melalui panel kontrol di bagian "Pembaruan Terpasang".



Skema pembaruan visual

Ada situasi ketika workstation atau server "crash" dan Anda harus mengembalikannya dari gambar yang dibuat beberapa waktu lalu. Saat memulihkan dari suatu gambar, ada kemungkinan bahwa kita mungkin kehilangan pembaruan yang kita butuhkan (yang datang dalam bentuk paket terisolasi) yang diinstal sebelum mesin crash. Dijelaskan sedetail mungkin, karena klarifikasi sudah akan menjadi rahasia dagang.

Itu sebabnya muncul ide untuk membuat program yang dapat mengekstrak daftar pembaruan ini (lebih disukai dari jarak jauh melalui jaringan lokal), menulis ke file / database, membandingkan daftar saat ini dengan templat tertentu dan mengirim pesan ke sistem SCADA melalui salah satu protokol - SNMP, OPC.

Seperti yang mungkin sudah Anda tebak dari judul artikel, saya sudah memiliki tugas yang sulit untuk memilih metode pencarian daftar. Seperti biasa, saya memutuskan untuk mencari yang tepat di mesin pencari, mengajukan pertanyaan tentang sumber daya khusus ( satu , dua , untuk beberapa alasan stackoverflow dalam bahasa Inggris tidak menyukai pertanyaan saya dan harus dihapus), tetapi semua jawaban tidak memberikan hasil yang diinginkan. Karena itu, saya harus mencari tahu sendiri, yang akan dibahas nanti.

Perintah konsol


Mari kita mulai dengan yang sederhana dan memanfaatkan apa yang ditawarkan Windows tanpa menggunakan alat pihak ketiga. Ini dapat dilakukan dengan menggunakan perintah berikut:

  • daftar qfe wmic
  • systeminfo
  • bongkar / online / dapatkan paket
  • melalui PowerShell:

    • Dapatkan perbaikan terbaru
    • Get-SilWindowsUpdate (hanya tersedia dalam edisi server)
    • Get-WmiObject -Class win32_quickfixengineering - melalui akses ke kelas WMI win32_quickfixengineering (tentang WMI beberapa saat kemudian)



Anda bisa mendapatkan daftar melalui antarmuka grafis melalui item standar dari Control Panel "Tambah / Hapus Program", tetapi kami tidak dapat menyalin apa pun dari sana. Setiap alat panel kontrol diwakili oleh file .cpl di folder Windows \ System. File .Cpl di folder sistem Windows secara otomatis diunduh ketika panel kontrol dimulai. File Appwiz.cpl bertanggung jawab atas item Program. Analisisnya tidak mengarah pada apa pun.

Output dari perintah konsol dapat diarahkan ke file dan kemudian dapat diuraikan, tetapi ini salah, ditambah panggilan program (menurut aturan SB, itu tidak akan berfungsi) dan tidak ada pertanyaan untuk menerima daftar dari jarak jauh. Karena itu, saya sarankan Anda cukup memanggil perintah, membandingkan jumlah pembaruan di setiap daftar, dengan daftar melalui Panel Kontrol dan melanjutkan penyelidikan kami lebih lanjut.

Secara formal, semua metode untuk mendapatkan daftar pembaruan dapat dibagi menjadi dua kelompok: lokal dan jaringan.

Metode lokal dan jaringan untuk memperoleh informasi

Semua metode diuji pada gambar sistem yang bersih (Windows 7, 8, Server 2012 R2) dengan pembaruan terintegrasi, setelah setiap pembaruan melalui Pusat Pembaruan dari server Microsoft resmi pemeriksaan tambahan dilakukan. Mari kita bahas masing-masing dengan lebih detail.

WUA


WUApi (Windows Agen Pemutakhiran API) - Menggunakan API Agen Pemutakhiran Windows. Opsi yang paling jelas, nama yang berbicara sendiri. Kami akan menggunakan perpustakaan Wuapi.dll untuk ini.
Catatan: selanjutnya, untuk kenyamanan saya, saya akan menyematkan semua hasil dalam Daftar. Ini mungkin tidak rasional, tapi menurut saya itu ide yang bagus.
Contoh implementasi
using WUApiLib; public static List<string> listUpdateHistory() { //WUApi List<string> result = new List<string>(200); try { UpdateSession uSession = new UpdateSession(); IUpdateSearcher uSearcher = uSession.CreateUpdateSearcher(); uSearcher.Online = false; ISearchResult sResult = uSearcher.Search("IsInstalled=1 And IsHidden=0"); string sw = "   WUApi: " + sResult.Updates.Count; result.Add(sw); foreach (WUApiLib.IUpdate update in sResult.Updates) { result.Add(update.Title); } } catch (Exception ex) { result.Add("-   : " + ex.Message); } return result; } 


Ada variasi kedua dari metode ini: Perbarui Sesi - menerima informasi dengan menghubungkan ke sesi pembaruan Agen Pembaruan Windows (dalam hal ini, kami tidak bekerja secara langsung dengan perpustakaan).

Contoh implementasi
 public static List<string> Sessionlist(string pc) { List<string> result = new List<string>(50); //    object sess = null; object search = null; object coll = null; try { sess = Activator.CreateInstance(Type.GetTypeFromProgID("Microsoft.Update.Session", pc)); search = (sess as dynamic).CreateUpdateSearcher(); int n = (search as dynamic).GetTotalHistoryCount(); int kol = 0; //coll = (search as dynamic).QueryHistory(1, n); coll = (search as dynamic).QueryHistory(0, n); result.Add("  Update.Session: " + n); foreach (dynamic item in coll as dynamic) { if (item.Operation == 1) result.Add(item.Title); kol++; //Console.WriteLine(": " + kol); } result.Add("  : " + kol); } catch (Exception ex) { result.Add("-   : " + ex.Message); } finally { if (sess != null) Marshal.ReleaseComObject(sess); if (search != null) Marshal.ReleaseComObject(search); if (coll != null) Marshal.ReleaseComObject(coll); } return result; } 


Microsoft menyarankan penggunaan API secara jarak jauh.

Kerugian utama dari kedua metode ini adalah mereka tidak memungkinkan Anda menemukan perbaikan KB yang tidak didistribusikan melalui Pembaruan Windows. Anda hanya dapat melihat apa yang melalui agen pembaruan itu sendiri, yaitu, opsi ini tidak cocok untuk kami.

DISM


Penerapan Gambar Servis dan Manajemen adalah alat baris perintah yang dapat digunakan untuk melayani gambar Windows atau untuk menyiapkan gambar Lingkungan Pra-Instalasi Windows (Windows PE). Ini adalah pengganti untuk Package Manager (Pkgmgr.exe), PEimg, dan Intlcfg.

Utilitas ini digunakan untuk mengintegrasikan pembaruan, paket layanan ke dalam gambar sistem. Pembaruan Windows adalah modul terpisah yang dapat disajikan dalam beberapa cara:

  • File .cab (Kabinet) - arsip. Dirancang untuk distribusi dan instalasi menggunakan modul Pembaruan Windows dalam mode otomatis;
  • file .msu (Microsoft Update Standalone Package) - file yang dapat dieksekusi. Dirancang untuk distribusi dan instalasi oleh pengguna sendiri dalam mode manual melalui katalog pembaruan Microsoft. Bahkan, mereka adalah paket yang terdiri dari file .cab-, .xml, .txt.

Perintah dism / online / get-paket yang disebutkan sebelumnya menampilkan informasi dasar tentang semua paket dalam gambar wim / sistem saat ini. Microsoft telah mengurus kami dan menyediakan paket NuGet untuk penggunaan API yang nyaman.

Contoh implementasi
 using Microsoft.Dism; public static List<string> DISMlist() { List<string> result = new List<string>(220); try { DismApi.Initialize(DismLogLevel.LogErrors); var dismsession = DismApi.OpenOnlineSession(); var listupdate = DismApi.GetPackages(dismsession); int ab = listupdate.Count; //Console.WriteLine("   DISM: " + ab); string sw = "   DISM: " + ab; result.Add(sw); foreach (DismPackage feature in listupdate) { result.Add(feature.PackageName); //result.Add($"[ ] {feature.PackageName}"); //result.Add($"[ ] {feature.InstallTime}"); //result.Add($"[ ] {feature.ReleaseType}"); } } catch (Exception ex) { result.Add("-   : " + ex.Message); } return result; } 


Jumlah pembaruan bertepatan dengan jumlah dari daftar Panel Kontrol sampai pembaruan pertama melalui pusat kontrol - setelah itu jumlah pembaruan menjadi kurang (itu adalah 214, menjadi 209), meskipun secara logis mereka seharusnya meningkat. Contoh output Sebelum memperbarui , Setelah memperbarui .

Apa alasannya, saya hanya bisa berspekulasi - mungkin beberapa pembaruan menggantikan yang sebelumnya, oleh karena itu, jumlahnya menjadi kurang.

Beberapa saat kemudian, saya menemukan sebuah utilitas dari Chinese DISM ++ , yang tidak didasarkan pada DISM API atau DISM Core API, tetapi perpustakaan itu tidak memiliki metode yang perlu saya buka, jadi saya meninggalkan ide ini dan melanjutkan pencarian lebih lanjut.

WSUS


Layanan Pembaruan Server Windows ( WSUS ) adalah server untuk memperbarui sistem operasi dan produk Microsoft. Server pembaruan disinkronkan dengan situs web Microsoft, mengunduh pembaruan yang dapat didistribusikan dalam LAN perusahaan. Sekali lagi, alat khusus yang dirancang untuk bekerja dengan pembaruan.

Didistribusikan hanya pada edisi server Windows, jadi dudukan berikut digunakan:

  • sistem utamanya adalah Windows Server 2016;
  • dan melalui sistem virtualisasi Hyper-V, dua OS klien dikerahkan:
    • Windows 8.1
    • Windows 7


Semua sistem terhubung ke jaringan area lokal virtual tunggal, tetapi tanpa akses ke Internet .

Beberapa tips
Agar tidak mengalokasikan partisi hard disk untuk sistem baru, saya menggunakan WinNTSetup dan menginstal sistem dalam disk VHD - bootloader, dimulai dengan Windows 7 (edisi Profesional / Ultimate), sangat cocok dengan booting dari disk image. Disk yang diperoleh dapat digunakan dengan aman di Hyper-V - Anda membunuh dua burung dengan satu batu sekaligus. Jangan lupa untuk membuat salinan repositori BCD terlebih dahulu melalui perintah bcdedit / ekspor e: \ bcd_backup.bcd .

Saya tidak ingin mengonfigurasi AD untuk distribusi pembaruan, oleh karena itu saya hanya mendaftarkan jalur ke server WSUS dalam kebijakan grup:

Pengaturan

Pastikan untuk memperhatikan port, karena kesalahan ketik (8350 bukannya 8530) saya tidak bisa menerima pembaruan pada mesin klien, meskipun semuanya dilakukan dengan benar. Juga, nama item dalam kebijakan grup pada Windows 7 dan Windows 8 berbeda.

Untuk menerima laporan menggunakan WSUS, Anda harus menginstal paket tambahan - sistem akan memberi tahu Anda mengenai hal ini.

Dan sekarang kode kecil
 //      using Microsoft.UpdateServices.Administration; public static List<string> GetWSUSlist(params string[] list) { List<string> result = new List<string>(200); //    string namehost = list[0]; // ,     string = "example1"; string servername = list[1]; //  string = "WIN-E1U41FA6E55"; string Username = list[2]; string Password = list[3]; try { ComputerTargetScope scope = new ComputerTargetScope(); IUpdateServer server = AdminProxy.GetUpdateServer(servername, false, 8530); ComputerTargetCollection targets = server.GetComputerTargets(scope); // Search targets = server.SearchComputerTargets(namehost); // To get only on server FindTarget method IComputerTarget target = FindTarget(targets, namehost); result.Add(" : " + target.FullDomainName); IUpdateSummary summary = target.GetUpdateInstallationSummary(); UpdateScope _updateScope = new UpdateScope(); // See in UpdateInstallationStates all other properties criteria //_updateScope.IncludedInstallationStates = UpdateInstallationStates.Downloaded; UpdateInstallationInfoCollection updatesInfo = target.GetUpdateInstallationInfoPerUpdate(_updateScope); int updateCount = updatesInfo.Count; result.Add(" -   - " + updateCount); foreach (IUpdateInstallationInfo updateInfo in updatesInfo) { result.Add(updateInfo.GetUpdate().Title); } } catch (Exception ex) { result.Add("-   : " + ex.Message); } return result; } public static IComputerTarget FindTarget(ComputerTargetCollection coll, string computername) { foreach (IComputerTarget target in coll) { if (target.FullDomainName.Contains(computername.ToLower())) return target; } return null; } 


Karena tidak ada Internet, situasi dengan pembaruan keluar seperti pada tangkapan layar di bawah ini:



Perilaku ini mirip dengan WUApi - jika pembaruan belum melewati mereka, maka mereka tidak mengetahuinya. Karena itu, metode ini tidak berfungsi lagi.

Wmi


Instrumentasi Manajemen Windows ( WMI ) dalam terjemahan literal adalah toolkit manajemen Windows.

WMI adalah standar yang diterapkan Microsoft untuk mengelola perusahaan melalui Internet untuk administrasi terpusat dan pemantauan berbagai bagian infrastruktur komputer yang menjalankan platform Windows. WMI adalah sistem antarmuka akses terbuka terpadu untuk parameter apa pun dari sistem operasi, perangkat, dan aplikasi yang beroperasi di dalamnya.

Metode ini memungkinkan Anda untuk menerima data baik dari mesin lokal dan jarak jauh dalam jaringan lokal. Untuk mengakses objek WMI, WMI Query Language (WQL) tertentu digunakan, yang merupakan salah satu varietas SQL. Kami akan menerima daftar melalui win32_quickfixengineering kelas WMI.

Contoh implementasi
 using System.Management; public static List<string> GetWMIlist(params string[] list) { List<string> result = new List<string>(200); //    ManagementScope Scope; string ComputerName = list[0]; string Username = list[1]; string Password = list[2]; int kol = 0; if (!ComputerName.Equals("localhost", StringComparison.OrdinalIgnoreCase)) { //    ,      //  . ConnectionOptions Conn = new ConnectionOptions(); Conn.Username = Username; Conn.Password = Password; //      «NTLMDOMAIN:»  NTLM  ,       NTLM. Conn.Authority = "ntlmdomain:DOMAIN"; Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), Conn); } else Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), null); try { Scope.Connect(); ObjectQuery Query = new ObjectQuery("SELECT * FROM Win32_QuickFixEngineering"); ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query); foreach (ManagementObject WmiObject in Searcher.Get()) { result.Add(WmiObject["HotFixID"].ToString()); //Console.WriteLine("{0,-35} {1,-40}", "HotFixID", WmiObject["HotFixID"]);// String //result.Add(); /*result.Add("{0,-17} {1}", " : ", WmiObject["Description"]); result.Add("{0,-17} {1}", ": ", WmiObject["Caption"]); result.Add("{0,-17} {1}", " : ", WmiObject["InstalledOn"]);*/ kol++; } result.Add("  " + kol); } catch (Exception ex) { result.Add("-   : " + ex.Message); } return result; } 


Secara kuantitatif, semuanya bertepatan (bahkan setelah pembaruan), jadi diputuskan untuk menggunakan metode ini. Untuk pembuatan permintaan WMI terprogram, saya menyarankan Anda untuk menggunakan utilitas berikut - WMI Delphi Code Creator . Berkat dia, saya melihat kode saya sedikit berbeda dan memutuskan untuk menggunakan blank dari program ini.

XML


Data yang diperoleh dengan metode WMI tidak menghentikan saya, dan saya memutuskan "rekayasa permukaan terbalik". Kami akan menggunakan utilitas Process Monitor dari kumpulan perangkat lunak Sysinternals Suite untuk mengidentifikasi file dan cabang registri yang digunakan saat memanggil perintah konsol yang tercantum di atas dan mengakses item "Pembaruan yang diinstal" melalui Panel Kontrol.

Perhatian saya tertuju pada file wuindex.xml yang terletak di folder C: \ Windows \ servicing \ Packages \. Untuk menganalisisnya, program berikut ini ditulis:

Contoh Aplikasi Konsol
 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; using System.Text.RegularExpressions; using System.IO; namespace XMLviewer { class Program { static void Main(string[] args) { string writePath = AppDomain.CurrentDomain.BaseDirectory + "XML  " + Environment.MachineName + ".txt"; if (!File.Exists(writePath)) { Console.WriteLine("  txt "); } else { Console.WriteLine(" XML .txt ,   "); File.Delete(writePath); } //      KB Regex regex = new Regex(@"KB[0-9]{6,7}"); //Regex(@"(\w{2}\d{6,7}) ?"); //SortedSet    ,     ""     SortedSet<string> spisok = new SortedSet<string>(); XmlDocument xDoc = new XmlDocument(); string path = "C:\\Windows\\servicing\\Packages\\wuindex.xml"; //   xml xDoc.Load(path); int kol = 0; //-  int total = 0; //-    xml int total2 = 0; //-   XmlNodeList name = xDoc.GetElementsByTagName("Mappings"); foreach (XmlNode xnode in name) { //Console.WriteLine(xnode.Name); kol++; XmlNode attr = xnode.Attributes.GetNamedItem("UpdateId"); //Console.WriteLine(attr.Value); foreach (XmlNode childnode in xnode.ChildNodes) { XmlNode childattr = childnode.Attributes.GetNamedItem("Package"); total++; //Console.WriteLine(childattr.Value); MatchCollection matches = regex.Matches(childattr.Value); if (matches.Count > 0) { foreach (Match match in matches) //Console.WriteLine(match.Value); spisok.Add(match.Value); } else { //Console.WriteLine("  "); } } } try { StreamWriter sw = new StreamWriter(writePath); foreach (string element in spisok) { //Console.WriteLine(element); sw.WriteLine(element); total2++; } sw.Close(); } catch (Exception ex) { Console.WriteLine(": " + ex.Message); } //Console.WriteLine("\n"); Console.WriteLine(" : " +kol); Console.WriteLine("    xml: " + total); Console.WriteLine(" KB : " + total2); Console.WriteLine("    ."); Console.Read(); } } } 


Sayangnya, file ini tidak ditemukan di semua sistem dan prinsip pembuatannya dan pemutakhiran tetap menjadi misteri bagi saya. Karena itu, sekali lagi metode ini tidak cocok untuk kita.

Cb


Di sini kita sampai pada apa yang terkait dengan semua metode ini. Melanjutkan analisis log Monitor Proses, saya mengidentifikasi folder dan file berikut.

File DataStore.edb terletak di folder C: \ Windows \ SoftwareDistribution \ DataStore . Ini adalah database yang berisi riwayat semua pembaruan untuk versi Windows yang diinstal, termasuk yang hanya di-antri.

Program ESEDatabaseView digunakan untuk menganalisis file DataStore.edb. Ada tabel tbUpdates dalam database, yang isinya sulit ditafsirkan.

Tabel TbUpdates di ESEDatabaseView

Setelah perhatian saya tertarik pada proses TiWorker.exe , yang dipanggil setiap kali saya membuka item di Control Panel. Dia "berjalan" melalui banyak folder, salah satunya membawa saya ke jalur yang benar.

C: \ Windows \ SoftwareDistribution adalah folder yang digunakan oleh Pembaruan Windows untuk mengunduh pembaruan ke komputer dan menginstalnya, dan juga menyimpan informasi tentang semua pembaruan yang diinstal sebelumnya.

Folder WinSxS terletak di C: \ Windows \ winsxs . Ini adalah folder layanan sistem operasi Windows yang digunakan untuk menyimpan versi komponen sistem yang diinstal sebelumnya. Karena keberadaannya, dimungkinkan untuk memutar kembali ke versi pembaruan yang lebih lama jika perlu.

C: \ Windows \ servicing - komponen utama dari keseluruhan sistem, yang namanya adalah Component-Based Servicing (CBS) .

CBS adalah layanan berbasis komponen yang merupakan bagian dari Windows dan terintegrasi dengan layanan Pembaruan Windows. Berbeda dengan layanan File-Based Servicing (FBS) (untuk sistem operasi sebelum Windows Vista), di mana file diperbarui langsung di direktori sistem, CBS memperkenalkan seluruh hierarki direktori dan seluruh keluarga (tumpukan) modul / perpustakaan layanan.

CbsApi.dll adalah perpustakaan dukungan teknologi CBS utama. Tidak ada metode terbuka, jadi saya tidak bisa menggunakannya secara langsung. Microsoft menggunakan TrustedInstaller.exe dan TiWorker.exe untuk mengakses metode perpustakaan ini dan sudah melalui proses ini menampilkan data yang kami butuhkan. Catatan dipelihara dalam C: \ Windows \ Logs \ CBS \ CBS.log .

Pada saat pembuatan prototipe program (Anda dapat melihat Mei 2019 di screenshot), tidak ada informasi berbahasa Rusia tentang CBS, tetapi pada akhir Agustus ada artikel blog yang sangat bagus - http://datadump.ru/component-based-servicing . Artikel yang sangat menarik yang mengkonfirmasi pengalaman saya dan mengumpulkan informasi yang diperlukan. Dan lebih banyak tentang topik: http://www.outsidethebox.ms/17988/

Kesimpulan


Microsoft telah terlalu rumit tugas sepele untuk mendapatkan daftar pembaruan dan membuat proses ini tidak sepenuhnya jelas. Semua ini dilakukan untuk keamanan, tetapi bukan untuk kemudahan penggunaan. Saya setuju dengan penulis artikel - prediktabilitas dan transparansi mulai tidak ada dalam menerima pembaruan.

Sebagai hasil dari penelitian ini, program berikut ini ditulis, sebuah demonstrasi yang dapat dilihat dalam video ini:


Rencana untuk menambahkan:

  1. membandingkan daftar pembaruan yang diperlukan dengan yang diterima;
  2. kirim hasilnya melalui SNMP / OPC (jika ada yang punya pengalaman, bagikan dalam komentar);
  3. mengatur instalasi pembaruan "offline" yang hilang dari folder yang ditentukan.

Jika Anda mengetahui lebih banyak metode untuk mendapatkan daftar tidak hanya pembaruan, tetapi juga komponen tambahan (Adobe Flash, Acrobat Reader, dll.) Atau Anda memiliki saran menarik lainnya, tulis tentang itu di komentar atau di pesan pribadi - Saya akan dengan senang hati menerima umpan balik . Dan ikut serta dalam survei untuk artikel ini - jadi saya akan tahu apakah pengalaman saya dengan audiens Habrahabr akan menarik.

Source: https://habr.com/ru/post/id467445/


All Articles