通过 GPO/GPP 部署打印机 - 是否有编程选项?

通过 GPO/GPP 部署打印机 - 是否有编程选项?

由于我无法控制的原因,我负责设置 GPO/GPP,以便将我们的 100 多台打印机部署到我们的 1000 多个客户。

好消息是我们有十几个站点,并且大多数情况下,我被允许将站点 X 上的所有打印机推送到站点 X 上的所有客户端 PC 上。

坏消息是,我知道的两种方法(“使用组策略部署...”,来自打印服务器”使用 GPP/组策略首选项) 涉及的手动工作量远远超过我愿意为这么多打印机所做的工作量。Deploy with Group Policy...例如,我甚至无法选择打印服务器上的所有打印机并使用该选项 - 它希望我逐个执行此操作,但这是不可能的。GPP 甚至更糟,因为它希望我从打印服务器中选择打印机的路径,然后手动输入一堆信息(例如打印机 IP),它应该能够从打印机连接中获取这些信息。

我用 Google-Fu 搜索一个脚本来将打印服务器上的所有打印机添加到 GPO/GPP,但却一无所获,而且我似乎找不到其他方法,哪怕是以半自动化的方式,但我坚持认为我遗漏了一些东西,因为任何理智的人都不会选择手动将数百台打印机添加到 GPO 中。

理想情况下,我希望找到一种以编程方式使用 GPP,但在这种情况下,任何不需要花费数十小时手动添加打印机的解决方案就很好了。

有人有办法做到这一点吗,或者我是否需要构建 PowerShell 脚本和/或欺骗下属这样做?

答案1

我用 Google 搜索了相当多的内容,甚至backup-GPO希望能够破解生成的 XML 文件并重新导入它,但我怀疑你将来会用到 PowerShell 脚本。

情况没那么糟。您可以从最近的服务器生成打印机列表,然后循环遍历并映射它们。

像这样:

$net = New-Object -COMObject WScript.Network
$printserver = 'yourserver'

$printerlist = Get-WMIObject -class Win32_Printer -computer $printserver | Where-Object {$_.ShareName -ne $null} | Select-Object ShareName
foreach ($printer in $printerlist) 
{
    $printerpath = '\\' + $printserver + '\' + $printer.ShareName
    #echo $printerpath
    $net.AddWindowsPrinterConnection($printerpath)
}

如果打印机的名称合乎逻辑,并且有某种合乎逻辑的方式来识别机器,那么您可能能够进一步完善它。例如,我过去常常根据提取客户端 IP 地址来选择最近的服务器。如果 IP 地址为 10.20.*,则转到 server1。等等。

我希望这能有所帮助。

编辑:

查看@EvanAnderson的文档,我很确定XML是容易被黑客入侵的。

我的导出文件的相关部分(带有删节):

<DSObject bkp:Path="CN={GUIDHERE},CN=PushedPrinterConnections,%GPO_MACH_DSPATH%" bkp:SourceExpandedPath="CN={13B9B596-452C-4652-A05D-78EF06610134},CN=PushedPrinterConnections,CN=Machine,CN={44A99FBA-0DB3-484C-808E-3DDAE9932A2B},CN=Policies,CN=System,DC=Domainname,DC=extension" bkp:ObjectClass="msPrint-ConnectionPolicy">
    <DSAttributeMultiString bkp:DSAttrName="showInAdvancedViewOnly">
        <DSValue><![CDATA[TRUE]]></DSValue>
    </DSAttributeMultiString>
    <DSAttributeMultiString bkp:DSAttrName="uNCName">
        <DSValue><![CDATA[\\Servername\PrinterShareName]]></DSValue>
    </DSAttributeMultiString>
    <DSAttributeMultiString bkp:DSAttrName="serverName">
        <DSValue><![CDATA[\\Servername]]></DSValue></DSAttributeMultiString>
    <DSAttributeMultiString bkp:DSAttrName="printAttributes">
        <DSValue><![CDATA[0]]></DSValue>
    </DSAttributeMultiString>
    <DSAttributeMultiString bkp:DSAttrName="printerName">
        <DSValue><![CDATA[PrinterShareName]]></DSValue>
    </DSAttributeMultiString>
</DSObject>

答案2

Powershell 管理组策略糟透了在我看来,没有第三方(商业)产品。

我觉得你被困住了通过 XML 进行传输(或在HTML(如果您喜欢)) 在组策略对象中执行您要查找的操作。

幸运的是XML 看起来并不那么可怕。每个打印机的 UID 值(我相信这是 @KatherineVillyard 在她的评论中所指的)只是为 XML 中引用的每台打印机生成的随机 GUID。

下面是一些 Powershell 代码示例,厚颜无耻地模仿了 Katherine 的代码:

@"
<?xml version="1.0" encoding="utf-8"?>
<Printers clsid="{1F577D12-3D1B-471e-A1B7-060317597B9C}" disabled="0">
"@

$net = New-Object -COMObject WScript.Network
$printserver = 'print-server'

$printerlist = Get-WMIObject -class Win32_Printer -computer $printserver | Where-Object {$_.ShareName -ne $null} | Select-Object ShareName
foreach ($printer in $printerlist) 
{
    $date = Get-Date
    echo '  <SharedPrinter clsid="{9A5E9697-9095-436d-A0EE-4D128FDFBCE5}"'
    '    name="' + $printer.ShareName + '"' | echo
    '    status="' + $printer.ShareName + '"' | echo
    echo '    image="2"'
    '    changed="' + $date + '"' | echo
    $ng = [GUID]::NewGuid().ToString('B')
    '    uid="' + $ng + '">' | echo

    echo '    <Properties'
    echo '      action="R"'
    echo '      comment=""'
    '      path="\\' + $printserver + '\' + $printer.ShareName + '"' | echo
    echo '      location=""'
    echo '      default="1"' 
    echo '      skipLocal="1"'
    echo '      deleteAll="0"'
    echo '      persistent="0"'
    echo '      deleteMaps="0"'
    echo '      port=""/>'
    echo '  </SharedPrinter>'
}

@"
</Printers>
"@

(我写的 Powershell 代码非常非常丑陋。)

我实际上还没有尝试让 GPP CSE 解析此 XML。至少 XML 确实经过验证。

我开始考虑编写一些复杂的程序,使用Get-GPO并解析 GUID 来获取 SYSVOL 中 GPO 的文件系统路径,但考虑到我今晚需要做一些真正的工作,我想我会把它留给读者作为练习。>微笑< 不过,这应该是非常可行的。

答案3

我最近承担了一个类似的项目,在研究了 GPO 推送方法、较新的 GPP 和脚本之后,我选择了编写整个脚本。我不知道哪种方法最适合您,但这里有一些建议供您参考:

  • 理想情况下,使用具有新操作系统(Windows 8/2012+)的客户端连接到打印服务器并从打印服务器获取打印机信息:

    获取打印机-计算机打印服务器名称

  • 使用 AD 安全组将打印队列映射到计算机。假设您有一个名为 \PrintServer1\MyColorPrinter123 的打印队列(您从上面的命令中收集),创建一个安全组,如 Printer.group.PrintServer1.MyColorPrinter123,并将计算机添加到该组

  • 在启动脚本中,有一个函数可以在计算机启动时检查其组成员身份,并查看它是否属于任何打印机组。如果是,请使用内置的 printui.exe(或 printui.dll)命令映射打印机,如下所示

    调用表达式 'rundll32 printui.dll,PrintUIEntry /ga /n"\PrintServer1\MyColorPrinter123" /q'

  • 一旦计算机启动,该打印后台处理程序服务就会将“打印连接”(GPO 过去所做的)推送给任何要登录的用户。

你可以讲得更详细**但是从高层次来看这就是必需的。

** 我创建了一个 GUI,允许用户(实际上是技术人员)选择任何打印服务器,并为他们提供该服务器上的打印机列表。如果他们选择一台,他们可以看到它的所有属性。该信息来自我上面提到的 Get-Printer。如果您将该数据导出为 csv,则可以重新使用它来显示信息。

** 技术人员使用该 GUI 发送请求,将计算机添加到它应该连接的打印机。这是一个“请求”,因为他们在 AD 中没有权限。

** 一个简单的后端脚本监视文件夹并将计算机添加到我上面提到的打印机组中。因此,如果您已经知道谁应该获得哪台打印机,那太好了,您可以轻松做到。使用 AD Cmdlet 将计算机添加到组是一项简单的工作。

** 您还可以安排一项作业来检查打印服务器,看是否有任何新的打印队列,并将它们与您的 AD 组进行比较。

因此,创建一个“托管”解决方案有点复杂,但很容易从基础开始,并不断添加,从而拥有一个非常灵活、易于使用且不涉及 GPO 的系统……只需要一点 PowerShell

相关内容