src/Gzip.ps1
|
# 固定版本的内置纯 C# 7-Zip Deflate 编码器,仅编译期使用;不依赖原生程序或宿主压缩实现。 $script:GzipPackCodecType = $null #_if PSEXE #_include_as_value gzipEncoderSource "$PSScriptRoot/programFrames/GzipEncode.cs" #_include_as_value gzipWrapperSource "$PSScriptRoot/programFrames/GzipWrapper.cs" #_else [string]$gzipEncoderSource = Get-Content -LiteralPath "$PSScriptRoot/programFrames/GzipEncode.cs" -Raw -Encoding UTF8 [string]$gzipWrapperSource = Get-Content -LiteralPath "$PSScriptRoot/programFrames/GzipWrapper.cs" -Raw -Encoding UTF8 #_endif $gzipCodecKey = Get-TextHash ("$gzipEncoderSource|$gzipWrapperSource") function Get-GzipPackCodecType { if ($script:GzipPackCodecType) { return $script:GzipPackCodecType } $key = $gzipCodecKey $typeName = "GzipPackCodec_$key" $loaded = Find-LoadedType $typeName if ($loaded) { $script:GzipPackCodecType = $loaded; return $loaded } [string]$cacheRoot = Get-CacheRoot 'gzip' Clear-StaleCache $cacheRoot # 编码流只由源码决定,DLL 缓存还区分宿主运行时。 $runtimeKey = Get-TextHash ("$($PSVersionTable.PSEdition)|$($PSVersionTable.PSVersion)|$key") $encoderPath = Join-Path $cacheRoot "GzipEncode_$runtimeKey.cs" $wrapperPath = Join-Path $cacheRoot "GzipWrapper_$runtimeKey.cs" $dllPath = Join-Path $cacheRoot "gzip_$runtimeKey.dll" $mutex = [System.Threading.Mutex]::new($false, "ps12exe-gzip-$runtimeKey") $locked = $false try { try { $locked = $mutex.WaitOne(120000) } catch [System.Threading.AbandonedMutexException] { $locked = $true } if (-not $locked) { throw 'Timed out waiting for the bundled gzip encoder cache' } if (-not (Test-Path -LiteralPath $dllPath)) { [IO.File]::WriteAllText($encoderPath, $gzipEncoderSource, [Text.UTF8Encoding]::new($true)) [IO.File]::WriteAllText($wrapperPath, ($gzipWrapperSource.Replace('GzipPackCodec', $typeName)), [Text.UTF8Encoding]::new($true)) # 不回退到机器相关的编码器;加载失败必须显式失败。 try { Add-Type -Path @($encoderPath, $wrapperPath) -OutputAssembly $dllPath -OutputType Library -ErrorAction Stop } catch { Remove-Item -LiteralPath $dllPath -Force -ErrorAction Ignore; throw } } [void][Reflection.Assembly]::LoadFrom($dllPath) $script:GzipPackCodecType = Find-LoadedType $typeName if (-not $script:GzipPackCodecType) { throw 'Bundled gzip encoder type was not loaded' } return $script:GzipPackCodecType } finally { if ($locked) { $mutex.ReleaseMutex() } $mutex.Dispose() } } function Compress-Gzip([byte[]]$Data) { $codec = Get-GzipPackCodecType return , ($codec.GetMethod('Compress').Invoke($null, @(, $Data))) } |