Иван Коробко
В настоящее время сети получили огромное распространение: теперь они не
только на работе, но и дома. Статья посвящена созданию скрипта, с помощью
которого осуществляется интеллектуальное управление сетевыми дисками, смена их
описаний в папке «Мой компьютер».
Сегодня почти на любом предприятии есть компьютеры, объединенные в сеть.
Каждому сотруднику, имеющему на своем рабочем месте компьютер, должен быть
предоставлен доступ к сетевым ресурсам. С ростом размера предприятия происходит
рост сети. У системного администратора и специалистов системной поддержки возрастают
временные затраты на ее администрирование. В том числе на опубликование новых
сетевых ресурсов, при переходе пользователя с одного рабочего места на другое;
возникают проблемы с ограничением количества дисков (их всего может быть 27,
включая сетевые, локальные, съемные диски). Затраты на администрирование можно
сократить, создав сценарий регистрации пользователей в сети или, как говорят,
сценарий загрузки, который на основе членства учетной записи пользователя в
соответствующих группах безопасности будет подключать необходимые сетевые
ресурсы в автоматическом режиме. При этом на одну и ту же букву можно
подключить разные ресурсы для разных пользователей при условии непересечения
членства пользователя в соответствующих группах безопасности. В противном
случае, некоторые ресурсы будут недоступны пользователям. Приступим к созданию
такого сценария.
Выбор языка программирования
Для создания сценариев регистрации пользователей существует множество
языков, однако остановим свой выбор на KIXTart. Этот язык является стандартным
языком программирования сценариев компании Microsoft. Его дистрибутив можно
найти в Microsoft Resource Kit или бесплатно загрузить последнюю версию из сети
Интернет (http://kixtart.org). В настоящее
время используется KIXTart версии 4.50.
Замечание: сценарии, созданные вами ранее на VBScript,
Jscript могут быть легко переписаны под KIXtart. Все примеры в этой статье
будут приведены на языке KIXTart.
Источник информации – файл или
база данных?
Чтобы успешно подключить сетевой ресурс, пользователю необходимо знать имя
сетевого диска, с которым будет ассоциироваться ресурс, и UNC-путь сетевого
подключаемого ресурса. Желательно иметь его описание, чтобы скорректировать
название диска в папке «Мой компьютер». Встает закономерный вопрос – где же
лучше всего хранить эту информацию? Можно в текстовом файле, лежащем в
каталоге Netlogon, или в каком-нибудь хранилище, например, в Active Directory
(далее AD). Мною использовались оба варианта, и в итоге выбор пал на AD. Было
достаточно много причин переместить данные из текстового файла в AD, например,
удобство в обслуживании, уменьшение программного кода и т. д.
Принцип работы сценария
Для хранения информации в AD о подключаемом ресурсе был использован
стандартный объект SharedFolder, который включал в себя информацию о букве, на
которую подключается сетевой ресурс; UNC-путь к сетевому ресурсу; описание сетевого
ресурса, которое фигурирует в папке «Мой Компьютер»; имя группы безопасности,
членам которой будет подключен ресурс.
Опишем механизм подключения одного из сетевых
ресурсов, на примере общей папки подразделения «Otdel1». Пусть папка имеет
следующий сетевой путь – «\\Esmiralda\Work$\Otdel1», подключается к диску «К» и
имеет описание «Служебные файлы» (см. рис. 1). В AD в любой OU, например «Shares»,
создайте объект «Share Folder» (см. рис. 2). В любой другой OU создайте группы
безопасности, имена которых совпадают с URL сетевого ресурса после последней
«точки». В приведенном примере группа, соответствующая подключаемому диску,
должна называться «Otdel1». Членам этой группы будет подключен сетевой ресурс
при условии, что она будет добавлена во вкладку безопасности папки «Otdel1» с
соответствующими правами на доступ к этой папке. Если необходимо сделать
несколько различных уровней доступа, в названии группы можно использовать
префикс.

Рисунок 1. Пример изменения
описания сетевого диска в папке «Мой Компьютер»

Рисунок 2. Свойства объекта Shared
Folder в Active Directory
Таким образом, каждому подключаемому скриптом
сетевому ресурсу соответствуют два объекта AD: опубликованная сетевая папка и
соответствующая ей группа безопасности.
Замечание: в том случае, если ресурс должен быть
доступен всем пользователям сети, то необходимо в соответствующую ресурсу
группу добавить группу «domain users» с соответствующими правами.
Сценарий подключения сетевых
дисков
Сценарий можно условно разбить на несколько логических
частей:
n определения списка групп, в которые входит
текущий пользователь;
n подключение к АD и чтение значений
соответствующих полей;
n отключение всех обрабатываемых скриптом сетевых
дисков;
n подключение необходимых сетевых дисков;
n корректировка описания сетевых дисков в папке
«Мой компьютер».
Определение членства в
соответствующих группах безопасности
Определение членства в соответствующих группах безопасности осуществляется с
помощью встроенной функции EnumGroup():
$i=0
Do
$Group = EnumGroup($i)
$i=$i+1
Until Len($Group) = 0
Список групп, возвращаемый этой функцией
(переменная $Group), имеет следующий шаблон: DOMAIN\GROUP. Поскольку в AD
группы хранятся без префикса (в данном случае префиксов является короткое имя
домена), то полученный список групп необходимо преобразовать. Результат
рекомендуется записать в ту же переменную, т.е. GROUP:
Group=Right($Group, Len($Group)-InstrRev($Group,"\")
Подключение к АD и чтение
значений соответствующих полей
Подключение к АD реализовано с помощью ADODB-соединения:
$strADSQuery = "SELECT keywords,
name, description, cn, uncname FROM '" +$domain_+"' WHERE objectClass='volume'"
$objConnection = CreateObject("ADODB.Connection")
$objCommand = CreateObject("ADODB.Command")
$objConnection.CommandTimeout
= 120
$objConnection.Provider =
"ADsDSOObject"
$objConnection.Open ("Active
Directory Provider")
$objCommand.ActiveConnection
= $objConnection
$objCommand.CommandText = $strADSQuery
$st = $objCommand.Execute
Поиск необходимых объектов осуществляется с
помощью SQL-запроса. В качестве фильтра указывается ObjectClass=’volume’:
"SELECT uname, keywords,
description, cn FROM '" +$domain+"' WHERE objectClass='volume'"
где $domain – имя текущего домена, который определяется чтением глобального
каталога RootDSE. Для его чтения достаточно прав обычного пользователя.
Переменная $domain имеет вид «DC=domain,DC=com»:
$rootDSE_ = GetObject("LDAP://RootDSE")
$domain = "LDAP://"
+ $rootDSE_.Get("defaultNamingContext")
Теперь необходимо правильно составить SQL-запрос.
Для этого понадобятся следующие теоретические знания, а именно: как называются
поля данного объекта и какому полю соответствует тот или иной тип данных
(строка или массив). Рассмотрим подробнее объект «Shared Folder». Каждое поле
любого объекта AD может быть либо строкой, либо массивом. Соответственно,
механизмы чтения полей, имеющих разный тип данных, также отличаются.
Чтение поля, соответствующего типу данных
«строка», осуществляется следующим образом:
$Value=$St.Fields("Field_Name").Value
Если тип данных массив:
$Val_Array=$St.Fields("Field_Name").Value
For Each $Val_Element in $Val_Array
$Value=$Value+$Val_Element
Next
В скрипте используются поля, описания и тип
данных, которые приведены в таблице 1 (см. рис. 2).
Таблица 1. Описание
используемых полей объекта Shared Folder
|
Название поля
|
Тип данных
|
Значение
|
|
Description
|
Массив
|
Буква, на которую будет подключаться ресурс
|
|
Cn
|
Строка
|
Имя, отображаемое в AD.
Используется для определения объекта подключения
|
|
UNCName
|
Строка
|
UNC-путь к сетевому ресурсу
|
|
Keywords
|
Строка
|
Имя диска, фигурирующее в папке «Мой Компьютер»
|
Чтение полей всех опубликованных сетевых ресурсов
осуществляется с помощью цикла Do…Until:
$st.Movefirst
Do
…
$st.MoveNext
Until $st.EOF
Как видно из приведенного примера, навигация по
объектам, отобранным в результате SQL-запроса, осуществляется с помощью функций
MoveFirst и MoveNext. Признаком конца списка является EOF.
Итак, чтение полей осуществляется следующим
образом:
$st.Movefirst
Do
$cn=$St.Fields("cn").Value
$uncname=$St.Fields("uncname").Value
$ds_s=""
$dss=$St.Fields("description").Value
for each $ds in $dss
$ds_s=$ds_s + $ds
Next
$keyw_s=""
$kss=$St.Fields("keywords").Value
for each $ks in $kss
$keyw_s=$keyw_s+cstr($ks)
Next
…
$st.MoveNext
Until $st.EOF
Отключение сетевых дисков
Отключение всех обрабатываемых скриптом сетевых дисков осуществляется с
помощью команды USE:
$st.Movefirst
Do
$ds_s=""
$dss=$St.Fields("description").Value
for each $ds in $dss
$ds_s=$ds_s
+ $ds
Next
use $ds_s+":" /delete
/persistent
$St.MoveNext
Until $St.EOF
где переменная $ds_s содержит значение поля, description – буква на
которую монтируется диск. Благодаря такому механизму, скрипт управляет только
теми сетевыми дисками, которые используются системным администратором в AD.
Подключение необходимых сетевых
дисков
Подключение дисков осуществляется по алгоритму:
Сначала определяется необходимая для подключения
сетевого диска информация, а именно буква, на которую монтируется диск (поле description);
UNC-путь ресурса (поле UNCName); группа, членам которой будет подключен ресурс
(поле cn).
У читателя скорее всего возникнет закономерный
вопрос: зачем использовать поле cn, когда имя группы фигурирует в UNC-путь
ресурса? Чтение поля CN жизненно необходимо. Дело в том, что сетевой ресурс
может быть двух видов: общий и индивидуальный. Приведем два примера. В первом
случае осуществляется подключение общей папки обмена данными, назовем ее «Exchange».
Исходя из этого папка, к которой предоставлен доступ, называется «Exchange»,
соответствующая ей группа безопасности – «Exchange» и поскольку в эту группу
входят все пользователи, то членом этой группы является группа «Domain Users».
Во втором случае, нам необходимо подключить каждому пользователю домашний
каталог. Для этого необходимо создать папку, например, «HomeDirs» и создать в
ней подкаталоги, соответствующие логинам пользователей. Ситуация изменилась –
сетевой путь к папке использовать нельзя, однако есть поле CN – имя ресурса,
где можно записать всю необходимую информацию: имя пользователя
и соответствующую группу безопасности (см. рис. 2).
Итак, после определения трех необходимых полей
узнать, входит ли пользователь в соответствующую ресурсу группу безопасности и
при положительном исходе проверки приступить к подключению ресурса по одному из
двух алгоритмов. Выбор алгоритма зависит от наличия логина в считанном значении
CN.
Подключение диска осуществляется с помощью
команды use:
; элементами массива $usergroup_name[]
являются группы, членами которых является текущий пользователь
for $t=0 to ubound($usergroup_name)
if instr($usergroup_name[$t],$group_b)<>0
; критерием персонализации
является членство
; в перечисленных группах
PersonalGroup1…3
if instr(ucase($group_b),ucase("PersonalGroup1"))<>0
or instr(ucase($group_b),ucase("PersonalGroup2"))<>0 or instr(ucase($group_b),ucase("PersonalGroup3"))<>0
if instr($cn,@userid)<>0
use $ds_s+":" $uncname
? " !!!!" + $ds_s+":"
$uncname
if @error=5
; ошибка доступа к ресурсу
$error_code="1"
$error_message=$error_message+"Не
удалось подключить диск "+$ds_s+" к ресурсу "+$cn+chr(13)
EndIf
endif
else
use $ds_s+":" $uncname
? " !!!!" + $ds_s+":"
$uncname
if @error=5
; ошибка доступа к ресурсу
$error_code="1"
$error_message=$error_message+"Не
удалось подключить диск "+$ds_s+" к ресурсу "+$cn+chr(13)
EndIf
endif
endif
next
Корректировка описаний дисков
в папке «Мой компьютер»
Механизм переименования сетевых дисков в папке «Мой компьютер» лучше всего
запускать после завершения процесса подключения самих сетевых дисков. У
читателя может возникнуть закономерный вопрос: «Зачем это вообще надо?».
Существует несколько причин. Приведем некоторые из них: представьте, что у вас
длинный сетевой путь – буквы диска не видно. Согласитесь, что это
неудобно. Во вторых, в некоторых ситуациях пользователь не должен знать,
где находится ресурс. В третьих, пусть пользователь читает не UNC-пути к дискам,
а нормальные их названия: «Файлы моего подразделения» или «Мои проекты». Ему
сразу становится ясно, для чего предназначен диск. Поверьте, не все
пользователи соответствуют термину «опытный пользователь». Это связано с тем,
что на подключение диска требуется время, которое зависит от местоположения
рабочей станции, загруженности сервера и других факторов. Точно его рассчитать
не представляется возможным, поэтому для ускорения работы скрипта лучше
разделить блоки подключения дисков и смены описания с помощью функции-задержки.
Действие функции основано на вычислении промежутка времени с помощью нового
макроса @Ticks, который возвращает количество миллисекунд с момента загрузки
компьютера, определяется разность времени – при достижении указанного интервала
во времени, задержки, осуществляется выход из цикла:
$delay_size=3
$Q = @Ticks +
$delay_size*1000 ; x – количество секунд задержки
Do
Until @Ticks >= $Q
Механизм смены описания в Windows 2000 и Windows XP
разный. Характеристики всех типов дисков (сетевых, локальных и съемных) в Windows
2000 хранятся в ветви реестра
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints
в Windows 2000, для Windows XP – в
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2.
Рассмотрим каждый механизм подключения сетевых
дисков отдельно. Начнем с Windows XP, т.к. там он наиболее понятен и прост.
Переименование описаний сетевых
дисков для Windows XP
Точки монтирования сетевых дисков организованы по следующему принципу: в
подпапке
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2
для сетевых дисков создаются подразделы, имена которых организованы по
принципу: «## имя сервера # имя папки, к которой предоставлен доступ # подпапка1
#.... # подпапкаX». В каждой из этих подпапок присутствуют 3 обязательных
параметра, четвертый – _LabelFromReg также должен быть создан (см. рис. 3).

Рисунок 3. Фрагмент реестра,
в котором описываются точки монтирования сетевых дисков (Windows XP)
Для смены имени сетевого диска в папке «Мой
Компьютер» необходимо изменить значение строковой переменной _LabelFromReg.
WriteValue(cstr($keyw_path+"\"+$temp1),"_LabelFromReg",cstr($keyw_s),"REG_SZ")
Для определения переменной $key_path необходимо
вычислить названия папок, UNC-путь: необходимо заменить символ «\» на «#»:
$st.Movefirst
Do
$uncname=$St.Fields(«uncname»).Value
…
$keyw_path="HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2"
$uncname=Right($uncname,Len($uncname)-2)
$keyw_array=split($uncname,»\»)
$temp1="#"
For Each $ugu in $keyw_array
$temp1=$temp1+"#"+$ugu
Next
WriteValue(cstr($keyw_path+"\"+$temp1),"_LabelFromReg",cstr($keyw_s),"REG_SZ")
$st.MoveNext
Until $st.EOF
Переименование описаний сетевых
дисков для Windows 2000
Логика подключения сетевых дисков Windows 2000 и XP сильно отличаются. В
ветви реестра
«HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints»
созданы подразделы (см. рис. 4), имена которых совпадают с буквой подключаемого
сетевого диска. Внутри каждого из них существуют еще подразделы. Среди них
обязательными являются Autorun, _DIL, _LabelFromDesktopINI. Для изменения
описания диска в папке «Мой Компьютер» в каждой из них необходимо создать
два раздела, если они еще не существуют: _GVI и _LabelFromReg. В каждом из них
при внесении изменений необходимо менять значение параметра Version, имеющего
тип данных REG_DWORD. В подпапке _LabelFromReg дополнительно необходимо создать
ключ Cache, в котором в зашифрованном виде находится описание подключаемого
сетевого диска. Тип данных параметра Cache – REG_BINARY. Опишем систему
шифрования данного параметра на примере фразы «Служебные файлы», причем
последняя буква «е» в первом слове пусть будет английская. Нам нужен пример
любой английской буквы. Надо рассмотреть алгоритм обработки латинских и русских
символов.

Рисунок 4. Фрагмент реестра,
в котором описываются точки монтирования сетевых дисков (Windows 2000)
Рассмотрим преобразование первой буквы
выражения – русской заглавной буквы «С». Процедура чтения кода символа
осуществляется с помощью функции ASC. Букве «С» соответствует номер 209 в
таблице ASCII (см. рис. 5). Затем необходимо перевести полученное значение
в шестнадцатеричное с помощью DecToHex, параметром которой является число –
ASCII-код символа. Символу с ASCII с номером 209 соответствует
шестнадцатеричное число D1. Теперь самое интересное: полученное значение
разбивают на два символа.

Рисунок 5. Кодовая таблица Windows
(CP-1251)
Буквенное значение первого символа преобразуют в
цифру в соответствии с таблицей 2, а для идентификации языка добавляют 2-й
байт. Первым байтом является два символа – НЕХ-код буквы.
Таблица 2. Преобразование
первого символа HEX-кода буквы
|
Буква
|
C
|
D
|
E
|
F
|
G
|
|
Значение
|
1
|
2
|
3
|
4
|
5
|
Таким образом, получаем, что первому символу
соответствует код «21» – это первый байт. Второй байт принимает значение в
зависимости от языка: 04 – русский язык и 00 – английский. Он определяется по
коду символа: если ASCII-код символа больше 128, то буква русская
(см. рис. 5), в противном случае – английская. Итак, второй байт
символа равен «04», а сам символ – «21 04». Для наглядности привожу таблицу
преобразования всего выражения (см. таблицу 3).
Таблица 3. Карта
преобразования фразы «Служебные файлы»
|
Символ
|
Язык
|
ASCII
|
>128
|
2-й байт
|
HEX
|
Преобразование
|
1-й байт
|
1+2 байт
|
|
С
|
Рус
|
209
|
+
|
04
|
D1
|
D->2
|
21
|
21
04
|
|
л
|
Рус
|
235
|
+
|
04
|
EB
|
E->3
|
3B
|
3B
04
|
|
у
|
Рус
|
243
|
+
|
04
|
F3
|
E->3
|
33
|
33
04
|
|
ж
|
Рус
|
230
|
+
|
04
|
E6
|
E->3
|
36
|
36
04
|
|
е
|
Рус
|
229
|
+
|
04
|
E5
|
E->3
|
35
|
35
04
|
|
б
|
Рус
|
225
|
+
|
04
|
E1
|
E->3
|
31
|
31
04
|
|
н
|
Рус
|
237
|
+
|
04
|
ED
|
E->3
|
3D
|
3D
04
|
|
ы
|
Рус
|
251
|
+
|
04
|
FB
|
F->4
|
4B
|
4B
04
|
|
е
|
Англ
|
101
|
-
|
00
|
65
|
6->6
|
65
|
65
00
|
|
_
|
Пробел
|
32
|
-
|
00
|
20
|
2->2
|
20
|
20
00
|
|
ф
|
Рус
|
244
|
+
|
04
|
F4
|
F->4
|
44
|
44
04
|
|
а
|
Рус
|
224
|
+
|
04
|
E0
|
E->3
|
30
|
30
04
|
|
й
|
Рус
|
233
|
+
|
04
|
E9
|
E->3
|
39
|
39
04
|
|
л
|
Рус
|
235
|
+
|
04
|
EB
|
E->3
|
3B
|
3B
04
|
|
ы
|
Рус
|
251
|
+
|
04
|
FB
|
F->4
|
|