loading embedded resources which live in a different assembly - c#

I have a Visual Studio 2015 solution which consists of an executable and a series of DLL projects. All code is managed C# and running on Windows 10 64-bit.
One of the DLLs needs to load a resource specified by the application. The app provides the full manifest resource path and the DLL uses this to load it.
The resources are set as "Embedded Resource" in solution explorer. An example path would be something like "The.DLL.Assembly.subdir.resources.image.png".
The DLL uses the below code to load the resource.
var asm = Assembly.GetExecutingAssembly();
var resStream = asm.GetManifestResourceStream(path);
This works great! Well, that is if the resource in question is stored inside the DLL assembly which is trying to load it. We'd prefer, though, not to have to locate all the resources in this DLL assembly. We'd like the freedom to let the application locate them in any of the projects and just provide the path letting the loading DLL know how to find them. This would allow the app to better organize the resources based on which project "owns" them as opposed to being forced to put them all in the assembly which will actually load them.
Where I'm stuck is being able to load the resource if it lives in another assembly.
I've tried:
GetEntryAssembly(), this returns the executable assembly, but loading the resource fails even with the full path, it appears GetManifestResourceStream() will only look in that assembly
GetEntryAssembly().GetModules(), thinking I could somehow find the other assembly this way, but this returns a single entry, just the exe itself
Any ideas? I'm thinking there must be a way to load an embedded resource which lives in another assembly, but I haven't yet found it.

Related

Could not load type 'myinterface' from assembly

I have a solution that includes several projects. A few are libs that are building dll's used in my main project in this solution.
My main project builds with output type console application.
This all works fine.
When i change the build output type to a class library (since i want to use this project as a plugin eventually). The project will still build, this time to a dll.
When i use this plugin in an application where i use it as a dll however, it will run up to a certain point where it's trying to load a type defined in an external dll (so NOT built by my solution) and throw the exception:
Could not load type 'externalinterface' from assembly 'externallib, version=3.0.0.0, Culture=neutral, PublicKeyToken=null'.
The dll's are all in the correct folder,etc.
Also worth noting, the plugin is tested in another location than where i built it. The executable still works on this location, the dll/plugin does not. Same amount of dll's in their folders etc.
EDIT: I already used ILSpy (dll inspector) to open the actual dll that is being referenced (so externallib in the errormessage) and checked if 'externalinterface' was present and it is.
EDIT2: RESOLVED! The program that loaded my plugin was loading the same dll that caused the exception. The dll it loaded was of another version than the one i loaded.
Check whether the type externalinterface is present in the referred dll.
You didn't include the details of the exception the application is throwing. However, based on the message you gave, it appears your assembly does not have a strong name. If the application attempting to load your assembly as a plugin does have a strong name, then .NET will require all assemblies loaded by it also have a strong name, so you need to configure your assembly to have a strong name before continuing.
Maybe some supported dll's which is used by the 'externalinterface' is missing in the target machine. In the target machine, check is all the necessary dll's are present in the output folder.
Or blindly copy paste all the dlls in the output folder from the machine where the code is working to the target machine where you have the problem. After this, if the code is working in the target machine, then try to analyze which supporting dll you are missed to copy.

Access resource within the calling assembly

I'm moving some code from an application to a helper class project. This application uses resource files that hold texts and their translations.
Is there a way to still access the resource files from the application within that new helper project? This would be very helpful, because then i don't have to move half of those resource files to that new project.
Assembly A (contains the resource file) -> Calls method on Assembly B and this method needs a resource text from Assembly A.
You could use Assembly.GetEntryAssembly().GetFile() method in dll to get the file from application assembly and use ResourceManager class to load it. Or possibly use Assembly.GetEntryAssembly().GetExportedTypes() to get strongly typed resource class. However, you should consider if referencing resources in application from library is the right approach. I would suggest either moving all resources to library assembly and referencing them from application, or (probably the best) - create separate assembly only for resources and use it both from app and dll.

From where is my silverlight application dll is loaded/used during debugging?

I've created a new Silverlight 3 from template and started a debugging session. However, when I looked to the modules window I saw the following:
The path to my Silverlight3Application.dll was lacking (even though the pdb was found just fine). I made sure that it isn't just a UI issue, indeed I could delete the Silverlight3Application.dll file that was located next to the PDB just fine without any issues.
Questions:
Where is my DLL actually loaded from UPDATE in runtime?
Why isn't it loaded from the expected location?
Is it possible to make it load from the location next to the PDB file, where I actually expected it to load from?
Update 1
What I really need is to find out the location of my Silverlight3Application.dll in runtime, using Reflection, for example.
However, just as the modules window hides the real location, so does reflection:
Assembly: {Silverlight3Application, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null} System.Reflection.Assembly {System.Reflection.RuntimeAssembly}
FullName: "Silverlight3Application, Version=1.0.0.0, Culture=neutral,
publicKeyToken=null" string
ImageRuntimeVersion: "v2.0.50727" string
IsDynamic: false bool
Location: "" string
I've tried located this assembly manually using Prcocess Explorer and its location seemed rather random:
C:\Users\Vitaly\AppData\Local\assembly\dl3\G1KDTYO5.XJ3\6GQ19BER.4OW\5e5cbf28\50366acf_1a3ecc01\Silverlight3Application.dll
Anyone knows how I can find the location of the assembly in runtime? If nothing else works, using external tools is an option, however, I must be able to execute the tool from code. I'll be happy to hear ideas.
Thanks!
By default, Silvelight DLL is located in \Bin\Debug of your Silverlight project.
If you want to see where an actuall DLL is loaded from:
output path is visible in Visual Studio Output Window during build
use ProcessMonitor.
Also see http://msdn.microsoft.com/en-us/library/cc838164%28v=vs.95%29.aspx for detailed description of Silverlight project structure.
To your Update1: see How do I get the path of the assembly the code is in?
Have you considered how the assembly is actually executed in your browser? It comes from a .XAP file, not via any DLLs built/stored under your project folders. More specifically, your project builds a DLL, which is then packaged into the XAP file, which is in turn served to your web browser, which unpacks the XAP file, reads the manifest, and loads the specified DLL entry point.
The path to the DLL from the XAP root is, well, the file name (unless you've done customized the XAP yourself). That's probably why there isn't any path specified.

Resource file shared as external file between solutions

I have two solutions, a solution named Server and a solution named Client. The Server contains a resources file named Server.Properties.Resources. That file is added to the Client solution as an external file.
When I debug inside Visual Studio, everything runs great. When I run the deployed version, I get the error
System.Resources.MissingManifestResourceException:
Could not find any resources appropriate for the specified culture or the neutral culture.
Make sure "Aexeo.DataLayer.Properties.Resources.resources" was correctly embedded or
linked into assembly "Core" at compile time, or that all the satellite assemblies required
are loadable and fully signed.
Is there a way to resolve this, maintaining the usage of the external file link?
I think this is what exactly you are looking for :
http://support.microsoft.com/kb/839861
The problem is caused when you manually create satellite assemblies. Satellite assemblies should be named in such a way that it could automatically be called from the application. To solve the issue you can use Assembly linker al.exe to link the assembly to the application properly.

.NET Load assemblies at runtime Again

I posted a similar question a time ago. I need to load an assembly at runtime.
This is easy if I know the absolute path of the dll at runtime.
But I dont :( The assembly.Load() or LoadFromFile() fails if the file is not in the application root.
The only thing I have is the dll name. The dll could be located in the root, system32 or in even in the GAC.
Is it possible for .net to automatically determine where the dll is at, like for example :
it should first look in the root. If its not there move on to the system folders, else try the GAC.
EDITED
I am using plug-in architecture. I do not need to register the dll. I have a multi user application. I have a applications table containing information regarding applications. Each application has a dll path associated with it, containing certain algorithms associated with that app. Hope this helps.
I hope you've read up on the following. My suggestion...
How the runtime locates assemblies
You can give Assembly.LoadWithPartialName a whirl.. might work.. it says it will search the application folder and the GAC unlike Assembly.Load. (However its less safe.. coz you might end up with the wrong version of the DLL since you dont specify all 4 parts of the Assembly Name)
Also try AppDomainSetup.PrivateBinPath (AppDomain.AppendPrivatePath has been deprecated in favor of this) to add subfolders of the application root to the list of folders to probe assemblies for. You can also try copying over files from other places into a [AppFolder]\MySandboxForDLLsToLoad, which is added to the PrivateBinPath.
When the current application looks for assemblies, it looks in several locations (bin folder, gac, etc..) if it can not find one, then the developer needs to manually tell the application where to look. You can do this by intercepting the AssemblyResolve event, and using the event args to tell the CLR where your assembly is.
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
....................
Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var strTempAssmbPath=
Path.GetFullPath("C:\\Windows\\System32\\" + args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll");
var strTempAssmbPath2=
Path.GetFullPath("C:\\Windows\\" + args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll");
if (File.Exists(strTempAssmbPath))
return Assembly.LoadFrom(strTempAssmbPath);
if (File.Exists(strTempAssmbPath2))
return Assembly.LoadFrom(strTempAssmbPath2);
}
You can hook up into AppDomain.CurrentDomain.AssemblyResolve event and load the assembly for your application manually on demand.
Yes there is a way and it depends on whether your dll is weakly(without a public key token) or strongly(with a public key token) named. If its weakly named and you have added a reference to the assembly with the dll within VS, then VS will first look in the application folder root and if it does not find it, it will then look in the subdirectories that you specify as the value of the privatePath attribute in your XML config file.
If its a strongly named dll, then the CLR will search in the GAC so you need to install the dll in the GAC. The CLR can also look in the application directory if you install an XML config file that has its codeBase element pointing to the dll's path.
To specify an assembly in the GAC you can use the /reference:[DLL name] switch when compiling your assembly.
The dll will be found automatically is it is in some location referenced in the PATH system variable (i.e., system32) or if the dll is registered. You can't find it if it can be anywhere on disk, but no one needs that functionality anyway.
EDIT: can the dll's be registered? how are you getting the assembly name if you don't know of the assembly ahead of time? Are you creating some type of plug-in architecture? I think it would help if you explained your situation a bit more.
EDIT2: If that is the case, why not provide a way for the user to register his or her plug in? You can get all the information that you need from an open file dialog. That or simply make them dump it into a folder that you specify.
You have three options
Install the assembly in the global assembly cache (GAC)
Use an application configuration (.config) file with the tags
Use the AssemblyResolve event
You can find the details here.
The resolution algorithm used by .NET to find the assemblies and their dependents is straight forward.
.NET identifies the required version. Usually the information about the dependant assemblies is present in the application's assembly manifest.
.NET searches GAC (Global Assembly Cache), only if the assembly is strong named.
If not found in GAC, and if a .config file presnt, then .NET searches the location specified in the cofiguration file, else .NET searches directory containing the executable (.EXE)
After this, If the assembly is still not found, the application terminates with error.
Click here for the video explaining the .net resolution algorithm, and click here for a video on late binding assemblies
Register this assembly into the GAC. How to do that
Use this
Assembly.LoadWithPartialName(assemblyName);

Categories