$source = @"
using System;
namespace Foo {
public static class Bar {
public static void Test() {
Console.BackgroundColor = (Console.ConsoleColor) -1;
}
}
}
"@
Add-Type -TypeDefinition $source -Language CSharp -ReferencedAssemblies System.Console
The type to be added.
Add-Type : (5) : The type 'Console' exists in both 'System.Console, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' and
'System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'
(4) : public static void Test() {
(5) : >>> System.Console.BackgroundColor = (System.Console.ConsoleColor) -1;
(6) : }
At line:1 char:1
+ Add-Type -TypeDefinition $source -Language CSharp -ReferencedAssembli ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (Microsoft.Power...peCompilerError:AddTypeCompilerError) [Add-Type], Exception
+ FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand
Add-Type : (5) : The type 'Console' exists in both 'System.Console, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' and
'System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'
(4) : public static void Test() {
(5) : >>> System.Console.BackgroundColor = (System.Console.ConsoleColor) -1;
(6) : }
At line:1 char:1
+ Add-Type -TypeDefinition $source -Language CSharp -ReferencedAssembli ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (Microsoft.Power...peCompilerError:AddTypeCompilerError) [Add-Type], Exception
+ FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand
Add-Type : Cannot add type. Compilation errors occurred.
At line:1 char:1
+ Add-Type -TypeDefinition $source -Language CSharp -ReferencedAssembli ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Add-Type], InvalidOperationException
+ FullyQualifiedErrorId : COMPILER_ERRORS,Microsoft.PowerShell.Commands.AddTypeCommand
> $PSVersionTable
Name Value
---- -----
PSVersion 5.1.10032.0
PSEdition PowerShellCore
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 3.0.0.0
GitCommitId v6.0.0-alpha.7
CLRVersion
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
/cc @vors
That is really weird. 馃槩
PS>[Console].AssemblyQualifiedName
System.Console, System.Console, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
There's even a test for that class being there
Which of course, means that if you don't use the -ReferencedAssemblies parameter (which is strangely plural), you get an error: 'Console' does not contain a definition for 'BackgroundColor' ... but...
PS> [Console]::BackgroundColor = "White"
PS> [Console]::BackgroundColor
White
Is there any _workaround_ for this? It's currently blocking my PowerLine module from working on Core :wink:
A similar issue is described in Roslyn at https://github.com/dotnet/roslyn/issues/13267
We're running into this problem as we expand our Puppet PowerShell module to be cross-platform, as we use a custom host.
In the 6.0 alpha 10 release, it was necessary to add more ReferencedAssemblies to the Add-Type call on OSX with -ReferencedAssemblies @('System.Collections', 'System.Console', 'System.Management.Automation', 'System.Globalization'). On Windows WMF 5.1, this was not necessary.
It's my understanding that System.Management.Automation should not be necessary to explicitly include based on the Add-Type documentation at https://technet.microsoft.com/en-us/library/hh849914.aspx
According to @tmat it's a bug in CoreFX.
They exporting the same public type from both assemblies.
There is a workaround: an internal Roslyn API that allows compiling such cases.
I will send a PR with it, but we need to discuss, do we want to use it or not.
Also, this API will become public at some point, this work is tracked in https://github.com/dotnet/roslyn/issues/5855
See https://github.com/dotnet/corefx/issues/5540 for the CoreFX issue.
Some things we discussed with @tmat for future context.
Add-Type but it's definitely will complicate our build process.Blocked on https://github.com/dotnet/corefx/issues/5540
It's unclear based on the commentary in https://github.com/dotnet/coreclr/issues/4651 whether or not https://github.com/dotnet/coreclr/pull/9269 was / will be successful in fixing this issue completely or not.
If you could follow up on this thread when a new build based on the https://github.com/dotnet/coreclr/pull/9269 merge has shipped, that would be great @vors
Thanks!
@lzybkr @vors for my own knowledge, is a "contract assembly" the same as what @lzybkr has been referring to as a "facade assembly" (per #3095)?
A contract assembly is analogous to a header file in C++ - it defines the api implemented by the assembly, but it does not provide an implementation.
A facade assembly is a fake implementation that points to the real implementation.
For a concrete example, consider a commonly used type System.String:
When building against netstandard1, you will reference System.Runtime.dll. This is (or should be) a contract assembly that contains no implementation.
When you build your application (not a library, but an exe), you will target a specific runtime, e.g. net45 or netcoreapp1.0, the build system will copy the implementation assembly to your build directory and you will deploy that implementation assembly, not the contract assembly.
If your assembly targets netstandard*, the build system does not copy your referenced assemblies - it's assumed the application provides those because it knows which runtime you are targeting.
If your assembly targets netcoreapp*, the build system will copy System.Runtime.dll from .Net Core - and it will contain the implementation of System.String.
If your assembly targets net45, the build system will copy a facade assembly for System.Runtime.dll. This facade assembly has a type forward that says System.String is really in mscorlib.dll.
It turns out that the facade assembly System.Runtime.dll is installed on Windows 10, so maybe the build system won't copy this one, I haven't tried it. But many facade assemblies are not installed, so the build system will help you copy the necessary assemblies if your application targets a specific runtime and not netstandard*.
Got it. Thanks for the detailed explanation. We just had a great conversation with the .NET folks today, and this dovetails nicely with some similar info I got from them.
Apologies in asking this question!!
Is it a "Requirement" to install .NET Core in order for PowerShell Open Source to work in Linux distribution?? This is been bugging me for some time.
:)
@MaximoTrinidad in a sense, no, the PowerShell end-user packages are self-contained (they bring the components of .NET Core that are necessary along with themselves; _having_ those components is necessary, but you do not have to install them separately). It _is_ required in order to develop on PowerShell, but that's a separate story.
@andschwa , Thanks for the quick reply!
So, would it make any difference if I install .NET Core? I mean, It should be fine along side PowerShell. Right!
:)
@MaximoTrinidad installing .NET Core separately shouldn't affect PowerShell whatsoever 馃槃
Thanks @andschwa! Greatly Appreciated!
:)
Given that the repro in #3264 is working, I played around with the original example (note that I suspected that Console.ConsoleColor should have been System.ConsoleColor). I think it's working now (adding @SteveL-MSFT to verify):
$source = @"
using System;
namespace Foo {
public static class Bar {
public static void Test() {
Console.BackgroundColor = (System.ConsoleColor) (-1);
}
}
}
"@
Add-Type -TypeDefinition $source -Language CSharp -ReferencedAssemblies System.Console
Yes, it looks to be working.
Most helpful comment
A contract assembly is analogous to a header file in C++ - it defines the api implemented by the assembly, but it does not provide an implementation.
A facade assembly is a fake implementation that points to the real implementation.
For a concrete example, consider a commonly used type
System.String:When building against
netstandard1, you will referenceSystem.Runtime.dll. This is (or should be) a contract assembly that contains no implementation.When you build your application (not a library, but an exe), you will target a specific runtime, e.g.
net45ornetcoreapp1.0, the build system will copy the implementation assembly to your build directory and you will deploy that implementation assembly, not the contract assembly.If your assembly targets
netstandard*, the build system does not copy your referenced assemblies - it's assumed the application provides those because it knows which runtime you are targeting.If your assembly targets
netcoreapp*, the build system will copySystem.Runtime.dllfrom .Net Core - and it will contain the implementation ofSystem.String.If your assembly targets
net45, the build system will copy a facade assembly for System.Runtime.dll. This facade assembly has a type forward that saysSystem.Stringis really inmscorlib.dll.It turns out that the facade assembly
System.Runtime.dllis installed on Windows 10, so maybe the build system won't copy this one, I haven't tried it. But many facade assemblies are not installed, so the build system will help you copy the necessary assemblies if your application targets a specific runtime and notnetstandard*.