انتقل إلى المحتوى الرئيسي

المختبر 8.3: إدارة النظام باستخدام PowerShell

الأهداف التعليمية​

في نهاية هذا المختبر، ستكون قادرًا على:

  • إنشاء سكربتات لإدارة النظام
  • أتمتة مهام الصيانة
  • توليد تقارير النظام
  • إدارة المستخدمين والأذونات

المدة المقدرة​

50 دقيقة

المتطلبات المسبقة​

  • VM Windows 10/11
  • حقوق المسؤول
  • معرفة أساسية بـ PowerShell

السياق المهني​

تُستخدم سكربتات الإدارة لـ:

  • أتمتة المهام المتكررة
  • الحفاظ على اتساق التكوينات
  • توليد تقارير الامتثال
  • إدارة حسابات المستخدمين

الجزء 1: تقرير النظام الكامل​

الخطوة 1.1: سكربت التقرير​

قم بإنشاء سكربت Get-SystemReport.ps1:

<#
.SYNOPSIS
يُولد تقريرًا كاملًا للنظام
.DESCRIPTION
يجمع معلومات النظام، الشبكة، التخزين والأمان
.EXAMPLE
.\Get-SystemReport.ps1
#>

param(
[string]$OutputPath = "$env:USERPROFILE\Desktop\SystemReport_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"
)

Write-Host "جاري توليد تقرير النظام..." -ForegroundColor Cyan

# CSS للتقرير HTML
$css = @"
<style>
body { font-family: 'Segoe UI', Arial; margin: 20px; background: #f5f5f5; }
h1 { color: #2c3e50; border-bottom: 2px solid #3498db; padding-bottom: 10px; }
h2 { color: #34495e; margin-top: 30px; }
table { border-collapse: collapse; width: 100%; margin: 10px 0; background: white; }
th { background: #3498db; color: white; padding: 12px; text-align: left; }
td { padding: 10px; border: 1px solid #ddd; }
tr:nth-child(even) { background: #f9f9f9; }
.warning { color: #e74c3c; font-weight: bold; }
.ok { color: #27ae60; font-weight: bold; }
.section { background: white; padding: 20px; margin: 20px 0; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
</style>
"@

# جمع المعلومات
$computerInfo = Get-CimInstance Win32_ComputerSystem
$osInfo = Get-CimInstance Win32_OperatingSystem
$cpuInfo = Get-CimInstance Win32_Processor
$diskInfo = Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3"
$networkInfo = Get-NetAdapter | Where-Object {$_.Status -eq "Up"}
$services = Get-Service | Where-Object {$_.Status -eq "Running"}
$processes = Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 10

# توليد HTML
$html = @"
<!DOCTYPE html>
<html>
<head>
<title>تقرير النظام - $($computerInfo.Name)</title>
$css
</head>
<body>
<h1>تقرير النظام - $($computerInfo.Name)</h1>
<p>تم التوليد في: $(Get-Date -Format 'dd/MM/yyyy HH:mm:ss')</p>

<div class="section">
<h2>معلومات عامة</h2>
<table>
<tr><th>خاصية</th><th>القيمة</th></tr>
<tr><td>اسم الكمبيوتر</td><td>$($computerInfo.Name)</td></tr>
<tr><td>النطاق</td><td>$($computerInfo.Domain)</td></tr>
<tr><td>الشركة المصنعة</td><td>$($computerInfo.Manufacturer)</td></tr>
<tr><td>النموذج</td><td>$($computerInfo.Model)</td></tr>
<tr><td>نظام التشغيل</td><td>$($osInfo.Caption)</td></tr>
<tr><td>الإصدار</td><td>$($osInfo.Version)</td></tr>
<tr><td>البنية</td><td>$($osInfo.OSArchitecture)</td></tr>
<tr><td>آخر تشغيل</td><td>$($osInfo.LastBootUpTime)</td></tr>
</table>
</div>

<div class="section">
<h2>المعالج</h2>
<table>
<tr><th>خاصية</th><th>القيمة</th></tr>
<tr><td>الاسم</td><td>$($cpuInfo.Name)</td></tr>
<tr><td>النوى</td><td>$($cpuInfo.NumberOfCores)</td></tr>
<tr><td>الخيوط</td><td>$($cpuInfo.NumberOfLogicalProcessors)</td></tr>
<tr><td>الاستخدام</td><td>$($cpuInfo.LoadPercentage)%</td></tr>
</table>
</div>

<div class="section">
<h2>الذاكرة</h2>
<table>
<tr><th>خاصية</th><th>القيمة</th></tr>
<tr><td>إجمالي الذاكرة العشوائية</td><td>$([math]::Round($computerInfo.TotalPhysicalMemory/1GB, 2)) جيجابايت</td></tr>
<tr><td>الذاكرة العشوائية المتاحة</td><td>$([math]::Round($osInfo.FreePhysicalMemory/1MB, 2)) جيجابايت</td></tr>
<tr><td>الاستخدام</td><td>$([math]::Round((1 - $osInfo.FreePhysicalMemory*1KB/$computerInfo.TotalPhysicalMemory)*100, 1))%</td></tr>
</table>
</div>

<div class="section">
<h2>التخزين</h2>
<table>
<tr><th>القرص</th><th>الحجم</th><th>المساحة الحرة</th><th>الاستخدام</th></tr>
"@

foreach ($disk in $diskInfo) {
$percentUsed = [math]::Round((1 - $disk.FreeSpace/$disk.Size)*100, 1)
$statusClass = if ($percentUsed -gt 90) { "warning" } else { "ok" }
$html += @"
<tr>
<td>$($disk.DeviceID)</td>
<td>$([math]::Round($disk.Size/1GB, 2)) جيجابايت</td>
<td>$([math]::Round($disk.FreeSpace/1GB, 2)) جيجابايت</td>
<td class="$statusClass">$percentUsed%</td>
</tr>
"@
}

$html += @"
</table>
</div>

<div class="section">
<h2>الشبكة</h2>
<table>
<tr><th>المحول</th><th>الحالة</th><th>السرعة</th></tr>
"@

foreach ($adapter in $networkInfo) {
$html += @"
<tr>
<td>$($adapter.Name)</td>
<td class="ok">$($adapter.Status)</td>
<td>$([math]::Round($adapter.LinkSpeed/1000000, 0)) ميجابت في الثانية</td>
</tr>
"@
}

$html += @"
</table>
</div>

<div class="section">
<h2>أفضل 10 عمليات (الذاكرة)</h2>
<table>
<tr><th>العملية</th><th>PID</th><th>الذاكرة</th><th>CPU (ث)</th></tr>
"@

foreach ($proc in $processes) {
$html += @"
<tr>
<td>$($proc.Name)</td>
<td>$($proc.Id)</td>
<td>$([math]::Round($proc.WorkingSet64/1MB, 2)) ميجابايت</td>
<td>$([math]::Round($proc.CPU, 2))</td>
</tr>
"@
}

$html += @"
</table>
</div>

<div class="section">
<h2>الخدمات الجارية ($($services.Count))</h2>
<p>إجمالي الخدمات الجارية: $($services.Count)</p>
</div>

</body>
</html>
"@

# حفظ
$html | Out-File $OutputPath -Encoding UTF8
Write-Host "تم حفظ التقرير: $OutputPath" -ForegroundColor Green

# فتح التقرير
Start-Process $OutputPath

الخطوة 1.2: تنفيذ السكربت​

.\Get-SystemReport.ps1

السؤال 1: ما هي المعلومات التي تجدها الأكثر فائدة في هذا التقرير؟


الجزء 2: إدارة المستخدمين​

الخطوة 2.1: سكربت إدارة المستخدمين​

# سكربت إدارة المستخدمين المحليين

function Get-LocalUserReport {
Write-Host "=== تقرير المستخدمين المحليين ===" -ForegroundColor Cyan

Get-LocalUser | ForEach-Object {
$user = $_
$groups = Get-LocalGroup | Where-Object {
(Get-LocalGroupMember $_.Name -ErrorAction SilentlyContinue).Name -contains "$env:COMPUTERNAME\$($user.Name)"
}

[PSCustomObject]@{
Nom = $user.Name
Actif = $user.Enabled
DernierLogin = $user.LastLogon
PasswordExpire = $user.PasswordExpires
Groupes = ($groups.Name -join ", ")
}
} | Format-Table -AutoSize
}

function New-StandardUser {
param(
[Parameter(Mandatory)]
[string]$Username,
[Parameter(Mandatory)]
[SecureString]$Password,
[string]$Description = "مستخدم عادي"
)

try {
New-LocalUser -Name $Username -Password $Password -Description $Description -ErrorAction Stop
Add-LocalGroupMember -Group "Utilisateurs" -Member $Username
Write-Host "[OK] تم إنشاء المستخدم $Username" -ForegroundColor Green
} catch {
Write-Host "[خطأ] $($_.Exception.Message)" -ForegroundColor Red
}
}

function Remove-UserCompletely {
param(
[Parameter(Mandatory)]
[string]$Username
)

$confirm = Read-Host "حذف المستخدم $Username وملفه الشخصي؟ (ن/ع)"
if ($confirm -eq "ن") {
try {
# حذف المستخدم
Remove-LocalUser -Name $Username -ErrorAction Stop

# حذف الملف الشخصي
$profilePath = "C:\Users\$Username"
if (Test-Path $profilePath) {
Remove-Item $profilePath -Recurse -Force
}

Write-Host "[OK] تم حذف المستخدم والملف الشخصي" -ForegroundColor Green
} catch {
Write-Host "[خطأ] $($_.Exception.Message)" -ForegroundColor Red
}
}
}

# القائمة
Write-Host @"

إدارة المستخدمين
========================
1. عرض تقرير المستخدمين
2. إنشاء مستخدم عادي
3. حذف مستخدم
4. الخروج

"@

$choice = Read-Host "الاختيار"
switch ($choice) {
"1" { Get-LocalUserReport }
"2" {
$name = Read-Host "اسم المستخدم"
$pass = Read-Host "كلمة المرور" -AsSecureString
New-StandardUser -Username $name -Password $pass
}
"3" {
$name = Read-Host "اسم المستخدم المراد حذفه"
Remove-UserCompletely -Username $name
}
}

الجزء 3: سكربت الصيانة​

الخطوة 3.1: الصيانة الآلية​

<#
.SYNOPSIS
سكربت صيانة النظام الآلي
#>

param(
[switch]$CleanTemp,
[switch]$CheckDisk,
[switch]$UpdateHelp,
[switch]$All
)

$ErrorActionPreference = "SilentlyContinue"

function Write-Log {
param([string]$Message, [string]$Level = "INFO")
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$color = switch ($Level) {
"INFO" { "White" }
"SUCCESS" { "Green" }
"WARNING" { "Yellow" }
"ERROR" { "Red" }
}
Write-Host "[$timestamp] [$Level] $Message" -ForegroundColor $color
}

function Clear-TempFiles {
Write-Log "تنظيف الملفات المؤقتة..." "INFO"

$paths = @(
$env:TEMP,
"C:\Windows\Temp",
"C:\Windows\Prefetch"
)

$totalSize = 0
$totalFiles = 0

foreach ($path in $paths) {
if (Test-Path $path) {
$files = Get-ChildItem $path -Recurse -Force -ErrorAction SilentlyContinue
$size = ($files | Measure-Object -Property Length -Sum).Sum
$count = $files.Count

Remove-Item "$path\*" -Recurse -Force -ErrorAction SilentlyContinue

$totalSize += $size
$totalFiles += $count
}
}

Write-Log "تم التنظيف: $totalFiles ملفات، $([math]::Round($totalSize/1MB, 2)) ميجابايت" "SUCCESS"
}

function Test-DiskHealth {
Write-Log "التحقق من حالة الأقراص..." "INFO"

Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" | ForEach-Object {
$disk = $_
$percentFree = [math]::Round($disk.FreeSpace / $disk.Size * 100, 1)

if ($percentFree -lt 10) {
Write-Log "تحذير: القرص $($disk.DeviceID) - فقط $percentFree% متاح!" "ERROR"
} elseif ($percentFree -lt 20) {
Write-Log "انتباه: القرص $($disk.DeviceID) - $percentFree% متاح" "WARNING"
} else {
Write-Log "القرص $($disk.DeviceID) - $percentFree% متاح" "SUCCESS"
}
}
}

function Update-PSHelp {
Write-Log "تحديث مساعدة PowerShell..." "INFO"
try {
Update-Help -Force -ErrorAction Stop
Write-Log "تم تحديث المساعدة" "SUCCESS"
} catch {
Write-Log "فشل تحديث المساعدة: $($_.Exception.Message)" "WARNING"
}
}

function Get-SystemHealth {
Write-Log "التحقق من صحة النظام..." "INFO"

# CPU
$cpu = (Get-CimInstance Win32_Processor).LoadPercentage
if ($cpu -gt 90) {
Write-Log "CPU: $cpu% (حرج)" "ERROR"
} elseif ($cpu -gt 70) {
Write-Log "CPU: $cpu% (مرتفع)" "WARNING"
} else {
Write-Log "CPU: $cpu% (طبيعي)" "SUCCESS"
}

# RAM
$os = Get-CimInstance Win32_OperatingSystem
$ramUsed = [math]::Round((1 - $os.FreePhysicalMemory*1KB / (Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory) * 100, 1)
if ($ramUsed -gt 90) {
Write-Log "RAM: $ramUsed% مستخدم (حرج)" "ERROR"
} elseif ($ramUsed -gt 80) {
Write-Log "RAM: $ramUsed% مستخدم (مرتفع)" "WARNING"
} else {
Write-Log "RAM: $ramUsed% مستخدم (طبيعي)" "SUCCESS"
}

# الخدمات الحرجة
$criticalServices = @("wuauserv", "EventLog", "Dnscache")
foreach ($svc in $criticalServices) {
$service = Get-Service $svc -ErrorAction SilentlyContinue
if ($service.Status -ne "Running") {
Write-Log "الخدمة $svc ليست قيد التشغيل!" "WARNING"
}
}
}

# التنفيذ
Write-Host @"
===============================================
سكربت صيانة النظام
$(Get-Date -Format "dd/MM/yyyy HH:mm")
===============================================
"@ -ForegroundColor Cyan

Get-SystemHealth

if ($All -or $CleanTemp) { Clear-TempFiles }
if ($All -or $CheckDisk) { Test-DiskHealth }
if ($All -or $UpdateHelp) { Update-PSHelp }

Write-Host "`n===============================================" -ForegroundColor Cyan
Write-Log "تم الانتهاء من الصيانة" "SUCCESS"

الخطوة 3.2: تنفيذ الصيانة​

# جميع المهام
.\Maintenance.ps1 -All

# أو بشكل انتقائي
.\Maintenance.ps1 -CleanTemp -CheckDisk

الجزء 4: تدقيق الأمان​

الخطوة 4.1: سكربت التدقيق​

# تدقيق أمني أساسي
Write-Host "=== تدقيق الأمان ===" -ForegroundColor Cyan

$findings = @()

# 1. التحقق من Windows Defender
$defender = Get-MpComputerStatus -ErrorAction SilentlyContinue
if ($defender) {
if (-not $defender.RealTimeProtectionEnabled) {
$findings += "[حرج] الحماية في الوقت الحقيقي معطلة"
}
if (-not $defender.AntivirusEnabled) {
$findings += "[حرج] برنامج مكافحة الفيروسات معطل"
}
}

# 2. التحقق من الجدار الناري
$firewall = Get-NetFirewallProfile
foreach ($profile in $firewall) {
if (-not $profile.Enabled) {
$findings += "[حرج] الجدار الناري $($profile.Name) معطل"
}
}

# 3. التحقق من التحديثات
$lastUpdate = (Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 1).InstalledOn
$daysSinceUpdate = (New-TimeSpan -Start $lastUpdate -End (Get-Date)).Days
if ($daysSinceUpdate -gt 30) {
$findings += "[تحذير] لا توجد تحديثات منذ $daysSinceUpdate يومًا"
}

# 4. التحقق من حسابات المسؤول
$admins = Get-LocalGroupMember -Group "Administrateurs"
if ($admins.Count -gt 3) {
$findings += "[تحذير] $($admins.Count) حسابات في مجموعة المسؤولين"
}

# 5. التحقق من المشاركات
$shares = Get-SmbShare | Where-Object {$_.Name -notmatch '^\$'}
if ($shares) {
$findings += "[معلومات] $($shares.Count) مشاركات نشطة: $($shares.Name -join ', ')"
}

# التقرير
Write-Host "`n=== النتائج ===" -ForegroundColor Yellow
if ($findings.Count -eq 0) {
Write-Host "[موافق] لم يتم اكتشاف أي مشاكل" -ForegroundColor Green
} else {
foreach ($finding in $findings) {
if ($finding -match "حرج") {
Write-Host $finding -ForegroundColor Red
} elseif ($finding -match "تحذير") {
Write-Host $finding -ForegroundColor Yellow
} else {
Write-Host $finding -ForegroundColor Cyan
}
}
}

التسليمات​

  1. السكربتات التي تم إنشاؤها:

    • Get-SystemReport.ps1
    • سكربت إدارة المستخدمين
    • سكربت الصيانة
    • سكربت التدقيق
  2. لقطات الشاشة:

    • التقرير HTML الذي تم توليده
    • تنفيذ الصيانة
    • نتيجة التدقيق
  3. الإجابة على السؤال 1


معايير التقييم​

المعيارالنقاط
سكربت التقرير30%
إدارة المستخدمين20%
سكربت الصيانة30%
سكربت التدقيق20%

تم تطوير المختبر في إطار دورة أنظمة التشغيل - الوحدة 8