ИВАН КОРОБКО
Управление сетевыми принтерами домена
Любой системный администратор хотел бы получить легкий, компактный и универсальный инструмент, с помощью которого можно одновременно контролировать состояние всех принтеров текущего домена Microsoft Windows; получать исчерпывающую статистику по настройкам принтера; управлять принтерами домена и их очередями; получать доступ к веб-интерфейсу принтеров, при его наличии; осуществлять поиск доступных принтеров по одному из критериев: по названию, по размещению, по месторасположению устройства.
Предлагается решение, созданное на основе ASP, особенностью которого является динамичность. Выбор ASP обусловлен его возможностью работать с OLE-объектами и требованием динамичности.
Для воплощения данного решения была использована библиотека интерфейса службы активного каталога (Active Directory Service Interface – ADSI), которая позволяет управлять пространством имен Microsoft Windows 2000.
ADSI выпущен в 1997 году корпорацией Microsoft. ADSI поддерживает пространства имен LDAP, WinNT, IIS, NDS. В работе используются пространства имен LDAP и WinNT. Пространство имен LDAP используется для чтения текущего домена, соответственно списка опубликованных в них принтеров и поля AD. Протокол WinNT используется для работы управления принтерами и очередями печати.
Файловая структура проекта
Инструмент представляет сайт, точкой входа в который является страница на языке HTML. Сайт создан на основе окон (Frameset): файл default.htm делит окно браузера на два столбца. Текст файла default.htm (HTML):
<HTML>
<HEAD>
<!-- Левый столбец составляет 30% от ширины всего окна. Левое окно имеет идентификатор "main", второе "var". -->
<TITLE>Список доступных сетевых принтеров </TITLE>
<META HTTP-EQUIV ="Content-Type" CONTENT="text/html; CHARSET=windows-1251">
</HEAD>
<FRAMESET cols="30%,*" FRAMEBORDER="5" BORDER="yes" FRAMESPACING="5" >
<FRMAE SRC="printer_adsi.asp?radGrp=1&Search_Text=" NAME="main" SCROLLING="yes" МАRGINHEIGHT=1 >
<FRAME SRC ="about:blank" NAME="var">
</FRAMESET >
</HTML>
Остальные страницы взаимосвязаны друг с другом и являются рекурсивными. Обе страницы написаны на ASP. Для создания обеих страниц был выбран VBScript. VBScript выбран потому, что является языком, поставляемым с Microsoft Windows; обладает необходимыми возможностями для реализации данного проекта, имеет простой синтаксис.
Каждый из ASP-файлов состоит из трех частей, которые взаимосвязаны друг с другом: WinNT, LDAP, HTML.
LDAP
В разделе LDAP рассмотрены следующие вопросы: определение доступного домена; построение запроса SQL; поиск опубликованных принтеров в AD; чтение полей принтеров.
Определение имени текущего домена
Название текущего домена определяется с помощью функции GetObject. Используя функцию GetObject, можго прочитать корень пространства имен, т.е. текущий домен.
SET rootDSE_ = GetObject("LDAP://RootDSE")
domain_ = "LDAP://" + rootDSE_.Get("defaultNamingContext")
Переменная domain_ имеет вид «dc=microsoft,dc=com», если домен «microsoft.com».
Имя текущего домена, полученного с помощью протокола WinNT, нельзя использовать, поскольку с помощью протокола WinNT, можно получить только сокращенное имя домена (в данном случае «Microsoft»). При указании сокращенного имени в строке с SQL-запросом произойдет ошибка. В сообщении, которое выведет браузер, будет указано, что путь к базе ошибочен, и базу невозможно открыть.
Построение запроса SQL
Запрос SQL используется для осуществления процедуры поиска объектов при заданном типе объекта.
В общем случае запрос SQL выглядит следующим образом:
SELECT поле_1, поле_2, …, поле_n FROM "LDAP://dc=домен_1,dc=домен_2…,domen_n" WHERE objectClass="тип_объекта"
В поле SELECT указываются поля, по которым идет выборка. Поля перечисляются через запятую, «пробелы» после запятой обязательны. Полный список полей объектов AD можно получить с помощью утилиты ADSI Edit, которая размещается в дистрибутиве Microsoft Windows 2000 в директории /Support/Tools.
В поле FROM указывается путь к объекту. В данном случае известен только домен. Пробелы в данном поле недопустимы.
В поле WHERE указывается тип объекта, к которому адресован запрос. Данное поле является фильтром. Протокол LDAP имеет несколько типов объектов, которые в запросе SQL определяются переменной objectClass: PrintQueue – массив принтеров, опубликованных в AD; Group – группы, созданные в AD; User – пользователи, созданные в AD; Computer – массив компьютеров, зарегистрированных в AD. Пример использования запроса SQL см. в разделе «Поиск опубликованных принтеров в AD».
«Поиск опубликованных принтеров в AD»
Для поиска объектов в AD с помощью протокола LDAP используется ADODB-соединение. После создания соединения формируется SQL-запрос и осуществляется поиск в соответствии с запросом. Результатом поиска является массив, который содержит значения полей, указаных в параметре SELECT SQL-запроса. Затем происходит вывод данных на экран. В приведенном примере осуществляется поиск всех опубликованных принтеров в текущем домене и вывод на экран названия принтера и его сетевого имени (VBScript):
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.CommandTimeout = 120
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
objCommand.CommandText = "SELECT printername, printsharename FROM '"&domain_&"' WHERE objectClass='printQueue'"
objCommand.properties("Timeout")=30
objCommand.properties("Cache Results")=false
Set st = objCommand.Execute
st.Movefirst
On Error Resume Next
Do Until st.EOF
printer_name=St.Fields("PrinterName").Value
shares_enum=""
shares=St.Fields("printsharename").Value
for each share in shares
shares_enum=shares_enum+share
next
Response.write printer_name & shares_enum & chr(13)
st.MoveNext
Loop
В Active Directory объектом класса printQueue является принтер. Данный объект имеет свойства, значение которых может быть двух типов: строкой и массивом. В приведенном примере значение, содержащее название принтера, является строкой, содержащее сетевые имена принтеров, является массивом.
Ниже приведена таблица, с названиями часто используемых полей, соответствующий им тип данных, описание полей и общий формат данных, находящихся в этих полях:
Поле
|
Описание
|
Тип
|
Пример
|
CanonicalName
|
Классический путь к принтеру, как в проводнике AD
|
Array
|
Domain.ru/Department/PrinterName
|
cn
|
Значение cn для принетра
|
String
|
Server-PrinterName
|
|
Описание принтера
|
Array
|
Принтер формата __ находится
в __ отделе
|
DistinguishedName
|
Путь к принтеру в формате протокола LDAP
|
String
|
CN=PrinterName, OU= Department, DC=Domain, DC=ru
|
driverName
|
Название драйвера, установленного на принтере
|
String
|
HP 1200 Printer Driver PCL
|
driverVersion
|
Версия драйвера
|
String
|
4
|
Location
|
Физическое место размещения принтера
|
String
|
2 эт., 10 комн.
|
Name
|
Название принтера (название, которо видит пользователь)
|
String
|
Server - PrinterName
|
PortName
|
Название порта принтера
|
Array
|
IP_xxx.xxx.xxx.xxx
|
PrintColor
|
Описание цветности принтера
|
String
|
True/False
|
PrinterName
|
То же, что и Name
|
String
|
PrinterName
|
PrintLanguage
|
Языки, поддерживаемые принтером
|
Array
|
|
PrintMaxResolutionSupported
|
Максимальное разрешение, выдаваемое принтером в dpi
|
String
|
1200
|
PrintMediaReady
|
Форматы лотков, которыми снабжен принтер
|
Array
|
A3, A4
|
PrintMemory
|
Количество памяти, встроенной в принтер (в байтах)
|
String
|
9082
|
PrintPagesPerMinute
|
Скорость печати в минуту
|
String
|
12
|
PrintShareName
|
Имя принтера для подключения
|
Array
|
Printer
|
ServerName
|
Полное имя сервера,
к которому подключен принтер
|
String
|
Server.Domain.Ru
|
ShortServerName
|
Краткое имя cервера
|
String
|
Server
|
uNCName
|
Путь в формате UNC
|
String
|
Server.Domain.ruPrinterName
|
url
|
URL-путь к принтеру
|
Array
|
http:Server.Domain.ruPrinterName
|
WhenCreated
|
Дата публикации принтера
в AD
|
String
|
Дата включает в себя время, число, месяц и год
|
WhenChanged
|
Дата последних изменений
в принтере в AD
|
String
|
WinNT
С помощью протокола WinNT осуществляется подключение к локальному принтеру; чтение настроек и параметров принтера; управление принтером; чтение и управление очередью печати принтера.
Подключение к локальному принтеру
Для подключения к принтеру в текущем домене необходимо знать два параметра – название компьютера, к которому подключен принтер, и название принтера. Поскольку принтеры сетевые, то имя компьютера, к которому подключены принтеры, является именем сервера печати (Print Server). Именем принтера является его сетевое имя (Share Name). Оба эти параметра определяются с помощью протокола LDAP. Синтаксис строки подключения в общем виде выглядит следующим образом:
Set pq = GetObject("WinNT://" & server_name & "/" & shares_enum)
где serve_name – имя сервера печати, а shares_enum – сетевое имя принтера.
Set st=objconnection.execute("SELECT shortservername, printsharename, FROM "" & Domain_ & " " WHERE objectClass="printQueue"" )
Do Until st.EOF
shares_enum=""
shares=St.Fields("printsharename").Value
for each share in shares
shares_enum=shares_enum & share
next
server_name=St.Fields("ShortServerNAme").Value
Set pq = GetObject("WinNT://" & server_name & "/" & shares_enum)
st.MoveNext
Loop
Чтение настроек и параметров принтера
Чтение настроек с помощью протокола WinNT осуществляется с помощью элементов массива объекта, вызванного с помощью функции GetObject :
Set pq = GetObject("WinNT://" & server_name & "/" & shares_enum)
pq.name
Элемент
|
Тип данных
|
Описание элемента
|
DataType
|
String
|
Тип данных, поддерживаемый принтером
|
Default Priority
|
String
|
Приоритет по умолчанию
|
|
String
|
Описание принтера
|
Location
|
String
|
Расположение принтера
|
Model
|
String
|
Модель принтера
|
Name
|
String
|
Название принтера
|
PrintDevices
|
String
|
Название устройства печати
|
PrinterPath
|
String
|
Путь к принтеру
|
PrintJobs
|
Array
|
Очередь печати (см. раздел «Чтение и управление очередью печати принтера»)
|
Status
|
String
|
Состояние принтера. Обозначается числом:
0 – Ready, 1 – Pause, 18 – Error.
|
UntilTime
|
String
|
Оставшееся время печати
|
В приведенном примере name является членом массива pq. По типу данных членом массива могут быть строки и массивы. Выше приведены часто используемые элементы массива, соответствующие элементам типы данных и описания элементов:
Управление принтером
Управление принтером также осуществляется с помощью элементов массива объекта, вызванного с помощью функции GetObject. Элементы массива содержат не только строки и массивы, но и команды:
Элемент
|
Тип данных
|
Описание элемента
|
Pause
|
Команда
|
Приостановить работу принтера
|
Purge
|
Команда
|
Удалить все задания из очереди печати
и переинициализировать принтер
|
Resume
|
Команда
|
Восстановить работу принтера
|
Set pq = GetObject("WinNT://" & server_name & "/" & shares_enum)
pq.purge
Чтение и управление очередью печати принтера
Очередь печати представляет собой массив, содержащий в себе задания, которые находятся в очереди печати на момент извлечения из нее данных с помощью протокола WinNT. Массив очереди печати является элементом массива, получаемого с помощью функции GetObject. Он содержит элементы, список которых приведен в таблице. Все элементы представляют собой строки:
Элемент массива
|
Описание элемента
|
|
Описание задания
|
Priority
|
Приоритет задания
|
Size
|
Размер задания в байтах
|
StartTime
|
Время начала печати
|
Status
|
Статус задания. Выражается числом
|
TimeSubmited
|
Время, оставшееся до окончания печати
|
TotalPages
|
Общее количество страниц в задании
|
UntilTime
|
Время окончания печати
|
User
|
Пользователь, пославший документ на печать
|
Пример, в котором читаются поля и выводятся на экран (ASP):
Set pq = GetObject("WinNT://" & server_name & "/" & shares_enum)
For Each printJob In pq.PrintJobs
status_pre=printJob.status
select case status_pre
case "0" status_="Нормально"
case "1" status_="Пауза"
case "18" status_="Ошибка"
end select
number_docum=number_docum
Next
Управление очередью осуществляется тем же способом, что и управление принтером. Существует три команды, которые могут быть использованы для управления документом, находящимся в очереди печати:
Элемент
|
Тип данных
|
Описание элемента
|
Pause
|
Команда
|
Приостановить печать задания
|
Remove
|
Команда
|
Удалить задание из очереди печати
|
Resume
|
Команда
|
Восстановить печать задания
|
On Error Resume Next
Set pq = GetObject("WinNT://" & server_name & "/" & shares_enum)
For Each printJob In pq.PrintJobs
If (number_docum=2) then
printJob.remove
end if
number_docum=number_docum
Next
HTML
Раздел HTML обеспечивает применение таблицы стилей и установку необходимой таблицы кодировки шрифта для графического оформления проекта, автоматическое обновление страниц; взаимодействие страниц, основанное на передаче форм с помощью метода POST; поиск по заданным критериям.
Таблица стилей и выбор кодировки страницы
Обе ASP-страницы используют таблицу стилей и работают в кодировке WIN-1251. Стили описываются в подключаемом файле style.css:
H4 {font-size:11; font-family:Arial;}
H5 {font-size:10; font-family:Arial;}
H6 {font-size:9; font-family:Arial;}
Файл стилей указывается в разделе LINK, необходимая кодировка – в разделе META (HTML):
<HEAD>
<LINK HREF="style.css" TYPE=text/css REL=stylesheet>
<META HTTP-EQUIV ="Content-Type" CONTENT="text/html; CHARSET=windows-1251">
</HEAD>
Параметр CHARSET отвечает за выбор кодировки, в которой будет отображаться документ.
Автоматическое обновление страниц
Особенностью проекта является его динамичность, которая достигается автоматическим обновлением страниц через определенный промежуток времени. Обновление обеих страниц происходит с частотой, которая указывается пользователем. Определение времени автоматического обновления является эвристической операцией. Рекомендуется использовать время автоматического обновления от 5 до 10 секунд. Время обновления указывается в разделе META (HTML):
</HEAD>
< META HTTP-EQUIV ="refresh" CONTENT=10 >
</HEAD>
Параметр CONTENT отвечает за временной интервал обновления страниц. Время указывается в секундах.
Взаимодействие страниц
Взаимодействие страниц основано на передаче форм, содержащих данные, методом GET.
Передача данных осуществляется с помощью двух методов: прямого и косвенного.
Прямой метод:
В исходной странице создается форма, которая содержит поля для ввода информации и кнопку для отправки информации и загрузки страницы, принимающей данные (HTML):
<FORM ACTION="printer_adsi.asp" TARGET="main" METHOD="get">
<INPUT TYPE="submit" VALUE="Поиск"></INPUT>
<INPUT NAME="Search_Text"></INPUT>
</FORM>
В разделе FORM присутствуют следующие параметры: ACTION, TARGET, METHOD. В параметре ACTION указывается файл, в который будут передаваться данные после нажатия на кнопку.
Подразделом, который обязательно присутствует в разделе FORM, является INPUT. INPUT имеет следующие параметры: TYPE, NAME, VALUE. Параметр TYPE определяет вид приемника информации: кнопка (TYPE=«submit» или «reset»); окно для ввода текста (TYPE=«text»), значение по умолчанию; кнопка выбора одного параметра из группы (TYPE=«radio»). VALUE – название поля, отображаемое в объекте. NAME – имя, которое участвует в формировании запроса.
Запрос, который формируется с помощью метода GET, в общем виде выглядит следующим образом:
http://имя_страница.asp(htm)?П1=З1&П2=З2&...Пn=Зn
В приведенной строке присутствуют следующие обозначения: П – параметр, З – значение.
В используемом примере данная стока будет выглядеть следующим образом:
http://printer_adsi.asp?Search_Text=HP
если в стоке было введено «HP».
Рассмотрим «страницу-приемник»: для получения переданных принимающей странице данных необходимо прочитать запрос и присвоить переданные значения переменным. Данная операция, опираясь на приведенный пример, осуществляется следующим образом:
set s_p_r= Request.QueryString("Search_Text")
Таким образом, параметр s_p_r=«HP».
Прямой метод используется для осуществления поиска.
Косвенный метод:
Косвенный метод используется для передачи данных из одной ASP-страницы в другую. Он основан на том, что при нажатии пользователем на картинку или текст, являющийся ссылкой, сразу формируется запрос, который передает данные.
Поскольку очередью принтера невозможно управлять, если принтер рассматривать как сетевое устройство, то использование протокола LDAP становится невозможным.
Для доступа к очереди принтера, как ранее отмечалось, используется протокол WinNT. Для использования протокола необходимо передавать 2 параметра: сетевое имя принтера (Share Name) и название окна (Frame), в котором необходимо вывести данную страницу. Опираясь на приведенные ранее примеры, данные будут передаваться на страницу View_Printer.asp, запрос будет иметь следующий вид (ASP):
<% <A HREF=" & chr(34) & "View_Printer.asp?Printer_to=" & printer_name & chr(34) & " target=" & chr(34) &"var"& chr(34) & " > <IMG SRC =imagespr1.jpg BORDER=0> </A> %>
Из-за особенностей ASP необходимо прибегать к обозначению кавычек функцией chr(34).
Подробнее о передаче данных будет рассказано в разделе, посвященном WinNT.
Поиск по заданным критериям
Поиск базируется на использовании фильтра. Перед осуществлением поиска пользователь выбирает критерий поиска, словосочетание для поиска и нажимает кнопку «Поиск», которая формирует запрос и загружает страницу. В качестве критерия может быть выбран один из параметров: «Название», «Описание», «Размещение». По умолчанию принято значение «Название». Выбор значения по умолчанию осуществляется меткой CHECKED в соответствующем разделе INPUT. Форма на странице-отправителе выглядит следующим образом (HTML):
<FORM ACTION="printer_adsi.asp" TARGET="main" METHOD="get">
<INPUT TYPE="submit" VALUE="Поиск"></INPUT>
<INPUT NAME="Search_Text"></INPUT>
<BR>
<INPUT CHECKED TYPE="radio" VALUE="1" NAME="radGrp">Название
< INPUT TYPE="radio" VALUE="2" NAME="radGrp">Описание
< INPUT TYPE ="radio" VALUE="3" NAME="radGrp">Размещение
</FORM>
Если, например, осуществляется поиск всех устройств, которые встречают в названии словосочетание «hp», то формируется следующий запрос:
http://printer_adsi.asp?Search_Text=hp&radGrp=1
В принимающем запрос файле printer_adsi.asp для расшифровки запроса используется следующая методика:
- данные, переданные форме, присваиваются переменным;
- происходит фильтрация данных в зависимости от параметра, отвечающего за критерий поиска;
- происходит поиск в соответствующих полях;
- вывод результатов поиска на экран.
Установка сайта и особенности конфигурирования IIS
Созданный сайт необходимо опубликовать с помощью IIS на любом компьютере домена, принтеры которого вы хотите инспектировать. Желательно, чтобы этим компьютером был компьютер, который функционирует круглосуточно. Таким компьютером является сервер.
Данный сайт работает с Active Directory. Поскольку для чтения AD необходимы права администратора, то сайт будет работать только в случае его использования системным администратором. Необходимо иметь возможность просматривать сайт с любого компьютера в домене без перерегистрации пользователя. Для достижения желаемого результата необходимо назначить следующие права доступа на папку, в которой опубликован сайт: группе «Domain Admins» необходимо предоставить уровень доступа «Full Control» на папку с сайтом; остальные группы и пользователи должны быть удалены (см. рисунок 1). В настройке IIS для данного сайта в его свойствах необходимо, как показано на рисунке 3, войти во вкладку «Authentication Methods», нажав на кнопку «Edit». Затем выключить анонимный доступ (Anonnymos access), убрав галку напротив соответствующей записи. В разделе «Authenticated access» необходимо установить галку только напротив «Basic authentication».
Рисунок 1
Рисунок 2. Иллюстрация свойств принтера и очереди печати
Желательно включить «Integrated Windows authentication» для того, чтобы системному администратору, который вошел в сеть под своей учетной записью, не предлагалось вводить пароль. Однако этот механизм доступа к сайту невозможен по неизвестным причинам. Рекомендуется не ставить эту галку.
Приложение:
Рисунок 3
Рисунок 4. Иллюстрация веб-интерфейса сетевого принтера
default.htm
<html>
<head>
<title>Принтеры издательства ПРОСВЕЩЕНИЯ</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<FONT FACE="Arial" size="3"></FONT>
</head>
<frameset cols="30%,*" FRAMEBORDER="5" BORDER="yes" FRAMESPACING="5" >
<frame src="printer_adsi.asp?radGrp=1&Search_Text=" name="main" scrolling="yes" МАRGINHEIGHT=1 >
<frame src="about:blank" name="var">
</frameset>
</html>
style.css
H4 {font-size:12; font-family:Arial;}
H5 {font-size:11; font-family:Arial;}
H6 {font-size:10; font-family:Arial;}
printer_adsi.asp
<%@ Language=VBScript CODEPAGE=1251%>
<HTML> <body link="red" VLINK=red> </body>
<TITLE> Выбор порядка упорядочивания админского софта </TITLE>
<HEAD>
<LINK href="style.css" type=text/css rel=stylesheet>
<meta http-equiv="Content-Type" content="text/html" charset=windows-1251>
<meta http-equiv="refresh" content=10 >
</HEAD> <BODY>
<FONT FACE="Arial">
<H4><b><center>"Принтеры"</center></H4> <br> <h6>
<FORM ACTION="printer_adsi.asp" target="main" METHOD="get">
<INPUT TYPE="submit" VALUE="Поиск"></INPUT>
<INPUT NAME="Search_Text"></INPUT>
<br>
<input checked type="radio" value="1" name="radGrp">Название
<input type="radio" value="2" name="radGrp">Описание
<input type="radio" value="3" name="radGrp">Размещение
</FORM> </h6>
<center><table widht=90% cellpadding=10%> <td>
<%
set rootDSE_ = GetObject("LDAP://RootDSE")
domain_ = "LDAP://" + rootDSE_.Get("defaultNamingContext")
Set objNameSpace = GetObject("WinNT:")
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.CommandTimeout = 120
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
objCommand.CommandText = "SELECT servername, printername, printsharename, location, description FROM '"&domain_&"' WHERE objectClass='printQueue'"
objCommand.properties("Page size")=1000
objCommand.properties("Timeout")=30
objCommand.properties("Cache Results")=false
Set st = objCommand.Execute
st.Movefirst
set radio_=Request.QueryString("radGrp") '- what is search - can 1 - fullname ,2 - location ,3 - description
set s_p_r= Request.QueryString("Search_Text")
summary="<Table width"& chr(61) & "100% > <TR> <TD></TD><Center> <TD> <B> <H5>Название принтера</H5></TD> <TD> </TD> <TD> </TD></tr></Center>"
flag=0
i=0
on error resume next
dim array_1(500)
i=0
Do Until st.EOF
printer_name=St.Fields("PrinterName").Value
shares_enum=""
shares=St.Fields("printsharename").Value
for each share in shares
shares_enum=shares_enum+share
next
server_name=St.Fields("servername").Value
descrits_enum=""
if vartype(St.Fields("description"))=8204 then
descrits=St.Fields("description")
for each des in descrits
descrits_enum=descrits_enum+des
next
end if
location_name=St.Fields("location").Value
Set pq = GetObject("WinNT://" & server_name & "/" & shares_enum)
status_printer=pq.status
select case status_printer
case "0" status_P="<img src=images\3normal.jpg border=0>"
case "1" status_P="<img src=images\2pause.jpg border=0>"
case "18" status_P="<img src=images\1error.jpg border=0>"
end select
select case radio_
case "1"
summary_where_search= shares_enum & printer_name
case "2"
summary_where_search= descrits_enum
case "3"
summary_where_search= location_name
end select
if instr(Lcase(summary_where_search), Lcase(s_p_r)) then
array_1(i)="<TR><td>" & status_P & " </td> <TD> <H6> " & printer_name & "</H6></TD> <TD><A href=" & chr(34) & "view_printer.asp?Printer_to=" & printer_name & chr(34) & " target=" & chr(34) &"var"& chr(34) & "title=" & chr(34) & printer_name & " - " & descrits_enum & chr(34) & " > <b> <img src=images\pr1.jpg border=0> </b></a> </td> <td> <A href=http:\\" & shares_enum & " target=" & chr(34) &"var"& chr(34) & "title=" & chr(34) & printer_name & " - " & descrits_enum & chr(34) & " > <b> <img src=images\pr2.jpg border=0> </b></a> </td></tr>"
i=i+1
flag=1
end if
st.MoveNext
Loop
up_array=ubound(array_1)
for j=0 to up_array
for i=0 to up_array
if strcomp(array_1(i),array_1(i+1),0)=1 then
temp=array_1(i)
array_1(i)=array_1(i+1)
array_1(i+1)=temp
end if
next
next
for i=0 to up_array
summary=summary&array_1(i)
next
result_search=summary_header & " <table > <tr> " & summary & " </tr> </table></h6>"
if flag=0 then
result_search="<center><FONT FACE=Arial size=3><B><I><H5>По запросу ничего не найдено!</H5></B></I></center>"
end if
Response.write result_search
%>
</BODY> </HTML>
view_printer.asp
<%@language=VBScript %>
<html><head>
<meta http-equiv="Content-Type" content="text/html" charset=windows-1251>
<meta http-equiv="refresh" content=10 >
<LINK href="style.css" type=text/css rel=stylesheet>
</head><body>
<FONT FACE="Arial">
<% set printer_name_to=Request.QueryString("Printer_to")
set rootDSE_ = GetObject("LDAP://RootDSE")
domain_ = "LDAP://" + rootDSE_.Get("defaultNamingContext")
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "ADSI"
set st=objconnection.execute("SELECT shortservername, printername, printsharename, location, description,driverversion, drivername, portname, printlanguage, printcolor, printmaxresolutionsupported, printmemory, whencreated, whenchanged, servername, printpagesperminute FROM '" & Domain_ & " ' WHERE objectClass='printQueue'" )
Do Until st.EOF
printer_name=St.Fields("PrinterName").Value
if printer_name_to=printer_name then
shares_enum=""
shares=St.Fields("printsharename").Value
for each share in shares
shares_enum=shares_enum & share
next
descrits_enum=""
if vartype(St.Fields("description"))=8204 then
descrits=St.Fields("description")
for each des in descrits
descrits_enum=descrits_enum+des
next
end if
location_name=St.Fields("location").Value
driver_name=St.Fields("driverName").Value
driver_version=St.Fields("driverVersion").Value
if vartype(St.Fields("portName"))=8204 then
ports=St.Fields("portName")
for each port in ports
port_name=port_name+port
next
end if
support_color=St.Fields("printColor").Value
Resolution=St.Fields("PrintMaxResolutionSupported").Value
print_speed=St.Fields("PrintPagesPerMinute").Value
server_name=St.Fields("ShortServerNAme").Value
print_memory=St.Fields("PrintMemory").Value
server_name=St.Fields("servername").Value
when_created=St.Fields("WhenCreated").Value
when_changed=St.Fields("WhenChanged").Value
language_enum=""
if vartype(St.Fields("printLanguage"))=8204 then
formats=St.Fields("printLanguage")
for each format in formats
language_enum=language_enum+format
next
end if
Set pq = GetObject("WinNT://" & server_name & "/" & shares_enum)
set printer_change_status=Request.QueryString("change_status")
select case printer_change_status
case "1" pq.pause
case "2" pq.resume
case "3" pq.purge
case "4"
number_=1
number_to_=""
For Each printJob In pq.PrintJobs
set number_to_=Request.QueryString("number_doc")
if cint(number_to_)=number_ then
printJob.pause
end if
number_=number_+1
next
case "5"
number_=1
number_to_=""
For Each printJob In pq.PrintJobs
set number_to_=Request.QueryString("number_doc")
if cint(number_to_)=number_ then
printJob.resume
end if
number_=number_+1
next
case "6"
number_=1
number_to_=""
For Each printJob In pq.PrintJobs
set number_to_=Request.QueryString("number_doc")
if cint(number_to_)=number_ then
set del_docum=pq.printJobs
del_docum.Remove cstr(printJob.name)
end if
number_=number_+1
next
end select
change_status=0
status_printer=pq.status
select case status_printer
case "0" status_P="<img src=images\3normal.jpg border=0>"
case "1" status_P="<img src=images\2pause.jpg border=0>"
case "18" status_P="<img src=images\1error.jpg border=0>"
end select
sum_jobs="<Table width=100% > <TR> <Center> <TD><h5>Операции</td><td><B><H5> Название документа </TD> <TD> <B> <H5> Пользователь </TD> <TD> <H5> <B> Приоритет </TD> <TD> <H5> <B> Кол-во(стр) </TD> <TD> <B> <H5> Размер (Мб)</TD> <TD> <B> <H5> Состояние </TD></Center>"
number_docum=0
For Each printJob In pq.PrintJobs
status_pre=printJob.status
select case status_pre
case "0" status_="<img src=images\3normal.jpg border=0>"
case "1" status_="<img src=images\2pause.jpg border=0>"
case "18" status_="<img src=images\1error.jpg border=0>"
end select
number_docum=number_docum+1
sum_jobs=sum_jobs & "<TR><TD width=60><h6><a href="&chr(34)&" view_printer.asp?Printer_to=" & printer_name_to & "&change_status=4&Number_Doc="&number_docum & chr(34)& " > <img src=images\l2.jpg border=0></a> <a href="&chr(34)&" view_printer.asp?Printer_to=" & printer_name_to & "&change_status=5&Number_Doc="&number_docum & chr(34)& "><img src=images\l1.jpg border=0></a> <a href="&chr(34)&" view_printer.asp?Printer_to=" & printer_name_to & "&change_status=6&Number_Doc="&number_docum & chr(34)& "><img src=images\l3.jpg border=0></a></td></center> <td> <h6>" & printJob.Description & "</td><TD><h6>" & printJob.User & "</TD> <TD width=40> <h6>" & printJob.Priority &" </TD> <TD width=50><h6>" & printJob.TotalPages & " </TD><TD width=40><h6>" & round(printJob.Size/1000000,2) & " </TD> <TD width=50><h6>"& status_ & "</TD>"
Next
s1="<center><b> <H4>" & printer_name & "</b></center><Br> <Table width=100% > <tr> <td> <h5> Описание: <Br></td> <td colspan=3> <h6>"& descrits_enum & "<Br></td></tr> <tr><td><b><h5>Расположение:</b><Br></td> <td><h6>" & location_name & "<Br></td> <td><h5>"
s2="<b> Драйвер: </b><Br></td> <td><h6>" & driver_name & "<Br></td> </tr> <tr> <td> <h5> <b> Сервер: </b> <Br></td> <td> <h6>" & server_name & "<Br></td> <td><b><h5> Версия: </b><Br></td> <td> <h6>" & driver_version & "<Br></td></tr> <tr><td><h5><b> Порт: </b><Br></td> <td> <h6>" & port_name & "<Br></td> <td> <h5>"
s3="<b> Тип данных: </b><Br></td> <td> <h6>"& pq.Datatype &"<Br></td></tr> <tr><td><b><h5> Язык: </b><Br></td> <td><h6>" & language_enum & "<Br></td> <td> <b><h5> Поддержка цвета: </b><Br></td> <td> <h6>" & support_color & "<Br></td> </tr> <tr> <td> <b><h5> Разрешение: </b><Br></td> <td><h6>" & resolution & " dpi <Br></td> <td><h5>"
s4="<b> Скорость: </b><Br></td> <td> <h6>" & print_speed & " стр./мин.<Br></td> </tr> <tr> <td><b><h5> Память: </b><Br></td> <td><h6>" & print_memory & " Kб <Br></td> <td><h5>"
s5="<b> Создан: <Br></td></b><td><h6>" & When_created & "<Br></td></tr><tr> <td><b><h5> Статус:</b><Br></td><td><center> <h6>"& status_P & "</center><Br></td> <td><b><h5> </b><Br></td> <td><h6>" & "<Br></td></tr> <td><h5>"
b1="<b>Принтер: </b></td><td><center> <a href="&chr(34)&" view_printer.asp?Printer_to=" & printer_name_to & "&change_status=1"&chr(34)& " > <img src=images\pause_pr.jpg border=0></a>      "
b2="<a href="&chr(34)&" view_printer.asp?Printer_to=" & printer_name_to & "&change_status=2"&chr(34)& "><img src=images\resume_pr.jpg border=0></a>      "
b3="<a href="&chr(34)&" view_printer.asp?Printer_to=" & printer_name_to & "&change_status=3"&chr(34)& "><img src=images\1error.jpg border=0></a></td></center></tr></table> "
summary=s1 & s2 & s3 & s4 & s5 & b1 & b2 & b3 & "<br> <br>"
end if
st.MoveNext
Loop
Response.write summary
Response.write num_docum
Response.write sum_jobs
%>
Отдельное спасибо Филиппу Зыкову, руководителю Центра ИТ Издательства «Просвещение», благодаря идее которого и возникла данная статья.