permissão de arquivo Win32 violação de compartilhamento ao excluir um arquivo temporário
-
07-07-2019 - |
Pergunta
Tenho uma aplicação onde eu estou tentando implementar uma "Substituir arquivo seguro" por:
- Criação de um arquivo (
A
) - Encher
A
com dados - Copiar
A
ao seu destino final (B
) viaSHFileOperation
- Exclusão
A
usandoDeleteFile
No entanto, na etapa 4 DeleteFile
sempre retorna ERROR_SHARING_VIOLATION. O processo todo leva milésimos de segundo, então eu não posso imaginar quem mais poderia estar interferindo com o meu arquivo. Algumas perguntas:
- Existe uma melhor técnica Win32 (C / C ++) para realizar o acima?
- Como posso obter mais informações sobre o "outro processo" que está me impedindo de apagar
A
arquivo? - Como eu suavemente ( wink wink nudge nudge ) força Windows para excluir meu arquivo temporário?
Quaisquer outras sugestões são bem-vindos
Solução
Meu melhor palpite seria que você precisa de um passo 2.5) Feche o identificador de arquivo criado em 1)
O que você está usando para criar / abrir o arquivo?
Se você usar CreateFile seguida, verifique se você está fechando o seu identificador de arquivo antes da chamada para apagar, ou então certifique-se de especificar o FILE_SHARE_DELETE
partilha bandeira.
HANDLE hFile = CreateFile("C:\\test.txt", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, 0, NULL);
Você também pode querer simplificar a sua cópia de código de arquivo usando a API Win32 CopyFile .
Outras dicas
Uma maneira de excluir o arquivo seria abri-lo com FILE_FLAG_DELETE_ON_CLOSE
que irá solicitar o sistema operacional para excluir automaticamente o arquivo após o último identificador para ele é fechado. Se você criar o arquivo com FILE_SHARE_READ
então SHFileOperation
deve ser capaz de lê-lo para copiá-lo, e você pode, então, fechar imediatamente o seu identificador para o arquivo. Quando os fecha shell sua identificador para o arquivo, o arquivo será excluído automaticamente.
-
Tente usar Handles.exe de www.sysinternals.com para ver se e como o arquivo está em uso.
-
Você pode usar GetLastError e FormatMessage para obter mais informações sobre a última função falhou:
Um código de exemplo:
char tx2[1024];
DWORD l;
if(l = GetLastError())
{
LPVOID lpMessageBuffer = 0;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
l,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language
(LPTSTR) &lpMessageBuffer,
0,
NULL
);
SetLastError(0);
MessageBox(NULL, tx2, "MyApplication", MB_ICONINFORMATION | MB_OK | (MB_SETFOREGROUND | MB_TOPMOST | MB_TASKMODAL));
}