F# newbie here, spent many painful hours trying to resolve the errors with a simple piece of code from MSDN F# tutorial.
#r "Microsoft.Office.Interop.Excel.dll"
// fails with invalid/not found errors
#r "Microsoft.Office.Interop.Excel" // works like a charm.
Any F# gurus know why?
"Microsoft.Office.Interop.Excel.dll" is the name of a file (inferred, because of the .dll suffix). When you supply a file name, #r will look for that file in the file system. Since you didn't supply a path, it'll look in your present working directory. Most likely, "Microsoft.Office.Interop.Excel.dll" isn't in your working directory. This explains why the first example fails.
"Microsoft.Office.Interop.Excel", on the other hand, is inferred to be the name of an assembly (because there's no file extension). Assemblies are libraries, and are normally distributed in .dll files. They don't have to, though; they can, for example, be dynamically emitted at run-time. Additionally, a .dll file can technically contain more than a single assembly, although I've never seen this in the wild. The most normal case is that a .dll file contains a single assembly, and that the name of the file corresponds to the name of the assembly.
When you request to load an assembly, the .NET assembly loader (called Fusion) starts looking for an assembly with the requested identity. It'll start looking in the Global Assembly Cache, and my guess is that it finds the "Microsoft.Office.Interop.Excel" assembly there. This explains why the second example succeeds.
Related
Is there anyway within Visual Studio / TFS to identify which project produces which dll?
I'm aware you can look under a particular project's properties and see what the name of the dll is, but in the circumstance where you have loads and loads of projects this doesn't seem very efficient.
I've got the situation where I've got a project that references a dll, which includes a method I want to examine, but I don't know what project produces this dll.
Unfortunately, no. The only way I know is that you may could use a decompile extension. (Strongly not recommend to use) Through the source code after decompile, you can view namespace and judge which project produces the dll. (Under normal circumstances)
And you may also have to face some problems such as:
Legal issues
Need to pay for the extension
Only work for C#/.Net
The source code may be confusion and not standard
This should be a one time activity, you can go ahead and take a look into the project file, in case of C# project the csproj file.
If you do not want to do it opening each file, then i would say write a small tool to read all the project files and look for the name.
BTW, this will be different for different projects, and you need to find out the proper location to look.
Whatever I download, source code, e.g. NHibernate, or .dll file, e.g. NHibernate.Caches.SysCache, there are the .snk file.
What does this mean?
For source code, I just delete the snk file and compile them directly, it works. But is there anything I do wrong? I don't use the snk file.
For dll file, I found problem on version.
Assemblies can be assigned a cryptographic signature called a strong name, which provides name uniqueness for the assembly and prevents someone from taking over the name of your assembly (name spoofing). If you are deploying an assembly that will be shared among many applications on the same computer, it must have a strong name.(msdn)
With snk file included in a project, you can able to generate PublicToken for your dll.
I have a program which stores plugins in multiple directories, like so:
root/
core/bin/
app.exe
core.dll
plugin.dll
support.dll
a/bin/
a.dll
a_support.dll
In this example, a.dll imports core.dll, support.dll, and a_support.dll (they are in that order in the import table). a_support.dll imports support.dll. I can change all but the support modules, those are redists of a third-party library.
My code calls LoadLibraryEx(name, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) to load each plugin. For core.dll and plugin.dll, this works fine.
When I try to load a.dll, it fails saying a_support.dll was not found. No errors about core.dll or support.dll, perhaps because they're already in memory.
My suspicion is that when a_support.dll is loaded, support.dll cannot be found, but this seems unusual as a.dll appears to import support.dll before a_support.dll.
Is this layout of modules even possible to use? Will the system be able to use the already-loaded support DLLs, or will it go searching for them and fail? Would there be a way to handle this through manifests? Is there a way to make this work, or will I have to relocate all modules into a single directory?
Edit: At Adrian McCarthy's suggestion, I ran the loading sequence with Process Monitor tracking, and it seems that when I call LoadLibrary("root/a/bin/a.dll", ...), it starts by searching the root directory, then system directories, then down through the path. For some reason, it never searches a/bin/, which it very much should.
I double-checked the paths, and noticed that my calls to load plugin.dll where using the wrong path (root, instead of root/core/bin). Either way, core.dll was loading correctly. After fixing that, I tried it again and this time a.dll does find a_support.dll and seems to load. However, that makes absolutely no sense, unless the loader is successfully using support.dll from... somewhere. The procmon log doesn't show it even attempting to load support.dll again, so I'm not entirely sure at this point if there actually is a problem (besides behavior from the loader that makes no sense).
I suggest using Process Monitor to see what's really happening. You'll see if it's looking in the right place, whether a_support.dll is opened but not loadable because something else is missing, etc.
Certainly one solution would be to place all DLLs in the same directory, the same directory as the .exe. If you can bring yourself to do that it would be the simplest approach for sure.
If not then you will have a bit more work on your hands. I guess you are expecting that the loader will search in the directory where the DLL lives. Sadly it doesn't. Instead the loader will look first in the executable file's directory, and then the rest of the DLL search order. This is why a_support.dll fails to load, because it is not in the same directory as the executable.
The fact that modules are already in memory is beside the point. The loader goes looking for the file. When it finds the file that it wants it then checks to see if it is already loaded. If so then it simply bumps the reference count to that module. Otherwise it loads it into the process.
You could switch to using LoadLibrary for all DLL loads and always being explicit about the path. That's probably inconvenient.
You could use side-by-side assemblies but that doesn't sound very compatible with a plugin architecture.
So I think the main remaining option is SetDllDirectory. Call this just before you load the plugin. You only need to add a/bin to the search path since the rest of the modules are in the executable directory and so will be found without trouble. Restore this setting to its default by calling SetDllDirectory again, passing NULL, once the plugin has loaded and resolved all of its imports.
If you have multiple sub-directories then use AddDllDirectory.
This is a rather confusing application.
Some questions then:
Which dll's does app.exe implicitly import?
core.dll is both implicitly loaded by a.dll AND as a plugin via LoadLibraryEx?
How was the call to LoadLibraryEx on /plugin.dll ever succeeding? If the path was FQ and did not point at an actual dll, LoadLibrary should have failed outright on that dll.
I can't tell if you're giving sample code or real code. You wrote:
LoadLibrary("root/a/bin/a.dll", ...)
If that's the real code, there are two problems here.
First, LoadLibrary doesn't do what you'd expect with a relative path. From MSDN:
To load a module from a relative path without searching any other
path, use GetFullPathName to get a nonrelative path and call
LoadLibrary with the nonrelative path. For more information on the DLL
search order, see Dynamic-Link Library Search Order.
Basically, you give it a full path and get that file, or you let it search for a name in all the "usual" locations. If you give it a relative path, it basically ignores that path, grabs the name, and looks in the usual locations.
If you really meant LoadLibraryEx, note that when you use LOAD_WITH_ALTERED_SEARCH_PATH you get "undefined behavior" if handed a relative path. Again quoting MSDN:
If this value is used and lpFileName specifies a relative path, the behavior is undefined.
Second, you have forward slashes instead of backslashes. Neither LoadLibrary nor LoadLibraryEx likes those.
The question is pretty much in the title: in terms of OS-level implementation, how are shared objects and dlls different?
The reason I ask this is because I recently read this page on extending Python, which states:
Unix and Windows use completely different paradigms for run-time loading of code. Before you try to build a module that can be dynamically loaded, be aware of how your system works.
In Unix, a shared object (.so) file contains code to be used by the program, and also the names of functions and data that it expects to find in the program. When the file is joined to the program, all references to those functions and data in the file’s code are changed to point to the actual locations in the program where the functions and data are placed in memory. This is basically a link operation.
In Windows, a dynamic-link library (.dll) file has no dangling references. Instead, an access to functions or data goes through a lookup table. So the DLL code does not have to be fixed up at runtime to refer to the program’s memory; instead, the code already uses the DLL’s lookup table, and the lookup table is modified at runtime to point to the functions and data.
Could anyone elaborate on that? Specifically I'm not sure I understand the description of shared objects containing references to what they expect to find. Similarly, a DLL sounds like pretty much the same mechanism to me.
Is this a complete explanation of what is going on? Are there better ones? Is there in fact any difference?
I am aware of how to link to a DLL or shared object and a couple of mechanisms (.def listings, dllexport/dllimport) for writing DLLs so I'm explicitly not looking for a how to on those areas; I'm more intrigued as to what is going on in the background.
(Edit: another obvious point - I'm aware they work on different platforms, use different file types (ELF vs PE), are ABI-incompatible etc...)
A Dll is pretty much the same mechanism as used by .so or .dylib (MacOS) files, so it is very hard to explain exactly what the differences are.
The core difference is in what is visible by default from each type of file. .so files export the language (gcc) level linkage - which means that (by default) all C & c++ symbols that are "extern" are available for linking when .so's are pulled in.
It also means that, as resolving .so files is essentially a link step, the loader doesn't care which .so file a symbol comes from. It just searches the specified .so files in some order following the usual link step rules that .a files adhere to.
Dll files on the other hand are an Operating system feature, completely separate to the link step of the language. MSVC uses .lib files for linking both static, and dynamic libraries (each dll file generates a paired .lib file that is used for linking) so the resulting program is fully "linked" (from a language centric point of view) once its built.
During the link stage however, symbols were resolved in the lib's that represents the Dlls, allowing the linker to build the import table in the PE file containing an explicit list of dlls and the entry points referenced in each dll. At load time, Windows does not have to perform a "link" to resolving symbols from shared libraries: That step was already done - the windows loader just loads up the dll's and hooks up the functions directly.
Background
I'm maintaining a plugin for an application. I'm Using Visual C++ 2003.
The plugin is composed of several DLLs - there's the main DLL, that's the one that the application loads using LoadLibrary, and there are several utility DLLs that are used by the main DLL and by each other.
Dependencies generally look like this:
plugin.dll -> utilA.dll, utilB.dll
utilA.dll -> utilB.dll
utilB.dll -> utilA.dll, utilC.dll
You get the picture.
Some of the dependencies between the DLLs are load-time and some run-time.
All the DLL files are stored in the executable's directory (not a requirement, just how it works now).
The problem
There's a new requirement - running multiple instances of the plugin within the application.
The application runs each instance of a plugin in its own thread, i.e. each thread calls functions exported by plugin.dll. The plugin's code, however, is anything but thread-safe - lots of global variables etc..
Unfortunately, fixing the whole thing isn't currently an option, so I need a way to load multiple (at most 3) copies of the plugin's DLLs in the same process.
Option 1: The distinct names approach
Creating 3 copies of each DLL file, so that each file has a distinct name. e.g. plugin1.dll, plugin2.dll, plugin3.dll, utilA1.dll, utilA2.dll, utilA3.dll, utilB1.dll, etc.. The application will load plugin1.dll, plugin2.dll and plugin3.dll. The files will be in the executable's directory.
For each group of DLLs to know each other by name (so the inter-dependencies work), the names need to be known at compilation time - meaning the DLLs need to be compiled multiple times, only each time with different output file names.
Not very complicated, but I'd hate having 3 copies of the VS project files, and don't like having to compile the same files over and over.
Option 2: The side-by-side assemblies approach
Creating 3 copies of the DLL files, each group in its own directory, and defining each group as an assembly by putting an assembly manifest file in the directory, listing the plugin's DLLs.
Each DLL will have an application manifest pointing to the assembly, so that the loader finds the copies of the utility DLLs that reside in the same directory. The manifest needs to be embedded for it to be found when a DLL is loaded using LoadLibrary. I'll use mt.exe from a later VS version for the job, since VS2003 has no built-in manifest embedding support.
I've tried this approach with partial success - dependencies are found during load-time of the DLLs, but not when a DLL function is called that loads another DLL.
This seems to be the expected behavior according to this article - A DLL's activation context is only used at the DLL's load-time, and afterwards it's deactivated and the process's activation context is used.
Edit: Works with ISOLATION_AWARE_ENABLED as expected - runtime loading of DLLs uses the original activation context of the loading DLL.
Questions
Got any other options? Any quick & dirty solution will do. :-)
Will ISOLATION_AWARE_ENABLED even work with VS2003? Edit: It does.
Comments will be greatly appreciated.
Thanks!
ISOLATION_AWARE_ENABLED is implemented by the Windows SDK header files and thus probably wont worth with VS2003 at all. However, it is possible to download the latest Windows 7 SDK and use that with VS2003.
You don't need to use MT to link in manifests. Manifests can be embedded as resources in environments that dont have explicit knowledge.
Add the following to a dll's .rc file to embed a manifest. (With a recent enough platform sdk RT_MANIFEST should already be defined):
#define RT_MANIFEST 24
#define APP_MANIFEST 1
#define DLL_MANIFEST 2
DLL_MANIFEST RT_MANIFEST dllName.dll.embed.manifest