Задача:
Имеется файл, изменения которого необходимо отслеживать. При его изменении/удалении/создании нужно выполнить какое-либо действие. Операционная система Windows 7 и выше.
Решение:
Для примера возьмем файл C:\Soft\Test\MyDoc.xls, и при изменении будем его копировать на рабочий стол компьютера в ЛВС. Например, путь куда будем копировать: \\Book01\c$\Documents and Settings\User\Рабочий стол\MyDoc.xls
-
В Локальных политиках безопасности (secpol.msc) -> Параметры безопасности -> Локальные политики -> Политика аудита -> включаем политику Аудит доступа к объектам -> Успех:
Включение аудита:
Примечание: Здесь лучше пользоваться «Расширенной политикой аудита», которая доступна в версиях Windows начиная с Vista и выше, поскольку включение всей политики «Аудит доступа к объектам» приведет к огромному количеству ненужных записей в журнале безопасности. А «Расширенная политика аудита» позволяет настраивать аудит для конкретных событий. В данном случае нам нужно включить параметр «Доступ к объектам» -> «Аудит файловой системы». Подробнее смотрим в статье «Расширенные политики аудита».
-
В свойствах безопасности папки, в которой находится отслеживаемый файл
Безопасность папки:
настраиваем политику аудита для группы ВСЕ:
-
Тип - Успех;
-
Применяется к: - Здесь указываем область, для которой нужно отслеживать доступ. Если это только один файл в папке, то нужно указать: «Только для файлов», если же требуется отслеживать все содержимое, в том числе и содержимое подпапок, то указываем: «Для этой папки, ее подпапок и файлов»;
Общие разрешения - Запись.
Настраиваем аудит:
Можно так же добавить аудит событий удаления подпапок и файлов (это может понадобиться, например, если наблюдаемый файл будет синхронизироваться сторонним ПО типа Яндекс.Диск):
Аудит с удалением:
и получаем настроенный аудит для папки:
Настроенный аудит папки:
-
-
Создаем PowerShell скрипт и сохраняем его, например по пути C:\Soft\Bat\MyDoc.ps1:
Код сценария PowerShell
Код: Выделить всё
$login = "UserName" #Имя пользователя для подключения сетевого диска $pass = ConvertTo-SecureString "MyPassword" -AsPlainText -Force #Преобразуем пароль для подключения сетевого диска в защищенную строку $creds = New-Object System.Management.Automation.PSCredential ($login, $pass) #Преобразуем учетные данные к типу PSCredential New-PSDrive -Name MyDrv -PSProvider FileSystem -Root "\\Book01\c$\Documents and Settings\User" -Credential $creds #Подключаем сетевой ресурс \\Book01\c$\Documents and Settings\User как диск с именем MyDrv, используя полученные ранее учетные данные Start-Sleep -s 10 #Даем спокойно закрыться файлу и записать все события в журнал $SourceFile="C:\Soft\Test\MyDoc.xls" #Источник - файл, за которым следим $DestFile="\\Book01\c$\Documents and Settings\User\Рабочий стол\MyDoc.xls" #Файл, в который будем копировать (здесь можно использовать синтаксис с использованием подключенного сетевого диска, тогда путь будет таким: "MyDrv:\Рабочий стол\MyDoc.xls") #Если за последние 30 секунд в журнале "Безопасность" возникло событие 4663, содержащее в описании имя исходного файла, то if (Get-WinEvent -maxevents 1 -FilterHashtable @{LogName=”Security”;ID=4663;Data=$SourceFile;StartTime=(Get-Date).AddSeconds(-30)}) { copy-item -path $SourceFile -destination $DestFile -Force #Копируем отслеживаемый файл в новое место }
Чуть дальше, при создании триггера будет понятно, что в скрипте можно было и не фильтровать события, поскольку сам триггер у нас будет настроен именно на событие записи именно отслеживаемого файла. В принципе, из всего скрипта можно оставить только подключение сетевого диска, задержку в 10 секунд и саму операцию копирования файла. То есть можно смело вместо PowerShell использовать обычный командный файл. Но мне как-то больше приглянулся PowerShell...
А можно чуть изменить скрипт. Например, при изменении файла будем отправлять его на электронную почту:
Измененный код PowerShell:
Код: Выделить всё
$ConstServer = "smtp.server.ru" #SMTP сервер $ConstSMTPPort = "25" #Порт SMTP сервера $ConstFrom = "sender@server.ru" #Адрес отправителя $ConstTo = "recepient@server.ru" #Адрес получателя $ConstMessageTypeHTML = $false #Формат сообщения HTML (true) или обычный текст (false) $ConstUserName = "sender@server.ru" #Имя пользователя (ящика) для авторизации на SMTP сервере $ConstUserPass = "MyPassword" #Пароль для авторизации на SMTP сервере $ConstMessageSubject = "Изменен файл " #Тема сообщения $ConstMessageBody = " - изменен файл " #Тело сообщения $SourceFile="C:\Soft\Test\MyDoc.xls" #Файл, за которым следим Start-Sleep -s 10 #Даем спокойно закрыться файлу и записать все события в журнал #Если за последние 30 секунд в журнале "Безопасность" возникло событие 4663, содержащее в описании имя исходного файла, то if (Get-WinEvent -maxevents 1 -FilterHashtable @{LogName=”Security”;ID=4663;Data=$SourceFile;StartTime=(Get-Date).AddSeconds(-30)}) { #Создаем необходимые объекты и задаем переменные, необходимые для отправки и формирования SMTP сообщения: $SmtpClient = New-Object System.Net.Mail.SmtpClient $Message = New-Object System.Net.Mail.MailMessage $SmtpClient.Host = $ConstServer $SmtpClient.Port = $ConstSMTPPort $Message.From = $ConstFrom $Message.To.Add($ConstTo) $Message.BodyEncoding = [System.Text.Encoding]::UTF8 $Message.SubjectEncoding = [System.Text.Encoding]::UTF8 $Message.IsBodyHtml = $ConstMessageTypeHTML $Message.Subject = $ConstMessageSubject + """" + $SourceFile + """" $SmtpClient.Credentials= New-Object System.Net.NetworkCredential($ConstUserName , $ConstUserPass) $Message.Attachments.Add($SourceFile) $Message.Body = (get-date).ToString() + $ConstMessageBody + """" + $SourceFile + """" $SmtpClient.Send($Message) #Отправляем SMTP сообщение $Message.Dispose() #Отправляем сообщение QUIT на SMTP-сервер (правильно завершаем TCP-подключение и освобождаем все ресурсы, используемые текущим экземпляром класса SmtpClient) }
-
В планировщике заданий создаем новую задачу:
-
На вкладке «Общие» настраиваем параметры: Скрытая задача, Для всех пользователей, Выполнять с наивысшими правами:
Вкладка «Общие»:
-
На вкладке «Триггеры» создаем триггер для этой задачи. В свойствах нового триггера указываем: Начинать задачу «При событии», в параметрах выбираем «Настраиваемое» и нажимаем «Создать фильтр события»:
Настройка триггера:
В свойствах фильтра события переходим на вкладку «XML», ставим галочку «изменить запрос вручную» и копируем содержимое запроса:
Свойства фильтра события:
Код XML запроса:
Код: Выделить всё
<QueryList> <Query Id="0" Path="Security"> <Select Path="Security"> ((*[System[Provider[@Name='Microsoft-Windows-Security-Auditing'] and (Level=4 or Level=0) and Task = 12800 and (band(Keywords,9007199254740992)) and (EventID=4663)]]) and (*[EventData[Data[@Name="ObjectName"] and (Data='c:\soft\Test\MyDoc.xls')]])) </Select> </Query> </QueryList>
Здесь c:\soft\Test\MyDoc.xls - полный путь до контролируемого файла.
Этот триггер отбирает все события из журнала «Безопасность» с Уровнем - Сведения, Источником - Microsoft Windows Security Auditing, Кодом - 4663, Категорией - Файловая система, Ключевым словом - Аудит успеха, у которых в данных самого события есть запись с именем «ObjectName», значение которой равно нашему контролируемому файлу c:\soft\Test\MyDoc.xls.
По-сути, мы фильтруем все события записи, относящиеся к искомому файлу.
В итоге получаем триггер с пользовательским фильтром событий:
Получившийся триггер
-
На вкладке «Действия» создаем новую задачу с параметрами: Действие - Запуск программы, Программа или сценарий - C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe, Добавить аргументы - -WindowStyle Hidden C:\Soft\Bat\MyDoc.ps1:
Новая задача:
То есть мы запускаем оболочку PowerShell, с параметром -WindowStyle Hidden (что означает - в скрытом режиме) и выполняем написанный нами ранее PowerShell скрипт C:\Soft\Bat\MyDoc.ps1
-
На вкладке «Условия» снимаем все галочки, поскольку задача должна запускаться вне зависимости от условий питания и простоя:
Условия:
-
И последняя вкладка «Параметры». Ставим галочки: Выполнять задачу по требованию, Принудительная остановка задачи, если она не прекращается по запросу, параметр «Останавливать задачу, выполняемую дольше» настраиваем на минимальное время, а параметру «Если задача уже выполняется, то применять правило» назначаем значение «Не запускать новый экземпляр»:
Параметры:
-
Теперь, после изменения файла C:\Soft\Test\MyDoc.xls он будет копироваться в \\Book01\c$\Documents and Settings\User\Рабочий стол\MyDoc.xls
Дополнение: в принципе, этот метод можно адаптировать и под Windows XP, но, честно говоря, эта ОС уходит в прошлое и уже просто не хочется тратить время. Тем не менее, если кому понадобится, то даю наводки - из журнала событий берем события 560 и 567 и совместно их анализируем - в 560-м имя файла, в 567-м - метод (чтение или запись). Для запроса событий журнала из PowerShell используем командлет Get-EventLog, будет запрос типа такого:
Код: Выделить всё
Get-EventLog -LogName Security -EntryType SuccessAudit -InstanceId 560 -Message *C:\Soft\Temp* -Newest 1 -Source Security
Сохраняем полученный скрипт в папке, например «c:\Soft\Bat\WriteFileAudit.ps1», ну и создаем триггер на событие 560 журнала Security так, как описано здесь, получится что-то подобное:
Код: Выделить всё
eventtriggers /create /TR "Write File" /TK "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -WindowStyle Hidden c:\Soft\Bat\WriteFileAudit.ps1" /L Security /EID 560