مجموعة أوامر PowerShell العمليّة ── إضافة وظائف صغيرة شائعة الاستخدام في العمل اليوميّ
· آخر تحديث: · غو كومورا · PowerShell, Windows, سطر الأوامر, الأتمتة, تحسين كفاءة العمل, الاستفادة من الأصول القائمة
1. الأساسيّات الواجب الإلمام بها أوّلاً
بعد إتقان أساسيّات PowerShell، تصبح الخطوة التالية هي زيادة «الوظائف الصغيرة الشائعة الاستخدام»، ما يجعله أسهل استخداماً في العمل الفعليّ.
المقصود هنا بالوظائف الصغيرة ليس الأسماء المستعارة (aliases) القصيرة. في هذا المقال، لن نستخدم اختصارات مثل ls أو cat، بل أسماء الأوامر الرسميّة مثل Get-ChildItem وGet-Content وSelect-String.
وبناءً على ذلك، سنجعل من الممكن تنفيذ الأعمال التالية بسطر واحد أو بضعة أسطر من الأوامر.
عدّ العناصر
معرفة الحجم الإجماليّ
حذف التكرارات
التجميع حسب النوع
استخراج القيم المطلوبة فقط
مقارنة نتيجتين
عرض الأسطر المحيطة في السجلّ (log)
الإرسال إلى الحافظة (clipboard)
حفظ نتيجة التنفيذ مع عرضها على الشاشة في آنٍ واحد
التحقّق من متغيّرات البيئة والشبكة
PowerShell مفيد حتّى دون كتابة سكربتات طويلة. لنبدأ بزيادة «القطع الشائعة الاستخدام»، بحيث يمكن تركيبها تدريجيّاً في العمل اليوميّ.
الأهمّ ليس حفظ الأوامر عن ظهر قلب، بل أن تتذكّر «في هذا الموقف يمكن استخدام هذه القطعة».
كما أنّ الشيفرة الواردة في هذا المقال منشورة على GitHub كمجموعة أمثلة كاملة قابلة للتنفيذ (سكربتات الوصفات واختبارات Pester)، مرتَّبة حسب الموضوع وفق تبويب الفصول.
powershell-practical-command-recipes - komurasoft-blog-samples (GitHub)
2. المنهجيّة المتَّبعة هنا
الافتراضات الثلاثة هي كالتالي.
- تُكتَب أسماء الأوامر بصيغتها الرسميّة
- التركيز على الأوامر القرائيّة (read)
- الأوامر التغييريّة تُدرَس دائماً مع تأكيد الهدف أو مع
-WhatIf
على سبيل المثال، بدل حفظ أمر حذف الملفّات مباشرةً، من الأسلم اكتساب التسلسل التالي أوّلاً.
عرض الهدف
→ تضييقه بشرط
→ عدّ العناصر
→ حفظه في CSV عند الحاجة
→ تأكيد خطّة التغيير
→ التنفيذ
في هذا المقال، سنركِّز على التحقيق والتجميع والمقارنة والإخراج، أكثر من العمليّات القويّة كالحذف أو الإيقاف.
3. خريطة الأوامر الشائعة الاستخدام
هذه هي الأوامر الرئيسيّة المستخدَمة في هذا المقال.
| ما تريد فعله | الأمر |
|---|---|
| معرفة العدد أو الإجماليّ | Measure-Object |
| ترتيب التكرارات | Sort-Object -Unique |
| التجميع حسب النوع | Group-Object |
| إخراج الأعمدة المطلوبة فقط | Select-Object |
| معالجة كلّ عنصر | ForEach-Object |
| البحث عن نصّ | Select-String |
| مقارنة نتيجتين | Compare-Object |
| حساب قيمة التجزئة (hash) | Get-FileHash |
| استخدام الحافظة | Set-Clipboard / Get-Clipboard |
| الإخراج إلى الشاشة والملفّ معاً | Tee-Object |
| قياس زمن المعالجة | Measure-Command |
| عرض تفاصيل الخطأ | Get-Error |
| التحقّق من اتّصال الشبكة | Test-Connection / Test-NetConnection |
لا حاجة لحفظها جميعاً دفعةً واحدة. يُنصَح بحفظها مقترنةً بالغرض منها، مثل «للعدّ استخدم Measure-Object» و«للتجميع استخدم Group-Object» و«للمقارنة استخدم Compare-Object».
4. عدّ العناصر ── Measure-Object
أوّل عمليّة شائعة الاستخدام هي عدّ العناصر.
عدّ عدد الملفّات في المجلّد الحاليّ.
Get-ChildItem . -File | Measure-Object
في حال العدّ بما يشمل المجلّدات الفرعيّة.
Get-ChildItem . -File -Recurse | Measure-Object
Count في نتيجة Measure-Object هو العدد.
إن أردتَ معرفة الحجم الإجماليّ لحجم الملفّات، اجمع Length.
Get-ChildItem . -File -Recurse |
Measure-Object -Property Length -Sum
لكن هذا يبقى بالبايت وصعب القراءة على الإنسان، فلنحوِّله إلى وحدة GB.
$size = Get-ChildItem . -File -Recurse |
Measure-Object -Property Length -Sum
[math]::Round($size.Sum / 1GB, 2)
هذا مفيد عندما تريد نظرة سريعة على حجم المجلّد كلّه.
5. معرفة الحدّ الأقصى والمتوسّط أيضاً
لا يقتصر Measure-Object على الإجماليّ، بل يمكنه أيضاً إخراج القيمة القصوى والمتوسّط.
Get-ChildItem . -File |
Measure-Object -Property Length -Sum -Average -Maximum -Minimum
يمكن استخدامه لرؤية تفاوت أحجام الملفّات.
يمكن أيضاً جمع زمن المعالج (CPU) التراكميّ للعمليّات. خاصيّة CPU في Get-Process ليست نسبة الاستخدام، بل عدد ثواني زمن المعالج المُستهلَك منذ بدء تشغيل العمليّة.
Get-Process |
Measure-Object -Property CPU -Sum
لكنّ هذه القيمة تراكميّة وليست نسبة استخدام المعالج اللحظيّة، لذا تتغيّر حسب توقيت التنفيذ ومدّة تشغيل العمليّة.
تكفي هذه القيمة للاستخدام كتحقيق استكشافيّ، لكن إن أردتَ مراقبة دقيقة، فستحتاج أيضاً إلى أداة مراقبة مخصّصة أو تصميم سجلّات مخصّص.
6. استخراج القيمة فقط ── Select-Object -ExpandProperty
يُستخدَم Select-Object كثيراً عند اختيار الأعمدة.
Get-Process |
Select-Object Name, Id, CPU
هذا يُخرِج «كائناً له أعمدة Name وId وCPU».
من ناحية أخرى، عند الرغبة باستخراج القيمة فقط، استخدم -ExpandProperty.
Get-Process -Name notepad -ErrorAction SilentlyContinue |
Select-Object -ExpandProperty Id
الأمر نفسه عند استخراج اسم الملفّ فقط.
Get-ChildItem . -File |
Select-Object -ExpandProperty Name
عند الرغبة بتمرير نتيجة الأمر إلى أمر آخر أو ملفّ نصّي، فإنّ -ExpandProperty مفيد.
على سبيل المثال، لحفظ قائمة أسماء الملفّات فقط.
Get-ChildItem . -File |
Select-Object -ExpandProperty Name |
Set-Content .\file-names.txt -Encoding UTF8
يتشابه Select-Object Name وSelect-Object -ExpandProperty Name لكنّ شكل النتيجة مختلف.
Select-Object Name
→ جدول له عمود باسم Name
Select-Object -ExpandProperty Name
→ قيمة Name نفسها
إن أردتَ تحويلها إلى CSV، فمن الأفضل إبقاؤها كعمود، وإن أردتَ تمريرها إلى معالجة نصّيّة أخرى، فالقيمة وحدها أسهل تعاملاً.
7. حذف التكرارات ── Sort-Object -Unique
عند الرغبة بعرض امتدادات الملفّات فقط دون تكرار.
Get-ChildItem . -File |
Select-Object -ExpandProperty Extension |
Sort-Object -Unique
عند التنفيذ، تظهر الامتدادات فقط دون تكرار، مثل .txt و.log و.csv.
يمكن أيضاً رؤية أنواع أسماء العمليّات فقط.
Get-Process |
Select-Object -ExpandProperty ProcessName |
Sort-Object -Unique
مثال على استخراج قائمة أسماء الأقسام فقط من CSV لقائمة المستخدمين.
Import-Csv .\users.csv |
Select-Object -ExpandProperty Department |
Sort-Object -Unique
عندما «تظهر نفس القيمة كثيراً في القائمة فيصعب القراءة»، من المفيد تذكّر Sort-Object -Unique أوّلاً.
8. التجميع حسب النوع ── Group-Object
عندما تريد معرفة «كم عنصراً من كلّ نوع» وليس مجرّد حذف التكرارات، استخدم Group-Object.
عدّ عدد الملفّات حسب الامتداد.
Get-ChildItem . -File |
Group-Object -Property Extension -NoElement |
Sort-Object -Property Count -Descending
بإضافة -NoElement، يمكن حذف محتوى كلّ مجموعة والاكتفاء بالعدد لسهولة القراءة.
العدّ حسب حالة الخدمة.
Get-Service |
Group-Object -Property Status -NoElement
العدّ حسب مستوى سجلّ الأحداث.
Get-WinEvent -LogName System -MaxEvents 500 |
Group-Object -Property LevelDisplayName -NoElement
Group-Object مناسب لأخذ نظرة عامّة في بداية التحقيق.
أيّ امتداد أكثر شيوعاً
أيّ حالة خدمة أكثر شيوعاً
أيّ مستوى خطأ أكثر شيوعاً
أيّ قسم لديه بيانات أكثر
يُستخدَم قبل النظر في التفاصيل، عندما تريد رؤية التوزيع أوّلاً.
9. إنشاء الأعمدة اللازمة ── إضافة عمود محسوب
يمكن الحصول على حجم الملفّ عبر Length، لكن الوحدة بايت. رؤية عدد البايتات في كلّ مرّة مرهقة، لذا من المفيد إنشاء عمود مُحوَّل إلى MB أو KB.
Get-ChildItem . -File |
Select-Object Name, @{Name="SizeKB"; Expression={ [math]::Round($_.Length / 1KB, 1) }}, LastWriteTime
مثال على رؤية الملفّات الأكبر حجماً أوّلاً، بما فيها المجلّدات الفرعيّة.
Get-ChildItem . -File -Recurse |
Sort-Object -Property Length -Descending |
Select-Object -First 20 FullName, @{Name="SizeMB"; Expression={ [math]::Round($_.Length / 1MB, 2) }}, LastWriteTime
الصيغة @{Name="..."; Expression={ ... }} هي طريقة إنشاء عمود محسوب. تبدو طويلة بعض الشيء في البداية، لكنّها شائعة الاستخدام في العمل الفعليّ.
على سبيل المثال، يمكن عرض استهلاك الذاكرة للعمليّة بوحدة MB.
Get-Process |
Sort-Object -Property WorkingSet -Descending |
Select-Object -First 10 Name, Id, @{Name="MemoryMB"; Expression={ [math]::Round($_.WorkingSet / 1MB, 1) }}
عند الإخراج في تقرير، يكون عمود مثل SizeMB أسهل قراءة من Length الأصليّ.
10. العرض بالأحدث والأقدم والأكبر
في PowerShell، يتمّ الترتيب عبر Sort-Object.
عرض الملفّات المُحدَّثة مؤخّراً.
Get-ChildItem . -File |
Sort-Object -Property LastWriteTime -Descending |
Select-Object -First 10 Name, LastWriteTime
عرض الملفّات القديمة.
Get-ChildItem . -File |
Sort-Object -Property LastWriteTime |
Select-Object -First 10 Name, LastWriteTime
عرض الملفّات الكبيرة.
Get-ChildItem . -File -Recurse |
Sort-Object -Property Length -Descending |
Select-Object -First 10 FullName, Length
هذه الأنماط الثلاثة شائعة الاستخدام.
الأحدث أوّلاً → LastWriteTime -Descending
الأقدم أوّلاً → LastWriteTime
الأكبر أوّلاً → Length -Descending
هذا التوليف كثير الاستخدام في تحقيق السجلّات، وتنظيف الملفّات غير الضروريّة، وتحقيق سعة القرص.
11. أوامر Format تُستخدَم فقط في آخر مرحلة عرض على الشاشة
عند الرغبة بعرض أوضح على الشاشة، استخدم Format-Table أو Format-List.
Get-Process |
Sort-Object -Property WorkingSet -Descending |
Select-Object -First 10 Name, Id, WorkingSet |
Format-Table -AutoSize
لرؤية تفاصيل عنصر واحد، Format-List مفيد.
Get-Process -Id $PID |
Format-List *
لكن Format-Table وFormat-List أوامر «للعرض».
من الأسلم عدم استخدامها قبل الإخراج إلى CSV أو قبل المعالجة بأمر لاحق.
# تجنَّب هذا
Get-Process |
Format-Table Name, Id |
Export-Csv .\process.csv -NoTypeInformation
عند الإخراج إلى CSV، اختر الأعمدة عبر Select-Object.
# الصحيح
Get-Process |
Select-Object Name, Id |
Export-Csv .\process.csv -NoTypeInformation -Encoding UTF8
عند التردّد، فكِّر كالتالي.
العرض على الشاشة فقط → Format-Table / Format-List
الاستخدام لاحقاً → Select-Object
12. تحسين بحث السجلّات قليلاً ── Select-String
للبحث عن نصّ، استخدم Select-String.
Select-String -Path .\logs\*.log -Pattern "ERROR"
يمكن تحديد أنماط متعدّدة أيضاً.
Select-String -Path .\logs\*.log -Pattern "ERROR", "WARN", "FATAL"
عند الرغبة برؤية الأسطر المحيطة، استخدم -Context.
Select-String -Path .\logs\*.log -Pattern "ERROR" -Context 2
هذا يعرض أيضاً السطرين السابق واللاحق للسطر المطابق، مفيد عند الرغبة بالتحقّق من سياق الخطأ.
عند الرغبة بالبحث كنصّ بسيط، استخدم -SimpleMatch.
Select-String -Path .\logs\*.log -Pattern "[ERROR]" -SimpleMatch
يُعامَل -Pattern في Select-String عادةً كتعبير نمطيّ (regular expression). عند الرغبة بالبحث عن رموز مثل [ أو . كما هي، فإنّ إضافة -SimpleMatch يجعل الأمر أوضح.
عند الرغبة بالتمييز بين الأحرف الكبيرة والصغيرة.
Select-String -Path .\logs\*.log -Pattern "Error" -CaseSensitive
يمكن أيضاً حفظ نتيجة البحث في CSV.
Select-String -Path .\logs\*.log -Pattern "ERROR" |
Select-Object Path, LineNumber, Line |
Export-Csv .\error-lines.csv -NoTypeInformation -Encoding UTF8
13. استبدال النصوص
لاستبدال جزء من نصّ، استخدم -replace.
"server01.example.com" -replace "\.example\.com$", ""
عند استبدال محتوى ملفّ، من الأسلم عدم الكتابة فوق الملفّ الأصليّ مباشرةً. أخرِج أوّلاً إلى ملفّ منفصل.
(Get-Content .\appsettings.json -Raw) -replace "localhost", "db01" |
Set-Content .\appsettings.preview.json -Encoding UTF8
بعد التحقّق، طبِّق التغيير على الملفّ الأصليّ عند الحاجة.
في ملفّات الإعدادات أو الاستبدال الجماعيّ، يؤدّي كثرة عناصر الاستبدال إلى حوادث. من الأسلم التحقّق من الهدف أوّلاً عبر Select-String قبل الاستبدال.
Select-String -Path .\appsettings.json -Pattern "localhost" -SimpleMatch
14. مقارنة نتيجتين ── Compare-Object
Compare-Object هو أمر لرؤية الفرق بين قائمتين.
على سبيل المثال، مقارنة قائمة أسماء الملفّات قبل التغيير وبعده.
Compare-Object `
-ReferenceObject (Get-Content .\before.txt) `
-DifferenceObject (Get-Content .\after.txt)
معنى SideIndicator كالتالي.
| العرض | المعنى |
|---|---|
<= |
موجود في الجانب الأيسر فقط، أي ReferenceObject |
=> |
موجود في الجانب الأيمن فقط، أي DifferenceObject |
== |
موجود في كليهما. يظهر عند إضافة -IncludeEqual |
مثال على حفظ قائمة أسماء ملفّات المجلّد ومقارنتها.
Get-ChildItem .\before -File |
Select-Object -ExpandProperty Name |
Set-Content .\before-list.txt -Encoding UTF8
Get-ChildItem .\after -File |
Select-Object -ExpandProperty Name |
Set-Content .\after-list.txt -Encoding UTF8
Compare-Object `
-ReferenceObject (Get-Content .\before-list.txt) `
-DifferenceObject (Get-Content .\after-list.txt)
يمكن أيضاً رؤية التغيّر في قائمة الخدمات.
Get-Service |
Select-Object Name, Status |
Export-Csv .\services-before.csv -NoTypeInformation -Encoding UTF8
بعد التغيير، أخرِج مرّة أخرى.
Get-Service |
Select-Object Name, Status |
Export-Csv .\services-after.csv -NoTypeInformation -Encoding UTF8
قارِن.
Compare-Object `
-ReferenceObject (Import-Csv .\services-before.csv) `
-DifferenceObject (Import-Csv .\services-after.csv) `
-Property Name, Status
حفظ الفرق قبل العمل وبعده يسهِّل التحقيق وإعداد التقارير.
15. التحقّق من قيمة تجزئة الملفّ ── Get-FileHash
عند الرغبة بالتحقّق من تطابق ملفّ تمّ تنزيله أو ملفّ توزيع، استخدم قيمة التجزئة (hash).
Get-FileHash .\installer.exe -Algorithm SHA256
مثال على التحقّق الجماعيّ من الملفّات داخل مجلّد.
Get-ChildItem .\downloads -File |
ForEach-Object { Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256 }
يمكن أيضاً حفظها في CSV.
Get-ChildItem .\downloads -File |
ForEach-Object { Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256 } |
Select-Object Path, Hash |
Export-Csv .\hashes.csv -NoTypeInformation -Encoding UTF8
قد تبدو أسماء الملفّات وحدها متطابقة لكنّ المحتوى مختلف. في التوزيعات والنسخ الاحتياطيّة وأعمال النقل، يسهِّل حفظ قيمة التجزئة عمليّة التحقّق.
16. الإرسال إلى الحافظة ── Set-Clipboard
عندما تريد لصق نتيجة الأمر في بريد إلكترونيّ أو محادثة، إرسالها إلى الحافظة مفيد.
Get-Service |
Select-Object Name, Status |
ConvertTo-Csv -NoTypeInformation |
Set-Clipboard
لرؤية محتوى الحافظة.
Get-Clipboard
عند الرغبة بلصق البيانات في Excel بصيغة مفصولة بعلامات تبويب، اجعل الفاصل في ConvertTo-Csv علامة تبويب.
Get-Process |
Select-Object Name, Id, CPU |
ConvertTo-Csv -NoTypeInformation -Delimiter "`t" |
Set-Clipboard
إن أردتَ فقط مشاركة النتيجة مؤقّتاً، فهذا أسهل من إنشاء ملفّ في كلّ مرّة. لكن إن أردتَ الحفاظ عليها كدليل، احفظها في ملفّ عبر Export-Csv.
17. العرض على الشاشة والحفظ في ملفّ معاً ── Tee-Object
عندما تريد رؤية النتيجة على الشاشة مع حفظها في ملفّ في آنٍ واحد، استخدم Tee-Object.
Get-Process |
Sort-Object -Property WorkingSet -Descending |
Select-Object -First 10 Name, Id, WorkingSet |
Tee-Object -FilePath .\top-process.txt
يُرسِل Tee-Object نتيجة الأنبوب (pipeline) في اتّجاهين.
العرض على الشاشة
الحفظ في ملفّ أيضاً
مناسب للاستخدام أثناء التحقيق عندما تريد «الرؤية مع التسجيل في آنٍ واحد». لكن إن أردتَ لاحقاً فتحها في Excel، فإنّ Export-Csv أسهل تعاملاً.
Get-Process |
Sort-Object -Property WorkingSet -Descending |
Select-Object -First 10 Name, Id, WorkingSet |
Export-Csv .\top-process.csv -NoTypeInformation -Encoding UTF8
من السهل التفكير كالتالي: للعرض على الشاشة استخدم Tee-Object، وللحفظ كبيانات جدوليّة استخدم Export-Csv.
18. حفظ سجلّ العمل ── Start-Transcript
عند الرغبة بتسجيل سلسلة من العمليّات، استخدم Start-Transcript.
Start-Transcript -Path .\work-log.txt
تُسجَّل بعد ذلك الأوامر المنفَّذة ومخرَجات الشاشة.
الإنهاء.
Stop-Transcript
في أعمال التحقيق، غالباً ما تحتاج لاحقاً إلى التحقّق من التالي.
أيّ أمر نُفِّذ
في أيّ مجلّد جرى العمل
ما النتيجة التي ظهرت
هل ظهر خطأ
يُعدّ Start-Transcript تأميناً ضدّ نسيان تدوين مذكّرات العمل. لكن انتبه في الأعمال التي تظهر فيها معلومات لا يجوز تسجيلها، مثل كلمات المرور أو الرموز المميّزة (tokens)، على الشاشة.
19. قراءة CSV وعرضه بشرط
في البيانات التجاريّة، كثيراً ما تظهر ملفّات CSV.
لنفترض وجود ملفّ users.csv كالتالي.
Name,Department,Enabled
Suzuki,Sales,true
Tanaka,Accounting,false
Sato,Sales,true
قراءته.
Import-Csv .\users.csv
عرض من يعمل في قسم Sales فقط.
Import-Csv .\users.csv |
Where-Object { $_.Department -eq "Sales" }
إخراج المستخدمين النشِطين فقط إلى CSV منفصل.
Import-Csv .\users.csv |
Where-Object { $_.Enabled -eq "true" } |
Export-Csv .\enabled-users.csv -NoTypeInformation -Encoding UTF8
غالباً ما تُعامَل قيم CSV كنصوص، لذا عند مقارنة true/false أو الأرقام، فكِّر في تحويل النوع عند الحاجة.
مثال على عرض الصفوف التي درجتها 80 فأكثر فقط.
Import-Csv .\scores.csv |
Where-Object { [int]$_.Score -ge 80 }
20. عرض قيم إعدادات JSON
يُستخدَم JSON كثيراً في ملفّات الإعدادات وواجهات Web API.
$config = Get-Content .\settings.json -Raw | ConvertFrom-Json
$config
يمكن أيضاً رؤية قيمة محدَّدة فقط.
$config.Database.Host
مثال على تغيير قيمة وحفظها في ملفّ منفصل.
$config.Database.Host = "db01"
$config |
ConvertTo-Json -Depth 10 |
Set-Content .\settings.updated.json -Encoding UTF8
عند التعامل مع JSON، يُستخدَم Get-Content -Raw كثيراً. بإضافة -Raw يُقرَأ الملفّ بأكمله كنصّ واحد، لذا يكون أوضح عند التعامل مع JSON متعدّد الأسطر.
21. عرض متغيّرات البيئة
تُستخدَم متغيّرات البيئة كثيراً في إعدادات التطبيقات والتحقّق من المسارات.
عرض القائمة.
Get-ChildItem Env:
عرض اسم المستخدم الحاليّ.
$env:USERNAME
عرض المجلّد المؤقّت.
$env:TEMP
تقسيم PATH لسهولة القراءة.
$env:PATH -split ";"
ضبط متغيّر بيئة لجلسة PowerShell الحاليّة فقط.
$env:APP_MODE = "Development"
هذا الضبط فعّال فقط داخل نافذة PowerShell المفتوحة حاليّاً.
للحفظ كمتغيّر بيئة على مستوى المستخدم، افعل كالتالي.
[Environment]::SetEnvironmentVariable("APP_MODE", "Development", "User")
هذه عمليّة تغيير للبيئة، لذا في أجهزة الشركة أو الخوادم الإنتاجيّة، تحقَّق من نطاق التأثير قبل التنفيذ.
22. التحقّق من ملفّ التعريف (profile)
يحتوي PowerShell على ملفّ تعريف (profile) يُقرَأ عند بدء التشغيل.
التحقّق من الموقع.
$PROFILE
التحقّق من وجوده.
Test-Path $PROFILE
إنشاؤه.
New-Item -ItemType File -Path $PROFILE -Force
فتحه بمفكّرة الملاحظات.
notepad $PROFILE
من المفيد كتابة الإعدادات أو الدوال الشائعة الاستخدام في ملفّ التعريف. لكن إن كتبتَ معالجة معقّدة أكثر من اللازم، فقد يبطئ بدء تشغيل PowerShell أو يصعب إعادة إنتاجه في بيئة أخرى، لذا يُنصَح بالاقتصار في البداية على المسارات وإعدادات العرض الشائعة الاستخدام.
23. عرض العمليّات (processes)
في تحقيق العمليّات، غالباً ما تبدأ برؤية الترتيب حسب استهلاك الذاكرة الأكبر.
Get-Process |
Sort-Object -Property WorkingSet -Descending |
Select-Object -First 10 Name, Id, @{Name="MemoryMB"; Expression={ [math]::Round($_.WorkingSet / 1MB, 1) }}
التضييق باسم محدَّد.
Get-Process -Name notepad -ErrorAction SilentlyContinue
عند إيقاف عمليّة، لا تُنفِّذ مباشرةً، بل تحقَّق أوّلاً عبر -WhatIf.
Stop-Process -Name notepad -WhatIf
نفِّذ إن لم تكن هناك مشكلة.
Stop-Process -Name notepad
في بيئة الإنتاج، قد يؤدّي إيقاف عمليّة إلى تأثير على العمل. تحقَّق من الهدف والمستخدِمين وطريقة الاستعادة قبل الإيقاف.
24. عرض الخدمات (services)
عرض قائمة الخدمات.
Get-Service
عرض الخدمات المتوقّفة فقط.
Get-Service |
Where-Object { $_.Status -eq "Stopped" }
البحث عن الخدمات المتوقّفة رغم أنّها مضبوطة على التشغيل التلقائيّ.
Get-Service |
Where-Object { $_.StartType -eq "Automatic" -and $_.Status -ne "Running" } |
Select-Object Name, DisplayName, Status, StartType
عند إعادة تشغيل خدمة، تحقَّق أوّلاً من الهدف.
Get-Service -Name "Spooler"
تنفيذ تجريبيّ.
Restart-Service -Name "Spooler" -WhatIf
لعمليّات الخدمات تأثير كبير، لذا نفِّذها بعد التحقّق من وقت الصيانة وإجراءات الاستعادة.
25. عرض سجلّ الأحداث (event log)
في تحقيقات Windows، كثيراً ما يُنظَر إلى سجلّ الأحداث.
عرض آخر 100 حدث في سجلّ النظام.
Get-WinEvent -LogName System -MaxEvents 100 |
Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, Message
التضييق على الأخطاء والتحذيرات فقط.
Get-WinEvent -LogName System -MaxEvents 500 |
Where-Object { $_.LevelDisplayName -in @("Error", "Warning") } |
Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, Message
عرض أخطاء آخر 24 ساعة فقط.
$start = (Get-Date).AddHours(-24)
Get-WinEvent -FilterHashtable @{ LogName = "System"; StartTime = $start } |
Where-Object { $_.LevelDisplayName -eq "Error" } |
Select-Object TimeCreated, ProviderName, Id, Message
مثال على حفظ نتيجة التحقيق في CSV.
Get-WinEvent -LogName System -MaxEvents 500 |
Where-Object { $_.LevelDisplayName -in @("Error", "Warning") } |
Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, Message |
Export-Csv .\system-events.csv -NoTypeInformation -Encoding UTF8
يميل عدد سجلّات الأحداث إلى الكِبر، لذا من المهمّ تضييق النطاق عبر -MaxEvents أو تحديد فترة زمنيّة.
26. التحقّق من الشبكة
للتحقّق من الاتّصال، استخدم Test-Connection.
Test-Connection example.com -Count 4
للتحقّق من اتّصال منفذ TCP في Windows، Test-NetConnection مفيد.
Test-NetConnection example.com -Port 443
للتحقّق من تحليل DNS.
Resolve-DnsName example.com
في تحقيق الشبكة، يُفصَل التحقيق كالتالي.
هل يمكن تحليل الاسم
هل يصل إلى عنوان IP
هل المنفذ المطلوب مفتوح
هل هناك تأثير من البروكسي أو جدار الحماية
بدل الاعتماد على PowerShell وحده للحكم على كلّ شيء، فإنّ استخدامه كمدخل للفصل بين الاحتمالات مفيد.
27. عرض نتائج الويب
لجلب صفحة ويب، استخدم Invoke-WebRequest.
Invoke-WebRequest https://example.com |
Select-Object StatusCode, StatusDescription
للتعامل مع نتيجة واجهة API بصيغة JSON، Invoke-RestMethod مفيد.
Invoke-RestMethod https://api.github.com/repos/PowerShell/PowerShell |
Select-Object full_name, stargazers_count, forks_count
غالباً ما تُعامَل نتيجة API منذ البداية ككائن PowerShell، ما يجعلها سهلة التركيب مع Select-Object وWhere-Object.
عند التحقيق في واجهة API داخليّة أيضاً، ابدأ أوّلاً بطلبات GET القرائيّة.
عند التعامل مع بيانات اعتماد أو رموز مميّزة (tokens)، انتبه لعدم ظهورها على الشاشة أو تسجيلها في transcript.
28. قياس زمن التنفيذ ── Measure-Command
عندما تريد معرفة المدّة التي تستغرقها معالجة ما، استخدم Measure-Command.
Measure-Command {
Get-ChildItem C:\Windows -File -Recurse -ErrorAction SilentlyContinue |
Measure-Object
}
تحتوي النتيجة على TotalSeconds وTotalMilliseconds.
$result = Measure-Command {
Get-ChildItem . -File -Recurse | Measure-Object
}
$result.TotalSeconds
عند الرغبة بتسريع سكربت، من المهمّ قياس الزمن بدل الاعتماد على الحدس. لكن النتيجة تتغيّر حسب عدد الملفّات وحالة القرص وحالة الشبكة، لذا لا تحكم بناءً على نتيجة واحدة فقط، بل تحقَّق عدّة مرّات.
29. تشغيل المعالجات الطويلة في الخلفيّة ── Start-Job
عندما تريد تنفيذ تحقيق يستغرق وقتاً طويلاً كمهمّة (job) منفصلة، استخدم Start-Job.
$job = Start-Job -ScriptBlock {
Get-ChildItem C:\Windows -File -Recurse -ErrorAction SilentlyContinue |
Measure-Object
}
عرض حالة المهمّة.
Get-Job
استلام النتيجة.
Receive-Job $job
حذف المهمّة غير الضروريّة.
Remove-Job $job
Start-Job مفيد، لكن لا حاجة لاستخدامه بكثرة منذ البداية. من الأفضل التنفيذ العاديّ أوّلاً، وتحويل المعالجة البطيئة فقط إلى مهمّة، لتسهيل الفهم.
30. استخدام سجلّ الأوامر
لرؤية الأوامر المنفَّذة سابقاً، استخدم Get-History.
Get-History
عرض سطر الأمر فقط لسهولة القراءة.
Get-History |
Select-Object Id, CommandLine
إعادة تنفيذ سجلّ محدَّد.
Invoke-History 12
السجلّ مفيد، لكن يمكن أيضاً إعادة تنفيذ أوامر خطِرة عن طريقه. عند إعادة تنفيذ أوامر تغييريّة من السجلّ مثل Remove-Item أو Stop-Process، تحقَّق من المحتوى قبل التنفيذ.
31. عرض تفاصيل الخطأ ── Get-Error
في PowerShell 7، يمكن استخدام Get-Error لرؤية تفاصيل الخطأ الأخير.
Get-Error
عند الرغبة برؤية رسالة الخطأ الأخيرة فقط.
$Error[0].Exception.Message
عند حدوث خطأ، لا تكتفِ برؤية النصّ الأحمر على الشاشة فقط، بل تحقَّق من النقاط التالية.
أيّ أمر فشل
أيّ مسار أو هدف فشل
هل هي مشكلة صلاحيّات
هل الملفّ غير موجود
هل هناك مشكلة شبكة أو قفل (lock)
عند الرغبة بحفظ نتيجة التحقيق، اجمعه مع Start-Transcript أو Export-Csv.
32. عوامل المقارنة الشائعة الاستخدام
في Where-Object، تُستخدَم عوامل المقارنة كثيراً.
| العامل | المعنى | مثال |
|---|---|---|
-eq |
يساوي | $_.Status -eq "Running" |
-ne |
لا يساوي | $_.Status -ne "Running" |
-gt |
أكبر من | $_.Length -gt 10MB |
-ge |
أكبر من أو يساوي | $_.Length -ge 10MB |
-lt |
أصغر من | $_.Length -lt 10MB |
-le |
أصغر من أو يساوي | $_.Length -le 10MB |
-like |
تطابق بأحرف البدل (wildcard) | $_.Name -like "*.log" |
-match |
تطابق تعبير نمطيّ | $_.Name -match "^app" |
-in |
القيمة موجودة في قائمة | $_.Status -in @("Running", "Paused") |
-contains |
القائمة تحتوي القيمة | @("a", "b") -contains "a" |
أمثلة.
Get-ChildItem . -File |
Where-Object { $_.Length -gt 10MB }
Get-Service |
Where-Object { $_.Status -in @("Running", "Paused") }
Get-ChildItem . -File |
Where-Object { $_.Name -match "\.log$" }
في البداية، تكفي -eq و-ne و-gt و-lt و-like فقط. بعد التعوّد، يصبح استخدام -match أو -in أسهل لكتابة الشروط.
33. وصفات عمليّة صغيرة
من هنا فصاعداً، أمثلة يمكن استخدامها مباشرةً في العمل الفعليّ.
عرض عدد الملفّات حسب الامتداد
Get-ChildItem C:\Work -File -Recurse |
Group-Object -Property Extension -NoElement |
Sort-Object -Property Count -Descending
يُستخدَم عند الرغبة بفهم محتوى المجلّد بنظرة سريعة.
عرض أكبر 20 ملفّاً
Get-ChildItem C:\Work -File -Recurse |
Sort-Object -Property Length -Descending |
Select-Object -First 20 FullName, @{Name="SizeMB"; Expression={ [math]::Round($_.Length / 1MB, 2) }}
شائع الاستخدام في تحقيق سعة القرص.
عرض الملفّات المُحدَّثة خلال آخر 24 ساعة
$since = (Get-Date).AddHours(-24)
Get-ChildItem C:\Work -File -Recurse |
Where-Object { $_.LastWriteTime -ge $since } |
Select-Object FullName, Length, LastWriteTime
يُستخدَم لرؤية أيّ ملفّ تحدَّث بعد وقوع عطل.
تحويل أسطر سجلّ تحتوي ERROR إلى CSV
Select-String -Path C:\App\Logs\*.log -Pattern "ERROR" |
Select-Object Path, LineNumber, Line |
Export-Csv .\error-lines.csv -NoTypeInformation -Encoding UTF8
يسهِّل مشاركة نتيجة التحقيق.
عرض السطرين المحيطين بـ ERROR
Select-String -Path C:\App\Logs\*.log -Pattern "ERROR" -Context 2
يُستخدَم عند الرغبة برؤية سياق السبب.
عرض العمليّات ذات استهلاك الذاكرة الكبير
Get-Process |
Sort-Object -Property WorkingSet -Descending |
Select-Object -First 10 Name, Id, @{Name="MemoryMB"; Expression={ [math]::Round($_.WorkingSet / 1MB, 1) }}
عرض الخدمات المتوقّفة رغم كونها تشغيلاً تلقائيّاً
Get-Service |
Where-Object { $_.StartType -eq "Automatic" -and $_.Status -ne "Running" } |
Select-Object Name, DisplayName, Status, StartType
تحويل أخطاء سجلّ النظام إلى CSV
Get-WinEvent -LogName System -MaxEvents 500 |
Where-Object { $_.LevelDisplayName -eq "Error" } |
Select-Object TimeCreated, ProviderName, Id, Message |
Export-Csv .\system-errors.csv -NoTypeInformation -Encoding UTF8
إرسال نتيجة الأمر إلى الحافظة
Get-Service |
Select-Object Name, DisplayName, Status |
ConvertTo-Csv -NoTypeInformation |
Set-Clipboard
مفيد عند اللصق في بريد إلكترونيّ أو محادثة.
مقارنة قائمة الملفّات قبل العمل وبعده
Get-ChildItem C:\Work -File |
Select-Object -ExpandProperty Name |
Set-Content .\before.txt -Encoding UTF8
بعد العمل، خذها مرّة أخرى.
Get-ChildItem C:\Work -File |
Select-Object -ExpandProperty Name |
Set-Content .\after.txt -Encoding UTF8
قارِن.
Compare-Object (Get-Content .\before.txt) (Get-Content .\after.txt)
عرض الحجم الإجماليّ للمجلّد بوحدة GB
$size = Get-ChildItem C:\Work -File -Recurse |
Measure-Object -Property Length -Sum
[math]::Round($size.Sum / 1GB, 2)
34. تنبيه عند الجمع بين الأوامر التغييريّة
معظم ما ورد حتّى الآن أوامر قرائيّة، ويمكن تجربتها بأمان نسبيّ إن اقتصر الأمر عليها. في المقابل، هذه أوامر تغييريّة.
| العمليّة | الأمر |
|---|---|
| النسخ | Copy-Item |
| النقل | Move-Item |
| الحذف | Remove-Item |
| تغيير الاسم | Rename-Item |
| إيقاف العمليّة | Stop-Process |
| إعادة تشغيل الخدمة | Restart-Service |
| ضبط متغيّر البيئة بشكل دائم | [Environment]::SetEnvironmentVariable() |
تُستخدَم الأوامر التغييريّة بالترتيب التالي.
1. رؤية الهدف عبر أوامر Get
2. التضييق عبر Where-Object
3. رؤية قائمة الأهداف عبر Select-Object
4. عدّ العناصر عبر Measure-Object
5. الحفظ عبر Export-Csv عند الحاجة
6. التنفيذ التجريبيّ إن كان -WhatIf متاحاً
7. التنفيذ
على سبيل المثال، حالة حذف ملفّات .tmp القديمة.
انظر الهدف أوّلاً.
$limit = (Get-Date).AddDays(-30)
$targets = Get-ChildItem C:\Temp -Filter *.tmp -File -Recurse |
Where-Object { $_.LastWriteTime -lt $limit }
$targets |
Select-Object FullName, Length, LastWriteTime
عدّ العناصر.
$targets | Measure-Object
احفظ في CSV.
$targets |
Select-Object FullName, Length, LastWriteTime |
Export-Csv .\delete-targets.csv -NoTypeInformation -Encoding UTF8
تأكَّد من خطّة الحذف.
$targets | Remove-Item -WhatIf
نفِّذ إن لم تكن هناك مشكلة.
$targets | Remove-Item
مجرّد الالتزام بهذا التسلسل يقلِّل الحوادث كثيراً.
35. طريقة الحفظ
محاولة حفظ الأوامر فرديّاً عن ظهر قلب أمر شاقّ، لذا حفظها حسب الغرض أسهل استخداماً.
| الغرض | الأمر الذي تتذكّره |
|---|---|
| أريد العدّ | Measure-Object |
| أريد الجمع | Measure-Object -Sum |
| أريد الرؤية حسب النوع | Group-Object |
| أريد حذف التكرارات | Sort-Object -Unique |
| أريد القيمة المطلوبة فقط | Select-Object -ExpandProperty |
| أريد ترتيب الأعمدة | Select-Object |
| أريد الرؤية بالأكبر أوّلاً | Sort-Object -Descending |
| أريد البحث عن نصّ | Select-String |
| أريد رؤية ما حوله | Select-String -Context |
| أريد مقارنة اثنين | Compare-Object |
| أريد حفظ الدليل | Export-Csv / Start-Transcript |
| أريد العرض على الشاشة والملفّ معاً | Tee-Object |
| أريد الإرسال إلى الحافظة | Set-Clipboard |
| أريد قياس الزمن | Measure-Command |
| أريد رؤية الخطأ بالتفصيل | Get-Error |
36. الخلاصة
PowerShell قويّ عندما تصبح قادراً على كتابة السكربتات. لكن الأكثر استخداماً في العمل الفعليّ هو، بشكل مفاجئ، توليفات الأوامر الصغيرة.
العدّ
الترتيب
التجميع
المقارنة
البحث
الاستخراج
الحفظ
الإرسال إلى الحافظة
حفظ سجلّ العمل
مجرّد القدرة على فعل هذه الأمور يجعل العمل اليوميّ أسهل بكثير. لا حاجة لاستهداف الأتمتة المعقّدة منذ البداية.
لنبدأ أوّلاً بالأوامر القرائيّة لنتمكّن من رؤية الوضع بدقّة، ثمّ نستخدم عند الحاجة فقط الأوامر التغييريّة مثل Copy-Item وMove-Item وRemove-Item وRestart-Service.
سرّ استخدام PowerShell بأمان هو هذا الترتيب.
الرؤية → العدّ → الترتيب → الحفظ → التنفيذ التجريبيّ → التنفيذ
عند اكتساب هذا النمط، لن يعود PowerShell «أداة كتابة أوامر على شاشة سوداء»، بل أداة عمليّة تدعم التحقيق اليوميّ والتنظيم والتقارير.
مقالات ذات صلة
أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.
أساسيّات أوامر PowerShell ── العمليّات الأولى الواجب تعلّمها والاستخدام الآمن
لكي لا يتوه مبتدئو PowerShell في العمل الفعليّ، نرتّب طريقة البحث عن الأوامر (cmdlets)، وخطّ الأنابيب (pipeline)، ومعالجة الملفّات، ومعال...
طريقة تشغيل PowerShell من C# (CSharp) واستقبال النتيجة ككائن
نرتّب من منظور عمليّ طريقة تشغيل PowerShell من C# واستقبال النتيجة ككائن PSObject بدل نصّ، بدءًا من PowerShell SDK وAddCommand وAddParame...
تهيئة اختبارات PowerShell عبر Pester ── الأسلوب العمليّ لجعل سكربتات التشغيل أقلّ عرضةً للكسر
نُنظِّم الإجراءات العمليّة لاختبار سكربتات PowerShell عبر Pester v5، بدءاً من معالجة التواريخ وعمليّات الملفّات وعمليّات الحذف، مروراً با...
معالجة الأخطاء وتصميم إعادة التنفيذ في PowerShell ── من فخّ عدم نجاعة try/catch إلى قواعد exit code وإعادة المحاولة
نرتّب من منظور عمليّ الفرق بين الأخطاء المُنهِية وغير المُنهِية في PowerShell، والفخّ الذي يجعل try/catch غير فعّال والقاعدة الثابتة لـ -...
سياسة تنفيذ PowerShell وتوقيع السكربتات ── دليل عمليّ للتخلّص من تشغيل «السدّ بـ Bypass»
سياسة تنفيذ PowerShell هي «جهاز أمان لا حدّ أمنيّ (security boundary)». نرتّب الفروق بين RemoteSigned وغيرها، وأولويّة النطاقات (scopes)،...
أين يتصل هذا الموضوع
ترتبط هذه المقالة بشكل طبيعي بصفحات الخدمات التالية.
تطوير تطبيقات ويندوز
ندعم تطوير برامج ويندوز للأعمال، وتكامل الأجهزة، وأدوات التواصل.
الأسئلة الشائعة
أسئلة شائعة حول موضوع هذه المقالة.
- كيف يمكن معرفة عدد الملفّات أو حجمها الإجماليّ في PowerShell؟
- مرِّر نتيجة Get-ChildItem عبر أنبوب (pipe) إلى Measure-Object. يمكن التحقّق من عدد العناصر عبر خاصيّة Count في النتيجة، وإن أردتَ تضمين المجلّدات الفرعيّة أضِف -Recurse. أمّا الحجم الإجماليّ فيُجمَع عبر Measure-Object -Property Length -Sum، ولأنّ الرقم يبقى بالبايت وهو صعب القراءة، فإنّ تحويله إلى وحدة GB عبر [math]::Round($size.Sum / 1GB, 2) يجعله أوضح. وبإضافة -Average أو -Maximum يمكن الحصول على المتوسّط والحدّ الأقصى في آنٍ واحد.
- ما الفرق بين -ExpandProperty في Select-Object والتحديد المعتاد؟
- يُرجِع الأمر Select-Object Name «جدولاً (كائناً) يحتوي عموداً باسم Name»، بينما يُرجِع Select-Object -ExpandProperty Name «قيمة Name نفسها». عند الرغبة في الإخراج إلى CSV، يناسب التحديد المعتاد الذي يُبقي القيمة كعمود، أمّا عند تمرير القيم فقط إلى أمر آخر أو معالجة نصّية أو ملفّ نصّي، فإنّ -ExpandProperty أسهل في التعامل. يُختار الأسلوب حسب الغرض.
- لماذا لا يجوز استخدام Format-Table قبل Export-Csv؟
- لأنّ Format-Table وFormat-List أوامر مخصّصة للعرض على الشاشة، وتُحوِّل المخرَجات إلى كائنات عرض (display objects)، ما يمنع تنفيذ عمليّة الإخراج إلى CSV أو المعالجة اللاحقة بشكل صحيح. عند الإخراج إلى CSV أو المعالجة بأمر لاحق، اختر الأعمدة عبر Select-Object ثمّ مرِّرها إلى Export-Csv. تذكَّر القاعدة: «إن كان العرض على الشاشة فقط فاستخدم أوامر Format، وإن كان الاستخدام لاحقاً فاستخدم Select-Object»، ولن تتردّد بعدها.
- هل توجد خطوات لاستخدام الأوامر التغييريّة مثل Remove-Item بأمان؟
- لا تُنفِّذ الأمر مباشرةً، بل انظر أوّلاً إلى الهدف عبر أوامر Get، ثمّ ضيِّق النطاق بـ Where-Object، وتحقَّق من قائمة الأهداف عبر Select-Object، وعُدَّ العناصر بـ Measure-Object، واحفظ دليلاً (إن لزم) عبر Export-Csv. بعد ذلك، إن كان الأمر يدعم -WhatIf، فنفِّذه تجريبيّاً أوّلاً للتحقّق من خطّة الحذف أو النقل، وإن لم تكن هناك مشكلة فنفِّذه فعليّاً. مجرّد الالتزام بهذا الترتيب يقلِّل الحوادث كثيراً.
الملف الشخصي للمؤلف
صفحة الملف الشخصي لمؤلف المقالة.
غو كومورا
مؤسّس شركة كومورا سوفت ذ.م.م.
يركّز على تطوير برامج ويندوز، والاستشارات التقنية، والتحقيق في الأخطاء، ويتميّز في المشاريع التي تبقى فيها الأصول القديمة ناشطة، وفي تشخيص الأعطال التي يصعب تحديد سببها.
روابط عامة