src/CodeAnalysisCompiler.ps1
$referenceAssembies = @() $Mscorlib = [Microsoft.CodeAnalysis.MetadataReference]::CreateFromFile(([type] 'object').Assembly.Location) $referenceAssembies += $Mscorlib # Add System.dll to the reference assemblies $systemDllPath = [System.IO.Path]::Combine([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory(), "System.dll") $referenceAssembies += $systemDllPath # Add System.Globalization.dll to the reference assemblies $globalizationDllPath = [System.IO.Path]::Combine([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory(), "System.Globalization.dll") if ([System.IO.File]::Exists($globalizationDllPath)) { $referenceAssembies += $globalizationDllPath } # Check if Microsoft.PowerShell.ConsoleHost.dll exists and add it to the reference assemblies $consoleHostDllPath = [System.Reflection.Assembly]::GetAssembly([System.Management.Automation.Runspaces.Runspace]).Location if ([System.IO.File]::Exists($consoleHostDllPath) -and !$noConsole) { $referenceAssembies += $consoleHostDllPath } # Add System.Management.Automation.dll to the reference assemblies $automationDllPath = [System.Reflection.Assembly]::GetAssembly([System.Management.Automation.PSObject]).Location if ([System.IO.File]::Exists($automationDllPath)) { $referenceAssembies += $automationDllPath } # Add System.Core.dll to the reference assemblies $coreDllPath = [System.IO.Path]::Combine([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory(), "System.Core.dll") if ([System.IO.File]::Exists($coreDllPath)) { $referenceAssembies += $coreDllPath } # If noConsole is true, add System.Windows.Forms.dll and System.Drawing.dll to the reference assemblies $OutputKind = [Microsoft.CodeAnalysis.OutputKind]::ConsoleApplication if ($noConsole) { $formsDllPath = [System.IO.Path]::Combine([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory(), "System.Windows.Forms.dll") $drawingDllPath = [System.IO.Path]::Combine([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory(), "System.Drawing.dll") if ([System.IO.File]::Exists($formsDllPath)) { $referenceAssembies += $formsDllPath } if ([System.IO.File]::Exists($drawingDllPath)) { $referenceAssembies += $drawingDllPath } $OutputKind = [Microsoft.CodeAnalysis.OutputKind]::WindowsApplication } $references = $referenceAssembies | ForEach-Object { if ([System.IO.File]::Exists($_)) { [Microsoft.CodeAnalysis.MetadataReference]::CreateFromFile($_) } } . $PSScriptRoot\BuildFrame.ps1 [string[]]$Constants = @() $Constants += $threadingModel if ($lcid) { $Constants += "culture" } if ($noError) { $Constants += "noError" } if ($noConsole) { $Constants += "noConsole" } if ($noOutput) { $Constants += "noOutput" } if ($resourceParams.version) { $Constants += "version" } if ($resourceParams.Count) { $Constants += "Resources" } if ($credentialGUI) { $Constants += "credentialGUI" } if ($noVisualStyles) { $Constants += "noVisualStyles" } if ($exitOnCancel) { $Constants += "exitOnCancel" } if ($UNICODEEncoding) { $Constants += "UNICODEEncoding" } if ($winFormsDPIAware) { $Constants += "winFormsDPIAware" } # Get a default CSharpParseOptions instance $parseOptions = [Microsoft.CodeAnalysis.CSharp.CSharpParseOptions]::Default # Set preprocessor symbols $parseOptions = $parseOptions.WithPreprocessorSymbols($Constants) $tree = [Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree]::ParseText($programFrame, $parseOptions) $compilationOptions = New-Object Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions($OutputKind) if (-not $TempDir) { $TempDir = $TempTempDir = [System.IO.Path]::GetTempPath() + [System.IO.Path]::GetRandomFileName() New-Item -Path $TempTempDir -ItemType Directory | Out-Null } $TempDir = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($TempDir) . $PSScriptRoot\BuildTempFiles.ps1 if ($iconFile) { $compilationOptions = $compilationOptions.WithWin32Icon($iconFilePath) } if (!$virtualize) { $compilationOptions = $compilationOptions.WithPlatform($( switch ($architecture) { "x86" { [Microsoft.CodeAnalysis.Platform]::X86 } "x64" { [Microsoft.CodeAnalysis.Platform]::X64 } "anycpu" { [Microsoft.CodeAnalysis.Platform]::AnyCpu } default { Write-Warning "Invalid platform $architecture, using AnyCpu" [Microsoft.CodeAnalysis.Platform]::AnyCpu } }) ) } else { Write-Host "Application virtualization is activated, forcing x86 platfom." $compilationOptions = $compilationOptions.WithPlatform([Microsoft.CodeAnalysis.Platform.X86]) } if(!$IsConstProgram) { $resourceDescription = New-Object Microsoft.CodeAnalysis.Emit.EmbeddedResource("$TempDir\main.ps1", [Microsoft.CodeAnalysis.ResourceDescriptionKind]::Embedded) $compilation = $compilation.AddReferences($resourceDescription) } if ($prepareDebug) { $compilationOptions = $compilationOptions.WithOptions($compilation.Options.WithOptimizationLevel([Microsoft.CodeAnalysis.OptimizationLevel]::Debug)).WithDebugPlusMode($TRUE) } $treeArray = New-Object System.Collections.Generic.List[Microsoft.CodeAnalysis.SyntaxTree] $treeArray.Add($tree) $referencesArray = New-Object System.Collections.Generic.List[Microsoft.CodeAnalysis.MetadataReference] $references | ForEach-Object { $referencesArray.Add($_) } $compilation = [Microsoft.CodeAnalysis.CSharp.CSharpCompilation]::Create( "PSRunner", $treeArray.ToArray(), $referencesArray.ToArray(), $compilationOptions ) # Create a new EmitOptions instance $emitOptions = New-Object Microsoft.CodeAnalysis.Emit.EmitOptions -ArgumentList @([Microsoft.CodeAnalysis.Emit.DebugInformationFormat]::PortablePdb) $peStream = New-Object System.IO.FileStream($outputFile, [System.IO.FileMode]::Create) $emitResult = $compilation.Emit($peStream, $null, $null, $null, $null, $emitOptions) $peStream.Close() Write-Host "Compiling file..." if ($emitResult.Success) { if (Test-Path $outputFile) { RollUp Write-Host "Compiled file written -> $((Get-Item $outputFile).Length) bytes" Write-Verbose "Path: $outputFile" if ($prepareDebug) { $cr.TempFiles | Where-Object { $_ -ilike "*.cs" } | Select-Object -First 1 | ForEach-Object { $dstSrc = ([System.IO.Path]::Combine([System.IO.Path]::GetDirectoryName($outputFile), [System.IO.Path]::GetFileNameWithoutExtension($outputFile) + ".cs")) Write-Host "Source file name for debug copied: $dstSrc" Copy-Item -Path $_ -Destination $dstSrc -Force } $cr.TempFiles | Remove-Item -Verbose:$FALSE -Force -ErrorAction SilentlyContinue } if ($CFGFILE) { $configFileForEXE3 | Set-Content ($outputFile + ".config") -Encoding UTF8 Write-Host "Config file for EXE created" } } else { Write-Error -ErrorAction "Continue" "Output file $outputFile not written" } } else { if (Test-Path $outputFile) { Remove-Item $outputFile -Verbose:$FALSE } RollUp Write-Host "Compilation failed!" -ForegroundColor Red $emitResult.Diagnostics -join "`n" | Write-Error } if ($TempTempDir) { Remove-Item $TempTempDir -Recurse -Force -ErrorAction SilentlyContinue } |