.Net: Does dynamically loading an Assembly also load it's config? - reflection

If in my project's execution/bin folder I have the following files:
MyDynamicLibrary.dll
MyDynamicLibrary.dll.config
and in my application I have this:
Assembly assembly = System.Reflection.Assembly.Load("MyDynamicLibrary");
if I invoke a method from this assembly object, will it have already loaded the information in the MyDnamicLibrary.dll.config? If not, is there a way to load it so the dll functions correctly? Or do I need to add the information in MyDynamicLibrary.dll.config to my application's .config file?

Quoting a previous answer:
"[...] the configuration file being read is the configuration file of the hosting executable." (Hans is right on his previous comment)
Please check this question; you'll probably also want to take a look on Microsoft's Best Practices for Assembly Loading.
Best,
Arthur

Related

Is there a way to run code when an assembly loads?

I'm building an application that will load untrusted assemblies for inspection (i.e. retrieval of the assembly full name). For security reasons, I'm trying to think of a way that these assemblies could be written that would allow them to execute code when loaded. I haven't code up with a method yet, but wanted to throw it out here to see if anyone could.
I'm aware that I could load these assemblies into an untrusted app domain, effectively stopping them from doing almost anything, but I wanted to avoid the complexity if it's un-needed.
Specifically, I will be calling Assembly.Load and <LoadedAssebmly>.FullName. Maybe there's a better way to load the assembly name without using the Assembly class?
Thanks,
Matt
First of all, there's the AssemblyName class. It allows you to find the assembly's name without loading it. Second, you can load assemblies using Assembly.ReflectionOnlyLoad, which uses the reflection-only context -- no code can be executed from such an assembly.
Yes, it is possible: .Net: Running code when assembly is loaded
I suggest, you use a method to inspect the assembly, that doesn't load it, i.e. Mono.Cecil

Satellite assembly is not picked up by ASP.NET app

I have a web project called "TestResourceApp" with Labels.resx in App_GlobalResources folder. I want to add another language by creating a satellite assembly.
Here are the steps I took to create the satellite assembly. The default text always get displayed. What did I do wrong ?
1) Create Labels.fr.resx in a different folder.
2) Generate resource file:
Resgen Labels.fr.resx TestResourceApp.App_GlobalResources.Labels.fr.resources
3) Generate satellite assembly:
AL /t:lib /embed:TestResourceApp.App_GlobalResources.Labels.fr.resources /out:french.dll /c:fr
4) Copy french.dll to TestResourceApp/bin/fr
I have uiculture set to auto in web.config and I have change the language on the browser.
I was able to use this page to solve some satellite assembly issues I was having. I'll throw in a few more things to check.
It's helpful to decompile the "neutral" assembly and see how it's put together. A tool like ILDASM.exe is helpful for this purpose. Once you get it decompiled, look through the text output for ".mresource", and you should see one with your naming. For example, if you add a resource to a Visual Studio project, they're named MyAssemblyName + ".Properties.Resources" + a language (if any) + ".resources" Examples:
MyAssembly.Properties.Resources.resources (neutral language)
MyAssembly.Properties.Resources.en-US.resources (English (US))
In my case, I had the file named properly, and in the appropriate folder (such as Bin\en-US). I was able to verify that much by using ProcMon.exe (by the SysInternals guys) and could see the worker process finding and reading in my DLL file (instead of just saying "PATH NOT FOUND"). However, it was not finding the resource by the name that it expected it to. That's when some disassembly helped to get to the bottom of the naming problem.
So, use ProcMon.exe to narrow down the kind of problem you might have. Hopefully that's helpful to someone.
It's complicated but here are a few tips for those who run into this problem:
Try to include the resx in the web project and let VS do the job for you.
Reflector is your friend. Compare satellite assemblies you created and those created by VS.
If you web app is targetting ASP.NET 2.0, you should use Resgex and AL that come with .net 2.0. Open the assemblies in Reflector and check the "references". It should reference mscorlib version 2.0.
If you deploy your web app using web deployment project, make sure the namespace for the resources in your satellite assemblies is correct. Again, compare with what VS creates. In my case, I used the wrong tool to generate the designer.cs file because I wanted them to be accessible from a different assembly. Make sure you are using GlobalResourceProxyGenerator. Otherwise, the namespaces won't match and the deployment code will not be able to find your resource. The namespace in the designer.cs should simply be "Resources", not "XXXX.App_GlobalResources"
Did you have set enableClientBasedCulture to true in globalization ?

ASP.NET - what files store method signature for xml web service?

i find this question tricky but what files store method signature info for xml webservice?
.dll, .asmx, .wsdl, .disco ?
TIA
It goes into a DLL once compiled, but it's in a code file when added to the project (referred to as a proxy class, it's in whatever language your project is). When you add a web reference it's imported this way. Updating the reference updates the .cs (or vb, whatever you're using).
If you want to see what happens, you can generate the code file yourself, see MSDN for details.
So overall: It is WSDL when fetched, converted to a code file when included (or updated), then finally compiled with the rest of your code into the DLL.

How do I reference assemblies outside the bin folder in an ASP.net application?

I've a working XML Web service written in ASP.Net. Now I need to reference certain assemblies lying in a specific folder e.g. c:\NotMyCode
I do not want to copy/duplicate zillions of dlls in that folder into my bin folder.
I tried to keep the CopyLocal=false for the assemblies referred in the Web Service. That ended up in a FileNotFound exception for the assembly.
When I switch to CopyLocal=true, the referenced DLLs are copied over to the bin folder.. and it works.
So my question here is:
How do I reference assemblies that do not lie in my bin folder or a subfolder beneath it ? Do I need to change some security policy files somewhere? I think I'm not the first person to ever want to do something like this.. so I'm assuming someone has already solved this problem.
(I've tried impersonating an admin user in the IIS ASP.net configuration panel, but that didnt work either.)
Update: Can't install it in the GAC either. To give an analogy, this web service is giving a simplified view to a third party app e.g. Starteam. I can't (shouldn't have to.. don't want to..) copy all the binaries in that folder to the bin folder or install it into the GAC
According to the MSDN documentation,
Referenced assemblies outside the application's root directory must have strong names and must either be installed in the global assembly cache or specified using the <codeBase> element.
So, it might appear that you're out of luck. Here's what I'd try:
Create an NTFS junction point under your application base directory which points to the directory containing your shared code. This is the key step. For example, in your application base directory, run linkd SharedCode c:\NotMyCode. This makes <yourappbase>\SharedCode effectively be an alias for c:\NotMyCode.
Tell ASP.NET to probe for assemblies in this path, using a <probing> element, referencing the junction point SharedCode. Since this is under your application base, it should work. Alternatively, use AppDomainSetup.PrivateBinPath to set the path probed for assemblies.
I'm quite curious to see if this works :-)
You could always use the:
AppDomain.CurrentDomain.AssemblyResolve Event
and call
Assemly.Load(Path.Combine(#"c:\NotMyStuff",args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll"))
See link for more info.
You could always put your referenced assemblies in the GAC, then the location would not matter. You can install the component by dragging it into the GAC (C:\windows\assembly) or running GACUtil.exe.
This article may help. It describes the "Best Practices for Assembly Loading."
At first I thought you could used the <probing privatePath="bin\debug"/> element in the runtime/assemblyBinding in the web.config, but the probing will only allow you to specify subdirectories under the root location.
I think you can reference specific assembly paths in code as well.
AppDomain.CurrentDomain.AppendPrivatePath("C:\\NotMyCode");
Doing that in your Global.asax Application_Start should do the trick.
You can put in GAC and access it from there.

Load XmlTextReader from a file in my web app via a method in another DLL

I am creating a method in a DLL that is going to be dropped into a web application.
The web application has a folder with a XML file in it:
/files/myfile.xml
My dll has to reference that DLL, but I can't hard code the path to the file obviously.
How can I reference that file and load a XmlTextReader with that file?
The best thing would be to have the path to the XML file be stored in a configuration file. Since both of your assemblies will be running in the same AppDomain they will both have access to the setting in the configuration file and you don't have to worry about hard-coding the path.
The simplest way that comes to mind would be to pass a filename parameter to the DLL's method from the web application. I'm sure you've already thought of this, but your question doesn't say what (if any) problems exist with that solution.

Resources