I'm trying to get assembly version of an exe in C# with the following code
Assembly asm = Assembly.LoadFrom(address);
return asm.GetName().Version;
it works perfect but if I try to delete the exe after I used this function, it says "Access Denied" since the exe is being used by another process!
is there any Dispose call or something which releases the file handle or any other solution?
There is no way to unload an assembly other than unloading the application domain. See How to: Load and Unload Assemblies:
There is no way to unload an
individual assembly without unloading
all of the application domains that
contain it. Use the Unload method from
AppDomain to unload the application
domains. For more information, see
Unloading an Application Domain.
If you just want to get the version of a file, try using FileVersionInfo.GetVersionInfo.
This issue was dealt with here
How to unload an assembly from the primary appdomain
Related
We have a .net plugin for an application that does not load a dependent library from the plugin folder.
Scenario:
Application (Revit.exe in program files) -> Loads plugin from c:\programdata\revit\plugindir\ourplugindir\<plugin.dll+dependencies>
On most machines, the load works fine. For the context of the issue, the dll dependencies are as follows
Revit.exe loads plugin.dll (revit.exe is in programfiles, plugins are in a separate predefined directory under programdata)
plugin.dll loads IdentityModel.dll (in ourplugindir directory)
IdentityModel.dll loads System.Text.Encodings.Web.DLL (in ourplugindir)
Successful probing looks like this:
IdentityModel requires System.Text.Encodings.Web.DLL
Initiate probing
Check GAC (fail)
Check root folder where Revit.exe is present (fail)
Check private sub folders where Revit.ext is present (fail)
Check ourplugindir (success)
On the machine where the plugin load fails, for some reason it does not probe ourplugindir and is hence unable to find System.Text.Encodings.Web.DLL.
The plugin dll is built using .net 4.7. The dependency is an indirect dependency.
From MSDN: https://learn.microsoft.com/en-us/dotnet/framework/deployment/how-the-runtime-locates-assemblies
Assembly location can also be determined using the current binding
context. This most often occurs when the Assembly.LoadFrom method is
used and in COM interop scenarios. If an assembly uses the LoadFrom
method to reference another assembly, the calling assembly's location
is considered to be a hint about where to find the referenced
assembly.
Since the plugins are dynamically loaded by Revit.exe, I can only assume that the application uses Assembly.LoadFrom or something similar to load the plugins.
So the question is, why does the runtime correctly probe and find the dependent dll in the plugin folder on some machines while it doesn't probe the same folder on other machines?
Have you tried using an assembly resolver?
I am working on assembly project and external program is executed through the assembly program.
System.Environment.CurrentDirectory assembly and Application.ExecutablePath paths are different due to external application.
System.Environment.CurrentDirectory is Assembly path.
Application.ExecutablePath External application path.
While deserialization it throw expcetion
assembly not found
because "Application.ExecutablePath " not having my dlls .
So i want to change use System.Environment.CurrentDirectory path for deserialization.
I recommend setting up an AssemblyResolve event on the current domain.
That way you can explicitly determine where your DLLs are and load them if they're not found automatically.
Jeremy Tammik wrote about it here:
http://thebuildingcoder.typepad.com/blog/2014/05/rvtva3c-assembly-resolver.html
The only thing to be careful of is that you should make sure the event is looking specifically for your DLLs (not any DLLs) - and that if it's not appropriate for you to load a DLL you return null (I occasionally run into scenarios where other people's addins don't implement this nicely, and it messes up my addin doing it).
My program runs perfectly except when it is launched as a startup program. When launched as a start up program it is not able to find a first party DLL (or one of it's dependencies).
I get the following exception:
Could not find file or assembly X or one of it's dependencies: C:\Windows\SysWow64\X.dll
It is looking for the first party DLL in the C:\Windows\SysWOW64\ directory instead of in the local directory C:\Program Files\MyProgram\.
The confusing part is, if I launch the program manually everything works fine.
How do I go about finding the source of this problem? I tried using Fusion Log but it only told me the same thing as the exception: That it was trying to load from C:\Windows\SysWOW64 only.
I read that this can occur when your application uses Assembly.Load - The culprit program does use Assembly.LoadFrom - but again, this works fine except when done at start up.
Furthermore, the culprit program does have some [DllImport] attributes.
The issue was to do with using Assembly.LoadFrom and the current directory at start up.
The Assembly.LoadFrom states that it:
assemblyFile may be absolute or relative to the current directory, and the assembly is loaded into the domain of the caller.
When the program is set as a start up program the current directory is
C:\Windows\SysWOW64 for whatever reason.
As you can demonstrate by outputting Directory.GetCurrentDirectory().
Instead of using Assembly.LoadFrom which does not follow the normal probing I am using Assembly.Load as this searches the normal directories where DLLs are contained.
The load context contains assemblies found by probing: in the GAC, in a host assembly store if the runtime is hosted, or in the ApplicationBase and PrivateBinPath of the application domain. Most overloads of the Load method load assemblies into this context.
The load-from context contains assemblies for which the user provided a path not included in the directories searched by probing. LoadFrom, CreateInstanceFrom, and ExecuteAssembly are examples of methods that load by path.
This also explains why Fusion was telling me it was only searching for DLLs in C:\Windows\SysWOW64 - as that's what LoadFrom does, only searches in the directory given. Which in my case was the current directory.
I understand how to load an F# dll into a project. But I would like to be able to load specific parts of them dynamically and without a big performance hit from the dll being purely functional.
To unload an application domain
There is no way to unload an individual assembly without unloading all of the application domains that contain it. Use the Unload method from AppDomain to unload the application domains. For more information, see How to: Unload an Application Domain.
Taken from https://msdn.microsoft.com/en-us/library/ms173101.aspx
The idea will be to initialize a new application domain for the F# library, then drop it after you're done using it. I think you're going to have to make sure you compile the F# lib as a Strong-Named assembly and add it to the GAC to accomplish this, but I'm not positive.
In my project I am loading a DLL using reflection and Assembly.LoadFrom(). This is a small DLL that is occasionally recompiled (from the source) dynamically during application execution.
Is there a way to unload the loaded DLL from the application so that I can reload it? I've tried reloading it, but I get an error:
file in use by another program
If the application that has the file open is a custom app, then you could modify it to load the DLL into another AppDomain. When you want to reload it, simply tear down that AppDomain and load the new DLL into the new AppDomain. I'd have a look at MEF (which does this) to see whether this might support your use case.
You can't. You have to kill the program. There is no way to unload an assembly in .Net.
Read these:
http://blogs.msdn.com/b/jasonz/archive/2004/05/31/145105.aspx
http://blogs.msdn.com/b/suzcook/archive/2003/07/08/unloading-an-assembly.aspx