2009-10-28 13 views
11

Lorsque je sauvegarde un fichier sur une clé USB dans mon application Delphi, comment puis-je m'assurer que le fichier est vraiment (définitivement) sauvegardé sur le port USB lorsque "Retirer le périphérique en toute sécurité" n'est pas utilisé?
Dire à notre client d'utiliser la fonction Windows «Retirer le périphérique en toute sécurité» ne fonctionne pas.
Y at-il une commande API Windows pour vider le tampon, de sorte que toutes les données sont écrites sur le disque USB de façon permanente?Comment vous assurer qu'un fichier a été enregistré de manière permanente sur un périphérique USB, lorsque l'utilisateur n'utilise pas "Supprimer le périphérique en toute sécurité"?

+7

À quiconque a voté pour la fermeture de la section «Non lié à la programmation», veuillez relire la question. –

+0

La même chose ici. La question est très liée à la programmation. –

+1

Je n'ai jamais eu de perte de données que je puisse attribuer à la suppression d'un périphérique de stockage USB sans effectuer "supprimer le matériel en toute sécurité". Je m'assure que les opérations de copie de fichiers sont terminées (la boîte de dialogue 'copier les fichiers' disparaît). Suis-je extrêmement chanceux? – Les

Répondre

3

Voici une fonction que je l'habitude de vider les données sur un lecteur USB avant de l'éjecter par programme. Cette fonctionnalité de clones de Mark Russinovich's "Sync" utility. Je n'ai eu aucun problème avec ce code et il fonctionne sur beaucoup de systèmes depuis quelques années.

La partie la plus pertinente de ce code est l'appel à FlushFileBuffers.

function FlushToDisk(sDriveLetter: string): boolean; 
var 
    hDrive: THandle; 
    S:  string; 
    OSFlushed: boolean; 
    bResult: boolean; 
begin 
    bResult := False; 
    S := '\\.\' + sDriveLetter + ':'; 

    //NOTE: this may only work for the SYSTEM user 
    hDrive := CreateFile(PAnsiChar(S), GENERIC_READ or 
    GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, 
    OPEN_EXISTING, 0, 0); 
    OSFlushed := FlushFileBuffers(hDrive); 

    CloseHandle(hDrive); 

    if OSFlushed then 
    begin 
    bResult := True; 
    end; 

    Result := bResult; 
end; 
+2

Pour vider tous les fichiers ouverts sur le volume. Si Max n'est concerné que par les fichiers que son programme écrit, et pas avec d'autres fichiers, l'utilisateur pourrait écrire sur le disque par d'autres moyens, alors il peut probablement vider les handles vers ses fichiers au lieu de vider tout le volume, et il n'aurait donc pas besoin de privilèges administratifs. –

+0

Il est presque impossible de garantir qu'il n'y aura pas de corruption. Le disque flash peut être retiré à tout moment. Je pense que la réponse de MSalters est plus correcte. Je suis d'accord avec Rob, c'est un disque large. – Matt

+0

Pourquoi ce code utilise 3 vars (OSFlushed, bResult et Result) quand un seul semble faire le travail? – EMBarbosa

2

Quoi qu'il arrive, vous pouvez débrancher l'appareil vous-même, je veux dire par programme. alors vous serez complètement sûr qu'ils ont enlevé l'appareil correctement.

jetez un oeil à la réponse à cette question: safe-remove-usb-drive-using-win32-api. en particulier this link to a msdn kb article donné dans la réponse.

+1

Mais que se passe-t-il si l'utilisateur ne veut pas retirer la clé USB? – simon

+0

l'utilisateur supprime déjà le lecteur USB, je ne pense pas qu'il en a besoin plus. Plus sérieusement, s'il attendait plus longtemps pour utiliser le disque, le fichier finirait par être écrit sur le disque (le fichier n'est pas conservé dans le cache pour toujours). (Je traite tous les jours avec ce type de client, plus c'est simple pour eux, mieux c'est pour tout le monde, dites-leur qu'ils ne peuvent pas utiliser le disque, c'est simple, dites-leur qu'ils doivent "retirer le matériel en toute sécurité", c'est trop, je peux parier que notre OP a déjà du code pour détecter automatiquement l'insertion du lecteur USB et copier le fichier nécessaire sur un chemin prédéterminé) –

+1

Adrien, nous savons seulement que l'utilisateur enlève le lecteur * parfois *. Nous ne savons pas que l'utilisateur * supprime toujours le disque après l'enregistrement. Nous ne savons pas non plus si le lecteur est utilisé pour d'autres choses que ce programme. –

11

Lorsque vous ouvrez le fichier, spécifiez "write through" (indicateur FILE_FLAG_WRITE_THROUGH à CreateFile()). Cela forcera l'OS à écrire le fichier directement. Il se peut que ce soit dans le cache du système d'exploitation pour accélérer les lectures suivantes, mais ce n'est pas un problème pour vous.

Si vous voulez vider les tampons de fichiers, il y a bien sûr toujours FlushFileBuffers()

+0

Lorsque j'utilise FlushFileBuffers(), puis-je être sûr que le fichier est stocké physiquement sur le lecteur USB? Donc, il ne disparaît pas, après débranchement "incontrôlé"? –

+1

@max: Oui, tant qu'il y a suffisamment de temps entre l'appel à FlushFileBuffers() et la suppression pour que l'écriture physique se produise. IOW, si vous essayez d'écrire un fichier de 2 Go sur le disque USB, appelez FlushFileBuffers(), puis + instantanément + supprimer le lecteur, il peut toujours être complètement écrit - il n'y a tout simplement pas assez de temps pour terminer l'opération d'écriture. Vous devez éduquer vos utilisateurs sur la façon de retirer le disque en toute sécurité, ou au moins attendre que votre application leur dise qu'ils peuvent le retirer; votre application peut déterminer combien de temps elle doit attendre avant de leur donner OK. –

+3

Ken, vous le faites sonner comme FlushFileBuffers retournera avant qu'il ait fini de vider les tampons de fichiers. Est-ce exact? Si oui, alors * comment * le programme devrait-il déterminer combien de temps il doit attendre? –