diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..594c8fe --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,218 @@ +# Release Notes + +## v4.9.7 +> Troisieme audit qualite — annulation, erreurs cachees et traductions manquantes + +### Corrections +- **Get-SnapshotAll.ps1** : le bloc `catch` utilisait `SA_LogFailed` qui n'affichait que le nom de la camera, sans le motif de l'echec. Remplace par `SA_LogError` (cle `"{0}": {1}` deja definie mais jamais utilisee) — l'erreur exacte est maintenant visible dans le journal. +- **fr.ps1 / en.ps1** : suppression de la cle `SA_LogFailed` devenue inutilisee apres le correctif ci-dessus. +- **Export-HardwareReport.ps1** : deux messages log etaient hardcodes en francais dans le chemin ImportExcel (`'Creation du fichier Excel via sous-processus...'` et `"ATTENTION: Impossible de supprimer l'ancien fichier Excel..."`). Remplaces par les nouvelles cles `EH_LogSubproc` et `EH_LogExcelLocked` (ajoutees dans fr.ps1 et en.ps1). +- **Export-HardwareReport.ps1** : les trois boucles de pre-capture du chemin ImportExcel (snapshot live, snapshot J-7, images de reference) n'appelaient jamais `$Cancel`. L'utilisateur pouvait cliquer "Annuler" sans effet pendant le telechargement des images. Ajout de `if (& $Cancel) { break }` en tete de chaque boucle — comportement coherent avec le chemin COM. +- **Get-PlaybackReport.ps1** : `Get-PlaybackInfo -Parallel` est un appel bloquant (30-60 s sur de grands systemes). Aucun message n'etait affiche pendant ce temps. Ajout d'un log apres le retour de l'appel (`PR_LogDataReceived`) pour signaler la fin de l'attente et le debut du traitement par camera. Cle ajoutee dans fr.ps1 et en.ps1. + +--- + +## v4.9.6 +> Deuxieme audit qualite — nettoyage de code mort, performance, UX et robustesse + +### Corrections +- **fr.ps1** : trois apostrophes manquantes corrigees — `App_Closing` (`l'application`), `Act_Playback` (`Dates d'enregistrement`), `PR_LogFound` (`plages d'enregistrement`). Ces clés etaient differentes des corrections du tour precedent. +- **Updater.ps1** : le `catch {}` silencieux sur `Copy-Item` est remplace par un log dans `%TEMP%\MilestoneToolkitUpdate_error.txt`. Si la copie des fichiers de mise a jour echoue (fichier verrouille, droits insuffisants), l'erreur est maintenant tracee au lieu de passer inapercue. +- **Initialize-Modules.ps1 line 53** : `(Join-Path ...)\*` remplace par `(Join-Path ... '*')` — forme idiomatique et coherente avec la ligne 56 du meme fichier. + +### Nettoyage de code mort +- **Bootstrap.ps1** : suppression des fonctions `Invoke-AutoUpdate`, `Get-GitHubLatestRelease` et `Get-ComparableVersion` (77 lignes) — jamais appelees depuis Bootstrap.ps1 ; la verification de mise a jour est assuree par Show-StartupCheck. +- **Show-StartupCheck.ps1** : suppression du scriptblock `$script:_SC_DownloadModuleNuGet` (54 lignes) — defini mais jamais reference nulle part dans le projet. + +### Ameliorations +- **Bootstrap.ps1** — persistence de la langue : la langue choisie au selecteur est sauvegardee dans `config.json` (cle `language`). Aux prochains demarrages, le selecteur est ignore et la langue sauvegardee est utilisee directement. +- **Set-CameraGroupByModel.ps1** — complexite O(n×m) -> O(n+m) : `Get-VmsDeviceGroupMember` est desormais appele une seule fois par groupe (et non une fois par camera). Les IDs existants sont charges dans un `HashSet` avant la boucle — irrelevant sur les petits systemes, significatif sur les grandes installations. +- **Invoke-PtzPreset.ps1** — l'attente de 2 500 ms apres repositionnement PTZ ne bloque plus le thread UI. Remplace par une boucle de 50 ms pompant le `Dispatcher` WPF, ce qui maintient l'interface reactive pendant la stabilisation de la camera. +- **Save-Dependencies.ps1** : TLS 1.2 force en debut de script — requis par PowerShell Gallery sous PS 5.1. + +--- + +## v4.9.5 +> Correctifs qualite et robustesse — audit complet du code + +### Corrections + +- **Bootstrap.ps1** : ajout de `-TimeoutSec 10` sur `Invoke-RestMethod` pour eviter un blocage indefini si l'API GitHub ne repond pas. +- **Show-StartupCheck.ps1** : meme correctif sur `Invoke-RestMethod` pour la verification de mise a jour au demarrage. +- **Show-StartupCheck.ps1** : suppression d'une branche morte (`elseif ($allOk -and $anyUpdate ...)`) — la propriete `UpdateAvailable` n'etait jamais definie sur les objets module, rendant cette branche inatteignable. +- **Write-ActivityLog.ps1** : remplacement de `Add-Content -Encoding UTF8` (ecrit UTF-8 avec BOM sous PowerShell 5.1) par `[System.IO.File]::AppendAllText` avec `UTF8Encoding($false)` — les fichiers de log sont desormais UTF-8 sans BOM. +- **App.ps1** — logCallback : ajout de `.TrimStart()` avant le matching regex `^ERREUR` / `^AVERTISSEMENT`. Les messages indentes (ex : ` ERREUR: ...`) etaient incorrectement classes comme INFO et affiches en blanc au lieu du rouge/jaune attendu. +- **App.ps1** — Write-UILog : limitation du journal a 2 000 entrees. Au-dela, la plus ancienne ligne est supprimee pour eviter l'accumulation memoire sur les longues sessions. +- **Get-RecordingStats.ps1** : le bloc `catch {}` silencieux sur `Get-VideoDeviceStatistics` est remplace par un log AVERTISSEMENT (`RS_LogLiveWarn`) — coherent avec les blocs catch des stats enregistrement et mouvement. +- **Get-PtzPresetSnapshot.ps1** : sanitisation du nom de fichier des snapshots PTZ — les noms de camera et de preset contenant des caracteres invalides (`\ / : * ? " < > |`) sont maintenant remplaces par `_` avant construction du nom de fichier. +- **fr.ps1 / en.ps1** — `EH_LogNoExcel` : corrige le prefixe `ERREUR:` en `AVERTISSEMENT:` — Excel absent n'est pas une erreur fatale puisque le fallback ImportExcel suit immediatement. +- **fr.ps1 / en.ps1** : ajout de la cle `RS_LogLiveWarn` utilisee par le correctif Get-RecordingStats. + +--- + +## v4.9.4 + +### Nouveautes +- Export Hardware : nouvelle option "Images de référence" dans le groupe Options. Permet de sélectionner un dossier sur le poste contenant une image par caméra (fichier nommé `NomCamera.ext` ou `NomCamera_.ext`, ex. snapshots horodatés — le plus récent est utilisé en cas de doublon). Ces images sont insérées dans une colonne dédiée du rapport Excel, selon le même fonctionnement que les colonnes Snapshot J-7 et Snapshot Live. + + +## v4.7.1 +> Correctifs de compatibilite PSTools et export Excel sans Office + +### Corrections +- Détection de `MilestonePSTools` améliorée : l'application prévient maintenant l'utilisateur si une version déjà installée est présente et indique si une mise à jour est disponible. +- L'outil inclut désormais `ImportExcel` comme dépendance de base. +- Export Hardware : si Excel n'est pas installé, l'application tente désormais d'utiliser le module PowerShell `ImportExcel` pour produire le fichier `.xlsx`. +- Export sans Excel : les snapshots ne sont plus inclus dans l'export en fallback `ImportExcel`, afin d'éviter des erreurs de génération. + +### Ameliorations +- Ajout d'une vérification de mise à jour GitHub au démarrage via `config.json`. +- `ImportExcel` est pris en charge comme module optionnel et installé automatiquement si nécessaire. +- Messages de fallback et d'erreur clarifiés dans l'UI et le journal. + +## v4.7 +- `ImportExcel` est pris en charge comme module optionnel et installé automatiquement si nécessaire. +- Messages de fallback et d'erreur clarifiés dans l'UI et le journal. + +## v4.7 +> Correctifs telechargement offline, robustesse globale et audit qualite + +### Corrections — telechargement offline +- **Preparer offline** : `Save-Module` remplace par un telechargement direct via `WebClient` + `Expand-Archive`. Aucune dependance sur PowerShellGet ou NuGet provider — fonctionne sur toute installation fraiche de Windows. +- **TLS 1.2** force des le demarrage de Bootstrap.ps1 (avant tout chargement de module). +- Nom de fichier temp unique par run (GUID) pour eviter les conflits d'extraction entre deux tentatives consecutives. + +### Corrections — robustesse +- **Fuite de ressources** : `WebClient` desormais dispose dans un bloc `try/finally`. +- **Fuite de threads** : pool de runspaces (snapshots paralleles) ferme dans un `try/finally` dans `Get-SnapshotAll` et `Export-HardwareReport`. +- **Timeout snapshots** : les operations de capture en parallele s'interrompent apres 10 minutes si une camera ne repond pas, au lieu de bloquer indefiniment. +- **Get-SnapshotDateTime** : retourne desormais `@{ Ok; Time }` au lieu de trois types differents (`$null`, `$false`, `[datetime]`) — comparaisons fiables dans tous les cas. +- **Export CSV** : `Export-Csv` entoure d'un `try/catch` dans Get-CameraStatus, Get-PlaybackReport et Get-RecordingStats — echec visible plutot que silencieux. +- **Set-CameraGroupByModel** : `New-VmsDeviceGroup` et `Add-VmsDeviceGroupMember` dans un `try/catch` — erreur par modele loggee sans interrompre les autres. +- **Get-LicenseInfo** : proprietes `CarePlus`/`CarePremium` utilisent desormais `$script:T` pour respecter la langue selectionnee. + +### Ameliorations +- **Version centralisee** : `$script:AppVersion` defini une seule fois dans `Bootstrap.ps1` et `App.ps1`, reference partout via `$ver` dans les fichiers de langue — une seule ligne a modifier pour changer de version. +- **Nouvelles cles de traduction** : `SA_LogTimeout`, `EH_LogSnapTimeout`, `GM_LogModelError`, `LI_LogCareProp`. + +--- + +## v4.5.1 +> Packaging Inno Setup — installeur Windows natif + +### Nouveautes +- **Installeur EXE** : Inno Setup compile deux variantes publiees automatiquement sur chaque release GitHub : + - `*-Online-Setup.exe` (~500 Ko) : leger, telecharge MilestonePSTools au premier lancement. + - `*-Offline-Setup.exe` (~80 Mo) : module MilestonePSTools bundle dans l'EXE, fonctionne sans Internet. +- **Raccourci Menu Demarrer** et optionnellement Bureau. Lance l'application sans aucune fenetre console (via `Start.vbs`). +- **Pas d'UAC requis** : installation dans `AppData\Local` par defaut. Option "Pour tous les utilisateurs" disponible pour les admins. +- **Deblocage automatique** : `Unblock-File` applique sur tous les scripts lors de l'installation — le flag Zone.Identifier n'est plus un probleme. +- **Mise a jour silencieuse** : reinstaller un EXE plus recent met a jour l'installation existante (meme AppId Inno Setup). +- **Desinstallation propre** : entree dans Programmes & fonctionnalites, suppression des dossiers `Output/`, `Logs/`, `Dependencies/`. +- **GitHub Actions** (`.github/workflows/release.yml`) : push d'un tag `vX.X` → build automatique des deux EXE → publication sur la page Releases. +- **Build local** : `installer\build.ps1 -Mode Online` ou `-Mode Offline` pour compiler sans passer par CI. + +--- + +## v4.5 +> Support multilingue FR / EN + +### Nouveautes +- **Selecteur de langue au demarrage** : une fenetre de choix FR / EN s'affiche avant la verification des dependances. La langue selectionnee s'applique a toute l'application pour la session. +- **Interface entierement traduite** : tous les textes de l'UI sont traduits — fenetre de demarrage, fenetre principale (categories, boutons, statuts, combo mode capture), fenetre de selection des colonnes Export Hardware. +- **Excel traduit** : les en-tetes de colonnes du fichier Excel suivent la langue choisie. Le nom du fichier change egalement (`Liste_des_Cameras.xlsx` en francais, `Camera_List.xlsx` en anglais). +- **CSV traduits** : les noms de colonnes et les noms de fichiers CSV s'adaptent a la langue (`Etat_Cameras.csv` / `Camera_Status.csv`, `Dates_Enregistrement.csv` / `Recording_Dates.csv`, `Stats_Enregistrement.csv` / `Recording_Stats.csv`). +- **Logs traduits** : tous les messages de journal d'activite (progression, erreurs, avertissements) sont emis dans la langue selectionnee. +- **Architecture i18n** : fichiers `src/Lang/fr.ps1` et `src/Lang/en.ps1` centralisant ~200 cles de traduction. Extensible a d'autres langues sans modifier le code applicatif. + +--- + +## v4.4 +> Export Hardware — selection des colonnes et securite mot de passe + +### Ameliorations +- **Export Hardware — Fenetre de selection des colonnes** : remplacement des dialogues MessageBox par une fenetre WPF avec cases a cocher groupees par categorie (Informations hardware, Flux video, Retention, Options). Seules les colonnes cochees apparaissent dans le fichier Excel. +- **Export Hardware — Mots de passe exclus par defaut** : la colonne `Mot de passe` est desormais decochee par defaut. Elle doit etre activee explicitement. L'appel `Get-VmsCameraReport -IncludePlainTextPassword` n'est effectue que si la colonne est selectionnee. +- **Export Hardware — Optimisation des appels API** : `Get-VmsCameraStream` et `Get-PlaybackInfo` ne sont appeles que si les colonnes flux video ou retention sont selectionnees, evitant des requetes inutiles. +- **Export Hardware — Boutons Tout cocher / Tout decocher** : selection rapide de toutes les colonnes ou remise a zero en un clic. +- **Export Hardware — Suppression de l'avertissement mot de passe** : la fenetre de confirmation redondante est supprimee, la case `Mot de passe (!)` marquee en orange suffit comme signal d'intention. + +--- + +## v4.3 +> Enrichissement de l'export Hardware + +### Ameliorations +- **Export Hardware — Flux video** : ajout de 7 nouvelles colonnes groupees par couleur dans le fichier Excel : `Codec (Enreg.)`, `Resolution (Enreg.)`, `FPS (Enreg.)`, `Codec (Live)`, `Resolution (Live)`, `FPS (Live)`, `Flux supplementaires`. Si le flux live et le flux enregistre sont identiques, les colonnes Live restent vides pour eviter la redondance. +- **Export Hardware — Retention disponible** : nouvelle colonne `Retention disponible` indiquant la duree totale d'archive accessible par camera, calculee via `Get-PlaybackInfo`. +- **Export Hardware — Adresse IP** : suppression automatique du protocole (`http://`) et du port (`:8000`) — seule l'adresse IP pure (4 blocs) est affichee. +- **En-tetes Excel colores par groupe** : hardware (sable), flux video (bleu marine), retention (vert), snapshot (violet) pour une lecture rapide. + +--- + +## v4.2 +> Nouvelle categorie Monitoring + +### Nouveautes +- **Etat des cameras** (`Get-ItemState`) : etat temps reel de chaque camera via l'Event Server. Les cameras Responding sont affichees en vert, les erreurs en rouge, les cameras desactivees sont automatiquement ignorees. Export CSV `Etat_Cameras.csv`. +- **Dates d'enregistrement** (`Get-PlaybackInfo`) : premier et dernier enregistrement disponible par camera avec la duree de retention calculee. Utilise le mode parallele natif du SDK pour les grands systemes. Export CSV `Dates_Enregistrement.csv`. +- **Nouvelle categorie MONITORING** dans la sidebar (couleur cyan) separee de DIAGNOSTIC pour distinguer les donnees temps reel des analyses historiques. + +--- + +## v4.1 +> Optimisation des performances + +### Ameliorations +- **Snapshot - Toutes les cameras** : les snapshots sont desormais recuperes en parallele via un pool de threads (jusqu'a 12 simultanees). Le temps de capture est divise par le nombre de cameras actives simultanement au lieu d'etre sequentiel. +- **Export Hardware - Snapshots** : meme amelioration — les snapshots sont pre-telecharges en parallele avant la construction du fichier Excel. Le log affiche chaque snapshot des qu'il est recu, dans l'ordre d'arrivee. +- **Configuration** : suppression du parametre `installMode` dans `config.json` — le mode Online/Offline est toujours auto-detecte (presence du dossier `Dependencies/`). + +--- + +## v4.0 +> Refonte de l'export hardware + nouvelles fonctions de diagnostic + mode capture historique + +### Nouveautes + +#### Export Hardware +- Format de sortie change de **CSV vers Excel (.xlsx)** avec mise en forme (en-tete colore, bordures, colonne figee) +- Option d'inclure un **snapshot integre dans la cellule** de chaque camera (ancre, redimensionne automatiquement) +- Suppression des colonnes GPS et Activation (inutiles) +- Demande de confirmation avant l'inclusion des snapshots (operation longue) + +#### Mode capture historique +- Nouveau selecteur **Live / Image historique** dans la sidebar +- En mode historique : choix de la date et de l'heure (hh:mm) +- Applicable aux trois actions snapshot : Selection, Toutes les cameras, Presets PTZ +- Utilise `Get-Snapshot -Behavior GetNearest` pour trouver l'image la plus proche + +#### Diagnostic (nouvelle categorie) +- **Stats Enregistrement (7j)** : sequences, pourcentage de temps enregistre, duree totale, detection de mouvement et statistiques live (FPS, bitrate, resolution) par camera. Export CSV. +- **Informations Licence** : produits licencies, date d'expiration avec alerte si < 30 jours, canaux utilises/total avec alerte si >= 90 %. Utilise `Get-VmsLicensedProducts`. + +### Corrections +- Rapport Stockage supprime (les donnees d'espace disque ne sont pas accessibles sans droits WMI sur le serveur distant) +- `Get-VmsLicensedProducts` : gestion correcte des valeurs d'expiration non-date (`"Unrestricted"`) +- Proprietes internes du SDK Milestone filtrees de l'affichage licence (Path, ParentPath, ServerId, etc.) + +--- + +## v3.0 +> Fork initial — refonte UX complete + +### Nouveautes +- **Journal d'activite colore** : remplacement du TextBox monochrome par un RichTextBox avec codes couleur par niveau (erreur, avertissement, succes, action) +- **Bouton Annuler** : toutes les actions longues peuvent etre interrompues entre chaque iteration +- **Barre de progression** : deterministe (avancement reel) pour les actions iteratives +- **Selecteur de dossier de sortie** : changement du repertoire sans modifier `config.json` +- **Snapshot - Presets PTZ** : progression basee sur le nombre total de presets toutes cameras confondues +- **Grouper par Modele** : verification des doublons avant ajout au groupe + +### Corrections +- Encodage du titre de fenetre corrige (`—` affiché correctement via entite XML `—`) +- Banniere de demarrage : distinction correcte entre mode hors ligne (cache local) et connexion Internet disponible +- ComboBox mode capture : template sombre complet pour etre lisible sur fond sombre +- `Get-CameraRecordingStats` : parametres corriges (`-StartTime`/`-EndTime`, proprietes `PercentRecorded`/`TimeRecorded`) +- `Get-VmsStorageRetention` : retourne un `[TimeSpan]` directement, `.TotalDays` utilise +- Confirmation avant inclusion des mots de passe en clair dans l'export hardware diff --git a/Demarrer Milestone Toolkit.bat b/Demarrer Milestone Toolkit.bat new file mode 100644 index 0000000..aaabd5a --- /dev/null +++ b/Demarrer Milestone Toolkit.bat @@ -0,0 +1,26 @@ +@echo off + +:: Si le dossier Dependencies/ n'est pas present mais qu'une archive Dependencies.zip existe, +:: la decompresser automatiquement une seule fois avant de lancer l'application. +if not exist "%~dp0Dependencies\" ( + if exist "%~dp0Dependencies.zip" ( + echo Extraction de Dependencies.zip... + powershell -NoProfile -ExecutionPolicy Bypass -Command "Add-Type -AssemblyName System.IO.Compression.FileSystem; $base = '%~dp0'; $zip = Join-Path $base 'Dependencies.zip'; $dest = Join-Path $base 'Dependencies'; if (-not (Test-Path $dest) -and (Test-Path $zip)) { [System.IO.Compression.ZipFile]::ExtractToDirectory($zip, $dest) }" + ) +) + +:: Si des archives .nupkg sont presentes dans Dependencies/, extraire chaque module manquant. +if exist "%~dp0Dependencies\" ( + echo Verification des archives Dependencies\*.nupkg... + powershell -NoProfile -ExecutionPolicy Bypass -Command "Add-Type -AssemblyName System.IO.Compression.FileSystem; $base = '%~dp0'; $deps = Join-Path $base 'Dependencies'; Get-ChildItem -Path $deps -Filter '*.nupkg' -File | ForEach-Object { $archive = $_.FullName; $name = $_.BaseName; $dest = Join-Path $deps $name; if (-not (Test-Path $dest)) { Write-Host 'Extraction de' $_.Name 'dans' $dest; [System.IO.Compression.ZipFile]::ExtractToDirectory($archive, $dest) } }" +) + +:: Deblocage de TOUS les fichiers du projet (telechargement ZIP depuis GitHub) +:: Sans ca, Windows bloque les scripts et les modules PowerShell +powershell -NoProfile -ExecutionPolicy Bypass -Command ^ + "Get-ChildItem -Path '%~dp0' -Recurse -File | Unblock-File -ErrorAction SilentlyContinue" + +:: Lancement +powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0src\Bootstrap.ps1" + +if %errorlevel% neq 0 ( echo. && echo ERREUR code %errorlevel% && pause ) diff --git a/Dependencies/importexcel.nupkg b/Dependencies/importexcel.nupkg new file mode 100644 index 0000000..422704e Binary files /dev/null and b/Dependencies/importexcel.nupkg differ diff --git a/Launch.ps1 b/Launch.ps1 deleted file mode 100644 index 9cbb7fa..0000000 --- a/Launch.ps1 +++ /dev/null @@ -1,33 +0,0 @@ -<# -.SYNOPSIS - Lance l'application Milestone Toolkit. -.DESCRIPTION - Point d'entree utilisateur. Double-cliquer ou executer depuis PowerShell. - Verifie la version de PowerShell et lance le bootstrap applicatif. -.NOTES - Prerequis : Windows PowerShell 5.1+ ou PowerShell 7+ sur Windows. - Les modules MilestonePSTools et ImportExcel seront installes automatiquement si absents. -#> - -#Requires -Version 5.1 - -# Determiner le repertoire racine du projet -$AppRoot = $PSScriptRoot - -# Verifier qu'on est sur Windows (Milestone est Windows only) -if ($PSVersionTable.PSVersion.Major -ge 6 -and -not $IsWindows) { - Write-Error "Milestone Toolkit necessite Windows." - Read-Host "Appuyez sur Entree pour quitter" - exit 1 -} - -# Lancer l'application -try { - & (Join-Path $AppRoot 'src/App.ps1') -RootPath $AppRoot -} -catch { - Write-Error "Erreur fatale : $_" - Write-Error $_.ScriptStackTrace - Read-Host "Appuyez sur Entree pour quitter" - exit 1 -} diff --git a/Logs/MilestoneToolkit_2026-05-05.log b/Logs/MilestoneToolkit_2026-05-05.log new file mode 100644 index 0000000..9de036e --- /dev/null +++ b/Logs/MilestoneToolkit_2026-05-05.log @@ -0,0 +1,3 @@ +[18:58:49] [SUCCESS] Application demarree. Connecte au serveur Milestone. +[18:58:49] [INFO] Repertoire de sortie : C:\Users\Vincent\Downloads\XProtect-Export-Tool-to-Excel-MilestonePSTools-GUI--4.7.1.1\XProtect-Export-Tool-to-Excel-MilestonePSTools-GUI--4.7.1.1\.\Output +[18:58:52] [INFO] Fermeture de l application diff --git a/Old/TMN_MilestonePSTool10.02.2026.ps1 b/Old/TMN_MilestonePSTool10.02.2026.ps1 deleted file mode 100644 index b090dbf..0000000 --- a/Old/TMN_MilestonePSTool10.02.2026.ps1 +++ /dev/null @@ -1,365 +0,0 @@ - -# -*- coding: utf-8 -*- - -Write-Host "Vérification de la présence des modules requis..." -ForegroundColor Red -BackgroundColor White - -# Vérifier et installer le module MilestonePSTools -if (-not (Get-Module -ListAvailable -Name MilestonePSTools)) { - Install-Module -Name MilestonePSTools -Force -Scope CurrentUser -} - -# Vérifier et installer le module ImportExcel -if (-not (Get-Module -ListAvailable -Name ImportExcel)) { - Install-Module -Name ImportExcel -Force -Scope CurrentUser -} - -# Importer les modules -Import-Module MilestonePSTools -Import-Module ImportExcel - -# Connexion au serveur Milestone XProtect -Write-Host "Connexion au serveur de Management..." -ForegroundColor Red -BackgroundColor White -Connect-ManagementServer -ShowDialog -AcceptEula -Force - -# Fonction pour masquer la console -function Hide-Console { - $consolePtr = [System.Runtime.InteropServices.Marshal]::GetHINSTANCE([System.Reflection.Assembly]::GetExecutingAssembly().GetModules()[0]) - $hwnd = Get-ConsoleWindow - ShowWindow $hwnd 0 -} - -# Déclarez les fonctions nécessaires -Add-Type @" -using System; -using System.Runtime.InteropServices; - -public class Win32 { - [DllImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool FreeConsole(); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr GetConsoleWindow(); - - [DllImport("user32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); -} -"@ - -# Raccourcis pour appeler les fonctions -$FreeConsole = [Win32]::FreeConsole -$GetConsoleWindow = [Win32]::GetConsoleWindow -$ShowWindow = [Win32]::ShowWindow - -# Charger les types nécessaires pour utiliser Windows Forms -Add-Type -AssemblyName System.Windows.Forms -Add-Type -AssemblyName System.Drawing - -# Constantes pour le style -$buttonSize = New-Object System.Drawing.Size(450, 50) -$buttonPadding = New-Object System.Windows.Forms.Padding(5) -$buttonMargin = New-Object System.Windows.Forms.Padding(5, 2, 5, 2) -$buttonFont = New-Object System.Drawing.Font("Segoe UI", 12) -$buttonBackColor = [System.Drawing.Color]::DodgerBlue -$buttonForeColor = [System.Drawing.Color]::White - -# Fonction pour créer un bouton -function Create-Button($text, $clickAction) { - $button = New-Object System.Windows.Forms.Button - $button.Text = $text - $button.Size = $buttonSize - $button.Padding = $buttonPadding - $button.Margin = $buttonMargin - $button.Font = $buttonFont - $button.BackColor = $buttonBackColor - $button.ForeColor = $buttonForeColor - $button.FlatStyle = "Flat" - $button.FlatAppearance.BorderSize = 0 - $button.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter - $button.Anchor = [System.Windows.Forms.AnchorStyles]::None - $button.Add_Click($clickAction) - return $button -} - -# Créer la fenêtre principale -$form = New-Object System.Windows.Forms.Form -$form.Text = "MilestonePSTool By TMN :)" -$form.Size = New-Object System.Drawing.Size(1000, 400) -$form.StartPosition = "CenterScreen" -$form.BackColor = [System.Drawing.Color]::Black - -# Créer le TableLayoutPanel pour organiser les contrôles -$tableLayoutPanel = New-Object System.Windows.Forms.TableLayoutPanel -$tableLayoutPanel.Dock = [System.Windows.Forms.DockStyle]::Fill -$tableLayoutPanel.ColumnCount = 2 -$tableLayoutPanel.RowCount = 5 -$tableLayoutPanel.BackColor = [System.Drawing.Color]::White -$tableLayoutPanel.Padding = New-Object System.Windows.Forms.Padding(10) -$tableLayoutPanel.CellBorderStyle = [System.Windows.Forms.TableLayoutPanelCellBorderStyle]::None - -# Ajouter des lignes au TableLayoutPanel -for ($i = 0; $i -lt $tableLayoutPanel.RowCount; $i++) { - $tableLayoutPanel.RowStyles.Add((New-Object System.Windows.Forms.RowStyle([System.Windows.Forms.SizeType]::AutoSize, 60))) -} - -# Créer une TextBox pour afficher les résultats -$resultTextBox = New-Object System.Windows.Forms.TextBox -$resultTextBox.Multiline = $true -$resultTextBox.ReadOnly = $true -$resultTextBox.ScrollBars = "Vertical" -$resultTextBox.Width = 450 -$resultTextBox.Height = 150 -$resultTextBox.Font = New-Object System.Drawing.Font("Segoe UI", 10) -$resultTextBox.BackColor = [System.Drawing.Color]::LightGray -$resultTextBox.ForeColor = [System.Drawing.Color]::Black -$resultTextBox.Anchor = [System.Windows.Forms.AnchorStyles]::None - -# Actions pour les boutons -$button1Action = { #Snapshot - Selection de Caméra - try { - $resultTextBox.AppendText("Opération en cours, cela peut prendre plusieurs minutes...`n") - New-Item -Name "Snapshot" -Path $PSScriptRoot -ItemType Directory | Join-Path "Snapshot" - - $camera = Select-Camera - $liveSnapshot = $camera | Get-Snapshot -UseFriendlyName -Behavior GetEnd -Quality 95 -Save -Path "Snapshot" - $resultTextBox.AppendText("fin`n") - } catch { - $resultTextBox.AppendText("Erreur : $_`n") - } -} - -$button2Action = { #Snapshot - Toute les Caméras - Start-Sleep -Milliseconds 100 - try { - $resultTextBox.AppendText("Opération en cours, cela peut prendre plusieurs minutes...`n") - New-Item -Name "Snapshot" -Path $PSScriptRoot -ItemType Directory | Join-Path "Snapshot" - - $camera = Get-VmsCamera - $Snapshot = $camera | Get-Snapshot -UseFriendlyName -Behavior GetEnd -Quality 95 -Save -Path "Snapshot" - $resultTextBox.AppendText("fin`n") - } catch { - $resultTextBox.AppendText("Erreur : $_`n") - } -} - -$button3Action = { #Export des Hardware - try { - $resultTextBox.AppendText("Opération en cours, cela peut prendre plusieurs minutes...`n") - $cameras = Get-VmsCameraReport -IncludePlainTextPassword | ForEach-Object { - [PSCustomObject]@{ - - Nom = $_.Name - - Fabricant = $_.DriverFamily - - Modèle = $_.Model - - IP = $_.Address - - MAC = $_.MAC - - Firmware = $_.Firmware - - Activation = $_.Enabled - - ServeurRec = $_.RecorderName - - User = $_.Username - - Pass = $_.Password - - Gps = $_.GpsCoordinates - - } - } - $csvPath = Join-Path -Path $PSScriptRoot -ChildPath "Liste des Caméras.csv" - $cameras | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8 -Delimiter ";" - $resultTextBox.AppendText("Fin`n") - } catch { - $resultTextBox.AppendText("Erreur : $_`n") - } -} - -$button4Action = { #Grouper les Caméras par modèle - try { - $resultTextBox.AppendText("Opération en cours, cela peut prendre plusieurs minutes...`n") - $parentFolderName = "Modèle" - $parentFolder = Get-VmsDeviceGroup -Name $parentFolderName -ErrorAction SilentlyContinue - if (-not $parentFolder) { - $parentFolder = New-VmsDeviceGroup -Name $parentFolderName - } - $cameras = Get-VmsCameraReport - $camerasByModel = $cameras | Group-Object -Property Model - foreach ($group in $camerasByModel) { - $model = $group.Name - $camerasInModel = $group.Group - $deviceGroup = Get-VmsDeviceGroup -ParentGroup $parentFolder -Name $model -ErrorAction SilentlyContinue - if (-not $deviceGroup) { - $deviceGroup = New-VmsDeviceGroup -ParentGroup $parentFolder -Name $model - } - foreach ($camera in $camerasInModel) { - Add-VmsDeviceGroupMember -Group $deviceGroup -DeviceId $camera.Id - } - } - $resultTextBox.AppendText("fin`n") - } catch { - $resultTextBox.AppendText("Erreur : $_`n") - } -} - -$button5Action = { #Snapshot - Par Preset Ptz - try { - $resultTextBox.AppendText("Opération en cours, cela peut prendre plusieurs minutes...`n") -New-Item -Name "Ptz Snapshot" -Path $PSScriptRoot -ItemType Directory | Join-Path "Ptz Snapshot" - -$cameras = Select-Camera | Where-Object Enabled | Get-Camera | Where-Object { $_.Enabled -and $_.PtzPresetFolder.PtzPresets.Count -gt 0 } - - -function Invoke-PtzPreset { - - [CmdletBinding()] - param ( - [Parameter(Mandatory)] - [VideoOS.Platform.ConfigurationItems.PtzPreset] - $PtzPreset, - - [Parameter()] - [switch] - $VerifyCoordinates, - - [Parameter()] - [double] - $Tolerance = 0.001, - - [Parameter()] - [int] - $Timeout = 5 - ) - - process { - $cameraId = if ($PtzPreset.ParentItemPath -match 'Camera\[(.{36})\]') { - $Matches[1] - } - else { - Write-Error "Could not parse camera ID from ParentItemPath value '$($PtzPreset.ParentItemPath)'" - return - } - - $camera = Get-Camera -Id $cameraId - $cameraItem = $camera | Get-PlatformItem - $presetItem = [VideoOS.Platform.Configuration]::Instance.GetItem([guid]::new($PtzPreset.Id), [VideoOS.Platform.Kind]::Preset) - - $params = @{ - MessageId = 'Control.TriggerCommand' - DestinationEndpoint = $presetItem.FQID - UseEnvironmentManager = $true - } - Send-MipMessage @params - - if (-not $VerifyCoordinates) { - return - } - - if ($cameraItem.Properties['pan'] -ne 'Absolute' -or $cameraItem.Properties['pan'] -ne 'Absolute' -or $cameraItem.Properties['zoom'] -ne 'Absolute') { - Write-Warning "VerifyCoordinates switch provided but camera does not use absolute PTZ positioning. Coordinates will not be verified." - return - } - - $positionReached = $false - $stopwatch = [Diagnostics.StopWatch]::StartNew() - while ($stopwatch.ElapsedMilliseconds -lt ($timeout * 1000)) { - $position = Send-MipMessage -MessageId Control.PTZGetAbsoluteRequest -DestinationEndpoint $cameraItem.FQID -UseEnvironmentManager - - $xDifference = [Math]::Abs($position.Pan) - [Math]::Abs($ptzPreset.Pan) - $yDifference = [Math]::Abs($position.Tilt) - [Math]::Abs($ptzPreset.Tilt) - $zDifference = [Math]::Abs($position.Zoom) - [Math]::Abs($ptzPreset.Zoom) - - if ($xDifference -gt $Tolerance) { - Write-Warning "Expected Pan = $($ptzPreset.Pan), Current Pan = $($position.Pan), Off by $xDifference" - } - elseif ($yDifference -gt $Tolerance) { - Write-Warning "Desired Tilt = $($ptzPreset.Tilt), Current Pan = $($position.Tilt), Off by $yDifference" - } - elseif ($zDifference -gt $Tolerance) { - Write-Warning "Desired Zoom = $($ptzPreset.Zoom), Current Pan = $($position.Zoom), Off by $zDifference" - } - else { - $positionReached = $true - Start-Sleep -Milliseconds 2500 - break - } - Start-Sleep -Milliseconds 100 - } - if (-not $positionReached) { - Write-Error "Camera failed to reach preset position" - } - } -} - - -foreach ($camera in $cameras) { - - foreach ($ptzPreset in $camera.PtzPresetFolder.PtzPresets) { - - $resultTextBox.AppendText("Moving $($camera.Name) to $($ptzPreset.Name) preset position`n") - Invoke-PtzPreset -PtzPreset $ptzPreset -VerifyCoordinates - - $resultTextBox.AppendText("Snapshot enregistré. . .`n") - $snapshotParams = @{ - - Quality = 95 - Save = $true - Path = "Ptz Snapshot" - FileName = "$($camera.Name) -- $($ptzPreset.Name).jpg" - } - $null = $camera | Get-Snapshot @snapshotParams -Behavior GetEnd - } -} - - - $resultTextBox.AppendText("fin`n") - } catch { - $resultTextBox.AppendText("Erreur : $_`n") - } -} - - -# Créer les boutons -$button1 = Create-Button "Snapshot - Selection de Caméra" $button1Action -$button2 = Create-Button "Snapshot - Toute les Caméras" $button2Action -$button3 = Create-Button "Export des Hardware" $button3Action -$button4 = Create-Button "Grouper les Caméras par modèle" $button4Action -$button5 = Create-Button "Snapshot - Par Preset Ptz" $button5Action - -# Ajouter les boutons et la TextBox au TableLayoutPanel -$tableLayoutPanel.Controls.Add($button1, 0, 0) #Select Snaps -$tableLayoutPanel.Controls.Add($button2, 0, 1) #All Snaps -$tableLayoutPanel.Controls.Add($button3, 1, 0) #Export Hardware -$tableLayoutPanel.Controls.Add($button4, 1, 1) #Group By Model -$tableLayoutPanel.Controls.Add($button5, 0, 3) #Ptz Snaps - - - -$tableLayoutPanel.Controls.Add($resultTextBox, 0, 4) - -# Centrer les contrôles dans le TableLayoutPanel -foreach ($control in $tableLayoutPanel.Controls) { - $control.Anchor = [System.Windows.Forms.AnchorStyles]::None -} - -# Ajouter le TableLayoutPanel au formulaire -$form.Controls.Add($tableLayoutPanel) - -# Ajouter un gestionnaire d'événements pour la fermeture du formulaire -$form.add_FormClosing({ - Disconnect-ManagementServer - Write-Host "Déconnecté du serveur de Management." -}) - -# Masquer la console -$ShowWindow.Invoke($GetConsoleWindow.Invoke(), 0) - -# Afficher la fenêtre -$form.Add_Shown({$form.Activate()}) -[void] $form.ShowDialog() diff --git a/README.md b/README.md index bf6df8f..c509730 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,111 @@ -# Milestone Toolkit +# Outil d’export XProtect vers Excel (GUI MilestonePSTools) + +Outil avec interface graphique permettant d’exporter les caméras, le hardware, la rétention et les données d’enregistrement depuis Milestone XProtect vers Excel ou CSV, en s’appuyant sur le module PowerShell MilestonePSTools. + +## Pourquoi cet outil + +Milestone XProtect ne propose pas simplement : +- l’export complet des caméras vers Excel +- l’audit de la rétention d’enregistrement +- la génération de rapports exploitables + +Cet outil permet de : +- gagner du temps sur les grosses installations +- générer des rapports clairs pour les clients +- auditer rapidement un système de vidéosurveillance + +--- + +# Milestone Toolkit Outil d'administration pour Milestone XProtect VMS, base sur le module PowerShell **MilestonePSTools**. +image + +## Lancement + +Cliquer sur Demarrer Milestone Toolkit.bat + +--- ## Fonctionnalites +### Snapshots + | Action | Description | |--------|-------------| -| **Snapshot - Selection** | Capture un snapshot d'une camera selectionnee via le dialogue Milestone | -| **Snapshot - Toutes** | Capture un snapshot de toutes les cameras du VMS | -| **Snapshot - Presets PTZ** | Parcourt les presets PTZ d'une camera et capture un snapshot a chaque position | -| **Export Hardware (CSV)** | Genere un rapport CSV de tous les equipements (IP, MAC, firmware, credentials, etc.) | -| **Grouper par Modele** | Cree des Device Groups dans Milestone organises par modele de camera | +| **Snapshot - Selection** | Capture un snapshot de la camera selectionnee via le dialogue Milestone | +| **Snapshot - Toutes les cameras** | Capture un snapshot de toutes les cameras en parallele (jusqu'a 12 simultanees) | +| **Snapshot - Presets PTZ** | Parcourt les presets PTZ et capture un snapshot a chaque position | -## Prerequis +Toutes les actions snapshot supportent deux modes : +- **Live** : derniere image disponible +- **Historique** : image la plus proche d'une date/heure choisie -- Windows 10/11 ou Windows Server 2016+ -- PowerShell 5.1+ (inclus dans Windows) ou PowerShell 7+ -- Acces reseau au serveur Milestone XProtect Management Server +### Gestion -Le module [MilestonePSTools](https://www.powershellgallery.com/packages/MilestonePSTools) est installe automatiquement au premier lancement (mode Online). +| Action | Description | +|--------|-------------| +| **Export Hardware** | Rapport Excel configurable : fenetre de selection des colonnes a inclure (hardware, flux video, retention, snapshot). Les mots de passe sont exclus par defaut et ne s'affichent que si la colonne est explicitement cochee. | +image -## Lancement -```powershell -.\Launch.ps1 -``` +| **Grouper par Modele** | Cree des groupes de cameras dans Milestone organises par modele | -Ou clic-droit sur `Launch.ps1` > **Executer avec PowerShell**. +### Monitoring -## Installation des dependances +| Action | Description | +|--------|-------------| +| **Etat des cameras** | Etat temps reel de chaque camera (OK / hors ligne / erreur) via l'Event Server. Les cameras desactivees sont ignorees. Export CSV. | +| **Dates d'enregistrement** | Premier et dernier enregistrement disponible par camera, avec duree totale de retention. Export CSV. | -L'application supporte deux modes d'installation : +### Diagnostic -### Mode Online (par defaut) +| Action | Description | +|--------|-------------| +| **Stats Enregistrement (7j)** | Statistiques d'enregistrement et de mouvement par camera sur 7 jours (CSV) | +| **Informations Licence** | Affiche les produits licencies, dates d'expiration et canaux utilises | -Si la machine a acces a Internet, le module MilestonePSTools est telecharge et installe automatiquement depuis PowerShell Gallery au premier lancement. Aucune action requise. +--- -### Mode Offline (machine isolee) +## Comment exporter toutes les caméras XProtect vers Excel -Pour deployer sur une machine sans acces Internet : +1. Lancer l’outil +2. Cliquer sur **Export Hardware** +3. Sélectionner les colonnes souhaitées +4. Exporter vers Excel -1. Sur une machine **avec** Internet, executez : - ```powershell - .\Save-Dependencies.ps1 - ``` - Cela telecharge le module dans le dossier `Dependencies/`. +--- -2. Copiez le **projet entier** (avec `Dependencies/`) sur la machine cible. +## Prerequis -3. Lancez normalement — le mode Offline est detecte automatiquement grace a la presence du dossier `Dependencies/`. +- Windows 10/11 ou Windows Server 2016+ +- PowerShell 5.1 (inclus dans Windows) +- Excel installe sur le poste (pour l'export Hardware avec snapshots) +- Acces reseau au serveur Milestone XProtect Management Server -### Configuration du mode +Le module **MilestonePSTools** est installe automatiquement au premier lancement si Internet est disponible. -Dans `config.json`, le parametre `installMode` accepte : +--- -| Valeur | Comportement | -|--------|-------------| -| `Auto` | Utilise `Dependencies/` si present, sinon telecharge en ligne *(defaut)* | -| `Online` | Force le telechargement depuis PSGallery | -| `Offline` | Force le chargement local (erreur si module absent) | +## Modes d'installation + +### Online (par defaut) +Le module est telecharge automatiquement depuis PowerShell Gallery. Aucune action requise. + +### Offline (machine sans Internet) +1. Sur une machine **avec** Internet, cliquer **Preparer offline** dans l'ecran de demarrage +2. Copier le projet entier (avec `Dependencies/`) sur la machine cible +3. Lancer normalement — le mode Offline est detecte automatiquement +image + +--- ## Configuration -Modifier `config.json` pour personnaliser le comportement : +Modifier `config.json` : ```json { - "installMode": "Auto", "outputDirectory": "./Output", "snapshotQuality": 95, "csvDelimiter": ";", @@ -76,60 +115,64 @@ Modifier `config.json` pour personnaliser le comportement : | Parametre | Description | Defaut | |-----------|-------------|--------| -| `installMode` | Mode d'installation des modules : `Auto`, `Online`, `Offline` | `Auto` | -| `outputDirectory` | Repertoire de sortie (snapshots, CSV, etc.) | `./Output` | +| `outputDirectory` | Dossier de sortie par defaut (snapshots, Excel, CSV) | `./Output` | | `snapshotQuality` | Qualite JPEG des snapshots (1-100) | `95` | -| `csvDelimiter` | Separateur pour l'export CSV | `;` | -| `csvEncoding` | Encodage du fichier CSV | `UTF8` | +| `csvDelimiter` | Separateur des fichiers CSV | `;` | +| `csvEncoding` | Encodage des fichiers CSV | `UTF8` | + +Le dossier de sortie peut aussi etre change en cours d'utilisation via le bouton **Changer** dans la sidebar. + +Le mode Online/Offline est detecte automatiquement selon la presence du dossier `Dependencies/`. + +--- ## Structure du projet ``` MilestonePSTools/ ├── Launch.ps1 # Point d'entree -├── Save-Dependencies.ps1 # Telecharge les modules pour usage offline -├── config.json # Configuration utilisateur -├── Dependencies/ # Modules offline (genere par Save-Dependencies.ps1) -├── src/ -│ ├── App.ps1 # Bootstrap, chargement UI, wiring evenements -│ ├── UI/ -│ │ └── MainWindow.xaml # Interface WPF (theme sombre) -│ ├── Actions/ # 1 fichier = 1 action -│ │ ├── Get-SnapshotSelected.ps1 -│ │ ├── Get-SnapshotAll.ps1 -│ │ ├── Export-HardwareReport.ps1 -│ │ ├── Set-CameraGroupByModel.ps1 -│ │ └── Get-PtzPresetSnapshot.ps1 -│ └── Core/ # Utilitaires partages -│ ├── Initialize-Modules.ps1 -│ ├── Write-ActivityLog.ps1 -│ └── Invoke-PtzPreset.ps1 -├── Logs/ # Logs d'activite (generes automatiquement) -├── Output/ # Fichiers de sortie (generes automatiquement) -└── Old/ # Script original archive +├── config.json # Configuration +├── Dependencies/ # Modules offline (optionnel) +├── Logs/ # Logs journaliers (auto) +├── Output/ # Fichiers generes (auto) +└── src/ + ├── App.ps1 # Chargement UI et evenements + ├── UI/ + │ └── MainWindow.xaml # Interface WPF (theme sombre Catppuccin) + ├── Actions/ + │ ├── Get-SnapshotSelected.ps1 + │ ├── Get-SnapshotAll.ps1 + │ ├── Get-PtzPresetSnapshot.ps1 + │ ├── Export-HardwareReport.ps1 + │ ├── Set-CameraGroupByModel.ps1 + │ ├── Get-RecordingStats.ps1 + │ ├── Get-LicenseInfo.ps1 + │ ├── Get-CameraStatus.ps1 + │ └── Get-PlaybackReport.ps1 + └── Core/ + ├── Initialize-Modules.ps1 + ├── Show-StartupCheck.ps1 + ├── Write-ActivityLog.ps1 + └── Invoke-PtzPreset.ps1 ``` -## Ajouter une nouvelle action - -1. Creer un fichier dans `src/Actions/` (ex: `New-MyAction.ps1`) -2. Implementer la fonction avec l'interface standard : +--- -```powershell -function New-MyAction { - param( - [hashtable]$Config, - [scriptblock]$Log - ) +## Cas d’usage - & $Log "Debut de l'action..." - # Votre code ici - & $Log "Terminee." -} -``` +- Audit de parc caméras +- Vérification de la rétention +- Export client +- Analyse de fonctionnement +- Maintenance système -3. Dans `src/App.ps1`, ajouter le dot-source et le bouton correspondant +--- -## Logs +## Mots-clés -Les logs sont ecrits dans le dossier `Logs/` avec un fichier par jour : -`MilestoneToolkit_2026-02-10.log` +Milestone XProtect export Excel +export caméras XProtect +outil audit vidéosurveillance +MilestonePSTools GUI +rapport caméras sécurité +export hardware XProtect diff --git a/Save-Dependencies.ps1 b/Save-Dependencies.ps1 index 8874b6b..065939a 100644 --- a/Save-Dependencies.ps1 +++ b/Save-Dependencies.ps1 @@ -28,6 +28,7 @@ if (-not (Test-Path $depPath)) { $modules = @( 'MilestonePSTools' + 'ImportExcel' ) Write-Host '============================================' -ForegroundColor Cyan diff --git a/config.json b/config.json index d672f9e..03ffc90 100644 --- a/config.json +++ b/config.json @@ -1,7 +1,10 @@ { - "installMode": "Auto", "outputDirectory": "./Output", "snapshotQuality": 95, "csvDelimiter": ";", - "csvEncoding": "UTF8" + "csvEncoding": "UTF8", + "autoUpdate": { + "enabled": true, + "repo": "Nothinx-44/XProtect-Export-Tool-to-Excel-MilestonePSTools-GUI-" + } } diff --git a/src/Actions/Export-HardwareReport.ps1 b/src/Actions/Export-HardwareReport.ps1 index 288e40f..9e2feee 100644 --- a/src/Actions/Export-HardwareReport.ps1 +++ b/src/Actions/Export-HardwareReport.ps1 @@ -1,53 +1,926 @@ <# .SYNOPSIS - Exporte un rapport CSV de tous les equipements (hardware) du VMS Milestone. -.PARAMETER Config - Hashtable de configuration (outputDirectory, csvDelimiter, csvEncoding). -.PARAMETER Log - Scriptblock callback pour logger vers l'UI. + Exporte un rapport Excel de tous les equipements Milestone. + Colonnes selectionnables via une fenetre de choix. Mots de passe exclus par defaut. #> +function Show-ExportColumnSelector { + $xaml = @" + + + + + + + + + + + + + + +'@ + + $reader = [System.Xml.XmlReader]::Create([System.IO.StringReader]::new($xaml)) + $win = [System.Windows.Markup.XamlReader]::Load($reader) + + $win.FindName('BtnFR').Add_Click({ + $win.Tag = 'fr' + $win.DialogResult = $true + }) + + $win.FindName('BtnEN').Add_Click({ + $win.Tag = 'en' + $win.DialogResult = $true + }) + + # Titre dynamique depuis la version centralisee + $appVer = if ($script:AppVersion) { $script:AppVersion } else { '' } + $win.Title = if ($appVer) { "Milestone Toolkit $appVer" } else { 'Milestone Toolkit' } + + [void]$win.ShowDialog() + + if ($win.Tag) { return [string]$win.Tag } + return 'fr' +} diff --git a/src/Core/Show-StartupCheck.ps1 b/src/Core/Show-StartupCheck.ps1 new file mode 100644 index 0000000..e2ee783 --- /dev/null +++ b/src/Core/Show-StartupCheck.ps1 @@ -0,0 +1,906 @@ +<# +.SYNOPSIS + Fenetre GUI de verification des dependances au demarrage. +#> + +function Show-StartupCheck { + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string]$AppRoot + ) + + Add-Type -AssemblyName PresentationFramework + Add-Type -AssemblyName PresentationCore + Add-Type -AssemblyName WindowsBase + + $script:_SC_Result = $false + $script:_SC_AppRoot = $AppRoot + $script:_SC_DepsPath = Join-Path $AppRoot 'Dependencies' + $script:_SC_IsOffline = Test-Path $script:_SC_DepsPath + $script:_SC_DepRows = @{} + $script:_SC_Modules = @( + @{ Name = 'MilestonePSTools'; Required = $true; Description = $script:T.SC_ModuleDesc } + @{ Name = 'ImportExcel'; Required = $true; Description = $script:T.SC_ModuleExcelDesc } + ) + + $xaml = @' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -162,7 +385,7 @@ Style="{StaticResource ActionButton}"> - + @@ -174,6 +397,48 @@ + + + + + + + + + + + + + + @@ -195,26 +460,29 @@ DockPanel.Dock="Right" Content="Effacer" Style="{StaticResource ClearButton}"/> - + - + - + @@ -232,7 +500,8 @@