J'écris un programme en C # qui doit accéder à plusieurs reprises à 1 fichier image. La plupart du temps, cela fonctionne, mais si mon ordinateur fonctionne rapidement, il essaiera d'accéder au fichier avant qu'il ne soit enregistré de nouveau dans le système de fichiers et générera une erreur: "Fichier utilisé par un autre processus" .
Je voudrais trouver un moyen de contourner cela, mais tout mon googling n'a donné lieu à la création de contrôles qu'en utilisant la gestion des exceptions. C'est contre ma religion, alors je me demandais si quelqu'un avait une meilleure façon de le faire?
Réponses:
REMARQUE mise à jour sur cette solution : la vérification avec
FileAccess.ReadWrite
échouera pour les fichiers en lecture seule, la solution a donc été modifiée pour vérifier avecFileAccess.Read
. Bien que cette solution fonctionne car la tentative de vérificationFileAccess.Read
échouera si le fichier possède un verrou en écriture ou en lecture, cependant, cette solution ne fonctionnera pas si le fichier n'a pas de verrou en écriture ou en lecture, c'est-à-dire qu'il a été ouvert. (pour la lecture ou l'écriture) avec un accès FileShare.Read ou FileShare.Write.ORIGINAL: J'utilise ce code depuis plusieurs années et je n'ai eu aucun problème avec lui.
Comprenez votre hésitation à utiliser des exceptions, mais vous ne pouvez pas les éviter tout le temps:
la source
public static bool IsLocked(this FileInfo file) {/*...*/}
.Vous pouvez souffrir d'une condition de concurrence critique sur les threads sur laquelle il existe des exemples documentés de cette utilisation comme vulnérabilité de sécurité. Si vous vérifiez que le fichier est disponible, mais essayez ensuite de l'utiliser, vous pouvez lancer à ce stade, qu'un utilisateur malveillant pourrait utiliser pour forcer et exploiter dans votre code.
Votre meilleur pari est un try catch / enfin qui essaie d'obtenir le traitement du fichier.
la source
Utilisez ceci pour vérifier si un fichier est verrouillé:
Pour des raisons de performances, je vous recommande de lire le contenu du fichier dans la même opération. Voici quelques exemples:
Essayez-le vous-même:
la source
IOException
, plutôt que généralException
, puis un test sur le type.IOException
après le général. Le général attrapera tout ce qui passe et le spécifiqueIOException
sera toujours seul. Échangez simplement les deux.Utilisez simplement l'exception comme prévu. Acceptez que le fichier est en cours d'utilisation et réessayez à plusieurs reprises jusqu'à ce que votre action soit terminée. C'est aussi le plus efficace car vous ne perdez aucun cycle à vérifier l'état avant d'agir.
Utilisez la fonction ci-dessous, par exemple
Méthode réutilisable qui expire après 2 secondes
la source
Vous pouvez peut-être utiliser un FileSystemWatcher et surveiller l'événement Changed.
Je ne l'ai pas utilisé moi-même, mais cela pourrait valoir le coup. Si le gestionnaire de système de fichiers s'avère être un peu lourd dans ce cas, je choisirais la boucle try / catch / sleep.
la source
Vous pouvez renvoyer une tâche qui vous donne un flux dès qu'il est disponible. C'est une solution simplifiée, mais c'est un bon point de départ. C'est thread-safe.
Vous pouvez utiliser ce flux comme d'habitude:
la source
GetStreamAsync()
?la seule façon que je sache est d'utiliser l'API de verrouillage exclusif Win32 qui n'est pas trop rapide, mais des exemples existent.
La plupart des gens, pour une solution simple à cela, essaient simplement les boucles / catch / sleep.
la source
J'espère que cela t'aides!
la source
Les réponses acceptées ci-dessus souffrent d'un problème où si le fichier a été ouvert pour l'écriture avec un mode FileShare.Read ou si le fichier a un attribut en lecture seule, le code ne fonctionnera pas. Cette solution modifiée fonctionne de la manière la plus fiable, avec deux choses à garder à l'esprit (comme c'est également le cas pour la solution acceptée):
En gardant à l'esprit ce qui précède, cela vérifie si le fichier est verrouillé pour l'écriture ou verrouillé pour empêcher la lecture :
la source
Mis à part le travail à 3 lignes et juste pour référence: Si vous voulez les informations complètes - il y a un petit projet sur Microsoft Dev Center:
https://code.msdn.microsoft.com/windowsapps/How-to-know-the-process-704839f4
De l'introduction:
Il fonctionne en se connectant à la "Session de redémarrage du gestionnaire".
Il pourrait être un peu trop conçu pour vos besoins particuliers ... Mais si c'est ce que vous voulez, allez-y et saisissez le projet vs.
la source
D'après mon expérience, vous voulez généralement le faire, puis «protéger» vos fichiers pour faire quelque chose de fantaisiste, puis utiliser les fichiers «protégés». Si vous ne souhaitez utiliser qu'un seul fichier comme celui-ci, vous pouvez utiliser l'astuce expliquée dans la réponse de Jeremy Thompson. Cependant, si vous essayez de le faire sur de nombreux fichiers (par exemple, lorsque vous écrivez un programme d'installation), vous risquez d'être un peu blessé.
Une manière très élégante de résoudre ce problème consiste à utiliser le fait que votre système de fichiers ne vous permettra pas de modifier le nom d'un dossier si l'un des fichiers qu'il contient est utilisé. Gardez le dossier dans le même système de fichiers et cela fonctionnera comme un charme.
Notez que vous devez être conscient des façons évidentes dont cela peut être exploité. Après tout, les fichiers ne seront pas verrouillés. Sachez également qu'il existe d'autres raisons pouvant entraîner l'
Move
échec de votre opération. De toute évidence, la gestion correcte des erreurs (MSDN) peut vous aider ici.Pour les fichiers individuels, je m'en tiendrai à la suggestion de verrouillage publiée par Jeremy Thompson.
la source
FileShare
et de la vérification d'un verrou.Voici un code qui, autant que je sache, fait la même chose que la réponse acceptée mais avec moins de code:
Cependant, je pense qu'il est plus robuste de le faire de la manière suivante:
la source
Vous pouvez utiliser ma bibliothèque pour accéder aux fichiers de plusieurs applications.
Vous pouvez l'installer à partir de nuget: Install-Package Xabe.FileLock
Si vous souhaitez plus d'informations à ce sujet, consultez https://github.com/tomaszzmuda/Xabe.FileLock
La méthode fileLock.Acquire renverra true uniquement si le verrouillage du fichier peut être exclusif pour cet objet. Mais l'application qui télécharge le fichier doit également le faire dans le verrouillage de fichier. Si l'objet est inaccessible, metod retourne false.
la source
Une fois, j'avais besoin de télécharger des fichiers PDF dans une archive de sauvegarde en ligne. Mais la sauvegarde échouerait si l'utilisateur avait ouvert le fichier dans un autre programme (tel que le lecteur PDF). Dans ma hâte, j'ai tenté quelques-unes des meilleures réponses de ce fil, mais je n'ai pas pu les faire fonctionner. Ce qui a fonctionné pour moi, c'était d'essayer de déplacer le fichier PDF dans son propre répertoire . J'ai trouvé que cela échouerait si le fichier était ouvert dans un autre programme, et si le déplacement était réussi, aucune opération de restauration ne serait nécessaire, comme si elle était déplacée vers un répertoire distinct. Je souhaite publier ma solution de base au cas où elle pourrait être utile pour les cas d'utilisation spécifiques des autres.
la source
Je suis intéressé de voir si cela déclenche des réflexes WTF. J'ai un processus qui crée et lance ensuite un document PDF à partir d'une application console. Cependant, je faisais face à une fragilité où si l'utilisateur devait exécuter le processus plusieurs fois, en générant le même fichier sans d'abord fermer le fichier généré précédemment, l'application lèverait une exception et mourrait. C'était un événement assez fréquent car les noms de fichiers sont basés sur les numéros de devis de vente.
Plutôt que d'échouer d'une manière aussi ingrate, j'ai décidé de compter sur la gestion des versions de fichiers auto-incrémentée:
Un peu plus d'attention peut probablement être accordée au
catch
bloc pour m'assurer que j'attrape les bonnes IOException (s). J'effacerai probablement également le stockage de l'application au démarrage, car ces fichiers sont de toute façon temporaires.Je me rends compte que cela dépasse la portée de la question du PO de vérifier simplement si le fichier est en cours d'utilisation, mais c'était effectivement le problème que je cherchais à résoudre quand je suis arrivé ici, alors peut-être qu'il sera utile à quelqu'un d'autre.
la source
Est-ce que quelque chose comme ça aiderait?
la source
Essayez de déplacer / copier le fichier dans un répertoire temporaire. Si vous le pouvez, il n'a pas de verrou et vous pouvez travailler en toute sécurité dans le répertoire temp sans obtenir de verrous. Sinon, essayez simplement de le déplacer à nouveau en x secondes.
la source
J'utilise cette solution de contournement, mais j'ai un délai entre le moment où je vérifie le verrouillage du fichier avec la fonction IsFileLocked et lorsque j'ouvre le fichier. Dans ce laps de temps, un autre thread peut ouvrir le fichier, donc j'obtiendrai IOException.
J'ai donc ajouté du code supplémentaire pour cela. Dans mon cas, je veux charger XDocument:
Qu'est-ce que tu penses? Puis-je changer quelque chose? Peut-être que je n'avais pas du tout besoin d'utiliser la fonction IsFileBeingUsed?
Merci
la source