ИВАН КОРОБКО
Автоматизация процесса подключения баз «1С»
с помощью сценария регистрации пользователей в сети
В крупных организациях, где штат бухгалтерии насчитывает не один десяток человек и одновременно эксплуатируется несколько баз «1С» версии 7.7, актуальна проблема автоматизированного управления подключением бухгалтерских баз. В статье речь пойдет о том, как с помощью сценария регистрации пользователей в сети подключить бухгалтеру только те базы, с которыми он работает.
Основная идея
Подключение баз основано на членстве учетных записей пользователей в соответствующих группах безопасности, находящихся в Active Directory, которые удовлетворяют нескольким условиям:
- Название группы состоит из 2 частей – префикса, который у всех групп одинаковый, и собственно названия группы. Оно совпадает с названием каталога, в котором физически находится подключаемая база «1С».
Рисунок 1
Во время входа в сеть от имени пользователя запускается сценарий регистрации пользователей в сети, который во время своей работы составляет два списка баз. Один из них – список подключаемых баз. Он формируется на основе данных из Active Directory. Второй список формируется на основе данных из реестра – список подключенных баз. Затем, изменяя ветвь реестра HKCU (HKEY_CURRENT_USER), осуществляется сопоставление созданных списков: подключаются недостающие базы и отключаются лишние.
Сценарий регистрации пользователей в сети
Для создания сценария рекомендуется использовать KIXTart (http://kixtart.org), поскольку он является наиболее подходящим для решения поставленной задачи.
Сценарий регистрации условно можно разделить на несколько логических частей:
- подключение сетевого диска;
- формирование списка баз, которые должны быть подключены;
- формирование списка баз, которые подключены в настоящее время;
- сопоставление сформированных списков, запись данных в реестр рабочей станции.
Подключение сетевых дисков
Доступ к базам, расположенным на сервере, рекомендуется осуществлять с помощью подключения сетевого диска. Для этого необходимо знать два параметра: букву, к которой будет монтироваться ресурс, и UNC-путь к нему.
Все задаваемые вручную параметры принято выносить в конфигурационный файл. KIXTart обладает встроенной поддержкой INI-файлов, которые удобно использовать в качестве конфигурационных файлов. INI-файл представляет собой текстовый файл, имеющий следующую структуру:
[разделM]
параметр1M=значение1M
параметр2M =значение2M
……………………….
параметрNM=значениеNM
Создадим конфигурационный файл config.ini со следующим содержимым:
[1C]
1C_Letter=R
1C_Path=Server1C_Bases$
Чтение конфигурационного файла осуществляется с помощью функции ReadProfileString():
value=ReadProfileString ("file_name", "section", "key")
где value – возвращаемое значение параметра key раздела section файла file_name. Подключение сетевого диска выглядит следующим образом:
$FName=”config.ini”
$Section=”1C”
$1C_Letter_VaL = ReadProfileString($FName, $Section, “1C_Letter”) ;чтение параметра 1C_Letter
$1C_Path_Val = ReadProfileString($FName, $Section, “1C_Path”) ; чтение параметра 1C_Path
Use $1C_Letter_Val + ":" /delete /persistent ; отключение сетевого диска
Use $1C_Letter_Val + ":" $1c_Path_Val ; подключение сетевого диска
Формирование списка подключаемых баз
Список подключаемых баз формируется на основе членства учетных записей пользователей в соответствующих группах безопасности. Как отмечалось ранее, в названиях этих групп присутствует префикс, который также необходимо указать в конфигурационном файле:
[1C]
1C_Prefix=”1C$_”
В результате формируется массив. Его элементами являются название базы и полный путь к каталогу, которые разделены специальным символом. Его также рекомендуется описать в конфигурационном файле:
[1C]
1C_Symbol=”#”
Такая структура элемента массива продиктована выполнением нескольких условий:
- Управление осуществляется только сетевыми базами. Список подключенных локальных баз не корректируется.
- Некорректные названия сетевых баз будут исправлены.
Поскольку сценарий загрузки запускается от имени поль-зователя, который осуществляет вход в сеть, то нет необходимости осуществлять поиск необходимых групп среди всех групп домена с помощью ADODB. Рационально воспользоваться встроенной функцией в KIXTart EnumGroup(), которая возвращает список групп, в которые входит текущий пользователь, и из этого списка отобрать группы, имеющие оговоренный префикс:
…
$meta = ReadProfileString($FName, $Section, “1C_Symbol”)
$p=0
DO
$group=EnumGoup($p)
If Instr($group, $meta)<>0
? $group
End if
UNTIL Len($group)=0
Значение переменной $group строится в соответствии со следующим шаблоном: DomainGroup_Name, поэтому для формирования пути к каталогу необходимо вычленить составляющую Group_Name. Листинг, формирующий полный путь к каталогу, содержащего базу 1C, следующий:
$1C_Letter_VaL = ReadProfileString($FName, $Section, “1C_Letter”)
$1C_Group=Right($group, Len(group)-InstrRev($group,””)-Len($meta))
$1C_Base=$1C_Letter_VaL+”:”+$1C_Group ; вид переменной R:Folder_with_Base
Второй частью элемента формирующегося массива является описание группы. Чтение этого свойства можно реализовать как с помощью провайдера WinNT, так и LDAP. Приведем оба варианта. Для доступа к объекту AD необходимо либо указать имя домена в явном виде, либо создать сценарий для определения текущего домена. По понятным причинам, указывать имя домена в явном виде некорректно, поэтому создадим сценарий для определения длинного (используется провайдером LDAP) и короткого (используется провайдером WinNT) имен доменов:
Set rootDSE_ = GetObject("LDAP://RootDSE")
d_def=rootDSE_.Get("defaultNamingContext")
long_Ldap_name = "LDAP://" + d_def
short_WinNT_name= mid(d_def, instr(d_def,"=")+1,instr(d_def,",")-instr(d_def,"=")-1)
Wscript.Echo long_Ldap_name ; имеет вид «DC=domain, DC=ru»
Wscript.Echo short_ WinNT_name ; имеет вид «Domain»
Для провайдера WinNT описание группы определяется следующим образом:
$1C_Group_Descr=GetObject(“WinNT://”+short_WinNT_name+”/”+$1C_Group).Description
Для провайдера LDAP описание группы определяется так:
$strADSQuery = "SELECT description FROM 'LDAP://" + $long_Ldap_name + "' WHERE Name = "' + $1C_Group + "' and objectClass='group'"
$objADOConn = createObject("ADODB.Connection")
$objADOConn.Provider = "ADsDSOObject"
$objADoConn.Open ("Active Directory Provider")
$objADOCommand = CreateObject("ADODB.Command")
$objADOCommand.ActiveConnection = $objADOConn
$objADOCommand.CommandText = $strADSQuery
$objQueryResultSet = $objADOCommand.Execute
$1C_Group_Descr =$objQueryResultSet.Fields("description")
Оба варианта имеют право на жизнь, и скорость их работы примерно одинакова, однако рекомендуется использовать второй вариант, несмотря на то что он выглядит громоздким. Дело в том, что провайдер WinNT был разработан для Windows NT, а LDAP – для Windows 2000. В ближайшем будущем, компания Microsoft, наверное, откажется от поддержки провайдера WinNT.
Таким образом, сценарий, формирующий массив, элементы которого включают в себя путь и название базы, выглядит следующим образом:
$meta = ReadProfileString($FName, $Section, “1C_Symbol”)
$1C_Letter_VaL = ReadProfileString($FName, $Section, “1C_Letter”)
Set rootDSE_ = GetObject("LDAP://RootDSE")
d_def=rootDSE_.Get("defaultNamingContext")
long_Ldap_name = "LDAP://" + d_def
$p=0
$q=0
Dim $1C_Must[]
DO
$group=EnumGoup($p)
If Instr($group, $meta)<>0
$1C_Group=Right($group,Len(group)-InstrRev($group,”\”)-Len($meta))
;вид переменной R:\Folder_with_Base
$1C_Base=$1C_Letter_VaL+”:\”+$1C_Group
$strADSQuery = "SELECT description FROM 'LDAP://" + $long_Ldap_name + "' WHERE Name = "' + $1C_Group + "' and objectClass='group'"
$objADOConn = createObject("ADODB.Connection")
$objADOConn.Provider = "ADsDSOObject"
$objADoConn.Open ("Active Directory Provider")
$objADOCommand = CreateObject("ADODB.Command")
$objADOCommand.ActiveConnection = $objADOConn
$objADOCommand.CommandText = $strADSQuery
$objQueryResultSet = $objADOCommand.Execute
$1C_Group_Descr =$objQueryResultSet.Fields("description")
; переопределение размера динамического массива
Redim Preserve $1C_Must[$q]
$1C_Must[$q]= UCase($1C_Base)+$meta+$1C_Group_Descr
$q=$q+1
End if
$p=$p+1
UNTIL Len($group)=0
Формирование списка подключенных баз
Список баз определяется чтением параметров и значений из соответствующей ветви реестра в массив, структура элементов которого аналогична элементам массива $1C_ Must[$q]. Ветвь реестра, из которой будет читаться информация, рекомендуется описать в конфигурационном файле (см. рис. 1):
[1C]
; по умолчанию ветвь HKCU
1C_Registry=Software\1c\1cv7\7.7\Titles
Чтение списка параметров из раздела Titles, названия которых являются путями к каталогам, в которых находятся базы «1С», осуществляется с помощью функции EnumValue() (см. рис. 1), а значений параметров, являющихся названиями баз, считываемые из поля Description групп безопасности, – с помощью функции ReadValue():
$1C_Registry_Val = ReadProfileString($FName, $Section, “1C_Registry”)
dim $1c_connected[]
$m=0
$n=0
DO
$1c_Title=EnumValue($1C_Registry_Val, $m)
$1c_Name=ReadValue($1C_Registry_Val, $1c_Title)
if Lcase(Left($1c_Title,1))=Lcase($1C_Letter_VaL)
ReDim Preserve $1C_Connected[$n]
$1C_Connected[$n]=Ucase($1c_Title)+$meta +$1c_Name
$n=$n+1
endif
$m = $m + 1
UNTIL Len($1c_Title) =0
Таким образом, имеется два массива – уже подключенных баз и баз, которые должны быть подключены. Структура элементов обоих массивов одинакова. Элемент массива включает в себя локальный путь к базе и ее название. Эти параметры разделены уникальным символом.
Сопоставление сформированных списков баз
Сопоставление списков осуществляется в два этапа: на первом из них происходит удаление лишних баз. Напомним, что управление реализовано только для сетевых баз. Локальные базы сценарий загрузки «не трогает». Сопоставление списков осуществляется с помощью функции AScan(), которая ищет совпадающие элементы в массивах. Удаление лишних баз осуществляется стиранием лишнего параметра в реестре с помощью функции DelValue(). На втором этапе добавляются отсутствующие базы с помощью той же самой функции AScan(). Используя её, в качестве параметров указывается и в первом и во втором случае одни и те же массивы. Только в первом случае анализируемым массивом является $1c_Must[], а во втором – 1c_Connected[]:
; удаление лишних баз
for $dfg=0 to ubound($1c_Сonnected)
$flag_p=0
$flag_p=AScan($1c_Must, $1c_Connected[$dfg])
if $flag_p=-1
$group=$1c_Connected[$dfg]
DelValue ($1c_path, ї
Left($Group,Instrrev($Group,$meta)-1))
endif
next
; подключение недостающих баз
for $dfg=0 to ubound($1c_must)
$flag_p=0
$flag_p=Ascan($1c_connected,$1c_must[$dfg])
if $flag_p=-1
$group=$1c_must[$dfg]
WriteValue ($1c_Path, Left($group, ї
Instrrev($group,$meta)-1), Right($group,Len($group)-Instrrev($group, $meta) - Len($meta)+1),"REG_SZ")
endif
next
Установка пользователя «1С» по умолчанию
Осуществив вход в сеть, пользователь, запускающий «1С» ожидает увидеть, что при авторизации входа в базу «1С» из списка ему будет предложено по умолчанию его имя. Для того чтобы это реализовать, необходимо, чтобы имя пользователя в сети и «1С» либо совпадали, либо были взаимосвязаны при помощи какого-либо правила. Для удобства работы пользователей рекомендуется сделать имена пользователей в сети и в «1С» идентичными. Имя пользователя по умолчанию в каждой базе отдельно в разделе HKCUSoft-ware1c1cv77.7BASE_NAME|startup значением параметра UserName. Поскольку значение этого параметра совпадает с именем пользователя в сети, то рекомендуется воспользоваться одним из встроенных макросов в KIXTart – @userid, с помощью которого определяется имя текущего пользователя.
Листинг этой функции выглядит следующим образом:
WriteValue ($1c_base+""+Right($group,Len($group) - Instrrev($group, $meta)-Len($meta)+1)+"StartUp", "UserName", @userid, "REG_SZ")
Листинг рекомендуется включить в процедуру сопоставления списка баз в раздел добавления баз, сразу после функции записи нового значения базы в разделе Titles.
В том случае если указанное имя пользователя не найдено (см. рис. 2) в списке пользователей «1С», то сама программа уничтожит созданную запись пользователя по умолчанию, и пользователь увидит пустое поле. С помощью раскрывающегося списка он должен будет выбрать имя пользователя, под которым он будет работать с базой «1С».
Рисунок 2
Заключение
Результатом работы созданного сценария является формирование списка баз «1С», с которыми пользователь имеет право работать. При выборе базы «1С», имя пользователя по умолчанию определяется автоматически. Таким образом, при переходе бухгалтера с одной рабочей станции на другую или смены его должностных обязанностей, затраты на администрирование значительно сокращаются: управление подключением баз осуществляется в автоматическом режиме. Новый инструмент может быть подключен к сценарию регистрации пользователей в сети в качестве функции. В приложении (на сайте журнала http://samag.ru в разделе «Исходный код») приведены примеры листинга конфигурационного файла config.ini и непосредственно сценарий.