Главная > Powershell > Перезапуск службы печати на удалённом ПК

Перезапуск службы печати на удалённом ПК

Недавно ко мне обратился человек с просьбой помочь в написании скрипта для перезапуска службы печати для того, чтобы очистить очередь печати от “застрявших” заданий – которые не печатаются, не отменяются и не удаляются. Мне это показалось банальным и скучным, поэтому я предложил сделать это сразу для удалённого компьютера.

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

Restart-Service spooler

Если службу нужно перезапустить на удалённом компьютере уже становится веселее, так как Restart-Service не умеет работать с удалёнными компьютерами. Впрочем, такой подход нам всё равно не подходит, так как не гарантирует очистку очереди печати.

Это ещё не всё, самое интересное впереди, но сначала…

Немного теории

Очередь печати – это файлы с расширениями

  • .SHD (содержит настройки задания печати)
  • .SPL (содержит, собственно, данные, которые нужно напечатать).

По умолчанию эти файлы находятся в каталоге %systemroot%\System32\spool\PRINTERS. “По умолчанию” как-бы намекает на то, что этот путь можно изменить. И нам для начала этот путь нужно было узнать, чтобы убедиться в том, что файлы очереди печати лежат здесь (наверное, бывало по другому).

Этот путь хранится в реестре, по адресу HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers, ключ DefaultSpoolDirectory:

 Registry - DefaultSpoolDirectory

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

Поэтому вырисовывается алгоритм:

  1. Остановить службу печати
  2. Определить путь к файлам очереди печати
  3. Удалить эти файлы
  4. Запустить очередь печати

Всё очень просто. Задача осложняется тем, что мы хотим это всё делать на удалённом компьютере.

Переходим к практике

Чтобы не загромождать статью, я не буду приводить кучу проверок (на то, что компьютер доступен, что у нас есть доступ к WMI и т.д.).

Итак, для начала нам нужно узнать путь к очереди печати, т.е. посмотреть значение реестра удалённого компьютера. Для этого используем .NET класс RegistryKey.

Для того, чтобы подключиться к реестру удалённого компьютера используем метод OpenRemoteBaseKey, передав ему в качестве параметров имя компьютера и раздел реестра:

$ServerKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey(
    [Microsoft.Win32.RegistryHive]::LocalMachine, $ComputerName)

Далее, пробираемся по интересующему нас пути, используя для полученного раздела метод OpenSubKey, задав ему в качестве параметра нужный подраздел:

$Key = $ServerKey.OpenSubKey('SYSTEM\CurrentControlSet\Control\Print\Printers')

Переменная $Key содержит весь подраздел Printers (на скриншоте выше). Нам из этого раздела нужно только одно значение:

$DefaultSpoolDirectory = $Key.GetValue('DefaultSpoolDirectory')

Переменная $DefaultSpoolDirectory содержит тот самый путь к файлам очереди печати:

PS C:\> $DefaultSpoolDirectory
C:\WINDOWS\System32\spool\PRINTERS

Отлично! Вот только появляется новая проблема: это локальный путь – по этому пути к удалённому компьютеру мы не доберёмся. Нужно преобразовать его в UNC-путь, т.е. из пути

C:\WINDOWS\system32\spool\PRINTERS

получить путь

\\ComputerName\C$\WINDOWS\system32\spool\PRINTERS

Это можно сделать простой манипуляцией со строкой:

$RemoteDefaultSpoolDirectory =
    '\\'+ $ComputerName + '\' +
    $DefaultSpoolDirectory[0] + '$' + $DefaultSpoolDirectory.Substring(2)

Т.е. просто дописываем в строку (наш локальный путь) недостающие символы.

Теперь всё готово, можем останавливать службу и очищать очередь печати.

Останавливаем службу печати:

# Получаем службу
$Service = Get-WmiObject Win32_Service @PSBoundParameters

# Останавливаем службу
$Service.StopService()

На всякий случай поясню – в данном случае при обращении к WMI используется сплаттинг, если такая форма кажется незнакомой и пугающей рекомендую почитать соответствующую статью, или воспользоваться более привычной формой:

$Service = Get-WmiObject Win32_Service `
            -Filter "name = 'spooler'" `
            -ComputerName $ComputerName

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

# Если в очереди печати что-то есть
if ($ContentSpoolDirecrory = Get-ChildItem $RemoteDefaultSpoolDirectory -Force)
{
    # Считаем размер каталога с очередью печати
    $FolderSize = ($ContentSpoolDirecrory |
        Measure-Object -Property Length -Sum).Sum / 1Mb
    
    # Выводим
    "`nВ {0} находится {1} файл(а/ов), общим объёмом {2:N} МБ" -f
        $RemoteDefaultSpoolDirectory, $ContentSpoolDirecrory.Count, $FolderSize
    
    # Очищаем каталог
    $ContentSpoolDirecrory | Remove-Item -Force
}

Вообще общепризнанным “best practice” не рекомендуется выводить простой текст в выводе скрипта, но так как это не было целью работы, и мне уже было лень с этим возиться, поэтому я просто воспользовался оператором –f.

Осталось только запустить службу:

$Service.StartService()

Если нужно перезапустить (остановить/запустить) другую службу, действия будут аналогичными, при необходимости можно имя службы и удалённого ПК засунуть в параметры, и запускать/останавливать/перезапускать любые службы на любых компьютерах 🙂 Только нужно проверить зависимости и убедиться в том, что заданную службу можно останавливать.

Реклама
Рубрики:Powershell Метки: , , ,
  1. Комментариев нет.
  1. No trackbacks yet.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: