CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Feb 2007
    Posts
    6

    TypeLoadException "access is denied" using TypeBuilder.CreateType() on internal types

    I'm getting a System.TypeLoadException "access is denied" when hitting the method System.Reflection.Emit.TypeBuilder.CreateType().

    Scenario:
    I'm trying to test a library (strong named) of mine using NMock2 (strong named); the testing-assembly is also strong named. I exposed the internal types of my library to the testing-assembly and NMock2 via the InternalsVisibleTo assembly attribute.

    This works fine up to the point where NMock2 tries to create a proxy type of an internal interface defined in my library (in this case "Foo.Client.UIAbstraction.IFormDocumentation"). Note that there's no problem when the interface is public; it's only the internal thingy.

    (param 'baseInterfaces' contains the internal interface to be created)
    Code:
    private Type CreateType(string typeName, Type[] baseInterfaces)
    {
        TypeBuilder typeBuilder = moduleBuilder.DefineType(
            typeName,
            TypeAttributes.Public | TypeAttributes.Abstract | 
                TypeAttributes.Interface,
            null,
            baseInterfaces);
    			
           return typeBuilder.CreateType(); // <--- Here the exception occurs.
    }
    NMock2 and my testing-assembly don't have a problem accessing internal types of my library.

    Since I'm new to the .NET thingy, my naive assumption is that this might somehow mean that also the mscorlib.dll (that's where System.Reflection.Emit.TypeBuilder resides) needs to be added to the friendly assemblies via the InternalsVisibleTo attribute. If yes, then how do I get the public key of the mscorlib.dll?

    Stack trace:
    (Note that "Zugriff verweigert" means "access is denied" in german)
    Code:
    TestCase 'Foo.Commands.CommandMetadataOpenTest.execute_TestUserAbortNoMetadataEntry'
    failed: System.TypeLoadException : Zugriff verweigert: Foo.Client.UIAbstraction.IFormDocumentation.
    	   bei System.Reflection.Emit.TypeBuilder.TermCreateClass(Int32 handle, Module module)
    	   bei System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
    	   bei System.Reflection.Emit.TypeBuilder.CreateType()
    	   bei NMock2.Monitoring.MultiInterfaceFactory.CreateType(String typeName, Type[] baseInterfaces) in C:\dev\libs\nmock2\src\NMock2\Monitoring\MultiInterfaceFactory.cs:Zeile 47.
    	   bei NMock2.Monitoring.MultiInterfaceFactory.GetType(Type[] baseInterfaces) in C:\dev\libs\nmock2\src\NMock2\Monitoring\MultiInterfaceFactory.cs:Zeile 33.
    	   bei NMock2.Mockery.NewMock(Type mockedType, String name) in C:\dev\libs\nmock2\src\NMock2\Mockery.cs:Zeile 43.
    	   bei NMock2.Mockery.NewMock(Type mockedType) in C:\dev\libs\nmock2\src\NMock2\Mockery.cs:Zeile 31.
    	   bei NMock2.Mockery.NewMock[InterfaceOfMock]() in C:\dev\libs\nmock2\src\NMock2\Mockery.cs:Zeile 37.
    	   bei Foo.Core.Commands.CommandMetadataOpenTest.SetUp() in C:\dev\projects\Foo\Commands\CommandMetadataOpenTest.cs:Zeile 41.
    Regards,

    Kasimier

  2. #2
    Join Date
    Feb 2007
    Posts
    6

    Re: TypeLoadException "access is denied" using TypeBuilder.CreateType() on internal types

    Here's a reduced scenario; it consists of a (strong named) assembly "FooLib.dll" and an executable "MyTypeBuilder.exe" (strong named).

    In the AssemblyInfo.cs of "FooLib.dll" I defined "MyTypeBuilder.exe" as a friendly assembly:
    [assembly: InternalsVisibleTo("MyTypeBuilder, PublicKey=00240...")]

    This time the TypeBuilder just tries to create a sub-type of the internal class "Foo" and fails with a System.TypeLoadException "access is denied".

    I still don't know if adding the mscorlib.dll to the friendly assemblies would heal the issue. Is there a public-key available for the mscorlib.dll?

    Does someone know if this is a restriction of the .NET framework? I.e. that I'm not *supposed* to be able to do what I'm trying by design?

    I'm using:
    Microsoft Visual Studio 2005 Version 8.0.50727.762 (SP.050727-7600)
    Microsoft .NET Framework Version 2.0.50727

    "FooLib.dll"
    Code:
    namespace FooLib
    {
        internal class Foo
        {}
    }
    "MyTypeBuilder.exe"
    Code:
    using System;
    using System.Reflection;
    using System.Reflection.Emit;
    using FooLib;
    
    namespace MyTypeBuilder
    {
        class Program
        {
            static void Main(string[] args)
            {
                string name = "Mocks";
                AssemblyName assemblyName = new AssemblyName();
                assemblyName.Name = name;
    
                AssemblyBuilder assemblyBuilder =
                AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
                ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(name);
    
                TypeBuilder typeBuilder =
                    moduleBuilder.DefineType(
                        "MockFoo",
                        TypeAttributes.NotPublic | TypeAttributes.Class,
                        typeof(FooLib.Foo));
    
                try
                {
                    Type myMockFoo = typeBuilder.CreateType();
                }
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine(e);
                }
            }
        }
    }
    This scenario produces:
    ("Zugriff verweigert" still means "access is denied")
    Code:
    System.TypeLoadException: Zugriff verweigert: FooLib.Foo.
       bei System.Reflection.Emit.TypeBuilder.TermCreateClass(Int32 handle, Module module)
       bei System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
       bei System.Reflection.Emit.TypeBuilder.CreateType()
       bei MyTypeBuilder.Program.Main(String[] args) in C:\dev\projects\Tests\TypeBuilder\TypeBuilder\Program.cs:Zeile 28.
    Regards,

    Kasimier

  3. #3
    Join Date
    Feb 2007
    Posts
    6

    Re: TypeLoadException "access is denied" using TypeBuilder.CreateType() on internal types

    I just tried to put the relevant internal class and the TypeBuilder code into the same assembly: same effect - still a TypeLoadException "access is denied".

  4. #4
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    Re: TypeLoadException "access is denied" using TypeBuilder.CreateType() on internal t

    I would try a few things to find out exactly what the problem is.

    Try to load the assembly (System.Reflection.Assembly.Load) and then create the object using Assembly's CreateInstance method.

    Try to make the internal class into a public class and see if that changes anything.
    My hobby projects:
    www.rclsoftware.org.uk

  5. #5
    Join Date
    Feb 2007
    Posts
    6

    Re: TypeLoadException "access is denied" using TypeBuilder.CreateType() on internal types

    Zaccheus, changing the internal class to public works fine.

    I found the solution for the issue: I need to make the *dynamically* created assembly a friend of the assembly where my internal class/interface resides (not the mscorlib.dll - what I first thought). This seems obvious now, because of course, also the new assembly needs to be given access-rights to an internal type of an other assembly.

    The code down below runs fine now. It loads a previously generated key-file "MyMockKey.snk". The resulting public key goes into my AssemblyInfo.cs.

    Finally I would like to get rid of loading the key-file. Maybe this is possible when creating the KeyPair via:
    Code:
    public StrongNameKeyPair (string keyPairContainer)
    but I haven't figured out yet what the keyPairContainer string should be exactly (the content of my "MyMockKey.snk"?).

    Code:
    using System;
    using System.IO;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace MyTypeBuilder
    {
        internal class Foo
        { }
    
        class Program
        {
            static void Main(string[] args)
            {
                string name = "Mocks";
                AssemblyName assemblyName = new AssemblyName();
                assemblyName.Name = name;
    
                // Assign the strong name key to the new assembly.
                using (FileStream keyStream = File.Open(@"..\..\MyMockKey.snk", FileMode.Open))
                    assemblyName.KeyPair = new StrongNameKeyPair(keyStream);
    
                // Get the public key to be added to "AssemblyInfo.cs".
                string publicKey = BitConverter.ToString(assemblyName.KeyPair.PublicKey).Replace("-", "");
                System.Diagnostics.Debug.WriteLine(
                    "Put this in AssemblyInfo.cs --> [assembly: InternalsVisibleTo(\"Mocks, PublicKey=" + publicKey + "\")]");
    
                AssemblyBuilder assemblyBuilder =
                AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
                ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(name);
    
                TypeBuilder typeBuilder =
                    moduleBuilder.DefineType(
                        "MockFoo",
                        TypeAttributes.NotPublic | TypeAttributes.Class,
                        typeof(Foo));
    
                Type myMockFoo = typeBuilder.CreateType();
            }
        }
    }
    Regards,

    Kasimier

  6. #6
    Join Date
    Jul 2015
    Posts
    1

    Lightbulb Re: TypeLoadException "access is denied" using TypeBuilder.CreateType() on internal t

    In the case that you still have problems to set the KeyPair property, which of course you shouldn't set at runtime for security reasons, I've got a solution that works without the full key pair.

    I ran into the same issue when I refactored the "dynamic query code sample snippet" for my project so that it not exports any of the types or methods. Also the "DynamicClass" class was now internal and the TypeBuilder was not able to create the actual usable type. I got the same "access is denied" error. With the aid of your posting I figured out how to fix the problem.

    You only need to set a valid public key for the AssemblyName that you use to create your AssemblyBuilder. The same public key needs to be added to the InternalsVisibleTo attribute which makes the new dynamic created assembly a friend of the assembly with this attribute. So it makes sense to me, to just use the public key of the assembly with the internal type for the new AssemblyName.

    To keep your example, here is the modified code:
    Code:
    using System;
    using System.IO;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace MyTypeBuilder
    {
        internal class Foo
        { }
    
        class Program
        {
            static void Main(string[] args)
            {
                string name = "Mocks";
                AssemblyName assemblyName = new AssemblyName();
                assemblyName.Name = name;
                // Grab the public key of the assembly which has the internal class.
                byte[] publicKey = typeof(Foo).Assembly.GetName().GetPublicKey();
    
                // Assign the public key to the new assembly.
                assemblyName.SetPublicKey(publicKey);
    
                // Get the public key to be added to "AssemblyInfo.cs".
                string publicKeyString = BitConverter.ToString(publicKey).Replace("-", "");
                System.Diagnostics.Debug.WriteLine(
                    "Put this in AssemblyInfo.cs --> [assembly: InternalsVisibleTo(\"Mocks, PublicKey=" +
                    publicKeyString + "\")]");
    
                AssemblyBuilder assemblyBuilder =
                AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
                ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(name);
    
                TypeBuilder typeBuilder =
                    moduleBuilder.DefineType(
                        "MockFoo",
                        TypeAttributes.NotPublic | TypeAttributes.Class,
                        typeof(Foo));
    
                Type myMockFoo = typeBuilder.CreateType();
            }
        }
    }
    Regards,

    Anateus

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured