none
Создание и удаление подключения к сетевому принтеру (VBS) RRS feed

  • Вопрос

  • В некотором домене на некотором сервере жил да был принтер. И решил великий директор заменить этот принтер на новый. И кинул он клич немалый: "Ой вы админы мои дорогие, замените у пользователей старую очередь печати на новую!" И поручили эту работу младшему админу. Он заглянул в Script Center Gallery и написал скриптик.

    А теперь сказка заканчивается и начинается горькая правда.

    При тестировании выяснилось, что скрипт замечательно отрабатывает, если у пользователя есть права админа. Если же таких прав нет, то ничего не происходит. При этом пользователь может самостоятельно подключить себе принтер просто набрав в адресной строке проводника \\server\printername.
    Собственно вопрос: как сделать так, чтобы этот скрипт работал у всех пользователей? Предполагается навешивать его через ГП как logon script.

    Текст скрипта:
    -----
    '==============================
    '=== Replace printer
    '=== Ver.1
    '=== Language: VBScript (.vbs)
    '==============================
    
    on error resume next
    
    '########## printer configuration ##########
    
    OldPrnName = "\\server\printershare"
    NewPrnName = "\\server\printershare"
    
    '##############################
    
    PrnIsInstalled = false
    PrnIsDefault = false
    set WmiService = GetObject("winmgmts:{impersonationlevel=impersonate}!\\.\root\cimv2")
    set WshNetwork = CreateObject("wscript.network")
    
    '##### получаем версию ОС
    set ColOs = WmiService.ExecQuery("select * from win32_operatingsystem")
    for each ObjOs in ColOs
    	OsVersion = ObjOs.Version
    next
    
    '##### если ОС не XP и не Vista, скрипт завершает работу
    if not (OsVersion = "5.1.2600" or OsVersion = "6.0.6000") then
    	wscript.quit
    end if
    
    '##### получаем список сетевых принтеров и выставляем флаги
    set ColPrinters = WmiService.ExecQuery("select * from win32_printer where network = true")
    for each ObjPrinter in ColPrinters
    	if ObjPrinter.Name = OldPrnName then
    		PrnIsInstalled = true
    		if ObjPrinter.Default then
    			PrnIsDefault = true
    		end if
    	end if
    next
    
    '##### если старый принтер был установлен, добавляем новый и удаляем старый
    '##### если старый принтер был по умолчанию, делаем новый по умолчанию
    if PrnIsInstalled then
    	WshNetwork.AddWindowsPrinterConnection NewPrnName
    	if PrnIsDefault then
    		WshNetwork.SetDefaultPrinter NewPrnName
    	end if
    	WshNetwork.RemovePrinterConnection OldPrnName
    end if
    wscript.quit

    MCP | scriptoholic | PowerShell | SCCM 2007 | SMS 2003
    8 сентября 2009 г. 12:28

Ответы

  • Переписал скрипт используя только методы WMI. Работает без прав админа.
    -----
    '==============================
    '=== Replace printer
    '=== Ver.2
    '=== Language: VBScript (.vbs)
    '==============================
    
    on error resume next
    
    '########## printer configuration ##########
    
    OldPrnName = "\\server\printershare"
    NewPrnName = "\\server\printershare"
    
    '##############################
    
    PrnIsInstalled = false
    PrnIsDefault = false
    set WmiService = GetObject("winmgmts:{impersonationlevel=impersonate,(loaddriver)}!\\.\root\cimv2")
    set WmiPrinterClass = WmiService.Get("win32_printer")
    
    '=== получаем версию ОС
    set ColOs = WmiService.ExecQuery("select * from win32_operatingsystem")
    for each ObjOs in ColOs
    	OsVersion = ObjOs.Version
    next
    
    '=== если ОС не XP и не Vista, скрипт завершает работу
    if not (OsVersion = "5.1.2600" or OsVersion = "6.0.6000") then
    	Wscript.Quit
    end if
    
    '=== получаем список сетевых принтеров и выставляем флаги
    set ColPrinters = WmiService.ExecQuery("select * from win32_printer where network = true")
    for each ObjPrinter in ColPrinters
    	if ObjPrinter.Name = OldPrnName then
    		PrnIsInstalled = true
    		if ObjPrinter.Default then
    			PrnIsDefault = true
    		end if
    	end if
    next
    
    '=== если старый принтер был установлен, добавляем новый и удаляем старый
    '=== если старый принтер был по умолчанию, делаем новый по умолчанию
    if PrnIsInstalled then
    	Result = WmiPrinterClass.AddPrinterConnection(NewPrnName)
    	if not Result = 0 then
    		Wscript.Quit 1
    	end if
    	if PrnIsDefault then
    		NewPrnName = Replace(NewPrnName,"\","\\")
    		set ColPrinters = WmiService.ExecQuery("select * from win32_printer where name = '" & NewPrnName & "'")
    		for each ObjPrinter in ColPrinters
    			ObjPrinter.SetDefaultPrinter()
    		next
    	end if
    	OldPrnName = Replace(OldPrnName,"\","\\")
    	set ColPrinters = WmiService.ExecQuery("select * from win32_printer where name = '" & OldPrnName & "'")
    	for each ObjPrinter in ColPrinters
    		ObjPrinter.Delete_
    	next
    end if
    Wscript.Quit

    MCP | scriptoholic | PowerShell | SCCM 2007 | SMS 2003
    25 сентября 2009 г. 9:24

Все ответы

  • Скажите, а чем вам GPP не подходит? там как раз есть все необходимое для решения данной задачи
    Так же вы наверно просто пробуете под юзверем его запустить? Если так то когда он будет через GPO работать у него будут повышенные привилегии достаточные для поставленной задачи.
    9 сентября 2009 г. 11:05
  • По видимому, нет прав на
    WshNetwork.AddWindowsPrinterConnection
    WshNetwork.RemovePrinterConnection OldPrnName
    Почему, почему - пока не понял....

    А чем не нравится вариант с prnmngr от MS?

    prnmngr -d  -p "\\server\pr-share-01"
    prnmngr -ac -p "\\server\pr-share-02"

    или с net use:

    net use \\server\pr-share-01 /delete
    net use \\server\pr-share-02

    та же задача - но решается проше. С правами пользователя - работает....
    Если ответ Вам помог, нажмите на изображение зеленой галочки - «пометить как ответ». Если ответ был для Вас полезен, Вы можете пометить это сообщение как «полезное», нажав на ссылку "проголосовать за полезное сообщение" в правом верхнем углу сообщения.
    9 сентября 2009 г. 11:11
  • Насколько я понял GPP есть начиная с 2008 сервера, а у нас 2003.

    Тестировалось просто запуском скрипта под пользователем без прав админа. Вопрос как раз в том и состоит, будут ли у пользователя достаточные права, если этот скрипт будет запускаться через GPO? Если да, то отлично.

    То, что у простого пользователя не хватает прав для использования объекта WshNetwork я как раз догадался, а вот про prnmngr - это вы мне хорошо напомнили. Я про него совсем забыл, а ведь это просто vbs скрипт, поэтому я его просмотрел и выяснил, что в нём все операции производятся через WMI.

    Как удалять или делать дефолтным принтер используя WMI я и раньше знал. Но я нигде не мог найти, как создавать соединение с принтером. Именно поэтому пришлось использовать WshNetwork. Завтра перепишу скрипт используя только WMI.
    MCP | scriptoholic | PowerShell | SCCM 2007 | SMS 2003
    9 сентября 2009 г. 16:11
  • GPP есть и на 2003 для этого надо установить обновление KB943729 на сервер и на клиентов. А дальше открыть политику с vista/2008/windows 7 и будет доступно GPP :)
    Скрипт из GPO выполняется с повышенными привилегиями на сколько я знаю чуть ли не под админом. Хотя я могу путать.
    10 сентября 2009 г. 7:44
  • Уж если в скрипте используете on error resume next, то хорошо было бы анализировать возможные ошибки хотя бы таким бы обазом:

    WshNetwork.AddWindowsPrinterConnection NewPrnName

    If Err.Number <> 0 Then
      WScript.Echo "Ошибка !!!" & Err.Description
      WScript.Quit(1)
     End If
    Может и увидите в чем проблема. Кстати, на этапе отладки on error resume next лучше отключать.

    PS: я обычно подобные скрипты снабжаю возможностью писать в небольшой лог-файл, чтобы знать где в случае чего собака зарыта.


    Andrew Mishechkin
    10 сентября 2009 г. 10:50
  • GPP есть и на 2003 для этого надо установить обновление KB943729 на сервер и на клиентов. А дальше открыть политику с vista/2008/windows 7 и будет доступно GPP :)
    Скрипт из GPO выполняется с повышенными привилегиями на сколько я знаю чуть ли не под админом. Хотя я могу путать.

    GPP создается в двух разделах: Computer и User - соответственно контекст исполнения будет тот или иной.
    Сазонов Илья http://www.itcommunity.ru/blogs/sie-wl/
    11 сентября 2009 г. 5:35
    Модератор
  • Переписал скрипт используя только методы WMI. Работает без прав админа.
    -----
    '==============================
    '=== Replace printer
    '=== Ver.2
    '=== Language: VBScript (.vbs)
    '==============================
    
    on error resume next
    
    '########## printer configuration ##########
    
    OldPrnName = "\\server\printershare"
    NewPrnName = "\\server\printershare"
    
    '##############################
    
    PrnIsInstalled = false
    PrnIsDefault = false
    set WmiService = GetObject("winmgmts:{impersonationlevel=impersonate,(loaddriver)}!\\.\root\cimv2")
    set WmiPrinterClass = WmiService.Get("win32_printer")
    
    '=== получаем версию ОС
    set ColOs = WmiService.ExecQuery("select * from win32_operatingsystem")
    for each ObjOs in ColOs
    	OsVersion = ObjOs.Version
    next
    
    '=== если ОС не XP и не Vista, скрипт завершает работу
    if not (OsVersion = "5.1.2600" or OsVersion = "6.0.6000") then
    	Wscript.Quit
    end if
    
    '=== получаем список сетевых принтеров и выставляем флаги
    set ColPrinters = WmiService.ExecQuery("select * from win32_printer where network = true")
    for each ObjPrinter in ColPrinters
    	if ObjPrinter.Name = OldPrnName then
    		PrnIsInstalled = true
    		if ObjPrinter.Default then
    			PrnIsDefault = true
    		end if
    	end if
    next
    
    '=== если старый принтер был установлен, добавляем новый и удаляем старый
    '=== если старый принтер был по умолчанию, делаем новый по умолчанию
    if PrnIsInstalled then
    	Result = WmiPrinterClass.AddPrinterConnection(NewPrnName)
    	if not Result = 0 then
    		Wscript.Quit 1
    	end if
    	if PrnIsDefault then
    		NewPrnName = Replace(NewPrnName,"\","\\")
    		set ColPrinters = WmiService.ExecQuery("select * from win32_printer where name = '" & NewPrnName & "'")
    		for each ObjPrinter in ColPrinters
    			ObjPrinter.SetDefaultPrinter()
    		next
    	end if
    	OldPrnName = Replace(OldPrnName,"\","\\")
    	set ColPrinters = WmiService.ExecQuery("select * from win32_printer where name = '" & OldPrnName & "'")
    	for each ObjPrinter in ColPrinters
    		ObjPrinter.Delete_
    	next
    end if
    Wscript.Quit

    MCP | scriptoholic | PowerShell | SCCM 2007 | SMS 2003
    25 сентября 2009 г. 9:24