2010-09-15 15 views
6

Tengo una tarea de larga duración que realiza una serie de operaciones de archivos en unidades USB montadas y quiero evitar que los usuarios expulsen la unidad del Finder (o de otro lugar) mientras esto sucede. Hay un botón Cancelar que permite que la tarea finalice en cualquier momento.¿Cómo puedo evitar la expulsión de un disco durante una operación en Mac OS X?

Había asumido que mantener un archivo manejador abierto en el volumen montado para la duración de la tarea haría el truco, pero no ha funcionado.

Esto es lo que he intentado (manejo de errores eliminado):

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

_tempFile = [NSFileHandle fileHandleForWritingAtPath:tempFilePath]; 

alguna idea acerca de lo que puedo hacer para asegurar que se evita que el volumen de expulsión?

+0

No quiero estallar su burbuja, pero ¿y si alguien simplemente desenchufa su unidad USB? Si la unidad está impulsada por hardware, es imposible evitar que se expulse. ¿Por qué no puedes simplemente darle al usuario una advertencia muy severa de que no deberían expulsar el disco o de lo contrario la operación fallará? –

+0

Me doy cuenta de que no podemos evitar por completo una desconexión inadvertida. En la medida de lo posible, me gustaría que el usuario se vea forzado a tomar la decisión consciente de detener la operación para que pueda entender por qué alguna funcionalidad no funciona para ellos más adelante. – mcsheffrey

+0

@ferrari fan: lo que mcsheffrey quiere es útil porque el usuario puede olvidar que esta tarea no está terminada y "retener" el disco de alguna manera ayudaría con las expulsiones accidentales. – mohsenr

Respuesta

10

Deberá utilizar la API Disk Arbitration, más específicamente la DARegisterDiskUnmountApprovalCallback.

Se puede crear un DADiskRef a través de las funciones avaliable en DADisk.h

Cuando la devolución de llamada se llama, a continuación, puede decidir si desea bloquear o no el desmontaje. Para un ejemplo artificioso:

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

Como se señaló en los comentarios, esto no impide que cualquier persona desde sólo tirando del enchufe, pero le dará una notificación por desmonta explícitos.

0

Está buscando las API de marco de Arbitraje de disco (o DiskArb).