Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Designer Rejecting User Control

I have a C++ 'Control Library Project' compiled using /CLR. Inside this project there is a User Control that makes a call to a native DLL. This user control appears in the designer toolbox as it should, but I cannot then drag it onto a form. Without the reference to the DLL the user control can be used fine, but with the reference I just get the message "Failed to load toolbox item" when trying to use it.

The native call is functional and not harming the User Control in anyway. The User Control can be viewed fine in the designer by itself with the DLL call included. Also if the control is added manually to a form and executed as a program, it will also display fine.

This makes me suspect that the problem is just a matter of Visual Studio Designer needing to know where that native DLL is located. But I'm not sure how to tell it, or where to put the DLL so that it can find it. As far as I known there is no way in the project settings to reference a native DLL. So it makes sense to me that designer is just complaining because it can't fine it.

Is there a way to make this work?

like image 418
Nicholas Avatar asked Jan 21 '11 04:01

Nicholas


3 Answers

Unfortunately, you've encountered a "bug by design" in VS (or in other words, a "feature").

Your suspicion that the problem is a matter of the Visual Studio designer needing to know where the native DLL is located is partially right. It's not a matter of ignorance to it's location, but rather the fact that the designer cannot reflect over mixed-mode assemblies (those that contain both managed and native code) in order to instantiate the control. This is causing the toolbox to show the error you noted.

The workaround is to compile the C++ source files using /clr:pure to create a purely managed EXE.


Another possibility (also a "bug by design" in VS) is that the control you're trying to add has been compiled as a 64-bit component. Because Visual Studio is a 32-bit process, it can only execute 32-bit modules. While it allows you to add a reference to a 64-bit assembly, it cannot actually JIT compile that 64-bit assembly and execute it within process.

The workaround here is to compile your user control assembly using the "AnyCPU" setting, which will cause it to execute as a 32-bit process in a 32-bit environment, and a 64-bit process in a 64-bit environment. Really, this is the best of both worlds, assuming you've written your code correctly.


Finally, if none of those work, there's always the option of bypassing the designer. You can still write the code necessary to instantiate your user control and set its properties in the form's initializer. All that you would be losing is the ability to use the control inside of the designer inside Visual Studio. Everything would work as expected at run-time.

like image 65
Cody Gray Avatar answered Sep 20 '22 07:09

Cody Gray


Link your library with /DELAYLOAD:"your_native.dll" option. This solved the same problem for me.

like image 20
giliaidzin Avatar answered Sep 22 '22 07:09

giliaidzin


I found this that looks like a similar problem?

https://connect.microsoft.com/VisualStudio/feedback/details/388107/winforms-designer-fails-to-load-managed-dll-having-unmanaged-dependencies#details

So MS seem to officially be saying upgrade from VS2008 to VS2010 as a workaround.

Did you ever find a different workaround?

This is a problem I am experiencing right now in VS2008 with a C# .net managed project using a managed C++ wrapper project using an unmanaged C++ project.

It certainly looks to me like the designer temporary assemblies that Visual Studio is using is a problem - it loads the detected dependency wrapper assembly into the temporary folder but not that wrapper assembly's unmanaged dependencies. I can see this is in C:\Users\Username\AppData\Local\Microsoft\VisualStudio\9.0\ProjectAssemblies. When I attempt to load the designer a new folder is created in there with the managed DLL in it but not the unmanaged dependencies. Unfortunately I can't understand what the person in the question from the Microsoft link above is saying is the workaround using $(TargetDir).

like image 22
Alan Macdonald Avatar answered Sep 23 '22 07:09

Alan Macdonald