استخدام WMI/CIM من C# وPowerShell ── دليل عمليّ لاسترجاع معلومات العتاد ومراقبة العمليّات والاستعلام عن بُعد
· غو كومورا · Windows, C#, .NET, PowerShell, WMI, CIM, تطبيقات الأعمال, تطوير Windows
«أريد عرض الرقم التسلسليّ للحاسوب واسم طرازه في شاشة تطبيق أعمال.» «أريد مراقبة المساحة الحرّة على قرص خادم ورفع تحذير.» «أريد كشف بدء عمليّة معيّنة.» «أريد جمع حالة حواسيب في موقع بعيد في موضع واحد.» ── متطلّبات من هذا النوع تظهر مراراً عند بناء تطبيقات أعمال Windows وأدوات الإدارة. والإجابة الكلاسيكيّة عليها هي WMI (Windows Management Instrumentation)، أو، باسمها القياسيّ، CIM (Common Information Model).
flowchart TB
accTitle: المتطلّبات الكلاسيكيّة وWMI/CIM
accDescr: الإجابة الكلاسيكيّة على متطلّبات تطبيقات الأعمال الكلاسيكيّة ── عرض الرقم التسلسليّ واسم الطراز، ومراقبة المساحة الحرّة على القرص، وكشف بدء عمليّة، واستعلام حاسوب بعيد ── هي WMI، أو CIM باسمها القياسيّ
r1["رقم تسلسليّ وطراز"] --> ans["WMI(الاسم القياسيّ CIM)"]
r2["مراقبة المساحة الحرّة"] --> ans
r3["كشف بدء عمليّة"] --> ans
r4["استعلام حاسوب بعيد"] --> ans
الشكل 1: الإجابة الكلاسيكيّة على المتطلّبات الأربعة الكلاسيكيّة لتطبيقات الأعمال هي WMI/CIM.
ما يجعل الأمر شائكاً أنّ معلومات WMI خليط من قديم وجديد. ابحث فتجد مقالات عمرها عشر سنوات تستخدم Get-WmiObject إلى جانب مقالات تستخدم Get-CimInstance، وعلى جانب C# سلالتان منفصلتان: System.Management وMicrosoft.Management.Infrastructure. يصعب تمييز أيّهما أسلوب الكتابة الحاليّ وأيّهما «ما يزال يعمل لكن لا ينبغي اختياره للكود الجديد». في الواقع، Get-WmiObject غير موجود في PowerShell 7 أصلاً، ويظهر ذلك فجأة عند ترحيل سكربت داخليّ كُتب لـ 5.1.
يستهدف هذا المقال مطوّري C#/PowerShell الذين ينفّذون استرجاع معلومات العتاد ومراقبة العمليّات واستعلام الحواسيب عن بُعد في تطبيقات الأعمال. ينطلق من فهم أدنى لبنية WMI/CIM، عبر أوامر CIM في PowerShell، والواجهتين في C#، ووصفات شائعة، ومزالق الأداء والامتيازات و64-bit، وصولاً إلى الحكم على «مواقف لا ينبغي فيها استخدام WMI» ── كلّ ذلك مرتَّباً من مصادر أوّليّة حتّى أغسطس 2026.
1. الخلاصة أوّلاً
- CIM هو النموذج القياسيّ الصناعيّ لمعلومات الإدارة الذي يضعه DMTF، وWMI هو تنفيذ Microsoft له. واجهات عائلة «CIM» في PowerShell وC# هي جيل الواجهات الحاليّ الذي يتّبع هذا المعيار، وتتّصل بأساس WMI نفسه.1
- في PowerShell، الجيل الحاليّ هو أوامر CIM (Get-CimInstance / Invoke-CimMethod / Register-CimIndicationEvent). أوامر WMI القديمة (Get-WmiObject وأربعة غيرها) حُذفت بدءاً من PowerShell 6 ولا تعمل في PowerShell 7.2
- فضاء الأسماء الافتراضيّ هو root/CIMV2، والاستعلام اليوميّ في جوهره تضييق أصناف Win32_* هناك بـ WQL.3
- الاستعلام عن بُعد يفترض WSMan (WinRM) افتراضيّاً. تحديد
-ComputerNameينشئ جلسة WSMan مؤقّتة. إن كنت ستستعلم الهدف نفسه مراراً، فإعادة استخدام جلسة CIM (New-CimSession) هي الممارسة المستقرّة للأداء، وللأهداف القديمة التي لا يمكن تكوين WinRM عليها يوجد خيار بروتوكول DCOM.34 - في C# سلالتان: System.Management (ManagementObjectSearcher) وMicrosoft.Management.Infrastructure (CimSession). كلاهما خاصّ بـ Windows، وعلى .NET الحاليّ تجلبهما عبر NuGet. إن كنت تبني استعلاماً عن بُعد أو مراقبة في منتج حقيقيّ، فواجهة MI ── التي تشارك نظام أنواع أوامر CIM ── الأنسب.56
- اكشف بدء العمليّات باشتراك في حدث، لا باستطلاع. اشتراك
Win32_ProcessStartTraceيجب تشغيله بامتيازات مدير.78 - لا تستخدم
SELECT *بالعادة. تضييق ما يُنقَل بـ-Filter/-Property/-KeyOnlyيقي من نحو نصف مشاكل أداء WMI.3 - WMI ليس حلاً لكلّ شيء. للمراقبة المستمرّة عالية التواتر، أو قراءة إعدادات تطبيقك وكتابتها، أو استدعاءات وظائف نظام التشغيل لمرّة واحدة، فإنّ عدّادات الأداء أو السجلّ أو Win32 API أو أوامر مخصّصة الغرض أنسب (انظر جدول القرار في القسم 8).
2. ما هو WMI/CIM ── المعيار والتنفيذ، فضاءات الأسماء، الأصناف، وWQL
أوّلاً، لنرتّب المصطلحات مرّة واحدة وإلى الأبد.
| المصطلح | ما هو |
|---|---|
| CIM (Common Information Model) | النموذج القياسيّ الصناعيّ لتمثيل أهداف الإدارة كالأنظمة والتطبيقات والشبكات والأجهزة. يضعه ويصونه DMTF (Distributed Management Task Force)1 |
| WBEM (Web-Based Enterprise Management) | مبادرة صناعيّة لإنشاء تقنيّات قياسيّة للوصول إلى معلومات الإدارة في بيئات المؤسّسات1 |
| WMI | تنفيذ Microsoft لـ WBEM. يمثّل أهداف الإدارة بمعيار CIM وهو مدمج في Windows1 |
| MI (Windows Management Infrastructure) | الجيل التالي من WMI. متوافق تماماً مع WMI القديم، ومعظم المزوّدات الجديدة مكتوبة بـ MI1 |
flowchart TB
accTitle: علاقة معيار CIM بتنفيذ WMI
accDescr: معيار CIM الذي يضعه ويصونه DMTF يُستخدَم في إطار مبادرة WBEM، وتنفيذ Microsoft له هو WMI، والجيل التالي MI متوافق تماماً مع WMI القديم، وواجهات عائلة CIM تتّصل بأساس WMI نفسه
dmtf["DMTF يضع المعيار ويصونه"] --> cim["CIM(نموذج قياسيّ صناعيّ)"]
wbem["WBEM(مبادرة صناعيّة)"] --> wmi["WMI(تنفيذ Microsoft)"]
cim --> wmi
wmi -.-> mi["MI(الجيل التالي・توافق كامل)"]
api["واجهات CIM(PowerShell / C#)"] --> wmi
الشكل 2: CIM هو المواصفة، وWMI هو التنفيذ على Windows. واجهات عائلة CIM تتّصل بأساس WMI نفسه.
بوصفك مطوّراً، هناك أربع قطع بنيويّة تستحقّ الفهم.
- فضاء الأسماء (namespace): تراتب يجمع الأصناف. للاستعلام اليوميّ ستستخدم تقريباً دائماً root/CIMV2، وهو أيضاً افتراضيّ أوامر CIM.3 ومن غيره
root\default(مزوّد السجلّ، بين أمور أخرى). - الصنف: نوع يمثّل هدف إدارة، مثل
Win32_ComputerSystem(الحاسوب نفسه)، أوWin32_LogicalDisk(محرّك منطقيّ)، أوWin32_Process(عمليّة). الأصناف الخاصّة بـ Windows التي ترث أصناف معيار CIM (مثلCIM_LogicalDisk) تحمل البادئةWin32_.9 - المزوّد: المكوّن الذي يقدّم مادّة الصنف. عندما تستعلمه، يسأل المزوّد نظام التشغيل في الحال ويبني القيم.
- WQL: لغة استعلام شبيهة بـ SQL. كما في
SELECT Name, State FROM Win32_Service WHERE StartMode = 'Auto'، تعامل الصنف كجدول وتضيّقه. وWQL أيضاً لغة الاستعلام الافتراضيّة لأوامر CIM.3
«قراءة معلومات نظام التشغيل والعتاد عبر مجموعة موحّدة من الأصناف ولغة استعلام» ── تلك هي قيمة WMI. وبالمقابل، الكتابة والتحكّم محصوران في المجموعة الفرعيّة من الأصناف التي تملك طرائق يمكن استدعاؤها عبر Invoke-CimMethod؛ ليست آليّة تفعل أيّ شيء على الإطلاق.
flowchart TB
accTitle: بنية استعلام WMI
accDescr: استعلام WQL يُوجَّه إلى أصناف Win32_* داخل فضاء الأسماء root/CIMV2، والمزوّد الذي يقدّم مادّة الصنف يسأل نظام التشغيل في الحال ويبني القيم ثمّ تُرجع النتيجة
wql["استعلام بـ WQL"] --> ns["فضاء الأسماء root/CIMV2"]
ns --> cls["أصناف Win32_*"]
cls --> prov["المزوّد"]
prov --> osq["يسأل نظام التشغيل في الحال"]
osq --> res["يُرجع النتيجة"]
الشكل 3: الاستعلام يسير من فضاء الأسماء إلى الصنف إلى المزوّد، والقيم تُبنى في الحال.
3. الاستخدام من PowerShell ── أوامر CIM هي الجيل الحاليّ، وأوامر WMI محذوفة
3.1. الأساس: Get-CimInstance
# تحديد الصنف (فضاء الأسماء الافتراضيّ root/CIMV2)
Get-CimInstance -ClassName Win32_OperatingSystem
# اكتب في -Filter محتوى جملة WHERE فقط (لا تكتب الكلمة WHERE نفسها)
Get-CimInstance -ClassName Win32_Service -Filter "StartMode = 'Auto' AND State <> 'Running'"
# اجلب الخصائص اللازمة فقط لتقليل حجم النقل
Get-CimInstance -ClassName Win32_Process -Property Name, ProcessId, CreationDate
# استخدم -Query إن أردت كتابة WQL كما هو
Get-CimInstance -Query "SELECT * FROM Win32_Process WHERE Name LIKE 'p%'"
-Filter هو جملة WHERE في WQL بحذافيرها، و-Property يقيّد الأعمدة المجلوبة.3 القيمة المُرجَعة كائن CimInstance، وخصائص التاريخ (مثل CreationDate أو LastBootUpTime) تعود وقد حُوِّلت سلفاً إلى DateTime. بخلاف Get-WmiObject القديم، الكائن المجلوب لا يحمل طرائق مباشرة، لذا تُجرى استدعاءات الطرائق بتمريره إلى Invoke-CimMethod.
flowchart TB
accTitle: استدعاء طرائق CimInstance
accDescr: CimInstance الذي يرجعه Get-CimInstance تعود خصائص تاريخه محوَّلة إلى DateTime، لكنّه لا يحمل طرائق مباشرة، لذا يُمرَّر المثيل إلى Invoke-CimMethod لاستدعاء الطريقة
gci["Get-CimInstance"] --> inst["كائن CimInstance"]
inst -.-> dt["التاريخ DateTime جاهز"]
inst -.-> nom["لا يحمل طرائق مباشرة"]
inst --> icm["يُمرَّر إلى Invoke-CimMethod"]
icm --> call["استدعاء الطريقة"]
الشكل 4: CimInstance لا يحمل طرائق، لذا يُمرَّر استدعاء الطريقة إلى Invoke-CimMethod.
# استدعاء طريقة على المثيل: الحصول على مالك كلّ عمليّة
Get-CimInstance -ClassName Win32_Process -Filter "Name = 'notepad.exe'" |
Invoke-CimMethod -MethodName GetOwner
# استدعاء طريقة صنف ساكنة: تشغيل عمليّة
Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{ CommandLine = 'notepad.exe' }
# فحص تعريف الصنف (الخصائص والطرائق)
Get-CimClass -ClassName Win32_Process
3.2. جدول الترحيل من أوامر WMI القديمة
بدءاً من PowerShell 6 (بما فيه PowerShell 7 الحاليّ)، حُذفت أوامر WMI v1 التالية. الوظيفة نفسها يوفّرها مكوّن CimCmdlets (WMI v2).2
| القديم (حتّى Windows PowerShell 5.1) | الحاليّ (أوامر CIM) | ملاحظات |
|---|---|---|
Get-WmiObject |
Get-CimInstance |
مفهوما -Filter / -Query هما نفسهما |
Get-WmiObject -List |
Get-CimClass |
اكتشاف تعريفات الأصناف وفحصها |
Invoke-WmiMethod |
Invoke-CimMethod |
تُمرَّر الوسائط كجدول تجزئة عبر -Arguments @{ } |
Register-WmiEvent |
Register-CimIndicationEvent |
اشتراك الأحداث (القسم 6.3) |
Set-WmiInstance |
Set-CimInstance |
تغيير الخصائص القابلة للكتابة |
Remove-WmiObject |
Remove-CimInstance |
حذف مثيل |
أوامر CIM تعمل أيضاً تحت Windows PowerShell 5.1، لذا أيّ شيء تكتبه من الآن فصاعداً ينبغي كتابته بـ CIM حتّى إن كان سيعمل تحت 5.1 ── بذلك لا تُبقي تكلفة ترحيل خلفك. للصورة الكاملة للتعايش بين 5.1 و7 والترحيل بينهما، انظر «الفروق بين Windows PowerShell 5.1 وPowerShell 7 ── دليل عمليّ لترحيل السكربتات الداخليّة».
flowchart TB
accTitle: لماذا تكتب السكربت الجديد بـ CIM
accDescr: سكربت كُتب بأوامر WMI يعمل على 5.1 لكنّه محذوف بدءاً من PowerShell 6 فيلزم إعادة كتابته عند الترحيل، وأوامر CIM تعمل على 5.1 أيضاً لذا كتابة الجديد على جانب CIM لا تُبقي تكلفة ترحيل
new["سكربت جديد تكتبه"] --> q1{"بماذا تكتبه؟"}
q1 -->|أوامر WMI| old["يعمل على 5.1"]
q1 -->|أوامر CIM| cur["يعمل على 5.1 أيضاً"]
old --> del["محذوف في PowerShell 7"]
del --> rew["إعادة كتابة عند الترحيل"]
cur --> norew["لا تكلفة ترحيل متبقية"]
الشكل 5: اكتب الجديد بأوامر CIM فلا تحتاج إعادة كتابة عند الترحيل إلى PowerShell 7.
4. الاستعلام عن بُعد ── جلسات CIM (WSMan افتراضيّاً) وخيار DCOM
إن لم تحدِّد هدفاً، تتّصل أوامر CIM بـ WMI المحلّيّ عبر COM؛ وإن حدّدت -ComputerName، أنشأت جلسة مؤقّتة عبر بروتوكول WSMan (WinRM) للاتّصال. عندما تؤدّي عدّة عمليّات ضدّ الحاسوب نفسه، إنشاء جلسة CIM وإعادة استخدامها أفضل للأداء.3
flowchart TB
accTitle: اختيار طريقة اتّصال CIM
accDescr: بلا تعيين يكون الاتّصال COM بـ WMI المحلّيّ، وتعيين ComputerName ينشئ جلسة WSMan مؤقّتة عند كلّ استعلام، والعمليّات المتعدّدة على الهدف نفسه تستفيد أداءً من إعادة استخدام New-CimSession، وللهدف بلا WinRM يوجد خيار بروتوكول DCOM
exec["تنفيذ أمر CIM"] --> q1{"هل حُدِّد ComputerName؟"}
q1 -->|لا| local["اتّصال COM بـ WMI المحلّيّ"]
q1 -->|نعم| q2{"عمليّات متعدّدة على الهدف نفسه؟"}
q2 -->|مرّة واحدة| temp["جلسة WSMan مؤقّتة"]
q2 -->|عدّة| sess["إعادة استخدام New-CimSession"]
temp -.-> cost["تُنشأ عند كلّ استعلام"]
nowinrm["هدف بلا تكوين WinRM"] -.-> dcom["خيار بروتوكول DCOM"]
الشكل 6: الاستعلام عن بُعد يفترض WSMan افتراضيّاً، والعمليّات المتعدّدة على الهدف نفسه تُعاد فيها استخدام جلسة CIM.
# لاستعلام لمرّة واحدة استخدم -ComputerName (تُنشأ جلسة مؤقّتة في كلّ مرّة)
Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName Server01, Server02
# للاستعلامات المتكرّرة أعد استخدام جلسة CIM
$session = New-CimSession -ComputerName Server01
Get-CimInstance -ClassName Win32_OperatingSystem -CimSession $session
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType = 3" -CimSession $session
Remove-CimSession $session
للأهداف التي لا تبلغها عبر WSMan ── كالآلات القديمة التي لا يمكن تكوين WinRM عليها ── يمكنك اختيار بروتوكول DCOM بدل ذلك.4
$dcom = New-CimSessionOption -Protocol Dcom
$session = New-CimSession -ComputerName OldServer -SessionOption $dcom
مقدّمات الاستعلام عن بُعد كما يلي.
- يجب أن يكون WinRM مكوَّناً على الهدف.
winrm quickconfigيضبط الخدمة لتبدأ تلقائيّاً، وينشئ مستمع HTTP (المنفذ الافتراضيّ 5985)، ويسجّل استثناء جدار حماية، دفعة واحدة.10 إن أردت الاتّصال عبر HTTPS (المنفذ الافتراضيّ 5986)، فهذا وحده لا يكفي ── تحتاج إلى إعداد شهادة خادم وتكوين مستمع HTTPS على حدة بأمر مثلwinrm quickconfig -transport:https.10 - يجب أن تكون المنافذ المعنيّة مفتوحة على أيّ جدران حماية على المسار. العمل العمليّ لتصميم قواعد الوارد وتسجيلها مشمول في مقال «جدار حماية Windows وتطبيقات الأعمال».
- المصادقة. في بيئة نطاق يوفّر Kerberos مصادقة متبادلة. في مجموعة عمل لا يتوفّر Kerberos، فقد تحتاج إلى تسجيل الهدف في قائمة
TrustedHostsلدى العميل. أبقِ تلك القائمة أضيق ما يمكن.10 - الامتيازات. في التكوين الافتراضيّ، تُجرى استعلامات WMI عن بُعد وعمليّاته أساساً بحساب ينتمي إلى مجموعة المديرين على الهدف. لفتح هذا للمستخدمين العاديّين، تحتاج إلى تكوين أذونات الوصول على WinRM وفضاء أسماء WMI كليهما.10
- لاحظ أنّ DCOM لا يملك منفذ استماع ثابتاً (يستخدم منافذ RPC ديناميكيّة)، ما يصعّب التصميم عبر حدود جدار حماية. الأسلم افتراض WSMan افتراضيّاً لأيّ شيء تبنيه من الآن فصاعداً.
flowchart TB
accTitle: التحقّق من مقدّمات الاستعلام عن بُعد
accDescr: على الهدف ينفّذ winrm quickconfig تشغيل الخدمة تلقائيّاً وإنشاء مستمع HTTP وتسجيل استثناء جدار حماية دفعة واحدة، ومستمع HTTPS يُكوَّن على حدة بعد إعداد شهادة، وفي بيئة مجموعة عمل قد يلزم التسجيل في TrustedHosts
qc["winrm quickconfig"] --> svc["تشغيل الخدمة تلقائيّاً"]
qc --> lis["إنشاء مستمع HTTP(5985)"]
qc --> fw["استثناء جدار الحماية"]
lis ~~~ https["مستمع HTTPS(5986)"]
https -.-> cert["جهِّز شهادة وكوِّنه منفصلاً"]
fw ~~~ wg["بيئة مجموعة عمل"]
wg -.-> th["التسجيل في TrustedHosts"]
الشكل 7: winrm quickconfig ينفّذ التكوين الافتراضيّ دفعة واحدة، ومستمع HTTPS ومصادقة مجموعة العمل يُعالَجان على حدة.
5. الاستخدام من C# ── System.Management مقابل Microsoft.Management.Infrastructure
هناك سلالتان من الواجهات لاستخدام WMI من C#. كلاهما خاصّ بـ Windows.
| System.Management | Microsoft.Management.Infrastructure (واجهة MI) | |
|---|---|---|
| الجلب | مضمَّن افتراضيّاً في .NET Framework. على .NET الحاليّ، حزمة NuGet System.Management5 | حزمة NuGet Microsoft.Management.Infrastructure6 |
| صنف المدخل | ManagementObjectSearcher (مرِّر WQL للاستعلام)5 |
CimSession (Create → QueryInstances / InvokeMethod / Subscribe)6 |
| نظام الأنواع | ManagementObject / ManagementEventWatcher11 |
CimInstance / CimSession ── الأنواع نفسها لأوامر CIM3 |
| الوصول عن بُعد | قائم على DCOM | قائم على WSMan (جلسة CIM). تتوفّر متغيّرات غير متزامنة (*Async)6 |
| الأنسب لـ | استرجاع معلومات محلّيّ. صيانة أصول كود قائمة | بناء استعلام عن بُعد ومراقبة. تصاميم تقترن بـ PowerShell |
5.1. System.Management: أساسيّات ManagementObjectSearcher
تمرّر WQL كسلسلة وتستقبل مجموعة نتائج عبر Get().5
// NuGet: System.Management (حصريّ لـ Windows)
using System.Management;
using var searcher = new ManagementObjectSearcher(
@"root\cimv2",
"SELECT DeviceID, FreeSpace, Size FROM Win32_LogicalDisk WHERE DriveType = 3");
foreach (ManagementObject disk in searcher.Get())
{
var freeGb = (ulong)disk["FreeSpace"] / 1024.0 / 1024.0 / 1024.0;
var sizeGb = (ulong)disk["Size"] / 1024.0 / 1024.0 / 1024.0;
Console.WriteLine($"{disk["DeviceID"]} فارغ {freeGb:F1} GB / الإجمالي {sizeGb:F1} GB");
}
تُرجع الخصائص كـ object عبر مفهرس، لذا تحتاج إلى التحقّق من توثيق الصنف لنوع CIM (في هذا المثال، FreeSpace / Size هما uint649) والتحويل تبعاً لذلك. افتراض أنّه int والتحويل على ذلك الافتراض، فينتج InvalidCastException، هو أوّل مطبّ كلاسيكيّ هنا.
flowchart TB
accTitle: مطبّ جلب الخاصّيّة والتحويل
accDescr: خصائص System.Management تُرجع كـ object عبر المفهرس، لذا يلزم التحقّق من نوع CIM في توثيق الصنف ثمّ التحويل، وافتراض int والتحويل عليه يُنتج InvalidCastException
idx["جلب بالمفهرس"] --> obj["يُرجع كـ object"]
obj --> chk["أكِّد نوع CIM من التوثيق"]
chk --> cast["حوِّل إلى النوع الصحيح"]
obj -.-> wrong["افترض int وحوِّل"]
wrong -.-> ex["InvalidCastException"]
الشكل 8: الخصائص تُرجع كـ object، فأكِّد نوع CIM ثمّ حوِّل.
5.2. واجهة MI: أساسيّات CimSession
CimSession يعالج الوصول المحلّيّ وعن بُعد بالشكل نفسه. يغطّي العدّ والاستعلام واستدعاء الطرائق واشتراك الأحداث والمتغيّرات غير المتزامنة في موضع واحد.6
// NuGet: Microsoft.Management.Infrastructure (حصريّ لـ Windows)
using Microsoft.Management.Infrastructure;
// للمحلّيّ CimSession.Create(null)، وللبعيد مرِّر اسم الحاسوب
using CimSession session = CimSession.Create(null);
IEnumerable<CimInstance> disks = session.QueryInstances(
@"root\cimv2", "WQL",
"SELECT DeviceID, FreeSpace, Size FROM Win32_LogicalDisk WHERE DriveType = 3");
foreach (CimInstance disk in disks)
{
var deviceId = (string)disk.CimInstanceProperties["DeviceID"].Value;
var free = (ulong)disk.CimInstanceProperties["FreeSpace"].Value;
Console.WriteLine($"{deviceId} فارغ {free / 1024.0 / 1024 / 1024:F1} GB");
}
ولأنّه يعمل مع CimInstance نفسه الذي ترجعه أوامر CIM في PowerShell، فإنّ تدفّق تطوير «جرِّبه في PowerShell أوّلاً، ثمّ انسخه إلى C#» يتّصل بسلاسة. إن كنت تصمّم التكامل بين C# وPowerShell نفسه، فانظر أيضاً «طريقة تشغيل PowerShell من C# (CSharp) واستقبال النتيجة ككائن».
flowchart TB
accTitle: جرِّب في PowerShell ثمّ انسخ إلى C#
accDescr: أوامر CIM في PowerShell وواجهة MI في C# تتعاملان مع نوع CimInstance نفسه، لذا يتّصل تدفّق التطوير من التجريب في PowerShell إلى النسخ إلى C# بسلاسة
trial["جرِّب في PowerShell"] --> gci["أوامر CIM"]
impl["نفِّذ في C#"] --> mi["واجهة MI"]
gci --> ci["نوع CimInstance نفسه"]
mi --> ci
ci -.-> flow["النسخ يسير بسلاسة"]
الشكل 9: أوامر CIM وواجهة MI تتعاملان مع نوع CimInstance نفسه، فيتّصل التجريب بالتنفيذ.
6. وصفات شائعة الاستخدام
6.1. مرجع سريع للأصناف الشائعة
| المعلومات المطلوبة | الصنف | الخصائص الرئيسة |
|---|---|---|
| الشركة المصنِّعة / اسم الطراز | Win32_ComputerSystem |
Manufacturer, Model |
| الرقم التسلسليّ للهيكل | Win32_BIOS |
SerialNumber |
| إصدار نظام التشغيل / وقت الإقلاع | Win32_OperatingSystem |
Caption, Version, LastBootUpTime |
| المساحة الحرّة على القرص | Win32_LogicalDisk |
DeviceID, FreeSpace, Size, DriveType9 |
| حالة الخدمة | Win32_Service |
Name, State, StartMode |
| قائمة العمليّات | Win32_Process |
Name, ProcessId, CommandLine |
6.2. ثابت إدارة الأصول: الرقم التسلسليّ واسم الطراز والمساحة الحرّة على القرص
# معلومات الطراز والرقم التسلسليّ (لمطابقتها مع سجلّ أصول الحواسيب)
$cs = Get-CimInstance -ClassName Win32_ComputerSystem -Property Manufacturer, Model
$bios = Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber
[pscustomobject]@{
Manufacturer = $cs.Manufacturer
Model = $cs.Model
Serial = $bios.SerialNumber
}
# المساحة الحرّة على الأقراص المحلّيّة (DriveType = 3)
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType = 3" |
Select-Object DeviceID,
@{ Name = 'FreeGB'; Expression = { [math]::Round($_.FreeSpace / 1GB, 1) } },
@{ Name = 'SizeGB'; Expression = { [math]::Round($_.Size / 1GB, 1) } }
DriveType = 3 يمثّل «قرصاً محلّيّاً»، مستبعداً القابل للإزالة (2)، ومحرّكات الشبكة (4)، ومحرّكات الأقراص المضغوطة (5).9 للمراقبة، يكفي تمرير هذا السكربت إلى كلّ خادم عبر جلسة CIM لتحصل على أساس مراقبة أقراص بلا وكيل.
flowchart TB
accTitle: أساس مراقبة أقراص بلا وكيل
accDescr: التضييق بـ DriveType 3 يستبعد القابل للإزالة ومحرّكات الشبكة والأقراص المضغوطة ليستهدف الأقراص المحلّيّة فقط، وتمرير السكربت نفسه عبر جلسة CIM إلى كلّ خادم يبني أساس مراقبة أقراص بلا وكيل
scr["سكربت المساحة الحرّة"] --> flt["صفِّ بـ DriveType = 3"]
flt -.-> exc["استبعد القابل للإزالة وغيره"]
scr --> ses["عبر جلسة CIM"]
ses --> srvs["مرِّره على كلّ خادم"]
srvs --> mon["مراقبة بلا وكيل"]
الشكل 10: تمرير سكربت مضيَّق إلى الأقراص المحلّيّة عبر جلسة CIM إلى كلّ خادم هو أساس المراقبة.
6.3. كشف بدء العمليّات ── اشتراك في الأحداث
بدل «جلب Win32_Process دوريّاً بالاستطلاع ومقارنة الفرق»، استخدم اشتراك حدث. أبسط طريقة لالتقاط بدء عمليّة هي الاشتراك في Win32_ProcessStartTrace (صنف حدث من مزوّد تتبّع النواة، بخصائص مثل ProcessName / ProcessID / ParentProcessID8).
# نفِّذ من جلسة PowerShell بامتياز المسؤول
$action = {
$name = $Event.SourceEventArgs.NewEvent.ProcessName
$id = $Event.SourceEventArgs.NewEvent.ProcessID
Write-Host "شُغِّلت العمليّة: $name (PID=$id)"
}
Register-CimIndicationEvent -ClassName Win32_ProcessStartTrace `
-SourceIdentifier ProcessStarted -Action $action
يبقى الاشتراك حيّاً ما دامت جلسة PowerShell التي سجّلته حيّة، و-Action يعمل في كلّ مرّة تبدأ فيها عمليّة. احذر ألا تشغّل أمر إلغاء الاشتراك مباشرة بعد هذا في الدفعة نفسها ── فذلك يجعل الاشتراك يختفي قبل أن تبدأ المراقبة أصلاً. نفِّذ خطوة الإلغاء فقط عندما تنتهي من المراقبة.
# عند إنهاء المراقبة: إلغاء الاشتراك
Unregister-Event -SourceIdentifier ProcessStarted
Register-CimIndicationEvent يسجّل اشتراكاً باسم صنف أو باستعلام حدث WQL، وكتلة السكربت -Action تعمل في كلّ مرّة يصل فيها حدث.7 الاشتراك في هذا الصنف يتطلّب امتيازات مدير.7 من يمكنه تلقّي الحدث يضبطه واصف أمن صنف الحدث، ويُرفض وصول مستخدم عاديّ بلا امتيازات مرتفعة.8
sequenceDiagram
accTitle: تدفّق اشتراك حدث بدء عمليّة
accDescr: في جلسة PowerShell بامتيازات مدير يسجّل Register-CimIndicationEvent الاشتراك، ويصل حدث عند كلّ بدء عمليّة فيُنفَّذ Action، وعند انتهاء المراقبة يُلغى بـ Unregister-Event
participant ps as جلسة PowerShell
participant wmi as WMI
ps->>wmi: تسجيل الاشتراك بـ Register-CimIndicationEvent
Note over ps: نفِّذ بامتيازات مدير
wmi-->>ps: وصول الحدث عند كلّ بدء عمليّة
ps->>ps: تنفيذ -Action
ps->>wmi: إلغاء بـ Unregister-Event(عند انتهاء المراقبة)
الشكل 11: الاشتراك يبقى سارياً ما دامت الجلسة التي سجّلته حيّة، والإلغاء يكون عند انتهاء المراقبة.
خيار آخر هو حدث إنشاء المثيل العامّ (__InstanceCreationEvent)، الذي يمكن استخدامه مع أيّ صنف. يعمل بأن يستطلع WMI بالفاصل الذي تحدّده بـ WITHIN ويحوّل الفرق الناتج إلى حدث، لذا تقرّر بنفسك المفاضلة بين فاصل الكشف والحمل.
flowchart TB
accTitle: طريقتا اشتراك لكشف بدء عمليّة
accDescr: Win32_ProcessStartTrace طريقة تشترك في صنف حدث مزوّد تتبّع النواة، و__InstanceCreationEvent العامّ يستطلع WMI بفاصل WITHIN ويحوّل الفرق إلى حدث لذا تقرّر بنفسك مفاضلة فاصل الكشف والحمل
goal["كشف بدء عمليّة"] --> t1["Win32_ProcessStartTrace"]
goal --> t2["__InstanceCreationEvent"]
t1 -.-> k1["اشتراك في تتبّع النواة"]
t2 -.-> w1["استطلاع بفاصل WITHIN"]
w1 -.-> tr["مفاضلة الفاصل والحمل"]
الشكل 12: إمّا الاشتراك في صنف حدث مخصّص، أو استخدام حدث إنشاء مثيل عامّ بفاصل استطلاع.
# راقب مثيلات Win32_Process الجديدة باستطلاع كلّ 5 ثوانٍ
$query = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'"
Register-CimIndicationEvent -Query $query -SourceIdentifier ProcPoll -Action {
Write-Host "شُغِّل: $($Event.SourceEventArgs.NewEvent.TargetInstance.Name)"
}
في C# (System.Management)، يؤدّي ManagementEventWatcher الدور نفسه.11
using System.Management;
// من عمليّة تعمل بامتياز المسؤول
var watcher = new ManagementEventWatcher(
new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace"));
watcher.EventArrived += (_, e) =>
{
var name = (string)e.NewEvent["ProcessName"];
var pid = (uint)e.NewEvent["ProcessID"];
Console.WriteLine($"شُغِّلت العمليّة: {name} (PID={pid})");
};
watcher.Start();
// عند انتهاء المراقبة لا تنسَ watcher.Stop() و Dispose
إن كنت تبني هذا في مكوّن مراقبة مقيم، فتأكّد أنّ تصميمك يشمل أيضاً إعادة تسجيل الاشتراك عندما ينقطع (عند إعادة تشغيل الخدمة أو عند خطأ). اعتبارات تصميم «التحقّق من الحالة وعرضها»، بما في ذلك مراقبة الأجهزة، مشمولة في «أفضل الممارسات للتحقّق من حالة الأجهزة الخارجيّة وعرضها - لماذا لا تكفي عبارة «متّصل» وحدها».
stateDiagram-v2
accTitle: دورة حياة اشتراك المراقبة المقيمة
accDescr: في المراقبة المقيمة قد تنقطع حالة الاشتراك بإعادة تشغيل الخدمة أو بخطأ، لذا يشمل التصميم رصد الانقطاع وإعادة التسجيل والعودة إلى حالة الاشتراك
s1: قيد الاشتراك
s2: انقطع الاشتراك
s3: إعادة التسجيل
[*] --> s1
s1 --> s2: إعادة تشغيل الخدمة・خطأ
s2 --> s3
s3 --> s1
الشكل 13: في المراقبة المقيمة، يشمل التصميم إعادة التسجيل والعودة إلى الاشتراك عندما ينقطع.
7. المزالق ── الأداء والامتيازات و64bit والمستودع والتواريخ
7.1. SELECT * والاستطلاع المفرط
استعلام WMI هو «مزوّد يبني القيم في الحال» ── ليس مجّانيّاً. هناك نمطان كلاسيكيّان مضادّان.
- استخدام
SELECT *بالعادة. جلب كلّ خاصّيّة من كلّ صفّ فيWin32_Processيضخّم عمل المزوّد والنقل عبر الشبكة (عند البعد) تبعاً لذلك. ضيِّق الصفوف بـ-Filter، والأعمدة بـ-Property، واستخدم-KeyOnlyإن لم تحتج إلا مفاتيح لعمليّة لاحقة. هذه كلّها وسائل رسميّة مخصّصة الغرض «لتقليل حجم الكائنات وحركة الشبكة».3 - استطلاع بفاصل قصير. تصميم مثل «
Get-CimInstance Win32_Processكلّ ثانية» ينبغي استبداله بنهج اشتراك الحدث في القسم 6.3. حتّى إن وجب استخدام أسلوب الاستطلاع (WITHIN)، فوسِّع الفاصل إلى ما يكفي المتطلّب فعلاً.
كذلك، تكرار -ComputerName هدفاً هدفاً ضدّ آلات بعيدة مُهدِر، لأنّ جلسة مؤقّتة تُنشأ لكلّ استعلام ── حوِّل إلى إعادة استخدام جلسة CIM للعمليّات المتعدّدة.3
flowchart TB
accTitle: أنماط الأداء المضادّة وبدائلها
accDescr: استخدام SELECT بنجمة بالعادة يُضيَّق بـ Filter وProperty للصفوف والأعمدة ويُستخدم KeyOnly للمفاتيح فقط، والاستطلاع القصير يُستبدل باشتراك حدث، وتكرار ComputerName جهازاً جهازاً يُستبدل بإعادة استخدام جلسة CIM
a1["استخدام SELECT * بالعادة"] --> f1["ضيِّق بـ Filter وProperty"]
f1 -.-> f2["KeyOnly إن أردت المفاتيح فقط"]
a2["استطلاع بفاصل قصير"] --> f3["استبدل باشتراك حدث"]
a3["ComputerName جهازاً جهازاً"] --> f4["أعد استخدام جلسة CIM"]
الشكل 14: تضييق الصفوف والأعمدة والمفاتيح والاستبدال باشتراك حدث يقيان من نصف مشاكل أداء WMI.
7.2. امتيازات اشتراك الأحداث
كما ورد في القسم 6.3، الاشتراك في عائلة Win32_ProcessStartTrace يفترض امتيازات مدير.7 «عمل على آلة التطوير (تشغيلاً كمدير)، لكنّ المراقبة لا تعمل في بيئة المستخدم العاديّ لدى العميل» نمط فشل كلاسيكيّ، يضاهي حوار إشعار جدار الحماية. إن كنت تبني مراقبة في تطبيق أعمال يعمل كمستخدم عاديّ، فانظر في فصل جزء المراقبة إلى خدمة Windows (تعمل كـ LocalSystem مثلاً) وربطها بالتطبيق الرئيس عبر اتّصال بين العمليّات.
flowchart TB
accTitle: تكوين المراقبة في بيئة مستخدم عاديّ
accDescr: الاشتراك الذي يفترض امتيازات مدير يُفصَل عن التطبيق الذي يعمل كمستخدم عاديّ، ويُعزَل جزء المراقبة في خدمة Windows تعمل كـ LocalSystem مثلاً، ويُربَط بالتطبيق عبر اتّصال بين العمليّات
svcm["خدمة Windows للمراقبة"] --> subm["تشترك في تتبّع البدء"]
svcm -.-> lsm["تعمل كـ LocalSystem مثلاً"]
appm["التطبيق(مستخدم عاديّ)"] ---|اتّصال بين العمليّات| svcm
الشكل 15: الاشتراك الذي يحتاج امتيازات مدير يُفصَل إلى جانب الخدمة ويُربَط بالتطبيق عبر اتّصال بين العمليّات.
7.3. 32-bit مقابل 64-bit والمزوّدات
على Windows ذي 64-bit، توجد بعض المزوّدات بنسختي 32-bit و64-bit، وافتراضيّاً النسخة المطابقة لبِتّية المستدعي تجيب الطلب.12 المثال الكلاسيكيّ هو مزوّد السجلّ (StdRegProv) تحت root\default: القراءة من تطبيق 32-bit تُرجع قيماً من جانب Wow6432Node (عرض 32-bit).12 إن كان «قيمة السجلّ المقروءة عبر WMI لا تطابق ما يظهره regedit»، فهذا أوّل ما يُشتبَه به. إن احتجت العرض المقابل، يمكنك طلبه صراحة بتعيين __ProviderArchitecture (و__RequiredArchitecture إن أردت فرضه) في سياق الاتّصال.12 الصورة العامّة لمسائل البِتّية مشمولة أيضاً في «استدعاء Win32 API بأمان من C# ── دليل P/Invoke العمليّ (DllImport / LibraryImport / CsWin32)».
flowchart TB
accTitle: اختيار المزوّد في بيئة 64bit
accDescr: افتراضيّاً يجيب المزوّد المطابق لبِتّية تطبيق المستدعي، واستعلام السجلّ من تطبيق 32bit يتلقّى قيم جانب Wow6432Node، ويمكن طلب العرض المقابل صراحة بتعيين __ProviderArchitecture
q1{"ما بِتّية المستدعي؟"} -->|32bit| p32["يجيب مزوّد 32bit"]
q1 -->|64bit| p64["يجيب مزوّد 64bit"]
p32 -.-> wow["السجلّ من جانب Wow6432Node"]
ctx["تعيين __ProviderArchitecture"] -.-> ov["اطلب العرض المقابل صراحة"]
الشكل 16: افتراضيّاً تجيب الجهة المطابقة لبِتّية المستدعي، لذا يقرأ تطبيق 32bit جانب Wow6432Node.
7.4. أعراض تلف مستودع WMI وعلاجها
تعريفات أصناف WMI مخزَّنة في مستودع (ليس ملفّاً واحداً ── الملفّات داخل مجلّد Repository تعمل معاً كقاعدة بيانات13). عندما يصير غير متّسق، تبدأ أخطاء مثل «صنف يُفترَض وجوده لا يُوجَد» أو «فضاء الأسماء غير صالح» بالظهور، رغم أنّ شيئاً لم يتغيّر في جانب التطبيق. استخدم winmgmt.exe للتشخيص والإصلاح.13
rem فحص الاتّساق (النتيجة inconsistent تعني وجود مشكلة)
winmgmt /verifyrepository
rem فحص الاتّساق وإعادة البناء إن وُجدت مشكلة (يُدمَج المحتوى المقروء)
winmgmt /salvagerepository
المهمّ ألّا تجعل حذف المستودع أو تهيئته خطوتك الأولى. الأخطاء التي تظهر عبر WMI قد تنشأ في موضع آخر من نظام التشغيل، ومايكروسوفت نفسها تنصّ صراحة على أنّ حذف المستودع كاستجابة أولى «قد يسبّب ضرراً للنظام أو للتطبيقات المثبَّتة».13 اتبع الترتيب: افحص بـ /verifyrepository، ثمّ أصلح بـ /salvagerepository.
flowchart TB
accTitle: إجراء فرز عدم اتّساق مستودع WMI
accDescr: إن ظهر خطأ كصنف غير موجود فافحص الاتّساق بـ verifyrepository لدى winmgmt، وأعد البناء بـ salvagerepository إن وُجد عدم اتّساق، ولا تجعل حذف المستودع أو تهيئته خطوتك الأولى
sym["خطأ كصنف غير موجود"] --> verify["winmgmt /verifyrepository"]
verify --> q1{"النتيجة inconsistent؟"}
q1 -->|نعم| salvage["winmgmt /salvagerepository"]
q1 -->|لا| other["اشتبه بجزء آخر من نظام التشغيل"]
salvage -.-> merge["يُدمَج المحتوى المقروء"]
del["حذف المستودع أو تهيئته"] -.-> ng["لا تجعله خطوتك الأولى"]
الشكل 17: احترم ترتيب الفحص بـ verify ثمّ الإصلاح بـ salvage، ولا تجعل الحذف خطوتك الأولى.
7.5. تحويل تنسيق تاريخ DMTF
تواريخ WMI مخزَّنة كسلاسل بتنسيق DMTF الذي تحدّده مواصفة CIM: yyyymmddHHMMSS.mmmmmm±UUU (القيمة في النهاية هي الإزاحة عن UTC بالدقائق ── مثلاً 20260801100000.000000+540). لا تقصّ القيمة الخام وتلصقها بمعالجة سلاسل؛ استخدم واجهة التحويل بدل ذلك.
- C# (System.Management): يوفّر
ManagementDateTimeConverterالتحويل بين تنسيق DMTF وDateTime/TimeSpan.11 - واجهات عائلة CIM (Get-CimInstance / واجهة MI): خصائص التاريخ تعود وقد حُوِّلت سلفاً إلى
DateTime، فلا تواجه هذه المشكلة أصلاً. يمكن استخدام(Get-CimInstance Win32_OperatingSystem).LastBootUpTimeمباشرة كـDateTimeفي الحسابات.
flowchart TB
accTitle: التعامل مع تنسيق تاريخ DMTF
accDescr: تواريخ WMI مخزَّنة كسلاسل بتنسيق DMTF، فإن قرأت القيمة الخام بـ System.Management فحوِّلها بـ ManagementDateTimeConverter، وواجهات عائلة CIM ترجع DateTime محوَّلاً سلفاً، فلا تقصّ السلسلة وتلصقها بنفسك
dmtf["سلسلة بتنسيق DMTF"] --> q1{"بأيّ واجهة جلبت؟"}
q1 -->|System.Management| conv["ManagementDateTimeConverter"]
q1 -->|واجهة CIM| done["يُرجع DateTime محوَّلاً"]
conv --> dtv["حوِّل إلى DateTime / TimeSpan"]
cut["قصّ ولصق السلسلة بنفسك"] -.-> ng["لا تستخدمه"]
الشكل 18: اترك تحويل سلسلة DMTF لواجهة التحويل، وواجهات عائلة CIM ترجع DateTime محوَّلاً فاستخدمه كما هو.
8. مواقف لا ينبغي فيها استخدام WMI ── جدول قرار الوسيلة
WMI ممتاز كـ «واجهة قراءة موحّدة»، لكنّه ليس دائماً الخيار الأمثل. هذه قاعدة عمليّة للاختيار بين الأدوات.
| ما تريد فعله | الأداة المناسبة | لماذا ليس WMI |
|---|---|---|
| استرجاع معلومات العتاد وتكوين نظام التشغيل، واستعلام بعيد بلا وكيل | WMI/CIM | هذا ملعب WMI بحذافيره ── أكثر توحيداً من طرق واجهات مخصّصة واحدة فواحدة |
| قراءة إعدادات تطبيقك وكتابتها | قراءة السجلّ مباشرة (Microsoft.Win32.Registry) أو ملفّات التكوين |
الوصول إلى السجلّ عبر WMI طريق ملتوٍ، ويرث أيضاً مسألة البِتّية من القسم 7.3 |
| مراقبة أداء مستمرّة عالية التواتر كاستخدام المعالج | عدّادات الأداء (System.Diagnostics.PerformanceCounter وغيرها) |
العدّادات مخصّصة لهذا الغرض. استطلاع WMI بفاصل قصير يخسر في الحمل والدقّة كليهما |
| استدعاء وظيفة نظام تشغيل لمرّة واحدة، أو معالجة تحتاج كموناً منخفضاً | Win32 API (P/Invoke) | WMI يحمل كلفة المرور عبر COM/مزوّد |
| عدّ العمليّات المحلّيّة والتلاعب بها عندما تكفي امتيازات عمليّتك | System.Diagnostics.Process |
مكتفٍ ذاتيّاً في المكتبة القياسيّة، بتبعيّات أقلّ |
| تكوين ميزات إدارة Windows كجدار الحماية أو الشبكات | أوامر CIM مخصّصة الغرض مثل Get-NetFirewallRule |
مجموعة أوامر بُنيت وصِينت لغرض محدّد أدقّ وأأمن من التفتيش في أصناف WMI الخام |
| كشف تغيّرات ملفّ أو مجلّد | FileSystemWatcher |
لا تُدخل WMI إلى إقليم يملك أصلاً واجهة مخصّصة |
قاعدة الحكم بسيطة: استخدم الآليّة المخصّصة حيث توجد، واحفظ WMI/CIM للاستعلام العابر والاستعلام عن بُعد. مثال Get-NetFirewallRule في الصفّ الأخير هو، داخليّاً، مجموعة أوامر مبنيّة فوق CIM ── حالة «نيل فائدة WMI/CIM دون لمسه مباشرة».
flowchart TB
accTitle: محور قرار الوسيلة
accDescr: في الأقاليم التي لها آليّة مخصّصة تُستخدم الآليّة المخصّصة، وفي ما عداها يُستخدم WMI وCIM للاستعلام العابر والاستعلام عن بُعد، وأوامر CIM مخصّصة الغرض شكل تنال فيه الفائدة دون لمس WMI وCIM مباشرة
q1{"هل توجد آليّة مخصّصة؟"} -->|نعم| ded["استخدم الآليّة المخصّصة"]
q1 -->|لا| wmi["استخدم WMI / CIM"]
wmi -.-> use["استعلام عابر・استعلام بعيد"]
cmd["أوامر CIM مخصّصة الغرض"] -.-> ben["شكل تنال فيه الفائدة فقط"]
الشكل 19: حيث توجد آليّة مخصّصة استخدمها، واحفظ WMI/CIM للاستعلام العابر والاستعلام عن بُعد.
9. الخلاصة
- CIM هو المعيار الصناعيّ لدى DMTF، وWMI هو تنفيذ Microsoft له. أوامر CIM في PowerShell وواجهة MI في C# كلاهما مدخل من الجيل الحاليّ يتّبع هذا المعيار.
- في PowerShell، Get-CimInstance / Invoke-CimMethod / Register-CimIndicationEvent هي الجيل الحاليّ. Get-WmiObject وأوامر WMI الأخرى غير موجودة في PowerShell 7، فاكتب السكربتات الجديدة على جانب CIM حتّى إن استهدفت 5.1.
- الاستعلام عن بُعد يفترض WSMan (WinRM) افتراضيّاً، والعمليّات المتعدّدة ينبغي أن تعيد استخدام جلسة CIM. لهدف لم يُكوَّن عليه WinRM، DCOM ملاذ متاح.
- في C#، اختر بين System.Management (عمليّ، موجَّه للمحلّيّ) وMicrosoft.Management.Infrastructure (موجَّه للبعد والمراقبة، يشارك نظام أنواع أوامر CIM). كلاهما حزمة NuGet خاصّة بـ Windows.
- راقب العمليّات باشتراك حدث، لا باستطلاع. الاشتراك في Win32_ProcessStartTrace يتطلّب امتيازات مدير.
- تجنّب SELECT * والاستطلاع بفاصل قصير ── ضيِّق بـ -Filter / -Property / -KeyOnly. تذكّر أنّ استعلاماً من عمليّة 32-bit يجيب عنه مزوّد 32-bit، وأنّ تواريخ DMTF تحتاج واجهة التحويل، وأنّ مستودعاً تالفاً يُعالَج بترتيب verify ثمّ salvage، لا بالحذف.
- لا تُدخل WMI إلى إقليم يملك أصلاً آليّة مخصّصة (الإعدادات، وعدّادات الأداء، واستدعاءات الواجهة لمرّة واحدة) ── احفظ WMI/CIM للاستعلام العابر والاستعلام عن بُعد. ذلك السطر يلخّص أين يقع مكانه.
مقالات ذات صلة
- طريقة تشغيل PowerShell من C# (CSharp) واستقبال النتيجة ككائن
- مجموعة أوامر PowerShell العمليّة ── إضافة وظائف صغيرة شائعة الاستخدام في العمل اليوميّ
- الفروق بين Windows PowerShell 5.1 وPowerShell 7 ── دليل عمليّ لترحيل السكربتات الداخليّة
- أفضل الممارسات للتحقّق من حالة الأجهزة الخارجيّة وعرضها - لماذا لا تكفي عبارة «متّصل» وحدها
- استدعاء Win32 API بأمان من C# ── دليل P/Invoke العمليّ (DllImport / LibraryImport / CsWin32)
- ما هو TPM في Windows؟ ── دليل مُصوَّر لـ«الخزنة التي لا تُخرج المفاتيح» والإقلاع المقيس
مجالات الاستشارة ذات الصلة
تتعامل شركة كومورا سوفت ذ.م.م. مع بناء استرجاع معلومات العتاد ومراقبة العمليّات واستعلام الحواسيب عن بُعد بـ WMI/CIM في تطبيقات الأعمال، وترحيل السكربتات الداخليّة القائمة على Get-WmiObject إلى أوامر CIM، والتحقيق في ضرب المشاكل التي «تعمل على آلة التطوير وتفشل بخطأ امتيازات لدى العميل». يمكننا دعمك على المسار بأكمله من التجريب في PowerShell إلى تنفيذ C# كامل.
- الاستشارات التقنيّة ومراجعة التصميم
- التحقيق في الأخطاء وتحليل السبب الجذري
- تطوير تطبيقات ويندوز
- التواصل معنا
روابط مرجعيّة
-
Microsoft Learn, About WMI. حول كون WMI تنفيذ Microsoft لـ WBEM (مبادرة صناعيّة لتطوير تقنيّات قياسيّة للوصول إلى معلومات الإدارة في بيئات المؤسّسات)، وتمثيل أهداف الإدارة بمعيار CIM (Common Information Model) الصناعيّ الذي يطوّره ويصونه DMTF (Distributed Management Task Force)؛ وحول توافق الجيل التالي MI (Windows Management Infrastructure) تماماً مع WMI القديم؛ وحول استخدام اتّصالات WMI عن بُعد لـ DCOM، مع WinRM القائم على WS-Management بديلاً. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Differences between Windows PowerShell 5.1 and PowerShell 7.x. حول حذف أوامر WMI v1 (Register-WmiEvent / Set-WmiInstance / Invoke-WmiMethod / Get-WmiObject / Remove-WmiObject) من PowerShell، وحول توفير أوامر مكوّن CimCmdlets (WMI v2) الوظيفة نفسها بميزات جديدة وبناء جملة معاد تصميمه. ↩ ↩2
-
Microsoft Learn, Get-CimInstance (CimCmdlets). حول الاتّصال بـ WMI المحلّيّ عبر جلسة COM عندما لا يُحدَّد ComputerName ولا CimSession، وإنشاء جلسة مؤقّتة عبر بروتوكول WsMan عند تحديد -ComputerName؛ وحول التوصية بالاتّصال عبر جلسة CIM للأداء عند أداء عدّة عمليّات ضدّ الحاسوب نفسه؛ وحول كون -Filter جملة where في WQL/CQL لا تتضمّن الكلمة المفتاحيّة WHERE؛ وحول تقليل -Property و-KeyOnly لحجم الكائن وحركة الشبكة؛ وحول كون فضاء الأسماء الافتراضيّ root/CIMV2 ولغة الاستعلام الافتراضيّة (-QueryDialect) WQL؛ وحول كون الخرج Microsoft.Management.Infrastructure.CimInstance؛ وحول مثال استدعاء GetOwner مع Invoke-CimMethod؛ وحول كون الأمر خاصّاً بـ Windows. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10
-
Microsoft Learn, New-CimSessionOption (CimCmdlets). حول امتلاك خيارات جلسة CIM مجموعتي وسائط، لـ WsMan ولـ DCOM؛ وحول قبول -Protocol لقيم Dcom / Default / Wsman؛ وحول مثال تمرير خيار أُنشئ بـ New-CimSessionOption -Protocol Dcom إلى -SessionOption لدى New-CimSession لإنشاء جلسة CIM عبر DCOM؛ وحول كون مستوى انتحال الهويّة الافتراضيّ لجلسة DCOM هو Impersonate. ↩ ↩2
-
Microsoft Learn, ManagementObjectSearcher Class (System.Management). حول كون هذا أشيع أصناف المدخل لاسترجاع معلومات الإدارة، جلباً لمجموعة كائنات إدارة بناء على استعلام WQL محدَّد؛ وحول قبوله ObjectQuery وManagementScope (فضاء أسماء WMI) وإرجاعه ManagementObjectCollection عبر Get()؛ وحول توفير System.Management.dll كحزمة NuGet باسم System.Management. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, CimSession Class (Microsoft.Management.Infrastructure). حول توفير Microsoft.Management.Infrastructure.dll كحزمة NuGet باسم Microsoft.Management.Infrastructure؛ وحول إنشاء جلسة عبر Create(computerName)؛ وحول تنفيذ استعلام عبر QueryInstances(namespace, queryDialect, query)؛ وحول توفيره EnumerateInstances / GetInstance / InvokeMethod / Subscribe مع متغيّرات غير متزامنة (*Async) لكلّ منها، مع تنفيذ IDisposable. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Register-CimIndicationEvent (CimCmdlets). حول الاشتراك في إشارة (حدث) باسم صنف أو بتعبير استعلام وتسمية الاشتراك بـ -SourceIdentifier؛ وحول مثال الاشتراك في Win32_ProcessStartTrace، مع ملاحظة أنّه يتطلّب تشغيل PowerShell كمدير؛ وحول مثال الإشارة إلى ProcessName / ProcessId من $Event.SourceEventArgs.NewEvent داخل كتلة سكربت -Action؛ وحول الاتّصال عبر جلسة WsMan مؤقّتة عند تحديد -ComputerName، ومحلّيّاً عبر COM عندما لا يُحدَّد؛ وحول استخدام Unregister-Event لإزالة اشتراك. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Win32_ProcessStartTrace class. حول كون هذا صنف حدث يشير إلى بدء عمليّة جديدة، بخصائص تشمل ProcessName / ProcessID / ParentProcessID / SessionID / Sid؛ وحول كون خاصّيّة SECURITY_DESCRIPTOR الواصف الذي يستخدمه مزوّد الحدث لتحديد أيّ مستخدمين يمكنهم تلقّي الحدث؛ وحول كون فضاء الأسماء Root\CIMV2، يقدّمه مزوّد تتبّع النواة (Krnlprov.dll). ↩ ↩2 ↩3
-
Microsoft Learn, Win32_LogicalDisk class. حول كون Win32_LogicalDisk صنفاً مشتقّاً من CIM_LogicalDisk يمثّل جهاز تخزين محلّيّاً؛ وحول قيم DriveType (2 = قابل للإزالة، 3 = قرص محلّيّ، 4 = محرّك شبكة، 5 = قرص مضغوط، وغيرها)؛ وحول كون FreeSpace / Size قيمتين uint64 بالبايت؛ وحول كون DeviceID هو المفتاح؛ وحول أمثلة استعلامات VBScript / C# تصفّي بـ DriveType = 3. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Installation and configuration for Windows Remote Management. حول عدم تكوين مستمع WinRM افتراضيّاً، ما يعني تعذّر إرسال رسائل WS-Management أو تلقّيها؛ وحول ضبط winrm quickconfig الخدمة لتبدأ تلقائيّاً، وتكوين مستمع HTTP/HTTPS، وتسجيل استثناء جدار حماية؛ وحول كون المنفذين الافتراضيّين لـ WinRM 2.0 هما HTTP 5985 / HTTPS 5986؛ وحول ضبط TrustedHosts بأضيق نطاق ممكن عندما يتعذّر إقامة مصادقة متبادلة (Kerberos)، كما في مجموعة عمل؛ وحول تحكّم واصف الأمن الافتراضيّ (RootSDDL) في الوصول عن بُعد إلى المستمع، زائد التكوين الإضافيّ المطلوب للسماح لمستخدمين غير مديرين باستخدام إضافات WMI. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, System.Management Namespace. حول كون هذا فضاء الأسماء الذي يستعلم بنية WMI عبر عائلة أصناف ManagementObjectSearcher، ويعالج اشتراك الأحداث عبر ManagementEventWatcher؛ وحول تمثيل WqlEventQuery لاستعلام حدث بصيغة WQL؛ وحول توفير ManagementDateTimeConverter طرائق للتحويل بين تمثيلات تاريخ/وقت وفاصل زمنيّ لدى DMTF وDateTime / TimeSpan لدى CLR. ↩ ↩2 ↩3
-
Microsoft Learn, Requesting WMI Data on a 64-bit Platform. حول أنّه، حيث يوجد مزوّد بنسختي 32-bit و64-bit، يجيب مزوّد 32-bit افتراضيّاً تطبيقات 32-bit (بما فيها السكربتات) ويجيب مزوّد 64-bit تطبيقات 64-bit؛ وحول إمكان طلب نسخة المزوّد غير الافتراضيّة أو فرضها عبر __ProviderArchitecture (32 أو 64) و__RequiredArchitecture في السياق (مع حدوث WBEM_E_PROVIDER_LOAD_FAILURE إن فُرضت نسخة غير موجودة)؛ وحول مثال مزوّد السجلّ حيث يتلقّى عميل 32-bit بيانات من جانب HKLM\SOFTWARE\Wow6432Node. ↩ ↩2 ↩3
-
Microsoft Learn, winmgmt. حول إجراء /verifyrepository لدى winmgmt.exe فحص اتّساق لمستودع WMI؛ وحول إجراء /salvagerepository فحص اتّساق، وإعادة بناء المستودع عند اكتشاف عدم اتّساق مع دمج أيّ محتوى أمكنت قراءته؛ وحول إعادة /resetrepository المستودع إلى حالته عند التثبيت الأوّليّ لنظام التشغيل؛ وحول عمل المستودع كقاعدة بيانات مكوَّنة من الملفّات داخل مجلّد Repository؛ وحول أنّ الأخطاء الظاهرة عبر WMI قد تنشأ أحياناً في موضع آخر من نظام التشغيل، لذا ينبغي تجنّب حذف المستودع كاستجابة أولى لأنّه قد يسبّب ضرراً للنظام أو للتطبيقات المثبَّتة. ↩ ↩2 ↩3
مقالات ذات صلة
أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.
أفضل الممارسات العمليّة لتعدّد مؤشّرات الترابط: نسخة .NET ── ما تقرِّره قبل إضافة مؤشّرات ترابط
قواعد تصميم عمليّة تمنع شيفرة .NET/C# متعدّدة مؤشّرات الترابط من الانهيار أو التجمّد أحياناً: اركب على Task بدل إنشاء المؤشّرات بنفسك، قل...
منع التشغيل المتعدّد لتطبيقات Windows ── Mutex المسمّى وتفعيل النافذة عند التشغيل المزدوج
نرتّب هنا طريقة تنفيذ منع التشغيل المتعدّد لتطبيقات Windows للأعمال باستخدام Mutex مسمّى. نشرح الفرق بين Global\ وLocal\ ومطبّاته في بيئا...
طريقة تشغيل PowerShell من C# (CSharp) واستقبال النتيجة ككائن
نرتّب من منظور عمليّ طريقة تشغيل PowerShell من C# واستقبال النتيجة ككائن PSObject بدل نصّ، بدءًا من PowerShell SDK وAddCommand وAddParame...
الأنابيب المسمّاة عمليّاً ── IPC القياسيّ في Windows من التصميم إلى الأمان
دليل عمليّ للأنابيب المسمّاة، وسيلة الاتّصال القياسيّة بين العمليّات في Windows. ينظّم المقال، من المصادر الأوّليّة، الاختيار بين وضع الب...
تطبيقات تتعطّل عند الاستئناف من السكون ── كيف تعمل أحداث الطاقة في Windows وكيف تبني تطبيقات أعمال تصمد أمامها
فتحت الحاسوب المحمول فوجدت اتّصالات تطبيق الأعمال ميّتة ── السبب تصميم لم يحسب حساب السكون. يغطّي المقال تدفّق إشعار WM_POWERBROADCAST، و...
أين يتصل هذا الموضوع
ترتبط هذه المقالة بشكل طبيعي بصفحات الخدمات التالية.
تطوير تطبيقات ويندوز
ندعم تطوير برامج ويندوز للأعمال، وتكامل الأجهزة، وأدوات التواصل.
الأسئلة الشائعة
أسئلة شائعة حول موضوع هذه المقالة.
- ما الفرق بين WMI وCIM؟
- CIM هو «النموذج القياسيّ الصناعيّ لتمثيل أهداف الإدارة كالأنظمة والأجهزة»، يضعه ويصونه DMTF (Distributed Management Task Force). أمّا WMI فهو تنفيذ Microsoft لـ WBEM، المبادرة التي تستخدم ذلك المعيار، وهو مدمج في Windows. بعبارة أخرى، CIM هو المواصفة وWMI هو التنفيذ على Windows. تسمّي Get-CimInstance في PowerShell وMicrosoft.Management.Infrastructure في C# نفسيهما «CIM» لأنّهما واجهتان تتّبعان هذا المعيار، لكنّهما تتّصلان بالأساس نفسه: WMI. في التطوير اليوميّ يكفي أن تفهم الأمر على أنّه «استعلام أصناف WMI (Win32_* وما شابه) عبر واجهات عائلة CIM».
- هل لم يعد ممكناً استخدام Get-WmiObject؟
- ما يزال يعمل في Windows PowerShell 5.1، لكن بدءاً من PowerShell 6 (بما فيه PowerShell 7 الحاليّ) حُذفت أوامر WMI v1 ── Get-WmiObject وInvoke-WmiMethod وRegister-WmiEvent وSet-WmiInstance وRemove-WmiObject ── ولم يعد تشغيلها ممكناً. الوظيفة نفسها يوفّرها مكوّن CimCmdlets (Get-CimInstance / Invoke-CimMethod / Register-CimIndicationEvent وغيرها). عند كتابة سكربتات جديدة، الأسلم كتابتها بأوامر CIM حتّى إن كانت ستعمل تحت 5.1. بذلك لن تضطرّ إلى إعادة كتابة جزء WMI عندما ترحّل لاحقاً إلى PowerShell 7.
- للوصول إلى WMI من C#، أأستخدم System.Management أم Microsoft.Management.Infrastructure؟
- كلاهما خاصّ بـ Windows، ومن .NET الحاليّ تجلبهما كحزمتي NuGet. System.Management هي الواجهة الكلاسيكيّة، تكفي بتمرير WQL إلى ManagementObjectSearcher، وتكفي وحدها إن كان محور عملك استرجاع معلومات محلّيّة. وتتضمّن أيضاً ManagementDateTimeConverter الذي يحوّل تواريخ DMTF. أمّا Microsoft.Management.Infrastructure (واجهة MI) فتشارك نظام الأنواع نفسه (CimSession / CimInstance) مع أوامر CIM في PowerShell، وتعالج الاستعلام عن بُعد عبر WSMan، والمتغيّرات غير المتزامنة للطرائق، واشتراك الأحداث (Subscribe) بأسلوب موحّد. إن كنت تبني استعلام حواسيب بعيدة ومراقبة في منتج حقيقيّ، فاختيار واجهة MI هو القرار المعقول.
- Get-CimInstance لا يتّصل بحاسوب بعيد. ماذا أفحص؟
- افحص أوّلاً ما إذا كان WinRM مكوَّناً على الجهاز الهدف. عمليّة CIM التي تحدِّد -ComputerName تنشئ جلسة مؤقّتة عبر بروتوكول WSMan (WinRM)، فتفترض أنّ خدمة WinRM ومستمعاً يعملان على الهدف. ينفّذ winrm quickconfig التكوين الافتراضيّ (تشغيل الخدمة، وإنشاء مستمع، وإضافة استثناء جدار حماية). المنفذان الافتراضيّان 5985 لـ HTTP و5986 لـ HTTPS، فافحص أيضاً أيّ جدران حماية على المسار. في بيئة مجموعة عمل لا تتوفّر المصادقة المتبادلة عبر Kerberos، فقد تحتاج إلى تسجيل الهدف في قائمة TrustedHosts لدى العميل. لهدف لا يمكنك فيه تكوين WinRM بأيّ حال، يمكنك الاتّصال عبر DCOM بخيار يُنشأ بـ New-CimSessionOption -Protocol Dcom.
- لماذا يعود تاريخ WMI بتنسيق مثل «20260801100000.000000+540»؟
- تواريخ WMI مخزَّنة بتنسيق السلسلة الذي تحدّده مواصفة CIM لدى DMTF (yyyymmddHHMMSS.mmmmmm±UUU، والقيمة في النهاية هي الإزاحة عن UTC بالدقائق). إن قرأت القيمة الخام بـ Get-WmiObject القديم أو بـ System.Management، حصلت على هذه السلسلة كما هي. في C# (System.Management) يوفّر ManagementDateTimeConverter طرائق للتحويل بين تنسيق DMTF وDateTime / TimeSpan، فاستخدمها بدل قصّ السلسلة بنفسك. لاحظ أنّك عندما تجلب البيانات عبر واجهة من عائلة CIM مثل Get-CimInstance، تُرجع خصائص التاريخ وقد حُوِّلت سلفاً إلى DateTime، فلا تواجه هذه المشكلة أصلاً.
الملف الشخصي للمؤلف
صفحة الملف الشخصي لمؤلف المقالة.
غو كومورا
مؤسّس شركة كومورا سوفت ذ.م.م.
يركّز على تطوير برامج ويندوز، والاستشارات التقنية، والتحقيق في الأخطاء، ويتميّز في المشاريع التي تبقى فيها الأصول القديمة ناشطة، وفي تشخيص الأعطال التي يصعب تحديد سببها.