2009-08-04 7 views
1

Ich habe eine Anwendung, die IMPLICITLY öffnet ein Handle auf eine DLL/Datei. Irgendwann in der Anwendung möchte ich dieses Handle freigeben. Wie kann ich es tun? Meine Anwendung ist in C#.Wie man einen Griff durch C# freigibt?

+0

Was ist die betreffende Datei schließen möchten? Ist es eine Ressource oder eine referenzierte Assembly? Sie scheinen zu wissen, warum es geöffnet ist, was der beste Hinweis darauf ist, wofür es verwendet wird und wann es geschlossen wird. Pflege lass uns rein? –

+0

Alles 280Z28 sagte ... plus "Schattenkopie" ;-p –

+0

Ok. Meine Anwendung verwendet ein GUI-Automatisierungstool, um einige Tests an einem Installer durchzuführen. Ich starte das Installationsprogramm, (xyx.exe) verwende Code, der vom Automatisierungstool erzeugt wurde, um GUI-Operationen durchzuführen, die die Software mit dem Installer aktualisieren. Währenddessen ist ein Handle auf 'xyz.exe' geöffnet, der nicht geschlossen wird. Dies ist das Handle, das ich schließen möchte. Der generierte Code enthält alle statischen Member. Daher kann ich keine Dispose- oder Close-Methode aufrufen. Ich lade auch die Assembly nicht, daher kann ich keine andere App-Domain erstellen und sie nach der Verwendung wieder entfernen. – Poulo

Antwort

4

Verwendung PInvoke wenn Sie eine Prozedur, die Sie

[System.Runtime.InteropServices.DllImport("Kernel32")] 
private extern static Boolean CloseHandle(IntPtr handle); 
+2

Aber wie finde ich den Griff, den ich schließen muss. Ich kenne nur den Dateinamen. Der Handle, den mein Prozess für diese Datei geöffnet hat, ist unbekannt. – Poulo

+0

Verwenden Sie die Process-Klasse zum Starten von exe? –

0

Verwenden Sie einfach die Methode Dispose oder Close der Klasse, die das Handle geöffnet hat.

0

Ich kenne keinen einfachen Weg. Übermäßige implizite Dateisperrung ist etwas, das ich über Windows immer nicht mochte.

Wenn Sie die Datei ersetzen müssen, kann MoveFileEx dies beim nächsten Start tun. Sie würden es verwenden, um das Original umzubenennen oder zu löschen, und dann etwas anderes in seinen Platz umzubenennen. http://msdn.microsoft.com/en-us/library/aa365240(VS.85).aspx http://www.pinvoke.net/default.aspx/kernel32/MoveFileEx.html

Wenn Sie es nicht direkt mit der API zu verwirren wollen ist Movefile in der Sysinternals Suite, die macht das gleiche: http://technet.microsoft.com/en-us/sysinternals/bb897556.aspx

Oder Sie können die Datei ein anderes Programm Zugriff haben, wenn Ihr Programm isn‘ t läuft.

Es gibt Möglichkeiten, eine Liste von Handles pro Prozess zu erhalten, wenn Sie wirklich versuchen, das Handle zu schließen, was höchstwahrscheinlich nur Ihr Programm zum Absturz bringen würde, wenn .NET versucht, wieder darauf zuzugreifen. Es ist nicht schön, und das Beispiel ist C++: http://www.codeguru.com/forum/showthread.php?t=176997

4

Was genau Sie versuchen zu tun? Wenn Sie eine Assembly laden möchten, um damit etwas zu tun und diese dann vollständig zu entladen, müssen Sie sich darauf verlassen, eine neue App-Domain zu erstellen.

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); 
} 

Werfen Sie einen Blick auf diesen Beitrag für mehr http://blogs.msdn.com/suzcook/archive/2003/07/08/57211.aspx

Oder, wenn Sie nur Sorgen um halten die Datei gesperrt sind, können Sie Schatten Kopieren verwenden könnte. Das wird eine Kopie der Datei auf der Festplatte erstellen und von den neuen Speicherort laden. Die Originaldatei wird von diesem Ladevorgang nicht gesperrt. Um zu tun, setzen Sie AppDomainSetup.ShadowCopyFiles auf "True" beim Erstellen der AppDomain oder Set AppDomain.ShadowCopyFiles auf True , nachdem es bereits erstellt wurde.

Verwandte Themen