2013-08-13 3 views
4

Я пытаюсь создать процесс на другом компьютере, который удаляет себя, когда он будет выполнен. Я использую флаг DELETE_ON_CLOSE с CreateFile. Этот метод немного популярен, но у меня проблемы, потому что я не могу выполнить его, пока он открыт (ожидается, но это то, что некоторые решения делают). Чтобы обойти это, я попытался открыть файл с разрешениями на чтение. Флаг DELETE_ON_CLOSE говорит, что он должен удалять только файл, когда все указатели на него исчезли. У меня есть указатель на это с чтением, я закрываю дескриптор записи, и файл удаляет, оставляя мой открытый дескриптор нечитаемым. Любой другой путь вокруг этого будет с радостью оценен.DELETE_ON_CLOSE встречается слишком рано

Я также рассмотрел возможность того, что, поскольку это удаленная файловая система, есть что-то напуганное с ручками.

Я не могу изменить код execuatble, который я отправляю, поэтому исполняемый файл самоочистки - последнее, что я хочу сделать.

Заставить мою программу ждать, чтобы очистить службу, приведет к ее зависанию в течение долгого времени из-за того, сколько времени потребуется для уничтожения службы в удаленном ящике.

//Open remote file for reading and set the delete flag 
HANDLE remote_fh = CreateFile(&remote_file_location[0], 
    GENERIC_WRITE, 
    FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 
    NULL, 
    CREATE_ALWAYS, 
    FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, 
    NULL); 

if(!remote_fh) 
{ 
    debug.DebugMessage(Error::GetErrorMessageW(GetLastError())); 
    RevertToSelf(); 
    return dead_return; 
} 

//File to read from 
HANDLE local_fh = CreateFile(&local_file_location[0], 
    GENERIC_READ, 
    FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 
    NULL, 
    OPEN_EXISTING, 
    FILE_ATTRIBUTE_NORMAL, 
    NULL); 


if(!local_fh) 
{ 

    debug.DebugMessage(Error::GetErrorMessageW(GetLastError())); 
    RevertToSelf(); 
    return dead_return; 
} 

byte buf[256]; 

DWORD bytesRead; 
DWORD bytesWritten; 

//Copy the file 
while(ReadFile(local_fh, buf, 256, &bytesRead, NULL) && bytesRead > 0) 
{ 
    WriteFile(remote_fh, buf, bytesRead, &bytesWritten, NULL); 
} 

CloseHandle(local_fh); 


//Create a file retainer to hold the pointer so the file doesn't get deleted before the service starts 
HANDLE remote_retain_fh = CreateFile(&remote_file_location[0], 
    GENERIC_READ, 
    FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 
    NULL, 
    OPEN_EXISTING, 
    FILE_ATTRIBUTE_NORMAL, 
    NULL); 

if (!remote_retain_fh) 
{ 
    debug.DebugMessage(Error::GetErrorMessageW(GetLastError())); 
    RevertToSelf(); 
    return dead_return; 
} 


CloseHandle(remote_fh); 


//if(!CopyFile(&local_file_location[0], &remote_file_location[0], false)) 
//{ 
// debug.DebugMessage(Error::GetErrorMessageW(GetLastError())); 
// RevertToSelf(); 
// return dead_return; 
//} 

remote_service.Create(Service::GetServiceName().c_str()); 

//In the words of my daughter: "OH, OH, FILE ALL GONE!" 
Pipe pipe(L"\\\\" + *hostname + L"\\pipe\\dbg"); 

CloseHandle(remote_fh); 
+4

Это тупик. Используйте [существующий ответ] (http://stackoverflow.com/questions/1606140/how-can-a-program-delete-its-own-executable) –

+0

Я не вижу подходящего существующего ответа. – Bluebaron

+1

Вы говорите: «Я пытаюсь создать процесс на другой машине, которая удаляет себя», но ваш код выглядит так, будто он просто пытается удалить удаленный файл при закрытии - что это такое? Вы пытаетесь создать автономный исполняемый файл? –

ответ

0

FILE_FLAG_DELETE_ON_CLOSE требует разрешения FILE_SHARE_DELETE. Проблема в том, что при запуске процесса операционная система открывает дескриптор файла исполняемому файлу и не требует обмена разрешениями FILE_SHARE_DELETE, чтобы вы не могли удалить исполняемый файл, пока процесс открыт.

Рассмотрите: вы открываете дескриптор исполняемого файла без эксклюзивного FILE_SHARE_DELETE, но говорите только FILE_GENERIC_READ. Кто-то другой (вы, позже или даже другой поток или процесс) запускает этот исполняемый файл. Нет проблем, потому что никто не пытается удалить исполняемый файл. Но если бы вы попытались получить разрешение FILE_SHARE_DELETE, вы потерпите неудачу, потому что исполняемый файл уже запущен с исключительным разрешением удаления файла.