ADN Open CIS
Сообщество программистов Autodesk в СНГ

16/02/2015

Подключить или отключить сетевой диск через LISP

Понадобилось тут мне поиграться с подключениями и отключениями сетевых дисков через LISP. Самое простое решение - использовать shell и стандартную команду Windows "net use ..." не подходило по нескольким причинам:

  1. Появляется (и не всегда гасится) окно cmd.exe. Уже не самое изящное решение
  2. Подключение выполняется под нестандартным пользователем и с указанием пароля. Если окно cmd.exe не закрывается "автоматом", то пользователь может прочитать информацию, не предназначенную для него
  3. Затруднительно отловить момент окончания выполнения net use. Если дальнейший код "завязан" на результат выполнения net use, можно получить очень неприятный результат: подключение выполнено, но не когда оно нужно
  4. И, наконец, последнее: практически нереально отловить ошибку выполнения 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, сетевое подключение будет удалено из профиля пользователя

Если пробовать написать лисп-код, то получится нечто типа:

Код - Auto/Visual LISP: [Выделить]
  1. (defun connect-net-drive (local-path net-path save name pwd / wsh)
  2.                          ;|
  3. *    Подключение сетевого диска
  4. *    Параметры:
  5.   local-path    Буква подключаемого диска
  6.   net-path      Серверный путь. Если содержит пробелы, обязательно заключать в кавычки
  7.   save          Сохранять в профиле пользователя (t || nil)
  8.   name          Имя пользователя. nil -> использовать текущий
  9.   pwd           Пароль подключения
  10. *    В принципе, возможна ситуация, когда подключение выполняется с текущим пользователем,
  11. * но пароль должен быть "предопределенным". Поэтому обработка и выполняется именно такми
  12. * методом.
  13. *    В случае успеха подключения сетевого диска возвращает t.
  14. |;
  15.   (setq wsh (vlax-get-or-create-object "WScript.Network")
  16.         res
  17.             (not (vl-catch-all-error-p
  18.                    (vl-catch-all-apply
  19.                      (function
  20.                        (lambda ()
  21.  
  22.                          (cond
  23.                            ((and name pwd)
  24.                             (vlax-invoke wsh 'mapnetworkdrive local-path net-path save name pwd)
  25.                             )
  26.                            ((and name (not pwd))
  27.                             (vlax-invoke wsh 'mapnetworkdrive local-path net-path save name)
  28.                             )
  29.                            ((and (not name) pwd)
  30.                             (vlax-invoke wsh
  31.                                          'mapnetworkdrive
  32.                                          local-path
  33.                                          net-path
  34.                                          save
  35.                                          (strcat (getenv "username") "@" (getenv "userdomain"))
  36.                                          pwd
  37.                                          ) ;_ end of vlax-invoke
  38.                             )
  39.                            ((and (not name) (not pwd))
  40.                             (vlax-invoke wsh 'mapnetworkdrive local-path net-path save)
  41.                             )
  42.                            ) ;_ end of lambda
  43.                          ) ;_ end of function
  44.                        ) ;_ end of vl-catch-all-apply
  45.                      ) ;_ end of vl-catch-all-apply
  46.                    ) ;_ end of vl-catch-all-error-p
  47.                  ) ;_ end of not
  48.         ) ;_ end of setq
  49.   (vlax-release-object wsh)
  50.   res
  51.   ) ;_ end of defun

Ну и соответственно отключение от диска (предполагаю, что отключать надо независимо ни от чего; подключение, если оно и было сохранено в профиле пользователя, должно быть оттуда удалено):

Код - Auto/Visual LISP: [Выделить]
  1. (defun disconnect-net-drive (name)
  2.                             ;|
  3. *    Отключение диска
  4. *    Параметры вызова:
  5.   name    имя локального диска
  6. *    Возвращает t, если диск удалось отключить. Если выполняется попытка отключить несуществующий
  7. * диск, или произошла ошибка отлюкчения, возвращает nil.
  8. |;
  9.   (setq wsh (vlax-get-or-create-object "WScript.Network")
  10.         res (not (vl-catch-all-error-p
  11.                    (vl-catch-all-apply
  12.                      (function
  13.                        (lambda ()
  14.                          (vlax-invoke wsh 'removenetworkdrive name t t)
  15.                          ) ;_ end of lambda
  16.                        ) ;_ end of function
  17.                      ) ;_ end of vl-catch-all-apply
  18.                    ) ;_ end of vl-catch-all-error-p
  19.                  ) ;_ end of not
  20.         ) ;_ end of setq
  21.   (vlax-release-object wsh)
  22.   res
  23.   ) ;_ 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