I've written a .NET assembly which uses P/Invoke to expose functionality of a native 3rd party library. I am, however, not distributing this library with my assembly. This means that the responsibility is on the user to provide the library through whatever means required. Which leads me to my question:
As either a library author with experience in this situation or a potential user of this assembly, what are some common user expectations one would have for resolving the DLL location in this use case?
Is the default Windows DLL search order enough? "If it blows up, it blows up. They should have read the documentation."
Should I automatically expand %PATH% at run-time to common library install locations to try and find it or at least increase the chances? I'm not really a fan of this as we're changing state behind the scenes.
Should I provide some form of configuration setting to allow the user to specify the location and then manually call LoadLibrary?
As per comments the users are developers:
I would go with convention over configuration... basically default Windows DLL search order... plus a configuration setting for situations where configuration is needed... if that setting is configured it takes precedence...
Related
I'm building a project that will support loading in external, managed DLLs, essentially as a modding system. However due to security reasons I'd like to restrict (as far as possible) what those external DLLs can access and do because they won't be made by myself.
My current plan was to simply blanket ban every assembly besides a select whitelist which I can add to upon request, however my main issue is the System.dll. It's probably the most important one to restrict access to due to the obvious reason that it can access System, however it also has vital namespaces like System.Collections, so it needs to be useable.
Is there a way to check specifically what assemblies and namespaces a loaded DLL is utilising or am I going about this the wrong way?
I have several C# assembly libraries, which are not strongly named (signed). I would like to make a SxS COM-wrapper over those components using the tlbexp.exe to consume in native programs. Is it necessary to sign them or is there another way to do it?
Thanks
There are strong misconceptions in this question, it confuzzles the roles of two programmers. You are the author of the library, somebody else uses your library and probably works for another company and has no idea who you are. The client programmer. You in turn have no idea how the client programmer uses your library, how many programs he wrote and what he does to deploy your library on his users' machines. You run Tlbexp.exe only to help him write his code.
This is a recipe for trouble, like it is no matter what language or tooling you use when you create libraries. That trouble starts when you make a change in the library and the client programmer has to rebuild and redeploy his programs that use your library.
There is extra trouble in a COM library because by default registration is machine-wide. Which is pretty nice if the change you made is a bug-fix, all of the client programs that use your library automatically get the fix. But it is not nice if the change is breaking and causes the old client program to fail. The standard disaster is that the client programmer rebuilds some of this programs but forgets or ignores some old ones he no longer maintains. The end-user is often the real victim, he's got a program that crashes but two programmers that don't think it is their problem to fix.
What is necessary is that programs that the client programmer does not update keep using the old version of your library so it is unaffected by the change. In other words, there need to be multiple copies of your DLL on the users machine and a program automagically needs to pick the right one.
Thankfully that is easy to do for a [ComVisible] .NET assembly. Either the client programmer, his user or an installer you provide for him can put the assembly in the GAC. Which allows multiple copies of an assembly to exist side-by-side and the CLR can automatically find the correct one. That has two requirements. You need to bump the [AssemblyVersion] of your library, that's standard. And the assembly needs to have a strong name so it can be put in the GAC. That is trivial to do by you, using Project > Properties > Signing and ticking the "Sign the assembly" checkbox. This has no security implications so the key doesn't matter and a password is entirely unnecessary. It is not easy to do by the client programmer so this is something that you must do. Always.
The client programmer also has the option to use isolated COM with a manifest (aka "regfree COM"), probably what you meant with "SxS COM-wrapper". With the benefit that each program he writes has its own copy of the DLL, the way it works by default in .NET. Bug-fixes need to be deployed manually but a change in your library can't break an unmaintained client program. But this is entirely his choice, there is nothing that you can do to ensure that this is done. You must assume that he doesn't use it, and he almost certainly won't at first, so you can't bypass the need to strong-name.
When an assembly is strongly named, its types can only be used from other strongly named assemblies. Since your assemblies are not strongly named, there's no need to sign your COM wrapper.
Signing an assembly makes it possible to place it in the Global Assembly Cache (GAC). This has the benefit of keeping multiple versions side by side, without breaking existing clients.
The alternative is to use the Windows registry via regasm's /codebase switch. Much in the same way as classic COM components are set up, this option registers your COM-visible assembly on a system wide basis.
Since you wish to deploy your COM wrapper via SxS / Registration-Free activation, thereby bypassing the registry and GAC altogether, there's really no need sign it.
Currently I'm working on a .NET hobby project that involves a complex system of objects which work in combination with eachother. However, I encountered a little problem, I am unable to find a mechanism in .NET to support replacing code at runtime, and be able to dispose of the old code, loaded previously. This means replacing a module/object dynamically and almost instantly displaying the changes to the user, for example, when he restarts a procedure, but not the whole program.
I have already taken into account the possibility of having separate AppDomain for each session and loading the necessary assemblies into it but this seems a little bit too expensive. I should also mention that every session benefits from a common base of assemblies, for instance, to connect to a database, so this means loading those classes into every single session. Marshalling data back and forth from the separate AppDomain also represents an additional overhead (could be used when data is sent to the client application through the network, code for this contained in the main AppDomain, which manages the sessions).
Is there a framework or way of replacing/unloading particular parts of code? How is it done in real-world applications? Can there be a workaround? Or have I picked the wrong set of tools?
You need some kind of plugin system with well defined interfaces. Then you load at runtime binaries (your plugin *.dll) and create objects from it and then execute methods on it.
When you create a system where objects from your plugins must be created through your IPluginManager you have no problem with replacing code at runtime. :)
Or
You have something like a folder with *.cs files which will on demand compiled (in memory) and create the objects you want to use from them and call the methods on them.
Which is basically the same like above, without compiling at run time.
From there you can make further improvements.
EDIT:
Like you wrote the only problem without using AppDomain is that once loaded assemblies can't be unloaded. But that's not really a problem.
I don't think you need separate AppDomains: you can dynamically load assemblies within the current AppDomain. And each assembly should probably implement some defined interfaces (depending on your usage). You could use the FileSystemWatcher class, for example, to load/unload assemblies as needed.
See http://msdn.microsoft.com/en-us/library/25y1ya39(v=vs.110).aspx
You can have a look at MEF. It stands for: Managed Extensibility Framework .
Here's another article about it MEF on codeproject.
It is used to load dll's in runtime by composing them. This is what is usually used for plugins or anything else you kinda drop into a folder and expect it to run .
Here's a link to some more tutorials as well: Where can I learn about MEF?
Yes, you're right, it is not possible to simply unload an assembly (only AppDomains). But I think one of the features of ASP.Net vNext is the ability to have just in-memory assemblies and when you simply alter the source code on the drive it gets automatically compiled and loaded. Therefor a mechanism must exist to unload the previous version.
I think they are doing that by simply creating a AppDomain where all assemblies are loaded into again to avoid any cross domain communication. But i don't really know and maybe if you would dig more into the mechanism on how they do this stuff in ASP.NET you maybe find a good solution. More informations about the hot topics from vNext you can maybe also find at Scotts Blog.
Well, I've found 2 solutions that work for me, which I would like to share. The first one is to use CollectibleAssembly and define the types. This is certainly a bit tricky, and a number of restrictions are imposed on this type of dynamic assembies.
The other option is to use a scripting language like IronPython or IronRuby. Also a great feature of the new Roslyn compiler is that it also provides scripting APIs, not previously available in the .NET framework. What's more, the Roslyn scripting languages tend to look very much like their full-blown equivalents (C# or VB). And I've also found a tiny example of its capabilites.
I want to use ironpython inside my C# App, but I am afraid that it will cause a security issue, I don't want the end user to use all the available DLLs of my App, instead I want to provide custom classes that user can use in python.
My question is how to secure my dlls from being used in ironpython.
the end user may addReference of the dll, I want to secure most of the classes from being used.
The trick is to run IronPython in its own AppDomain and only provide the assemblies you want the user to be able to call to that AppDomain, and then set the security policy to prevent them from referencing more.
What recommendations can you give for a system which must do the following:
Load Plugins (and eventually execute them) but have 2 methods of loading these plugins:
Load only authorized plugins
(developed by the owner of the
software)
Load all plugins
And we need to be reasonably secure that the authorized plugins are the real deal (unmodified). However all plugins must be in seperate assemblies. I've been looking at using strong named assemblies for the plugins, with the public key stored in the loader application, but to me this seems too easy to modify the public key within the loader application (if the user was so inclined) regardless of any obfuscation of the loader application. Any more secure ideas?
Basically, if you're putting your code on someone else's machine, there's no absolute guarantee of security.
You can look at all kinds of security tricks, but in the end, the code is on their machine so it's out of your control.
How much do you stand to lose if the end user loads an unauthorised plugin?
How much do you stand to lose if the end user loads an unauthorised plugin?
Admittedly this won't happen often, but when/if it does happen we lose a lot and I although I understand we will produce nothing 100% secure, I want to make it enough of a hindrance to put people off doing it.
The annoying thing about going with a simple dynamic loading with full strong name, is that all it takes is a simple string literal change within the loader app to load any other assembly even though the plugins are signed.
you can broaden your question : "how can I protect my .net assemblies from reverse engineering ?"
the answer is - you can not. for those who havent seen it yet, just look up "reflector", and run it on some naive exe.
(by the way, this is always the answer for code that is out of your hands, as long as you do not have en/decryption hardware sent with it),
obfuscating tries to make the reverse engineering to be harder (cost more money) than development, and for some types of algorithems it succeeds.
Sign the assemblies.
Strong-name signing, or strong-naming,
gives a software component a globally
unique identity that cannot be spoofed
by someone else. Strong names are used
to guarantee that component
dependencies and configuration
statements map to exactly the right
component and component version.
http://msdn.microsoft.com/en-us/library/h4fa028b(VS.80).aspx