Evgenii Legotckoi
11 травня 2020 р. 15:38

Qt WinAPI - Урок 010. Як перевірити, заборонена чи запис файлу іншим процесом.

Дивно, але факт, в процесі своєї професійної діяльності я натрапив на одну цікаву особливість QFile. З його допомогою можна перевірити, чи можна вважати або записати інформацію в файл. Але при цьому QFile ігнорує права читання і запису файлу, якщо файл відкривається декількома екземплярами однієї програми. Це означає, що якщо файл відкритий в іншому екземплярі програми, то QFile визначить цей файл як можливий до читання або запису, а також успішно зможе зробити запис в файл.


Опис проблеми

Перевірку заборони запису можна виконати наступним чином, але це не завжди працює, як я і сказав вище. Але виконати перевірку можна так

  1. bool isFileWritable(const QString& fileName)
  2. {
  3.      QFile file(fileName);
  4.      bool isWritable = file.open(QFile::ReadWrite);
  5.      file.close();
  6.      return isWritable;
  7. }

Однак перевірити твердження сказане на самому початку статті можна за допомогою наступного коду.

  1. #include <QCoreApplication>
  2.  
  3. #include <QFile>
  4. #include <QDebug>
  5. #include <QDateTime>
  6.  
  7. int main(int argc, char *argv[])
  8. {
  9. QCoreApplication a(argc, argv);
  10.  
  11. // Подставьте любой удобный для вас путь к файлу
  12. QFile file("D:/check.txt");
  13. file.write(QDateTime::currentDateTime().toString().toLatin1());
  14. file.flush();
  15.  
  16. return a.exec();
  17. }
  18.  

Після складання програми запустіть кілька екземплярів разом і ви побачите, що вміст файлу буде відповідати часу останнього запущеного екземпляра. Тобто QFile повністю ігнорує права доступу і володіння файлом іншими процесами. Однак якщо запустити цю програму, а потім спробувати переписати вміст файлу іншою програмою, наприклад стандартним Notepad, то ви отримаєте наступне повідомлення.

Рішення

Я знайшов рішення даної ситуації у використанні платформозавісімого функціоналу в WinAPI, напевно можливі аналоги і для інших ОС.

Для цього вам потрібно створити унікальний покажчик на потік введення/виводу std::wofstream , який буде володіти файлом, можна його розташувати в якомусь класі MyFileBlocker , наприклад.
Питання організації місця для блокувальника файлу вже залишу на ваш розсуд.

  1. std::unique_ptr<std::wofstream> m_openedFile;

А потім написати дві функції для блокування і розблокування файлу.

  1. void MyFileBlocker::unlockFile()
  2. {
  3. m_openedFile.reset(nullptr);
  4. }
  5.  
  6. void MyFileBlocker::relockFile(std::wstring fileName)
  7. {
  8. m_openedFile.reset(new std::wofstream());
  9. // _SH_DENYWR is WinAPI dependent deny write mode
  10. m_openedFile->open(fileName, std::ios_base::app, _SH_DENYWR);
  11. if (!m_openedFile->is_open())
  12. {
  13. m_openedFile.reset(nullptr);
  14. }
  15. }

А потім вже можна робити перевірку, і якщо покажчик існує, то можна виконувати дії записи у файл.

  1. if (m_openedFile)
  2. {
  3. // You can write to file
  4. }

Також, припускаю, що можна вирішити цю проблему за допомогою уніфікації запущеного процесу програми, щоб кожен екземпляр визначався як унікальний щодо прав доступу до файлу.
Але буду чесний, на момент вирішення цього завдання мені це в голову не прийшло, тому вирішив цю проблему з використанням std::wofstream .

Рекомендовані статті на цю тему

По статті запитували0питання

1

Вам це подобається? Поділіться в соціальних мережах!

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
  • Останні коментарі
  • Evgenii Legotckoi
    16 квітня 2025 р. 17:08
    Благодарю за отзыв. И вам желаю всяческих успехов!
  • IscanderChe
    12 квітня 2025 р. 17:12
    Добрый день. Спасибо Вам за этот проект и отдельно за ответы на форуме, которые мне очень помогли в некоммерческих пет-проектах. Профессиональным программистом я так и не стал, но узнал мно…
  • AK
    01 квітня 2025 р. 11:41
    Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
  • Evgenii Legotckoi
    09 березня 2025 р. 21:02
    К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
  • VP
    09 березня 2025 р. 16:14
    Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…