2009-08-04 9 views
1

J'ai une application qui IMPLICITEMENT ouvre un handle sur un dll/fichier. À un certain moment dans l'application, je veux libérer ce handle. Comment puis-je le faire? Mon application est en C#. Utilisez simplement la méthode Dispose ou Close de la classe qui a ouvert le handle.Comment libérer une poignée via C#?

+0

Quel est le fichier en question? Est-ce une ressource ou un assemblage référencé? Vous semblez savoir pour sûr pourquoi il est ouvert, ce qui est le meilleur indice pour savoir à quoi il sert et quand il sera fermé. Care nous laisser entrer? –

+0

Tout 280Z28 dit ... plus "copie de l'ombre" ;-p –

+0

Ok. Mon application utilise un outil d'automatisation GUI pour effectuer des tests sur un programme d'installation. Je lance le programme d'installation, (xyx.exe) utilise le code généré par l'outil d'automatisation pour effectuer des opérations de GUI qui mettent à jour le logiciel en utilisant le programme d'installation. Pendant ce temps, il y a un handle ouvert sur 'xyz.exe' qui ne se ferme pas. Ceci est le handle que je veux fermer. Le code généré contient tous les membres statiques, donc je ne peux pas appeler une méthode Dispose ou Close. Je ne charge pas non plus l'assemblage, donc je ne peux pas créer un autre domaine d'application, puis le décharger après utilisation. – Poulo

Répondre

4

utilisation PInvoke si vous avez un gestionnaire que vous voulez fermer

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

Mais comment puis-je trouver la poignée que je dois fermer. Je ne connais que le nom du fichier. Le handle que mon processus a ouvert sur ce fichier est inconnu. – Poulo

+0

utilisez-vous classe de processus pour lancer exe? –

0

0

Je ne connais pas un moyen facile. Le verrouillage de fichier implicite excessif est quelque chose que j'ai toujours détesté à propos de Windows.

Si vous devez remplacer le fichier, MoveFileEx peut le faire au prochain démarrage. Vous l'utiliseriez pour renommer ou supprimer l'original, puis renommer un autre élément à sa place. http://msdn.microsoft.com/en-us/library/aa365240(VS.85).aspx http://www.pinvoke.net/default.aspx/kernel32/MoveFileEx.html

Si vous ne voulez pas gâcher avec l'API directement, il y a MoveFile dans la Sysinternals suite qui fait la même chose: http://technet.microsoft.com/en-us/sysinternals/bb897556.aspx

Ou vous pouvez avoir un autre accès au programme le fichier lorsque votre ISN programme » t en cours d'exécution.

Il y a des façons d'obtenir une liste de descripteurs par processus, si vous voulez vraiment essayer de fermer la poignée, ce qui serait très probablement simplement de démarrer votre programme si .NET tente d'y accéder à nouveau. Ce n'est pas joli, et l'exemple est C++: http://www.codeguru.com/forum/showthread.php?t=176997

4

Qu'est-ce que vous essayez exactement de faire? Si vous voulez charger un assemblage pour faire quelque chose avec ça, et le décharger complètement, vous devez vous appuyer sur la création d'un nouveau domaine d'application.

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

Jetez un oeil à ce poste pour plus, http://blogs.msdn.com/suzcook/archive/2003/07/08/57211.aspx

Ou, si vous êtes seulement inquiet pour garder le fichier verrouillé, vous pouvez utiliser copie d'ombre. Cela va faire une copie du fichier sur le disque et le charger du le nouvel emplacement. Le fichier original ne sera pas verrouillé par cette charge. Pour faire, réglez AppDomainSetup.ShadowCopyFiles à « true » lors de la création du AppDomain ou ensemble AppDomain.ShadowCopyFiles true après qu'il a déjà été créé.

Questions connexes