1

I have an application that IMPLICITLY opens a handle on a dll/file. At some point in the application, I want to release this handle. How can I do it? My application is in C#.

Poulo
  • 1,551
  • 3
  • 14
  • 22
  • What is the file in question? Is it a resource or referenced assembly? You seem to know FOR SURE why it's opened, which is the greatest hint to what it's used for and when it will be closed. Care let us in? – Sam Harwell Aug 04 '09 at 06:36
  • Everything 280Z28 said... plus "shadow copy" ;-p – Marc Gravell Aug 04 '09 at 06:43
  • Ok. My application is making use of a GUI automation tool to do some testing on an installer. I launch the installer, (xyx.exe) use code generated by the automation tool to perform GUI operations that update the software using the installer. During this, there is a handle opened on 'xyz.exe' which does not get closed. This is the handle that I want to close. The generated code contains all static members, hence I cannot call a Dispose or Close method. Neither do I load the assembly, so I cannot create another app domain and then unload it after use. – Poulo Aug 04 '09 at 08:38

4 Answers4

4

What exactly you are trying to do? If you want to load an assembly to do some stuff with that, and then unload it completely, you need to rely on creating a new app domain.

public static void Main(string[] args)
{
AppDomain appDomain = AppDomain.CreateDomain("NewAppDomain");
appDomain.DoCallBack(new CrossAppDomainDelegate(AsmLoad));

// At this point, your assembly is locked, you can't delete

AppDomain.Unload(appDomain);
Console.WriteLine("AppDomain unloaded");

//You've completely unloaded your assembly. Now if you want, you can delete the same

}

public static void AsmLoad()
{
Assembly assembly = Assembly.LoadFrom(@"c:\Yourassembly.dll");

//Loaded to the new app domain. You can do some stuff here
Console.WriteLine("Assembly loaded in {0}",AppDomain.CurrentDomain.FriendlyName);
}

Have a look at this post for more, http://blogs.msdn.com/suzcook/archive/2003/07/08/57211.aspx

Or, if you're only worried about keeping the file locked, you could use shadow copying. That will make a copy of the file on disk and load it from the new location. The original file will not be locked by that load. To do that, set AppDomainSetup.ShadowCopyFiles to "true" when creating the AppDomain or set AppDomain.ShadowCopyFiles to true after it's already been created.

amazedsaint
  • 7,642
  • 7
  • 54
  • 83
4

use PInvoke if you have an handler that you want to close

[System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);
Arsen Mkrtchyan
  • 49,896
  • 32
  • 148
  • 184
0

Just use the Dispose or Close method of the class that opened the handle.

Thomas Danecker
  • 4,635
  • 4
  • 32
  • 31
0

I don't know an easy way. Excessive implicit file locking is something I've always disliked about Windows.

If you need to replace the file, MoveFileEx can do it at next boot. You'd use it to rename or delete the original, and then rename something else into its place. http://msdn.microsoft.com/en-us/library/aa365240(VS.85).aspx http://www.pinvoke.net/default.aspx/kernel32/MoveFileEx.html

If you don't want to mess with the API directly there's MoveFile in the SysInternals suite which does the same: http://technet.microsoft.com/en-us/sysinternals/bb897556.aspx

Or you can have another program access the file when your program isn't running.

There's ways to get a list of handles per process, if you really want to try to close the handle, which would most likely just crash your program if .NET tries to access it again. It's not pretty, and the example is C++: http://www.codeguru.com/forum/showthread.php?t=176997

David
  • 2,164
  • 13
  • 11