2010-09-15 12 views
6

J'ai une tâche de longue durée qui effectue une série d'opérations de fichiers sur les lecteurs USB montés et je veux empêcher les utilisateurs d'éjecter le lecteur du Finder (ou ailleurs) pendant que cela se produit. Il y a un bouton Annuler qui permet de terminer la tâche à tout moment.Comment puis-je empêcher l'éjection d'un disque pendant une opération sur Mac OS X?

J'avais supposé que garder une poignée de fichier ouverte sur le volume monté pendant la durée de la tâche ferait l'affaire, mais cela n'a pas fonctionné.

C'est ce que j'ai essayé (manipulation supprimé erreur):

NSString *tempFilePath = @"/Volumes/myVolume/.myTempFile"; 
if ([[NSFileManager defaultManager] fileExistsAtPath:tempFilePath] == NO) { 
    [[NSFileManager defaultManager] createFileAtPath:tempFilePath contents:nil attributes:nil] 
} 

_tempFile = [NSFileHandle fileHandleForWritingAtPath:tempFilePath]; 

Toutes les idées sur ce que je peux faire pour vous assurer que le volume ne peut pas éjectant?

+0

Vous ne voulez pas faire éclater votre bulle, mais que se passe-t-il si quelqu'un débranche simplement sa clé USB? Si le disque est piloté par le matériel, il est impossible de ne pas l'empêcher d'être éjecté. Pourquoi ne pouvez-vous pas donner à l'utilisateur un avertissement très sévère qu'il ne devrait pas éjecter le lecteur sinon l'opération échouera? –

+0

Je réalise que nous ne pouvons pas complètement empêcher une déconnexion accidentelle. Dans la mesure du possible, j'aimerais que l'utilisateur soit obligé de prendre la décision consciente d'arrêter l'opération afin de pouvoir comprendre pourquoi certaines fonctionnalités ne fonctionnent plus pour eux plus tard. – mcsheffrey

+0

fan @ferrari: ce que mcsheffrey veut est utile parce que l'utilisateur peut oublier que cette tâche n'est pas terminée et "retenir" le disque d'une certaine manière aiderait à des éjections accidentelles. – mohsenr

Répondre

10

Vous devez utiliser l'API Disk Arbitration, plus précisément DARegisterDiskUnmountApprovalCallback.

Vous pouvez créer un DADiskRef via les fonctions avaliable dans DADisk.h

Lorsque le rappel est appelé, vous pouvez alors décider si vous voulez bloquer l'Démontez ou non. Pour un exemple artificiel:

DADissenterRef myUnmountApprovalCallback(DADiskRef disk, void *context) 
{ 
    DADissenterRef result = NULL; // NULL means approval 
    if (stillWorking) { 
     // This is released by the caller, according to the docs 
     result = DADissenterCreate(kCFAllocatorDefault, kDAReturnBusy, CFSTR("<Your App> is busy writing to this device. Please cancel the operation first."); 
    } 
    return result; 
} 

Comme il est indiqué dans les commentaires, cela ne l'empêche pas quiconque de simplement tirer le bouchon, mais il vous donnera une notification des démontages explicites.

0

Vous recherchez les API de structure Disk Arbitration (ou DiskArb).