param( [Parameter(Mandatory = $true)] [string]$SourceDir, [Parameter(Mandatory = $true)] [string]$OutputPath ) $ErrorActionPreference = "Stop" function ConvertTo-NsisString { param([string]$Value) return $Value.Replace('$', '$$').Replace('"', '$\"') } $sourceRoot = (Resolve-Path -LiteralPath $SourceDir).Path.TrimEnd('\') $sourcePrefix = "$sourceRoot\" $files = @( Get-ChildItem -LiteralPath $sourceRoot -Recurse -File -Force | Sort-Object FullName ) if ($files.Count -eq 0) { throw "No files were found in NSIS application source directory: $sourceRoot" } [long]$totalBytes = ($files | Measure-Object -Property Length -Sum).Sum $lines = [System.Collections.Generic.List[string]]::new() $lines.Add("!define APP_COPY_TOTAL_BYTES `"$totalBytes`"") $lines.Add("!macro copyApplicationFilesWithProgress") $lastRelativeDirectory = $null foreach ($file in $files) { $relativePath = $file.FullName.Substring($sourcePrefix.Length) $relativeDirectory = Split-Path -Parent $relativePath $escapedRelativePath = ConvertTo-NsisString $relativePath $escapedSourcePath = ConvertTo-NsisString $file.FullName $escapedFileName = ConvertTo-NsisString $file.Name if ($relativeDirectory -ne $lastRelativeDirectory) { if ([string]::IsNullOrEmpty($relativeDirectory)) { $lines.Add(' SetOutPath "$INSTDIR"') } else { $escapedDirectory = ConvertTo-NsisString $relativeDirectory $lines.Add(" SetOutPath `"`$INSTDIR\$escapedDirectory`"") } $lastRelativeDirectory = $relativeDirectory } $lines.Add(" File `"/oname=$escapedFileName`" `"$escapedSourcePath`"") $lines.Add( " !insertmacro progressCopyFile `"$($file.Length)`" `"$escapedRelativePath`"" ) } $lines.Add("!macroend") $encoding = [System.Text.UTF8Encoding]::new($false) [System.IO.File]::WriteAllLines($OutputPath, $lines, $encoding) Write-Host "Generated NSIS commands for $($files.Count) files ($totalBytes bytes)."