我有一个应用程序隐式打开 dll/文件的句柄。在应用程序的某个时刻,我想释放这个句柄。我该怎么做?我的应用程序在 C# 中。
4 回答
你到底想做什么?如果你想加载一个程序集来做一些事情,然后完全卸载它,你需要依赖创建一个新的应用程序域。
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);
}
看看这篇文章了解更多,http://blogs.msdn.com/suzcook/archive/2003/07/08/57211.aspx
或者,如果您只担心保持文件锁定,您可以使用卷影复制。这将在磁盘上复制文件并从新位置加载它。原始文件不会被该负载锁定。为此,请在创建 AppDomain 时将 AppDomainSetup.ShadowCopyFiles 设置为“true”,或在创建 AppDomain.ShadowCopyFiles 后将其设置为 true。
如果您有要关闭的处理程序,请使用 PInvoke
[System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);
只需使用打开句柄的类的 Dispose 或 Close 方法。
我不知道一个简单的方法。过度隐式文件锁定是我一直不喜欢 Windows 的地方。
如果您需要替换文件,MoveFileEx 可以在下次启动时完成。您将使用它来重命名或删除原始文件,然后将其他内容重命名到它的位置。 http://msdn.microsoft.com/en-us/library/aa365240(VS.85).aspx http://www.pinvoke.net/default.aspx/kernel32/MoveFileEx.html
如果您不想直接与 API 混淆,则 SysInternals 套件中的 MoveFile 可以执行相同的操作:http ://technet.microsoft.com/en-us/sysinternals/bb897556.aspx
或者,当您的程序未运行时,您可以让另一个程序访问该文件。
如果您真的想尝试关闭句柄,则有一些方法可以获取每个进程的句柄列表,如果.NET 尝试再次访问它,这很可能会使您的程序崩溃。不漂亮,例子是C++: http ://www.codeguru.com/forum/showthread.php?t=176997