How to get the physical file name of running class library - c#

I'm trying to create a class library which will load different files depending on its physical file name.
i.e. if physical file name is called "test.dll" it will load its settings from "test.config", if the file is duplicated and renamed to "copy.dll" then it will load its settings from "copy.config"....
System.Diagnostics.Process.GetCurrentProcess();
//doesn't work as I'm loading the dll's dynamically into a console application and calling their methods.
Any ideas?

string filePath = typeof(SomeAssemblyMemberType).Assembly.CodeBase;
CodeBase property returns absolute path to the loaded manifest-containing file, or if assembly was loaded using Load method, returns path to assembly in which loader method is.
For example if you had the following code in a class object in your DLL:
public class Grace
{
public Grace() {}
public string AbsoluteFileName
{
get {
return this.GetType().Assembly.CodeBase;
}
}
}

Use Assembly:
string filePath = System.Reflection.Assembly.GetCallingAssembly().Location;

Related

Search priority for views using EmbeddedFileProvider

I'm have this code pulling views embedded as resource in my referenced assembly:
services.Configure<RazorViewEngineOptions>(options =>
{
options.FileProviders.Add(new EmbeddedFileProvider(typeof(SomeTypeInMyAssembly).GetTypeInfo().Assembly));
});
It successfully finds views in the embedded location (Views\Shared\Components\ViewComponentName\Default.cshtml). I need it to FIRST search for the files in the current project BEFORE looking at any assemblies, this way I can create defaults in an assembly, and allow "overrides" in the main project (same path). Anyone have any ideas how this can be done? I'm still trying to look through the source to figure this out.
And no, ViewLocationExpander is not the answer. I need to use the exact same path and file names, thanks.
Turns out there are TWO options:
Add
options.FileProviders.Add(HostingEnvironment.ContentRootFileProvider);
just before EmbeddedFileProvider. (HostingEnvironment was simply taken
from the Startup() constructor and stored locally in the Startup class. The physical file on disk (could also be in the cache) will be found before the assembly version.
Wrap EmbeddedFileProvider in your own type (implement IFileProvider) and pass in IHostingEnvironment. The GetFileInfo() method is
called while trying to locate files. The
IHostingEnvironment instance is used to detect physical
files from the root content path, and returns NotFoundFileInfo if a local file exists:
public virtual IFileInfo GetFileInfo(string subpath)
{
if (_HostingEnvironment != null)
{
var filepath = Path.Combine(_HostingEnvironment.ContentRootPath, subpath.TrimStart('/'));
if (File.Exists(filepath))
return new NotFoundFileInfo(filepath);
}
return _EmbeddedFileProvider.GetFileInfo(subpath)
}
and add it to Startup.ConfigureServices():
services.Configure<RazorViewEngineOptions>(options =>
{
options.FileProviders.Add(new MyEmbeddedFileProvider(typeof(SomeTypeInTheTargetAssembly).GetTypeInfo().Assembly, HostingEnvironment));
});
}

AppDomain exception is thrown

I've found a lot of similar questions but couldn't find any solution.
I have following code:
string file = "c:\\abc.dll";
AppDomainSetup ads = new AppDomainSetup();
ads.PrivateBinPath = Path.GetDirectoryName(file);
AppDomain ad2 = AppDomain.CreateDomain("AD2", null, ads);
ProxyDomain proxy = (ProxyDomain)ad2.CreateInstanceAndUnwrap(typeof(ProxyDomain).Assembly.FullName, typeof(ProxyDomain).FullName);
Assembly asm = proxy.GetAssembly(file); // exception File.IO assembly not found is thrown here after succesfully running the funktion GetAssembly.
public class ProxyDomain : MarshalByRefObject
{
public Assembly GetAssembly(string assemblyPath)
{
try
{
Assembly asm = Assembly.LoadFile(assemblyPath);
//...asm is initialized correctly, I can see everything with debugger
return asm;
}
catch
{
return null;
}
}
}
The most Interesting thing that then my GetAssembly funktion returns some other type, even my custom serializable class, everything is fine. Does someone know what I'm missing? Or It's just impossible to return loaded assembly to another domain?
Thank you
I imagine File.IO is sitting in your main application's bin directory? If so, your abc.dll will not know where to find it (unless your main application is also sitting in C:\\).
You need to do one of
Bind to the AppDomain.AssemblyResolve event and manually load the referenced dll
Change the AppDomainSetup's base directory (which is one of the places .NET knows to look for dlls)
Install File.IO to the GAC (which is another one of the places .NET knows to look for dlls)
Add the location of File.IO to your AppDomainSetup's private probing path (which is another one of the places .NET will try to look for dlls).

Why doesn't my ScriptReference find the Embedded Resource?

I have an AJAX control project that has a .js file which is configured as an embedded resource.
My main web application references this project, and when I try to load up the control I get this error:
Assembly does not contain a Web resource with name 'MyFile.js'.
Here is my implementation of getScriptReferences:
public IEnumerable GetScriptReferences()
{
// create reference to the JS
ScriptReference jsReference = new ScriptReference();
jsReference.Assembly = "MyNamespace";
jsReference.Name = "MyNamespace.MyFile.js";
return new ScriptReference[] { jsReference };
}
I'm not quite sure what I'm missing. I've tried changing the Name parameter to be just the file name, the namespace and file name, the namespace, assembly, and file name...and I"m not having any luck. Any suggestions are appreciated.
You have to define the web resource in code on the assembly that contains your embedded resource. Typically you would do this in an AssemblyInfo.vb or .cs file.
[assembly: System.Web.UI.WebResource(
"MyNamespace.MyFile.js",
"text/javascript", PerformSubstitution = true)]
See this article if you need some more help.
Did you make sure to add an entry for the Javascript file into your AssemblyInfo.cs? Something like:
[assembly: WebResource("MyNamespace.MyFile.js", "text/javascript")]
Otherwise, the assembly won't allow access to the resource.

C# Reflection Utility

I have written the following Utility class to get an instance of any class of name "className".
public class AssemblyUtils
{
private AssemblyUtils()
{
}
public static T GetInstance<T>(string assemblyName, string className)
{
T classInstance = default(T);
System.Reflection.Assembly assembly = System.Reflection.Assembly.Load(assemblyName);
object o = assembly.CreateInstance(className);
if (o is T)
{
classInstance = (T)o;
}
else
{
o = null;
}
return classInstance;
}
I have called this like:
IMyInterface ins = AssemblyUtils.GetInstance<IMyInterface>(#"MyNamespace.DA.dll", "MyClassDA");
But I am getting the following error message:
Could not load file or assembly 'MyNamespace.DA.dll' or one of its dependencies. The system cannot find the file specified.
Note that, I called the AssemblyUtils.GetInstance() from separate assemblies which are in the same sln.
How can I resolve the assembly path???
My guess is that it cannot find assembly because it's not in the same folder and not in the GAC, or other directories where the system is looking for.
You need either move them in the same folder where an executing assembly. You can change the folder where assembly is loaded from by using AppDomainSetup.PrivateBinPath Property.
I think, the assembly you want to load (MyNamespace.DA.dll) is dependent to another assembly which is not located in you folder you're looking for. Copy the dependent assemblies into the folder where you located MyNamespace.DA.dll assembly.
Check your bin\Debug folder, is the MyNamespace.DA.dll in that folder? If not you're going to have to move it in there manually. Maybe add a postcondition so that its copied in automatically. Also try using the full assembly strong name.
Also JMSA, how about some upvotes and accepting answers on your other thread?
As Vadim mentioned Assembly.Load will only look in a limited set of places. Assembly.LoadFrom might be a better bet for you. It takes a path (with filename) to the assembly.
Assembly.Load works off the assembly name, not the path.

Changes in App.config do not reflect after restarting the application

I am using an app.config file to store the dynamic parameters of my application. The problem is, when I change a value in app.config file, and start the application, it doesn't load the new value from config file. Seems like the values in app.config file are being read and embedded in exe file only at compile time!
This is how I read the config file:
public class Helper
{
static Helper()
{
Foo = ConfigurationManager.AppSettings["Foo"];
}
public static string Foo { get; set; }
}
Am I missing something?
Are you sure you are changing the correct file? You don't want to change the app.config file, but the <exename>.exe.config file, in the same directory as the .exe
The app.config file is what you edit in the ide, but when you compile your app this file is renamed to <exename>.exe.config and copied to the output directory when you compile. The .exe looks for a file with the same name as itself with the .config extension when looking for the default configuration.
The static nature of your class and method may be causing you the issue. Maybe refactor it to the following...
public static class Helper
{
public static string Foo
{
get
{
return ConfigurationManager.AppSettings["Foo"];
}
}
}
Actually, thinking about it, it doesn't help you a great deal since ConfigurationManager.AppSettings["Foo"] is already (effectively) a static call - you're just adding another layer of abstraction that may well not be required.

Categories

Resources