Подключить или отключить сетевой диск через 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, сетевое подключение будет удалено из профиля пользователя
Если пробовать написать лисп-код, то получится нечто типа:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | (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 |
Ну и соответственно отключение от диска (предполагаю, что отключать надо независимо ни от чего; подключение, если оно и было сохранено в профиле пользователя, должно быть оттуда удалено):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | (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).