Подключить или отключить сетевой диск через LISP
Понадобилось тут мне поиграться с подключениями и отключениями сетевых дисков через LISP. Самое простое решение - использовать shell и стандартную команду Windows "net use ..." не подходило по нескольким причинам:
- Появляется (и не всегда гасится) окно cmd.exe. Уже не самое изящное решение
- Подключение выполняется под нестандартным пользователем и с указанием пароля. Если окно cmd.exe не закрывается "автоматом", то пользователь может прочитать информацию, не предназначенную для него
- Затруднительно отловить момент окончания выполнения net use. Если дальнейший код "завязан" на результат выполнения net use, можно получить очень неприятный результат: подключение выполнено, но не когда оно нужно
- И, наконец, последнее: практически нереально отловить ошибку выполнения net use
Непродолжительный поиск по MSDN привел к объекту WScript.Network и его методам MapNetWorkDrive и RemoveNetworkDrive:
MapNetworkDriveСинтаксис:
MapNetworkDrive(<LocalName>, <RemoteName>, <UpdateProfile>, <User>, <Password>)
Назначение: подключает сетевой диск.
Параметры:
<LocalName> Строка, локальное имя диска <RemoteName> Строка, имя сетевого ресурса <UpdateProfile> Необязательный, булево. Если указано True, создаваемое сетевое подключение будет сохранено в профиле пользователя. В LISP используется t или nil <User> Необязательный, строка. Имя пользователя, если сетевой диск подключается от пользователя, отличного от текущего <Password> Необязательный, строка. Пароль пользователя, если сетевой диск подключается от пользователя, отличного от текущего
RemoveNetworkDriveСинтаксис:
RemoveNetworkDrive(<Name>, <Force>, <UpdateProfile>)
Назначение: отключает сетевой диск.
Параметры:
<Name> строка, локальное имя диска (или сетевое имя, если ресурсу не сопоставлена никакая буква) <Force> необязательный, число (булево). Если указано True, отключение будет произведено вне зависимости от того, используется ресурс в настоящий момент или нет <UpdateProfile> необязательный, число (булево). Если указано True, сетевое подключение будет удалено из профиля пользователя
Если пробовать написать лисп-код, то получится нечто типа:
- (defun connect-net-drive (local-path net-path save name pwd / wsh)
- ;|
- * Подключение сетевого диска
- * Параметры:
- local-path Буква подключаемого диска
- net-path Серверный путь. Если содержит пробелы, обязательно заключать в кавычки
- save Сохранять в профиле пользователя (t || nil)
- name Имя пользователя. nil -> использовать текущий
- pwd Пароль подключения
- * В принципе, возможна ситуация, когда подключение выполняется с текущим пользователем,
- * но пароль должен быть "предопределенным". Поэтому обработка и выполняется именно такми
- * методом.
- * В случае успеха подключения сетевого диска возвращает t.
- |;
- (setq wsh (vlax-get-or-create-object "WScript.Network")
- res
- (not (vl-catch-all-error-p
- (vl-catch-all-apply
- (function
- (lambda ()
- (cond
- ((and name pwd)
- (vlax-invoke wsh 'mapnetworkdrive local-path net-path save name pwd)
- )
- ((and name (not pwd))
- (vlax-invoke wsh 'mapnetworkdrive local-path net-path save name)
- )
- ((and (not name) pwd)
- (vlax-invoke wsh
- 'mapnetworkdrive
- local-path
- net-path
- save
- (strcat (getenv "username") "@" (getenv "userdomain"))
- pwd
- ) ;_ end of vlax-invoke
- )
- ((and (not name) (not pwd))
- (vlax-invoke wsh 'mapnetworkdrive local-path net-path save)
- )
- ) ;_ end of lambda
- ) ;_ end of function
- ) ;_ end of vl-catch-all-apply
- ) ;_ end of vl-catch-all-apply
- ) ;_ end of vl-catch-all-error-p
- ) ;_ end of not
- ) ;_ end of setq
- (vlax-release-object wsh)
- res
- ) ;_ end of defun
Ну и соответственно отключение от диска (предполагаю, что отключать надо независимо ни от чего; подключение, если оно и было сохранено в профиле пользователя, должно быть оттуда удалено):
- (defun disconnect-net-drive (name)
- ;|
- * Отключение диска
- * Параметры вызова:
- name имя локального диска
- * Возвращает t, если диск удалось отключить. Если выполняется попытка отключить несуществующий
- * диск, или произошла ошибка отлюкчения, возвращает nil.
- |;
- (setq wsh (vlax-get-or-create-object "WScript.Network")
- res (not (vl-catch-all-error-p
- (vl-catch-all-apply
- (function
- (lambda ()
- (vlax-invoke wsh 'removenetworkdrive name t t)
- ) ;_ end of lambda
- ) ;_ end of function
- ) ;_ end of vl-catch-all-apply
- ) ;_ end of vl-catch-all-error-p
- ) ;_ end of not
- ) ;_ end of setq
- (vlax-release-object wsh)
- res
- ) ;_ end of defun
Вообще говоря, WScript.Network весьма занятный объект. В качестве примера можно использовать страницу http://www.script-coding.com/WSH/WshNetwork.html#3.3.
P.S. Работа кодов проверена на AutoCAD 2009, 2013 (x64).
Автор: Алексей Кулик.
Обсуждение: http://adn-cis.org/forum/index.php?topic=1870
Опубликовано 16.02.2015