2010-06-19 3 views
0

У меня есть приложение, которое изменяет файл XML с помощью:нарушения обмена на файл, который действительно должен быть закрыт

(а) его открытия,

(б) создание временного файла и запись модифицированной версии это,

(с) закрытие обоих файлов, и

(d) заменить исходный файл во временный файл.

Когда я тестирую его на своем ноутбуке под управлением Vista, все работает так, как должно. На встроенном ПК с XP Professional SP2 с флеш-накопителем вместо жесткого диска (что может быть или не быть релевантным), он не работает на этапе (d) с нарушением прав доступа (код ошибки 5).

Если я вставляю код между шагами (c) и (d), чтобы проверить, что файлы закрыты, он подтверждает, что они; если я поставил код между шагами (c) и (d), чтобы попытаться удалить исходный файл, он не работает с нарушением совместного доступа (код 32). Если я приостановил программу в этот момент и попытаюсь удалить файл из графического интерфейса пользователя, он не сможет выполнить нарушение доступа. Если я использую systinternals «Process Explorer» в этот момент, он показывает, что приложение все еще имеет дескриптор файла.

Вот некоторые из кода:

// Open the file which is to be updated: 
_wfopen_s(&inStream, m_fileName, L"r, ccs=UTF-8"); 

// Obtain a suitable temporary filename from the operating system: 
TCHAR lpTempPathBuffer[MAX_PATH];  // Buffer to hold temporary file path 
TCHAR szTempFileName[MAX_PATH];   // Buffer to hold temporary file name 
GetTempPath(MAX_PATH, lpTempPathBuffer); 
GetTempFileName(lpTempPathBuffer, 
       TEXT("TMP"), 
       0, 
       szTempFileName); 

// Now open a temporary file to hold the updates: 
errno_t err = _wfopen_s(&outStream, szTempFileName, L"w, ccs=UTF-8"); 
if (err == 0) 
    printf ("Temporary file opened successfully\r\n"); 
else 
    printf ("Temporary file not opened; error code %d\r\n", err); 

Тогда Габбинс что модифицирует файл, а затем ...

// Finally, we must close both files and copy the temporary file to 
// overwrite the original input file: 
int closerr = fclose(inStream); 
if (closerr == 0) 
    printf("Original file closed properly\r\n"); 
else 
    printf("Original file not closed properly\r\n"); 

closerr = fclose(outStream); 
if (closerr == 0) 
    printf("Temp file closed properly\r\n"); 
else 
    printf("Temp file not closed properly\r\n"); 

int numclosed = _fcloseall(); 
printf("Number of files closed = %d\r\n", numclosed); 
     // Should be zero, as we've already closed everything manually 

if (!DeleteFile(m_fileName)) 
{ 
    int err = GetLastError(); 
    printf ("Delete file failed, error code was %d\r\n", err); 
} 
else 
    printf ("Delete file succeeded\r\n"); 


if (!MoveFileEx(szTempFileName, m_fileName, 
      MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH)) 
{ 
    int err = GetLastError(); 
    printf ("Move file failed, error code was %d\r\n", err); 
} 
else 
    printf ("Move file succeeded\r\n"); 

Журнал вывода показывает:

«Временный файл успешно открыт

Оригинальный файл правильно закрыт

файл Temp закрыта

Количество файлов закрыто = 0

Удалить файл не удалось, код ошибки был 32

Переместить файл не удалось, код ошибки был 5"

Это не имеет никакого смысла ... Почему я получаю нарушение доступа к файлу, который настаивает операционная система, закрыт? И есть ли причина, почему это работает в Vista, но не в XP?

Огромное спасибо за советы, Stephen.

+0

Вы уверены, что не существует какой-либо другой код, где-то, что открывает файл снова (или предотвращая его закрытия)? Вы должны запустить Process Monitor, чтобы убедиться, что все вызовы Open имеют соответствующие вызовы Close. – Luke

+0

Нет, это определенно не проблема; это проблема с правами доступа к файлам (см. ниже). –

ответ

0

Возможно, проблема связана с правами доступа к файлам. Попробовав различные другие вещи, которые не сработали, я решил попробовать открыть файл с разрешениями на чтение/запись (т. Е. С атрибутом «r +», а не «r»), а затем перезаписать исходное содержимое файла с содержимым временный файл. На этот раз сама команда «_wfopen_s» потерпела неудачу с кодом ошибки 13 («Permission denied»), что указывает на то, что операционная система явно не захотела запретить программе изменять этот файл ни при каких обстоятельствах.

Так что я думаю, мне нужно сформулировать вопрос немного по-другому: почему, когда

(а) мое приложение работает отлично, как есть в Vista, и

(б) можно свободно редактировать файл когда я использую GUI в XP, и все права доступа к файлу выглядят корректно, и

(c) программа, которая пытается изменить файл, запускается из сеанса, который «зарегистрирован», как владелец файла

... может файл не быть модифицированным по программе?

Это любопытство XP или факт, что он работает на встроенном компьютере с флэш-памятью? Если бы это было последнее, я ожидал, что возникнут проблемы при создании новых временных файлов, но это, похоже, работает нормально.

Я еще раз оценил любые предложения.

Стивен

+0

Чтобы сократить длинную историю, это, оказалось, было проблемой с IXMLReader. Ранее в приложении файл был открыт с использованием IXMLReader, но я не смог его явно закрыть. При работе под Vista система каким-то образом размещала это (предположительно, закрывая файл автоматически в какой-то момент), тогда как в XP файл был оставлен открытым, поэтому, естественно, впоследствии не мог быть повторно открыт с доступом для записи. –

+0

Переписывая раздел кода, который вызвал IXMLReader, чтобы убедиться, что файл был закрыт в конце процесса, решил проблему, и приложение теперь хорошо работает как в XP, так и в Vista. –

2

Следует помнить, что время доступа может быть намного длиннее, и действия с файлами часто обрабатываются асинхронно. Windows может вернуться к вашему коду, заявив, что файл закрыт до того, как драйвер устройства действительно выпустил его. Вы идете удалить его, и он действительно все еще используется, в соответствии с драйвером устройства.

Я предлагаю установить задержку там для тестирования (скажем, 5-10 секунд) после закрытия файла и перед попыткой удалить файл. Если это сработает, то вам нужно выполнить цикл действия удаления пару раз (с небольшой задержкой в ​​цикле) и выйти из цикла, когда удастся удастся, или вы нажмете максимальное количество попыток (скажем, 4 -5).

Если у вас все еще есть такая же проблема, даже при 30-секундной задержке, то проблема, вероятно, лежит где-то в другом месте.

Смежные вопросы