# Module ZipBuilder - Creation ZIP en memoire pour envoi config Enocean Add-Type -AssemblyName System.IO.Compression function New-EnoceanZip { [CmdletBinding()] param( [Parameter(Mandatory)] [hashtable[]]$XmlFiles # Chaque hashtable : @{ Name = "enoceandevice1.xml"; Content = "..." } ) $memoryStream = New-Object System.IO.MemoryStream # leaveOpen = $true pour pouvoir lire le stream apres fermeture de l'archive $archive = New-Object System.IO.Compression.ZipArchive($memoryStream, [System.IO.Compression.ZipArchiveMode]::Create, $true) foreach ($xmlFile in $XmlFiles) { # Chemin interne avec forward slashes $entryPath = "enocean/configuration/devices/$($xmlFile.Name)" $entry = $archive.CreateEntry($entryPath, [System.IO.Compression.CompressionLevel]::Optimal) $entryStream = $entry.Open() $utf8NoBom = New-Object System.Text.UTF8Encoding($false) $writer = New-Object System.IO.StreamWriter($entryStream, $utf8NoBom) $writer.Write($xmlFile.Content) $writer.Flush() $writer.Close() $entryStream.Close() } $archive.Dispose() $zipBytes = $memoryStream.ToArray() $memoryStream.Close() Write-Log -Message "ZIP cree en memoire : $($XmlFiles.Count) fichier(s), $($zipBytes.Length) octets" -Level INFO return $zipBytes } function Get-ZipFilename { [CmdletBinding()] param( [Parameter(Mandatory)] [byte[]]$ZipBytes ) $md5 = [System.Security.Cryptography.MD5]::Create() $hashBytes = $md5.ComputeHash($ZipBytes) $hashString = ($hashBytes | ForEach-Object { $_.ToString("x2") }) -join "" return "fullConfig.$hashString.zip" } function Read-GfxMainXml { [CmdletBinding()] param( [Parameter(Mandatory)] [byte[]]$GfxBytes ) $memStream = New-Object System.IO.MemoryStream(, $GfxBytes) $archive = New-Object System.IO.Compression.ZipArchive($memStream, [System.IO.Compression.ZipArchiveMode]::Read) $entry = $archive.GetEntry("Main.xml") if (-not $entry) { $archive.Dispose() $memStream.Close() throw "Main.xml non trouve dans le fichier GFx" } $entryStream = $entry.Open() $reader = New-Object System.IO.StreamReader($entryStream, [System.Text.Encoding]::UTF8) $content = $reader.ReadToEnd() $reader.Close() $entryStream.Close() $archive.Dispose() $memStream.Close() return $content } function Update-GfxZip { [CmdletBinding()] param( [Parameter(Mandatory)] [byte[]]$GfxBytes, [Parameter(Mandatory)] [string]$ModifiedMainXml ) # Copier les bytes dans un MemoryStream modifiable $memStream = New-Object System.IO.MemoryStream $memStream.Write($GfxBytes, 0, $GfxBytes.Length) $memStream.Position = 0 $archive = New-Object System.IO.Compression.ZipArchive($memStream, [System.IO.Compression.ZipArchiveMode]::Update, $true) # Supprimer l'ancien Main.xml et recreer avec le contenu modifie $entry = $archive.GetEntry("Main.xml") if ($entry) { $entry.Delete() } $newEntry = $archive.CreateEntry("Main.xml", [System.IO.Compression.CompressionLevel]::Optimal) $entryStream = $newEntry.Open() $utf8NoBom = New-Object System.Text.UTF8Encoding($false) $writer = New-Object System.IO.StreamWriter($entryStream, $utf8NoBom) $writer.Write($ModifiedMainXml) $writer.Flush() $writer.Close() $entryStream.Close() $archive.Dispose() $newBytes = $memStream.ToArray() $memStream.Close() Write-Log -Message "GFx mis a jour en memoire : $($newBytes.Length) octets" -Level INFO return $newBytes } Export-ModuleMember -Function New-EnoceanZip, Get-ZipFilename, Read-GfxMainXml, Update-GfxZip