When I try Mr. Hoffman's approach, I get the following error:
Add-Type : Could not find a part of the path 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\bin\roslyn\csc.exe'.
user1676558 mentions two solutions:
- A NuGet package that contains a fix for this specific problem
- A snippet of C# that reflects out the offending private field and fixes it
Being a (little league) PowerShell hacker, I came up with my own PowerShellian solution, based on examination of the source code:
$dncpTypes = Add-Type -Path C:\<path where I put the dll>\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll -PassThru
$dncpTypTab = [ordered]@{}
$dncpTypes | %{$dncpTypTab[$_.Name] = $_}
$compSetCtor = $dncpTypTab.CompilerSettings.GetConstructor(@([string],[int]))
$compSettings = $compSetCtor.Invoke(@('C:\Program Files (x86)\MSBuild\14.0\Bin\csc.exe', 10))
$cscpOtherCtor = $dncpTypTab.CSharpCodeProvider.GetConstructor('NonPublic,Instance', $null, @($dncpTypTab.ICompilerSettings), $null)
$roslynProvider = $cscpOtherCtor.Invoke($compSettings)
Needless to say, there's some discussion on the innertubes about whether or not this is a bug. Looks like the provider was targeted at ASP.NET and does the right thing there. People also disagree on where to pick up csc.exe. I suspect this may continue to be in flux.
[later edit: in VS2017, csc appears to live at ${env:ProgramFiles(x86)}\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Roslyn\csc.exe.]
[Edit VS2022]
The API seems to have change a bit with VS2022, now I had to use the following code to set it up:
$pathToCodeDomProvider = 'C:\<WhereEver>\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll'
$pathToCompiler = 'C:\<WhereEver>\csc.exe'
$dncpTypes = Add-Type -LiteralPath $pathToCodeDomProvider -PassThru
$dncpTypTab = [ordered]@{}
$dncpTypes | %{$dncpTypTab[$_.Name] = $_}
$compSetCtor = $dncpTypTab.ProviderOptions.GetConstructor(@([string],[int]))
$compSettings = $compSetCtor.Invoke(@($pathToCompiler, 10))
$cscpOtherCtor = $dncpTypTab.CSharpCodeProvider.GetConstructor(@([Microsoft.CodeDom.Providers.DotNetCompilerPlatform.IProviderOptions]))
$roslynProvider = $cscpOtherCtor.Invoke($compSettings)