Как скопировать занятый процессом файл

Обновлено: 06.07.2024

Как скопировать файл, который занят другим приложением?

Здравствуйте.
Есть необходимость скопировать файл, но есть и проблема.

Суть проблемы:
- есть специфичное клиент-серверное приложение, написанное по заказу сторонними разработчиками;
- исходников, естественно, нету;
- приложение использует неизвестный формат БД (один файл

80 мб);
- сервер постоянно запущен и останавливать его крайне нежелательно, а уж о постоянных остановках и речи быть не может;
- недавно появилась необходимость бэкапить БД;
- когда я пытаюсь скопировать файл с базой данных, мне ОС пишет, что данный файл занят другим процессом;
- то же самое происходит, когда я пытаюсь создать поток TFileStream к этому файлу

Подскажите пожалуйста, можно ли прочитать такой файл из своей программы (это в идеале), или существуют ли какие-нибудь утилиты для копирования таких файлов?

зависит от способа открытия БД.

Но, даже если файловая система и позволит это сделать - это будет НЕПРАВИЛЬНО.
В момент копирования могут быть незавершённые транзакции - возможно (теоретически) получить битый набор данных.
Для начала попробуйте воспользоваться штатными средствами Backup'а данных, имеющихся в Вашей СУБД (впрочем, если это самописная БД - тогда всё намного хуже ).

p.s. кстати, попробуйте скопировать файл (или просмотреть файл по ALT-F3) в Far Commander. Если он не сумеет этого сделать, значит СУБД открыто в монопольном режиме и скопировать (без остановки процесса) не получится.

Для начала попробуйте воспользоваться штатными средствами Backup'а данных, имеющихся в Вашей СУБД (впрочем, если это самописная БД - тогда всё намного хуже ).

p.s. кстати, попробуйте скопировать файл (или просмотреть файл по ALT-F3) в Far Commander. Если он не сумеет этого сделать, значит СУБД открыто в монопольном режиме и скопировать (без остановки процесса) не получится.

Я подозреваю, что именно в монопольном режиме файл и открыт.
Собственно, я надеялся, что может быть есть возможность прочитать файловую систему (NTFS), найти все смещения для требуемого файла и побайтно считать его напрямую с жёсткого диска в обход операционки.
Такое, в принципе, возможно (т.е. есть такая физ. возможность и про это можно найти материалы в интернете)? Потому что, если не получится - то придётся изгаляться с ночными отключениями и запусками сервера приложений.

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

Примеры открытых файлов:

  • файлы MS Outlook (*.pst, *.ost)
  • файлы MS Exchange Server
  • диски виртуальных машин - Virtual Hard Disk (файлы VHD, VHDX)
  • файлы MS SQL Server (*.mdf, *.ldf)
  • файлы MS Access (*.mdb, *.ldb)
  • файлы MS Word, MS Excel (*.docx, *.xlsx)
  • файлы NTUSER.dat в папке с профилями пользователей C:\Users
  • и другие

Например, в MS Outlook все ваши данные (почта, контакты, задачи, календарь) хранятся в файле вида:
"C:\Users\<Ваш профиль>\Documents\Файлы Outlook\yourname@domain.com.pst"
или
"C:\Users\<Ваш профиль>\AppData\Local\Microsoft\Outlook\yourname@domain.com.pst",
в зависимости от настроек, расположенных в меню "Файл -> Настройка учетных записей", вкладка "Файлы данных".

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

(The process cannot access the file because it is being used by another process).

или текст ошибки может выглядеть немного иначе:

0x80070021: Процесс не может получить доступ к файлу, так как часть этого файла заблокирована другим процессом (Отказано в доступе).

0x80070021: The process cannot access the file because another process has locked a portion of the file (Access denied).

Процесс не может получить доступ к файлу (файл используется другим процессом)

Ошибка копирования файла, если файл занят другим процессом

Решение проблемы резервного копирования занятых (открытых) файлов

Существует 2 способа:

  1. Перед созданием дубликата файлов закрыть программу, которая использует эти файлы. Например, вы можете жестко закрыть MS Outlook ("убить" процесс), используя команду: taskkill /im outlook.exe /f
  2. Использовать Volume Shadow Copy для "горячего" копирования открытых файлов (заблокированных файлов).

Первый способ - слишком жесткий и не всегда возможен, т.к. иногда для снятия задачи (kill process) в Диспетчере задач требуются повышенные привилегии. К тому же, целостность данных не гарантирована, поскольку во время жесткой выгрузки процесса из памяти этот процесс может производить запись на диск и тогда файл останется поврежденным (недописанным).

Второй способ - более гуманный, так как использует технологию теневого копирования тома Volume Shadow Copy от Microsoft и гарантирует целостность данных на диске.

Ниже будет рассмотрен способ создания копии файлов "на горячую", которые используются другим приложением, то есть 2 способ с помощью утилиты Exiland Backup Professional.


Скачайте демо-версию Exiland Backup Professional.
Далее рассмотрим как делать бэкап залоченных файлов

Что такое горячее или теневое копирование (shadow copying)?

Теневое копирование - это технология Microsoft, которая позволяет копировать файлы, занятые другим приложением. Это возможно благодаря созданию мгновенного снимка файловой системы (Shapshot), в то время как файловая система продолжает работать в штатном режиме без каких-либо блокировок. Таким образом, процесс создания дубликата возможен без прерывания работы текущих приложений. Служба теневого копирования VSS - Volume Shadow Service работает фоном и осуществляет доступ к данным на диске, даже если файл в этот момент используется другим приложением. Целостность данных при этом не нарушается.

ОБРАТИТЕ ВНИМАНИЕ!. Технология Volume Shadow Copy относится ко всему диску целиком, а не к отдельным файлам на диске, таким образом, вы не сможете создать теневую копию какого-либо отдельного файла. Тем не менее, вы можете сначала создать копию всего тома, затем подключить ее в системе как отдельный логический диск, например, Z:\ и после этого выборочно скопировать нужные вам файлы с этого диска (из shadow копии).

Где хранятся теневые копии и сколько занимают места?

Теневые копии тома, как правило, хранятся в скрытой системной папке "System Volume Information", расположенной в корне каждого диска. Размер одной теневой копии диска составляет около 100-300 МБ, что значительно меньше суммарного объема данных, хранящихся на диске. Место под хранение таких копий на диске отведено системой заранее и вам не нужно об этом беспокоиться.

Как Exiland Backup Professional копирует залоченные файлы

В программе Exiland Backup, начиная с версии 4.9, резервное копирование открытых файлов, таких как MS Outlook (pst, ost), MS Access (*.mdb), MS SQL Server (*.mdf) и других полностью автоматизировано. Если у вас нет глубоких знаний операционной системы или вы просто хотите сэкономить время, используйте Exiland Backup. Утилита взаимодействует со службой теневого копирования, встроенной в операционную систему Windows.

Алгоритм горячего бэкапа в Exiland Backup достаточно простой:

  1. сначала программа создает временную теневую копию тома (слепок файловой системы - snapshot), из которого необходимо скопировать файлы.
  2. затем созданная копия подключается как логический диск
  3. производится копирование выбранных файлов с подключенного диска (из теневой копии) в папку назначения
  4. удаление этой временной копии.

Как настроить копирование файлов Outlook (PST, OST), не закрывая Outlook у пользователей

При создании задания вы указываете исходные файлы и папки. Если вы знаете, что исходные файлы во время создания бэкапа могут использоваться другим приложением, то установите опцию "[x] Использовать теневое копирование VSS (Volume Shadow Copy) для диска", как показано на скриншоте ниже. Если исходные данные расположены на нескольких дисках, то программа предложит создание теневых копий для нескольких томов поочередно.

Настройка теневого создания резервной копии открытых файлов

Процесс копирование открытых файлов

Во время выполнения задания в журнале будет видно, что программа сначала создает временную теневую копию диска C, затем копирует из нее данные, а после выполнения задания удаляет ранее созданную shadow копию, чтобы она не занимала место на диске. Пример журнала выполнения задания показан ниже.

VSS Backup: создание резервной копии, используя теневое копирование тома

Таким образом, нам удалось создать резервную копию нужных нам залоченных файлов "нагорячую" благодаря поддержки VSS в Exiland Backup Professional. Главное удобство в том, что не нужно никого "выгонять" из программ - копирование происходит незаметно для пользователя.

Предположим, что вы хотите скопировать файл, который намертво заблокирован другой программой. В результате Windows нам радостно сообщит о том, что системный процесс не может получить доступа к файлу, поскольку последний заблокирован другим процессом. Как же тогда скопировать такой файл?

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

заблокированный файл

Начиная с Windows XP операционная система от Microsoft поддерживает технологию теневого копирования (она же Volume Shadow Copy). Данная технология используется для резервного копирования данных и восстановления системы. В частности, теневая копия представляет собой временный “снимок” файла или раздела жесткого диска. При этом одна программа может получить доступ чтения именно к снимку, в то время как другие программы могут в это же время работать с файлом или изменять его.

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

На следующей странице можно загрузить HoboCopy для Windows XP и Windows Vista/7 в версиях 32/64 бит:

Для работы HoboCopy (да и многих других программ для резервного копирования) нам надобятся две следующих службы Windows:

  • Теневое копирование тома
  • MS Software Shadow Copy Provider

Если вы забыли, где просмотреть службы, то в Windows 7 перейдите по пути Панель управления > Система и безопасность > Администрирование > Службы (а в Windows XP – Панель управления > Администрирование > Службы).

Убедитесь в том, что службы не отключены. Если для них указан режим запуска Вручную, то программа HoboCopy самостоятельно запустит эти службы, когда понадобится и отключит их по завершению своей работы.

Резервное копирование одного файла с помощью HoboCopy

Как вы помните, HoboCopy – утилита командной строки. К слову сказать, в Windows 7 и Windows Vista ее нужно запускать в режиме администратора, для чего щелкните на файле программы правой кнопкой мыши, выберите команду Свойства > Дополнительно и установите флажок Запуск от имени администратора. Также будет не лишним ознакомиться со статьей Запуск программ Windows 7 в режиме администратора.

Синтаксис команды выглядит следующим образом:

К примеру, мы решили скопировать файл c:\users\windata\mail\outlook.pst прямо вот сюда: d:\backups\outlook.pst.

Команда будет выглядеть следующим образом:

Резервное копирование каталога с помощью HoboCopy

Чем копировать по одному файлу, разумеется, куда лучше настроить резервное копирование целыми папками. Для этого нам понадобятся такие ключи:

Синтаксис команды следующий:

Например, используя предыдущий пример, скопируем всю пользовательскую папку в папку d:\backups\. Для этого нам понадобится такая команда:

Инкрементное копирование файлов с помощью HoboCopy

Утилита HoboCopy поддерживает и инкрементный тип копирования. Что это такое? Весьма полезная функция, она позволяет копировать только те файлы, что изменились с момента предыдущего резервного копирования. При этом последняя дата копирования хранится в файле, который вам нужно указать непосредственно в команде утилиты.

Для инкрементного копирования потребуются два ключа:

  • /statefile=имя_файла – это имя файла, в котором будут записаны данные о последнем копировании
  • /incremental – а это, как понятно из названия, ключ для инкрементного копирования

Синтаксис команды выглядит так:

Таким образом, утилита HoboCopy позволяет настроить автоматическое копирование папок, для чего нужно лишь запланировать процедуру копирования. В Windows 7/Vista для этого используйте системную программу Планировщик заданий (Панель управления > Система и безопасность > Администрирование > Расписание выполнения задач), а в Windows XP – окно Назначенные задания (Панель управления > Назначенные задания).

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

Как скопировать занятый файл

  • Как скопировать занятый файл
  • Как скопировать System файл
  • Как скопировать из архива

Проверьте, какой программой занят нужный вам файл. Особое внимание уделите программам, работающим в фоновом режиме, обычно они бывают свернуты в трей на панель задач в правом нижнем углу экрана. Также проверьте различные проигрыватели, редакторы, программы просмотра изображений и так далее. Также файл может быть занят параллельным копированием, перемещением или удалением.

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

После этого запустите диспетчер задач Windows при помощи нажатия сочетания клавиш Shift+Ctrl+Esc или Alt+Ctrl+Delete, перейдите к запущенным на вашем компьютере процессам, найдите нужный в списке и нажмите на него правой кнопкой мыши. Выберите вариант «Завершить дерево процессов» в контекстном меню.

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

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

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

Поиск хэндла открытого файла.

Если файл открыт каким-либо процессом, то этот процесс имеет его хэндл. Во второй моей статье по перехвату апи я описывал открытие процесса путем поиска нужного хэндла, ничто не мешает нам использовать этот метод и для доступа к открытым файлам. Нам нужно перечислить хэндлы с помощью ZwQuerySystemInformation, скопировать каждый хэндл себе с помощью DuplicateHandle, определить файл к которому он относиться (ZwQueryInformationFile), и если это нужный файл, то наконец можно его копировать.

Попробуем для начала реализовать перечисление всех открытых в системе файлов. При перечислении хэндлов, каждый хэндл будет описываться следующей структурой:

Теперь зная тип хзндла мы можем перечислить открытые в системе файлы. Для начала реализуем получение имени открытого файла по его хэндлу:

Вот теперь собственно можно и перечислить открытые файлы:

Теперь для копирования файла нам остается лишь прочитать его с помощью ReadFile при нахождении нужного хэндла. При необходимости следует принять вышеописанные меры осторожности.

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

Изменение прав доступа существующего хэндла.

Все занятые файлы (за исключением файлов подкачек) обычно удается открыть на чтение атрибутов (FILE_READ_ATTRIBUTES), это позволяет читать атрибуты файла, получать его размер, перечислять NTFS потоки, но к сожалению ReadFile завершается неудачно. Чем отличается открытие файла с разными атрибутами доступа? Очевидно, что при открытии файла система запоминает атрибуты доступа, и потом сравнивает запрашиваемый доступ с этими атрибутами. Если найти то место, куда система сохраняет эту информацию и изменить атрибуты доступа, то можно будет не только читать, а даже писать в любой файл который удалось вообще как-либо открыть.

На уровне пользователя мы работаем с файлом не напрямую, а через его хэндл (этот хэндл указывает на FileObject), а функции ReadFile/WriteFile вызывают ObReferenceObjectByHandle указывая ему соответствующий тип доступа. Из этого можно сделать вывод, что права доступа хранятся в самой структуре описывающей хэндл. И действительно, структура HANDLE_TABLE_ENTRY содержит поле GrantedAccess, которое и есть ни что иное, как эти самые права доступа связанные с хэндлом. К сожалению, программисты Mocrosoft не предусмотрели API для изменения доступа хэндлов, поэтому, как вы поняли, нам придется писать драйвер чтобы это сделать.

Для получения указателя на структуру хэндла случит неэкспортируемая функция ExpLookupHandleTableEntry, но искать мы ее не будем, так как на нее нет прямых ссылок из экспортируемых функций и поиск будет слишком ненадежным, к тому же нам тогда понадобиться еще и функция ExUnlockHandleTableEntry. Лучшим выходом будет написать свою функцию лукапа по таблицам хэндлов. В виду отличия структур таблиц хэндлов в Windows 2000 и XP, эта функция для них будет выглядеть по разному.

Для начала сделаем такую функцию для Windows 2000:

Этот код прост и понятен. Так как значение хэндла представляет из себя три индекса в трехуровневой таблице, то мы просто извлекаем их чисти и смотрим соответствующий элемент таблицы (если он конечно существует). Так как таблица хэндлов в Windows XP может иметь от одного до трех уровней, то код лукапа соответственно будет сложнее:

Как вы видите, хэндл в этом коде представлен не ULONG значением, а структурой EXHANDLE:

Как вы видите, хэндл содержит не только индексы в таблице, но и 2 бита служебных флагов. Наверное вы замечали, что одинаковый хэндл может иметь несколько разных значений, это связано с тем, что не все биты значения хэндла используются (зависит от числа уровней в таблице). Наиболее характерно это явление проявляется в Windows XP.

Итак, теперь мы можем получить нужный элемент таблицы хэндлов, пора писать функцию устанавливающую на хэндл нужные атрибуты доступа:

Теперь сделаем драйвер устанавливающие атрибуты доступа на хэндл переданный ему по DeviceIoControl. Его код будет выглядеть так:

Поле GrantedAccess в структуре хэндла к сожалению не соответствует атрибутам открытия файла (GENERIC_READ, GENERIC_WRITE e.t.c.), поэтому при установке новых атрибутов доступа нам понадобятся следующие константы:

Теперь напишем простую программку которая используя этот драйвер будет копировать SAM файл в корень диска c:

Самым большим недостатком этого метода является сильная зависимость от операционной системы. Также его применение вынуждает таскать с своей прогой драйвер, что не всегда приемлемо. Но в плане надежности этот способ один из лучших, поэтому я рекомендую его применять в бекаперах (но только после продолжительного тестирования и отладки!). Но так как способ не подходит для любых ситуаций, мы перейдем к следующему способу.

Чтение файла с помощью прямого доступа к диску.

При вызове DeviceIoControl с этим кодом, InputBuffer должен содержать структуру STARTING_VCN_INPUT_BUFFER описывающую начальный элемент цепочки кластеров с которого мы хотим получить карту размещения файла, а после успешного выполнения функции OutputBuffer будет содержать структуру RETRIEVAL_POINTERS_BUFFER которая описывает карту размещения. Давайте рассмотрим эти структуры подробнее:

Итак, теперь структура выходной информации понятна, и пришла пора написать функцию получающую полный список кластеров файла и представляющую его в виде массива:

На выходе этой функции мы имеем массив описывающий кластеры файла и число этих кластеров, теперь можно легко скопировать файл:

Вот собственно и все, скопировать SAM теперь просто как три рубля :). В примерах к статье есть программка копирующая SAM в файл указанный в ее командной строке.

Несомненно этот метод выглядит просто и кажется весьма мощным, но к сожалению и ему присущи недостатки. Таким способом можно читать только файлы которые можно открыть с доступом FILE_READ_ATTRIBUTES (не читаются только файлы подкачки), файл обязательно должен быть не сжат, не зашифрован (иначе мы прочитаем ерунду), и должен иметь свой кластер (маленькие файлы в NTFS могут целиком размещаться в MFT). Также следует учесть, что во время чтения файл может быть изменен (и мы получим в результате фиг знает что).

Итак, как работать с файловой системой на низком уровне, я думаю всем теперь понятно. Эта методика открывает немалые возможности для различных руткитов. Существуют программы защищающие системные файлы от модификации, (примером такой программы может быть антивирус), но при наличии прав достаточных для открытия тома в RAW режиме, такие ограничения быстро сходят на нет. К тому же хороший администратор может настроить ведение логов чтения/записи важных файлов на своем сервере, а прямой доступ к тому никаких логов не оставляет, но для полноценного доступа к файлам придется писать свой драйвер NTFS.

Читайте также: