# Powershell
# Nom: Info PC
# Description: Récupère les informations du PC
# Version: 0.5.0
# Categorie: Tools
# Changelog:
# - Ajout de la section Batterie complète
# - Amélioration de la gestion des erreurs
# - Configuration externalisée (SMTP)
# - Utilisation cohérente de Get-CimInstance
# - Ajout d'informations système supplémentaires
# - Meilleure détection du type de RAM
# - Ajout des informations TPM
# - Optimisation des performances
#Requires -Version 5.1
# ============================================================================
# CONFIGURATION
# ============================================================================
$Script:Config = @{
# Configuration SMTP - À externaliser dans un fichier config.json
SMTP = @{
Server = "ssl0.ovh.net"
Port = 587
From = "system@microinfoservice.fr"
To = "system@microinfoservice.fr"
Username = "system@microinfoservice.fr"
# ATTENTION: Ne pas laisser le mot de passe en clair en production!
# Utiliser: Get-Credential | Export-Clixml -Path "cred.xml"
# Puis: Import-Clixml -Path "cred.xml"
Password = $null # Sera demandé ou chargé depuis un fichier sécurisé
}
# Options du script
Options = @{
SendEmail = $true
OpenReportOnEnd = $true
IncludeWifiPasswords = $false # Attention: nécessite droits admin
}
}
# ============================================================================
# FONCTIONS UTILITAIRES
# ============================================================================
function Write-Log {
param(
[string]$Message,
[ValidateSet('Info', 'Warning', 'Error', 'Success')]
[string]$Level = 'Info'
)
$colors = @{
'Info' = 'White'
'Warning' = 'Yellow'
'Error' = 'Red'
'Success' = 'Green'
}
$timestamp = Get-Date -Format "HH:mm:ss"
Write-Host "[$timestamp] " -NoNewline -ForegroundColor Gray
Write-Host $Message -ForegroundColor $colors[$Level]
}
function Format-Size {
param([int64]$Size)
if ($Size -lt 0) { return "N/A" }
if ($Size -gt 1TB) { return "{0:N2} To" -f ($Size / 1TB) }
if ($Size -gt 1GB) { return "{0:N2} Go" -f ($Size / 1GB) }
if ($Size -gt 1MB) { return "{0:N2} Mo" -f ($Size / 1MB) }
if ($Size -gt 1KB) { return "{0:N2} Ko" -f ($Size / 1KB) }
return "$Size octets"
}
function Get-FormattedInstallDate {
param([string]$InstallDate)
if ([string]::IsNullOrEmpty($InstallDate)) { return 'N/A' }
try {
return [DateTime]::ParseExact($InstallDate, 'yyyyMMdd', $null).ToString("dd/MM/yyyy")
}
catch {
return 'N/A'
}
}
function Get-SafeValue {
param(
$Value,
[string]$Default = "N/A"
)
if ($null -eq $Value -or [string]::IsNullOrWhiteSpace($Value.ToString())) {
return $Default
}
return $Value
}
function Get-RAMTypeName {
param([int]$TypeCode)
$ramTypes = @{
0 = "Unknown"
1 = "Other"
2 = "DRAM"
3 = "Synchronous DRAM"
4 = "Cache DRAM"
5 = "EDO"
6 = "EDRAM"
7 = "VRAM"
8 = "SRAM"
9 = "RAM"
10 = "ROM"
11 = "Flash"
12 = "EEPROM"
13 = "FEPROM"
14 = "EPROM"
15 = "CDRAM"
16 = "3DRAM"
17 = "SDRAM"
18 = "SGRAM"
19 = "RDRAM"
20 = "DDR"
21 = "DDR2"
22 = "DDR2 FB-DIMM"
24 = "DDR3"
25 = "FBD2"
26 = "DDR4"
27 = "LPDDR"
28 = "LPDDR2"
29 = "LPDDR3"
30 = "LPDDR4"
34 = "DDR5"
35 = "LPDDR5"
}
if ($ramTypes.ContainsKey($TypeCode)) {
return $ramTypes[$TypeCode]
}
return "Unknown ($TypeCode)"
}
function Test-IsAdmin {
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
return $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
# ============================================================================
# FONCTIONS DE COLLECTE D'INFORMATIONS
# ============================================================================
function Get-SystemInfo {
Write-Log "Collecte des informations système..." -Level Info
try {
$os = Get-CimInstance Win32_OperatingSystem
$cs = Get-CimInstance Win32_ComputerSystem
$bios = Get-CimInstance Win32_BIOS
$mb = Get-CimInstance Win32_BaseBoard
$cpu = Get-CimInstance Win32_Processor | Select-Object -First 1
# Correction pour Windows 11
$buildNumber = [int](Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion').CurrentBuildNumber
$windowsVersion = $os.Caption
if ($buildNumber -ge 22000) {
$windowsVersion = $windowsVersion -replace "Windows 10", "Windows 11"
}
# DisplayVersion (ex: 23H2)
$displayVersion = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -ErrorAction SilentlyContinue).DisplayVersion
if ($displayVersion) {
$windowsVersion += " ($displayVersion)"
}
# Secure Boot
try {
$secureBootStatus = Confirm-SecureBootUEFI -ErrorAction Stop
$secureBootText = if ($secureBootStatus) { "Activé" } else { "Désactivé" }
}
catch {
$secureBootText = "Non disponible (BIOS legacy)"
}
# TPM
try {
$tpm = Get-CimInstance -Namespace "root\cimv2\Security\MicrosoftTpm" -ClassName Win32_Tpm -ErrorAction Stop
$tpmInfo = @{
Present = $true
Version = $tpm.SpecVersion
Enabled = $tpm.IsEnabled_InitialValue
Activated = $tpm.IsActivated_InitialValue
}
}
catch {
$tpmInfo = @{
Present = $false
Version = "N/A"
Enabled = $false
Activated = $false
}
}
# Uptime
$uptime = (Get-Date) - $os.LastBootUpTime
$uptimeString = "{0}j {1}h {2}m" -f $uptime.Days, $uptime.Hours, $uptime.Minutes
return @{
ComputerName = $env:COMPUTERNAME
WindowsVersion = $windowsVersion
BuildNumber = $buildNumber
Architecture = $os.OSArchitecture
InstallDate = $os.InstallDate.ToString("dd/MM/yyyy HH:mm")
LastBoot = $os.LastBootUpTime.ToString("dd/MM/yyyy HH:mm")
Uptime = $uptimeString
SecureBoot = $secureBootText
TPM = $tpmInfo
Manufacturer = Get-SafeValue $cs.Manufacturer
Model = Get-SafeValue $cs.Model
Motherboard = Get-SafeValue $mb.Product
MotherboardMfr = Get-SafeValue $mb.Manufacturer
BiosVersion = Get-SafeValue $bios.SMBIOSBIOSVersion
BiosManufacturer = Get-SafeValue $bios.Manufacturer
BiosName = Get-SafeValue $bios.Name
BiosDate = if ($bios.ReleaseDate) { $bios.ReleaseDate.ToString("dd/MM/yyyy") } else { "N/A" }
CPU = Get-SafeValue $cpu.Name
CPUCores = $cpu.NumberOfCores
CPUThreads = $cpu.NumberOfLogicalProcessors
CPUSocket = Get-SafeValue $cpu.SocketDesignation
CPUMaxSpeed = "{0} MHz" -f $cpu.MaxClockSpeed
}
}
catch {
Write-Log "Erreur lors de la collecte des informations système: $_" -Level Error
return $null
}
}
function Get-MemoryInfo {
Write-Log "Collecte des informations mémoire..." -Level Info
try {
$memoryArray = Get-CimInstance Win32_PhysicalMemoryArray
$memoryModules = Get-CimInstance Win32_PhysicalMemory
$totalSlots = ($memoryArray | Measure-Object -Property MemoryDevices -Sum).Sum
$usedSlots = ($memoryModules | Measure-Object).Count
$totalCapacity = ($memoryModules | Measure-Object -Property Capacity -Sum).Sum
$modules = @()
foreach ($module in $memoryModules) {
$modules += @{
Manufacturer = Get-SafeValue $module.Manufacturer
PartNumber = Get-SafeValue ($module.PartNumber -replace '\s+', ' ').Trim()
Capacity = Format-Size $module.Capacity
Speed = "{0} MHz" -f $module.ConfiguredClockSpeed
Type = Get-RAMTypeName $module.SMBIOSMemoryType
DeviceLocator = Get-SafeValue $module.DeviceLocator
FormFactor = switch ($module.FormFactor) {
8 { "DIMM" }
12 { "SO-DIMM" }
default { "Autre" }
}
}
}
return @{
TotalCapacity = Format-Size $totalCapacity
TotalSlots = $totalSlots
UsedSlots = $usedSlots
Modules = $modules
}
}
catch {
Write-Log "Erreur lors de la collecte des informations mémoire: $_" -Level Error
return $null
}
}
function Get-GPUInfo {
Write-Log "Collecte des informations GPU..." -Level Info
try {
$gpus = Get-CimInstance Win32_VideoController
$gpuList = @()
foreach ($gpu in $gpus) {
$gpuList += @{
Name = Get-SafeValue $gpu.Name
Processor = Get-SafeValue $gpu.VideoProcessor
RAM = if ($gpu.AdapterRAM -gt 0) { Format-Size $gpu.AdapterRAM } else { "N/A" }
Driver = Get-SafeValue $gpu.DriverVersion
Resolution = "{0}x{1}" -f $gpu.CurrentHorizontalResolution, $gpu.CurrentVerticalResolution
RefreshRate = "{0} Hz" -f $gpu.CurrentRefreshRate
}
}
return $gpuList
}
catch {
Write-Log "Erreur lors de la collecte des informations GPU: $_" -Level Error
return @()
}
}
function Get-StorageInfo {
Write-Log "Collecte des informations stockage..." -Level Info
try {
$disks = Get-PhysicalDisk -ErrorAction SilentlyContinue
$volumes = Get-Volume -ErrorAction SilentlyContinue | Where-Object { $_.DriveLetter }
$bitlockerVolumes = @{}
try {
$blVolumes = Get-BitLockerVolume -ErrorAction SilentlyContinue
foreach ($bl in $blVolumes) {
$bitlockerVolumes[$bl.MountPoint.TrimEnd('\')] = $bl
}
}
catch {
Write-Log "BitLocker non disponible ou accès refusé" -Level Warning
}
$diskList = @()
foreach ($disk in $disks) {
$diskList += @{
Model = Get-SafeValue $disk.FriendlyName
Type = Get-SafeValue $disk.MediaType "Unknown"
Size = Format-Size $disk.Size
Health = Get-SafeValue $disk.HealthStatus
BusType = Get-SafeValue $disk.BusType
Serial = Get-SafeValue $disk.SerialNumber
}
}
$volumeList = @()
foreach ($vol in $volumes) {
$driveLetter = "$($vol.DriveLetter):"
$bl = $bitlockerVolumes[$driveLetter]
$usedPercent = 0
if ($vol.Size -gt 0) {
$usedPercent = [math]::Round((($vol.Size - $vol.SizeRemaining) / $vol.Size) * 100)
}
$volumeList += @{
Letter = $driveLetter
Label = Get-SafeValue $vol.FileSystemLabel "Sans nom"
FileSystem = Get-SafeValue $vol.FileSystem
Size = Format-Size $vol.Size
Free = Format-Size $vol.SizeRemaining
Used = Format-Size ($vol.Size - $vol.SizeRemaining)
UsedPercent = $usedPercent
BitLockerStatus = if ($bl) { $bl.ProtectionStatus.ToString() } else { "Non protégé" }
BitLockerMethod = if ($bl -and $bl.EncryptionMethod) { $bl.EncryptionMethod.ToString() } else { "N/A" }
}
}
return @{
Disks = $diskList
Volumes = $volumeList
}
}
catch {
Write-Log "Erreur lors de la collecte des informations stockage: $_" -Level Error
return @{ Disks = @(); Volumes = @() }
}
}
function Get-NetworkInfo {
Write-Log "Collecte des informations réseau..." -Level Info
try {
$cs = Get-CimInstance Win32_ComputerSystem
$adapters = Get-NetAdapter | Where-Object { $_.Status -eq 'Up' -or $_.PhysicalMediaType }
$ipConfigs = Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.InterfaceAlias -ne 'Loopback Pseudo-Interface 1' }
$dnsServers = (Get-DnsClientServerAddress -AddressFamily IPv4 | Select-Object -ExpandProperty ServerAddresses) -join ', '
$gateway = (Get-NetRoute -AddressFamily IPv4 | Where-Object { $_.DestinationPrefix -eq '0.0.0.0/0' } | Select-Object -First 1).NextHop
$networkDrives = Get-CimInstance Win32_NetworkConnection | Where-Object { $_.LocalName }
# Domaine/Workgroup
$domainInfo = if ($cs.PartOfDomain) {
"Domaine: $($cs.Domain)"
} else {
"Groupe de travail: $($cs.Workgroup)"
}
# Adaptateurs
$adapterList = @()
foreach ($adapter in $adapters) {
$ipConfig = $ipConfigs | Where-Object { $_.InterfaceAlias -eq $adapter.Name }
$adapterList += @{
Name = $adapter.Name
Description = $adapter.InterfaceDescription
Status = $adapter.Status
Speed = if ($adapter.LinkSpeed) { $adapter.LinkSpeed } else { "N/A" }
MAC = $adapter.MacAddress
IPAddress = if ($ipConfig) { $ipConfig.IPAddress -join ', ' } else { "N/A" }
Type = Get-SafeValue $adapter.MediaType
}
}
# Lecteurs réseau
$drivesList = @()
foreach ($drive in $networkDrives) {
$drivesList += @{
Letter = $drive.LocalName
Path = $drive.RemoteName
}
}
# Profils WiFi
$wifiProfiles = @()
try {
$profilesOutput = netsh wlan show profiles 2>$null
if ($profilesOutput) {
$profileNames = $profilesOutput | Select-String -Pattern ':\s*(.+)$' | ForEach-Object {
$_.ToString().Split(':')[-1].Trim()
} | Where-Object { $_ }
foreach ($profileName in $profileNames) {
if ([string]::IsNullOrWhiteSpace($profileName)) { continue }
$profileDetails = netsh wlan show profile name="$profileName" 2>$null | Out-String
$authType = "N/A"
if ($profileDetails -match "(Type d'authentification|Authentication)\s*:\s*(.*)") {
$authType = $matches[2].Trim()
}
$wifiProfiles += @{
SSID = $profileName
Authentication = $authType
}
}
}
}
catch {
Write-Log "Erreur lors de la récupération des profils WiFi: $_" -Level Warning
}
# Fichier hosts
$hostsContent = ""
try {
$hostsPath = "$env:SystemRoot\System32\drivers\etc\hosts"
$hostsContent = Get-Content -Path $hostsPath -Raw -ErrorAction Stop
}
catch {
$hostsContent = "Impossible de lire le fichier hosts"
}
return @{
DomainInfo = $domainInfo
Adapters = $adapterList
DNS = $dnsServers
Gateway = Get-SafeValue $gateway
NetworkDrives = $drivesList
WifiProfiles = $wifiProfiles
HostsFile = $hostsContent
}
}
catch {
Write-Log "Erreur lors de la collecte des informations réseau: $_" -Level Error
return $null
}
}
function Get-UserInfo {
Write-Log "Collecte des informations utilisateurs..." -Level Info
try {
$users = Get-CimInstance Win32_UserAccount | Where-Object { $_.LocalAccount -eq $true }
$userList = @()
foreach ($user in $users) {
$userList += @{
Name = $user.Name
FullName = Get-SafeValue $user.FullName
Description = Get-SafeValue $user.Description
Status = if ($user.Disabled) { "Désactivé" } else { "Actif" }
SID = $user.SID
}
}
return $userList
}
catch {
Write-Log "Erreur lors de la collecte des informations utilisateurs: $_" -Level Error
return @()
}
}
function Get-SoftwareInfo {
Write-Log "Collecte des logiciels installés..." -Level Info
try {
$software = @()
$regPaths = @(
"HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*",
"HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
)
foreach ($path in $regPaths) {
$items = Get-ItemProperty $path -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName } |
Select-Object DisplayName, DisplayVersion, Publisher, InstallDate
$software += $items
}
$software = $software | Sort-Object -Property DisplayName -Unique | ForEach-Object {
@{
Name = $_.DisplayName
Version = Get-SafeValue $_.DisplayVersion
Publisher = Get-SafeValue $_.Publisher
InstallDate = Get-FormattedInstallDate $_.InstallDate
}
}
return $software
}
catch {
Write-Log "Erreur lors de la collecte des logiciels: $_" -Level Error
return @()
}
}
function Get-StartupInfo {
Write-Log "Collecte des programmes de démarrage..." -Level Info
try {
$startupItems = @()
# WMI Startup Commands
$wmiItems = Get-CimInstance Win32_StartupCommand -ErrorAction SilentlyContinue
foreach ($item in $wmiItems) {
$startupItems += @{
Name = Get-SafeValue $item.Name
Command = Get-SafeValue $item.Command
Location = Get-SafeValue $item.Location
User = if ([string]::IsNullOrEmpty($item.User)) { "Tous" } else { $item.User }
Status = "Activé"
}
}
# Registry Run keys
$runKeys = @(
@{ Path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; User = "Tous" },
@{ Path = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; User = $env:USERNAME }
)
foreach ($key in $runKeys) {
if (Test-Path $key.Path) {
$items = Get-ItemProperty -Path $key.Path -ErrorAction SilentlyContinue
foreach ($prop in $items.PSObject.Properties) {
if ($prop.Name -notin @("PSPath", "PSParentPath", "PSChildName", "PSDrive", "PSProvider")) {
$startupItems += @{
Name = $prop.Name
Command = $prop.Value
Location = $key.Path -replace 'HKLM:|HKCU:', ''
User = $key.User
Status = "Activé"
}
}
}
}
}
# Remove duplicates based on Name
$uniqueItems = @{}
foreach ($item in $startupItems) {
if (-not $uniqueItems.ContainsKey($item.Name)) {
$uniqueItems[$item.Name] = $item
}
}
return $uniqueItems.Values
}
catch {
Write-Log "Erreur lors de la collecte des programmes de démarrage: $_" -Level Error
return @()
}
}
function Get-PrinterInfo {
Write-Log "Collecte des informations imprimantes..." -Level Info
try {
$printers = Get-CimInstance Win32_Printer
$printerList = @()
foreach ($printer in $printers) {
$driver = Get-PrinterDriver -Name $printer.DriverName -ErrorAction SilentlyContinue
$printerList += @{
Name = $printer.Name
Status = switch ($printer.PrinterStatus) {
1 { "Other" }
2 { "Unknown" }
3 { "Idle" }
4 { "Printing" }
5 { "Warmup" }
6 { "Stopped Printing" }
7 { "Offline" }
default { $printer.PrinterStatus }
}
Port = Get-SafeValue $printer.PortName
Driver = Get-SafeValue $printer.DriverName
Manufacturer = if ($driver) { Get-SafeValue $driver.Manufacturer } else { "N/A" }
Default = $printer.Default
Shared = $printer.Shared
}
}
return $printerList
}
catch {
Write-Log "Erreur lors de la collecte des informations imprimantes: $_" -Level Error
return @()
}
}
function Get-MailInfo {
Write-Log "Collecte des informations mail..." -Level Info
$result = @{
OutlookAccounts = @()
OutlookFiles = @()
ThunderbirdProfiles = @()
}
# Fichiers Outlook (PST/OST)
$searchPaths = @(
"$env:LOCALAPPDATA\Microsoft\Outlook",
[System.IO.Path]::Combine($env:USERPROFILE, 'Documents'),
[System.IO.Path]::Combine($env:USERPROFILE, 'Documents', 'Outlook Files')
)
foreach ($searchPath in $searchPaths) {
if (Test-Path $searchPath) {
try {
$files = Get-ChildItem -Path $searchPath -Include "*.pst", "*.ost" -Recurse -ErrorAction SilentlyContinue
foreach ($file in $files) {
$result.OutlookFiles += @{
Name = $file.Name
Path = $file.FullName
Size = Format-Size $file.Length
Type = $file.Extension.ToUpper().TrimStart('.')
}
}
}
catch {
Write-Log "Erreur lors de la recherche des fichiers Outlook dans $searchPath" -Level Warning
}
}
}
# Profils Thunderbird
$thunderbirdPath = "$env:APPDATA\Thunderbird\Profiles"
if (Test-Path $thunderbirdPath) {
try {
$profiles = Get-ChildItem -Path $thunderbirdPath -Directory -ErrorAction SilentlyContinue
foreach ($profile in $profiles) {
$size = (Get-ChildItem -Path $profile.FullName -Recurse -File -ErrorAction SilentlyContinue |
Measure-Object -Property Length -Sum).Sum
$result.ThunderbirdProfiles += @{
Name = $profile.Name
Path = $profile.FullName
Size = Format-Size $size
}
}
}
catch {
Write-Log "Erreur lors de la recherche des profils Thunderbird" -Level Warning
}
}
# Comptes Outlook (via COM)
try {
$outlook = New-Object -ComObject Outlook.Application -ErrorAction Stop
$namespace = $outlook.GetNamespace("MAPI")
foreach ($account in $outlook.Session.Accounts) {
$accountType = "Inconnu"
$deliveryStore = $account.DeliveryStore.FilePath
if ($deliveryStore -like "*.ost") {
$accountType = "Exchange/Office 365"
}
elseif ($deliveryStore -like "*.pst") {
$accountType = switch ($account.AccountType) {
1 { "IMAP" }
2 { "POP3" }
default { "POP3/IMAP" }
}
}
$result.OutlookAccounts += @{
Name = $account.DisplayName
Email = $account.SmtpAddress
Type = $accountType
Store = $deliveryStore
}
}
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($namespace) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($outlook) | Out-Null
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
}
catch {
Write-Log "Outlook non installé ou non accessible" -Level Warning
}
return $result
}
function Get-BatteryInfo {
param([bool]$IncludeBatteryTest)
if (-not $IncludeBatteryTest) {
return @{
Available = $false
Message = "Test de batterie ignoré (PC de bureau)"
}
}
Write-Log "Collecte des informations batterie..." -Level Info
try {
$battery = Get-CimInstance Win32_Battery -ErrorAction SilentlyContinue
if (-not $battery) {
return @{
Available = $false
Message = "Aucune batterie détectée"
}
}
# Générer le rapport batterie Windows
$reportPath = [System.IO.Path]::Combine($script:FolderPath, 'battery_report.html')
try {
$null = powercfg /batteryreport /output $reportPath 2>&1
$reportGenerated = Test-Path $reportPath
}
catch {
$reportGenerated = $false
}
# Status de la batterie
$batteryStatus = switch ($battery.BatteryStatus) {
1 { "Décharge" }
2 { "Secteur (non en charge)" }
3 { "Chargement" }
4 { "Charge faible" }
5 { "Charge critique" }
6 { "En charge" }
7 { "En charge et haute" }
8 { "En charge et faible" }
9 { "En charge et critique" }
10 { "Non défini" }
11 { "Partiellement chargée" }
default { "Inconnu" }
}
# Santé estimée
$designCapacity = $battery.DesignCapacity
$fullChargeCapacity = $battery.FullChargeCapacity
$healthPercent = 100
if ($designCapacity -gt 0 -and $fullChargeCapacity -gt 0) {
$healthPercent = [math]::Round(($fullChargeCapacity / $designCapacity) * 100)
}
$healthStatus = if ($healthPercent -ge 80) { "Bonne" }
elseif ($healthPercent -ge 50) { "Moyenne" }
else { "Faible" }
return @{
Available = $true
ChargeLevel = "$($battery.EstimatedChargeRemaining)%"
Status = $batteryStatus
DesignCapacity = if ($designCapacity) { "$designCapacity mWh" } else { "N/A" }
FullChargeCapacity = if ($fullChargeCapacity) { "$fullChargeCapacity mWh" } else { "N/A" }
HealthPercent = $healthPercent
HealthStatus = $healthStatus
DeviceID = Get-SafeValue $battery.DeviceID
ReportGenerated = $reportGenerated
ReportPath = if ($reportGenerated) { $reportPath } else { $null }
}
}
catch {
Write-Log "Erreur lors de la collecte des informations batterie: $_" -Level Error
return @{
Available = $false
Message = "Erreur: $_"
}
}
}
# ============================================================================
# GÉNÉRATION HTML
# ============================================================================
function New-HTMLReport {
param(
[hashtable]$SystemInfo,
[hashtable]$MemoryInfo,
[array]$GPUInfo,
[hashtable]$StorageInfo,
[hashtable]$NetworkInfo,
[array]$UserInfo,
[array]$SoftwareInfo,
[array]$StartupInfo,
[array]$PrinterInfo,
[hashtable]$MailInfo,
[hashtable]$BatteryInfo
)
$htmlTemplate = @"
Info PC - $($SystemInfo.ComputerName)
Informations Système
| Nom du PC | $($SystemInfo.ComputerName) |
| Windows | $($SystemInfo.WindowsVersion) |
| Architecture | $($SystemInfo.Architecture) |
| Date d'installation | $($SystemInfo.InstallDate) |
| Dernier démarrage | $($SystemInfo.LastBoot) |
| Uptime | $($SystemInfo.Uptime) |
Sécurité
| Secure Boot | $(if($SystemInfo.SecureBoot -eq 'Activé'){'Activé'}else{''+$SystemInfo.SecureBoot+''}) |
| TPM | $(if($SystemInfo.TPM.Present){'Présent'}else{'Non détecté'}) |
$(if($SystemInfo.TPM.Present){"| Version TPM | $($SystemInfo.TPM.Version) |
"}else{""})
Matériel
| Fabricant | $($SystemInfo.Manufacturer) |
| Modèle | $($SystemInfo.Model) |
| Carte mère | $($SystemInfo.MotherboardMfr) $($SystemInfo.Motherboard) |
BIOS
| Version | $($SystemInfo.BiosVersion) |
| Fabricant | $($SystemInfo.BiosManufacturer) |
| Date | $($SystemInfo.BiosDate) |
Processeur
| CPU | $($SystemInfo.CPU) |
| Cœurs / Threads | $($SystemInfo.CPUCores) cœurs / $($SystemInfo.CPUThreads) threads |
| Socket | $($SystemInfo.CPUSocket) |
| Fréquence max | $($SystemInfo.CPUMaxSpeed) |
Mémoire RAM
| Capacité totale | $($MemoryInfo.TotalCapacity) |
| Slots utilisés | $($MemoryInfo.UsedSlots) / $($MemoryInfo.TotalSlots) |
Détails des modules
| Emplacement | Fabricant | Référence | Capacité | Type | Vitesse |
$(foreach($module in $MemoryInfo.Modules) {
"| $($module.DeviceLocator) | $($module.Manufacturer) | $($module.PartNumber) | $($module.Capacity) | $($module.Type) | $($module.Speed) |
"
})
Carte(s) Graphique(s)
| Nom | Processeur | VRAM | Driver | Résolution |
$(foreach($gpu in $GPUInfo) {
"| $($gpu.Name) | $($gpu.Processor) | $($gpu.RAM) | $($gpu.Driver) | $($gpu.Resolution) @ $($gpu.RefreshRate) |
"
})
Comptes Utilisateurs Locaux
| Nom | Nom complet | Description | Statut |
$(foreach($user in $UserInfo) {
$statusBadge = if($user.Status -eq 'Actif'){'Actif'}else{'Désactivé'}
"| $($user.Name) | $($user.FullName) | $($user.Description) | $statusBadge |
"
})
Logiciels Installés ($($SoftwareInfo.Count) programmes)
| Nom | Version | Éditeur | Date d'installation |
$(foreach($soft in $SoftwareInfo) {
"| $($soft.Name) | $($soft.Version) | $($soft.Publisher) | $($soft.InstallDate) |
"
})
Configuration Réseau
| Domaine / Groupe | $($NetworkInfo.DomainInfo) |
| DNS | $($NetworkInfo.DNS) |
| Passerelle | $($NetworkInfo.Gateway) |
Adaptateurs Réseau
| Nom | Description | Statut | Vitesse | MAC | IP |
$(foreach($adapter in $NetworkInfo.Adapters) {
$statusBadge = if($adapter.Status -eq 'Up'){'Connecté'}else{''+$adapter.Status+''}
"| $($adapter.Name) | $($adapter.Description) | $statusBadge | $($adapter.Speed) | $($adapter.MAC) | $($adapter.IPAddress) |
"
})
$(if($NetworkInfo.NetworkDrives.Count -gt 0) {
"
Lecteurs Réseau
| Lettre | Chemin réseau |
$(foreach($drive in $NetworkInfo.NetworkDrives) {
"| $($drive.Letter) | $($drive.Path) |
"
})
"
} else {
"
Lecteurs Réseau
Aucun lecteur réseau connecté.
"
})
$(if($NetworkInfo.WifiProfiles.Count -gt 0) {
"
Profils WiFi Enregistrés ($($NetworkInfo.WifiProfiles.Count))
| SSID | Authentification |
$(foreach($wifi in $NetworkInfo.WifiProfiles) {
"| $($wifi.SSID) | $($wifi.Authentication) |
"
})
"
})
Fichier Hosts
$($NetworkInfo.HostsFile)
Disques Physiques
| Modèle | Type | Capacité | Interface | Santé | N° Série |
$(foreach($disk in $StorageInfo.Disks) {
$healthBadge = switch($disk.Health) {
'Healthy' { 'Bon' }
'Warning' { 'Attention' }
'Unhealthy' { 'Défectueux' }
default { $disk.Health }
}
"| $($disk.Model) | $($disk.Type) | $($disk.Size) | $($disk.BusType) | $healthBadge | $($disk.Serial) |
"
})
Volumes
| Lettre | Nom | Système de fichiers | Utilisation | BitLocker |
$(foreach($vol in $StorageInfo.Volumes) {
$progressClass = if($vol.UsedPercent -gt 90){'progress-red'}elseif($vol.UsedPercent -gt 75){'progress-yellow'}else{'progress-green'}
$blBadge = switch($vol.BitLockerStatus) {
'On' { 'Protégé' }
'Off' { 'Désactivé' }
default { 'Non protégé' }
}
"
| $($vol.Letter) |
$($vol.Label) |
$($vol.FileSystem) |
$($vol.Used) / $($vol.Size) (libre: $($vol.Free))
|
$blBadge |
"
})
⚠️ Note: Le script scanne uniquement les dossiers AppData\Microsoft\Outlook, Thunderbird\Profiles, et le dossier Documents.
$(if($MailInfo.OutlookAccounts.Count -gt 0) {
"
Comptes Outlook Configurés
| Nom | Email | Type | Fichier de données |
$(foreach($account in $MailInfo.OutlookAccounts) {
"| $($account.Name) | $($account.Email) | $($account.Type) | $($account.Store) |
"
})
"
} else {
"
Comptes Outlook
Aucun compte Outlook détecté ou Outlook n'est pas installé.
"
})
Fichiers Outlook (PST/OST)
$(if($MailInfo.OutlookFiles.Count -gt 0) {
"
| Fichier | Type | Taille | Chemin |
$(foreach($file in $MailInfo.OutlookFiles) {
"| $($file.Name) | $($file.Type) | $($file.Size) | $($file.Path) |
"
})
"
} else {
"
Aucun fichier PST ou OST trouvé.
"
})
Profils Thunderbird
$(if($MailInfo.ThunderbirdProfiles.Count -gt 0) {
"
| Profil | Taille | Chemin |
$(foreach($profile in $MailInfo.ThunderbirdProfiles) {
"| $($profile.Name) | $($profile.Size) | $($profile.Path) |
"
})
"
} else {
"
Aucun profil Thunderbird trouvé.
"
})
Programmes au Démarrage ($($StartupInfo.Count))
$(if($StartupInfo.Count -gt 0) {
"
| Nom | Statut | Commande | Emplacement | Utilisateur |
$(foreach($item in $StartupInfo) {
$statusBadge = if($item.Status -eq 'Activé'){'Activé'}else{'Désactivé'}
"
| $($item.Name) |
$statusBadge |
$($item.Command) |
$($item.Location) |
$($item.User) |
"
})
💡 Survolez les cellules tronquées pour voir le contenu complet.
"
} else {
"
Aucun programme de démarrage trouvé.
"
})
$(if($BatteryInfo.Available) {
$healthClass = if ($BatteryInfo.HealthPercent -ge 80) { 'health-ok' } elseif ($BatteryInfo.HealthPercent -ge 50) { 'health-warning' } else { 'health-error' }
$batteryHtml = "
État de la Batterie
| Niveau de charge | $($BatteryInfo.ChargeLevel) |
| Statut | $($BatteryInfo.Status) |
| Identifiant | $($BatteryInfo.DeviceID) |
| Capacité d'origine | $($BatteryInfo.DesignCapacity) |
| Capacité actuelle | $($BatteryInfo.FullChargeCapacity) |
| Santé estimée | $($BatteryInfo.HealthPercent)% ($($BatteryInfo.HealthStatus)) |
"
if($BatteryInfo.ReportGenerated) {
$batteryHtml += "
Rapport Windows Battery Report
Le rapport détaillé de la batterie a été généré : $($BatteryInfo.ReportPath)
Ce fichier contient l'historique complet de la batterie et est inclus dans le dossier du rapport.
"
}
$batteryHtml
} else {
"
Batterie
$($BatteryInfo.Message)
"
})
Imprimantes Installées
$(if($PrinterInfo.Count -gt 0) {
"
| Nom | Statut | Port | Pilote | Par défaut | Partagée |
$(foreach($printer in $PrinterInfo) {
$defaultBadge = if($printer.Default){'Oui'}else{'Non'}
$sharedBadge = if($printer.Shared){'Oui'}else{'Non'}
"
| $($printer.Name) |
$($printer.Status) |
$($printer.Port) |
$($printer.Driver) |
$defaultBadge |
$sharedBadge |
"
})
"
} else {
"
Aucune imprimante installée sur ce système.
"
})
"@
return $htmlTemplate
}
# ============================================================================
# ENVOI EMAIL
# ============================================================================
function Send-ReportEmail {
param(
[string]$ReportPath,
[string]$BatteryReportPath,
[string]$ComputerName
)
Write-Log "Préparation de l'envoi par email..." -Level Info
# Charger les credentials de manière sécurisée
$credPath = [System.IO.Path]::Combine($PSScriptRoot, "smtp_credentials.xml")
if (Test-Path $credPath) {
try {
$credential = Import-Clixml -Path $credPath
}
catch {
Write-Log "Impossible de charger les credentials SMTP" -Level Error
return $false
}
}
else {
# Demander les credentials
Write-Log "Fichier de credentials non trouvé. Veuillez entrer les informations SMTP." -Level Warning
$saveCredentials = Read-Host "Voulez-vous sauvegarder les credentials pour une utilisation future ? (O/N)"
$credential = Get-Credential -Message "Entrez les identifiants SMTP" -UserName $Script:Config.SMTP.Username
if ($saveCredentials -eq 'O') {
$credential | Export-Clixml -Path $credPath
Write-Log "Credentials sauvegardés dans $credPath" -Level Success
}
}
$attachments = @($ReportPath)
if ($BatteryReportPath -and (Test-Path $BatteryReportPath)) {
$attachments += $BatteryReportPath
}
try {
$mailParams = @{
SmtpServer = $Script:Config.SMTP.Server
Port = $Script:Config.SMTP.Port
UseSsl = $true
From = $Script:Config.SMTP.From
To = $Script:Config.SMTP.To
Subject = "Rapport PC - $ComputerName - $(Get-Date -Format 'dd/MM/yyyy HH:mm')"
Body = @"
Bonjour,
Veuillez trouver ci-joint le rapport PC généré pour la machine : $ComputerName
Rapport généré le : $(Get-Date -Format 'dd/MM/yyyy à HH:mm:ss')
Cordialement,
Script Info PC v0.5.0
"@
Credential = $credential
Attachments = $attachments
}
Send-MailMessage @mailParams -WarningAction SilentlyContinue
Write-Log "Email envoyé avec succès!" -Level Success
return $true
}
catch {
Write-Log "Erreur lors de l'envoi de l'email: $_" -Level Error
return $false
}
}
# ============================================================================
# SCRIPT PRINCIPAL
# ============================================================================
# Affichage du header
Clear-Host
Write-Host ""
Write-Host " ╔══════════════════════════════════════════╗" -ForegroundColor Cyan
Write-Host " ║ INFO PC - Version 0.5.0 ║" -ForegroundColor Cyan
Write-Host " ║ Diagnostic complet du système ║" -ForegroundColor Cyan
Write-Host " ╚══════════════════════════════════════════╝" -ForegroundColor Cyan
Write-Host ""
# Vérification des droits admin
if (-not (Test-IsAdmin)) {
Write-Log "Ce script nécessite des droits administrateur pour certaines fonctionnalités." -Level Warning
Write-Log "Certaines informations pourraient être incomplètes." -Level Warning
Write-Host ""
}
# Demande du nom du fichier
$htmlFileName = Read-Host "Entrez le nom du rapport (sans extension) [défaut: nom de la machine]"
if ([string]::IsNullOrWhiteSpace($htmlFileName)) {
$htmlFileName = $env:COMPUTERNAME
}
# Choix du type de PC
Write-Host ""
Write-Host "Type de PC :" -ForegroundColor White
Write-Host " 1 - PC de bureau (pas de test batterie)"
Write-Host " 2 - PC Portable (test batterie inclus)"
Write-Host ""
do {
$choice = Read-Host "Votre choix [1]"
if ([string]::IsNullOrWhiteSpace($choice)) { $choice = '1' }
} while ($choice -notin @('1', '2'))
$includeBatteryTest = ($choice -eq '2')
Write-Host ""
Write-Log "Démarrage de la collecte des informations..." -Level Info
Write-Host ""
# Création du dossier de sortie
$folderName = "$htmlFileName - Info PC"
$script:FolderPath = [System.IO.Path]::Combine($PSScriptRoot, $folderName)
$null = New-Item -ItemType Directory -Path $script:FolderPath -Force -ErrorAction SilentlyContinue
# Collecte des informations
$systemInfo = Get-SystemInfo
$memoryInfo = Get-MemoryInfo
$gpuInfo = Get-GPUInfo
$storageInfo = Get-StorageInfo
$networkInfo = Get-NetworkInfo
$userInfo = Get-UserInfo
$softwareInfo = Get-SoftwareInfo
$startupInfo = Get-StartupInfo
$printerInfo = Get-PrinterInfo
$mailInfo = Get-MailInfo
$batteryInfo = Get-BatteryInfo -IncludeBatteryTest $includeBatteryTest
# Génération du rapport HTML
Write-Log "Génération du rapport HTML..." -Level Info
$htmlContent = New-HTMLReport `
-SystemInfo $systemInfo `
-MemoryInfo $memoryInfo `
-GPUInfo $gpuInfo `
-StorageInfo $storageInfo `
-NetworkInfo $networkInfo `
-UserInfo $userInfo `
-SoftwareInfo $softwareInfo `
-StartupInfo $startupInfo `
-PrinterInfo $printerInfo `
-MailInfo $mailInfo `
-BatteryInfo $batteryInfo
$htmlFilePath = [System.IO.Path]::Combine($script:FolderPath, "$htmlFileName.html")
$htmlContent | Out-File -FilePath $htmlFilePath -Encoding UTF8
Write-Log "Rapport généré: $htmlFilePath" -Level Success
# Envoi par email
if ($Script:Config.Options.SendEmail) {
Write-Host ""
$sendEmail = Read-Host "Voulez-vous envoyer le rapport par email ? (O/N) [O]"
if ([string]::IsNullOrWhiteSpace($sendEmail) -or $sendEmail -eq 'O') {
$batteryReportPath = if ($batteryInfo.ReportPath) { $batteryInfo.ReportPath } else { $null }
Send-ReportEmail -ReportPath $htmlFilePath -BatteryReportPath $batteryReportPath -ComputerName $systemInfo.ComputerName
}
}
# Ouverture du rapport
if ($Script:Config.Options.OpenReportOnEnd) {
Write-Host ""
Write-Log "Ouverture du rapport..." -Level Info
Invoke-Item -Path $htmlFilePath
}
Write-Host ""
Write-Host " ╔══════════════════════════════════════════╗" -ForegroundColor Green
Write-Host " ║ Script terminé ! ║" -ForegroundColor Green
Write-Host " ╚══════════════════════════════════════════╝" -ForegroundColor Green
Write-Host ""
Write-Host " Dossier: $script:FolderPath" -ForegroundColor Gray
Write-Host ""