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

Hop*_*00b 10 scripting active-directory group-policy network-printer

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

好消息是我们有十多个站点,而且在大多数情况下,我可以将站点 X 的所有打印机推送到站点 X 的所有客户端 PC。

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

我的用于将打印服务器上的所有打印机添加到 GPO/GPP 的脚本的 Google-Fu 是空的,我似乎看不到以半自动方式执行此操作的另一种方法,但我坚持相信我遗漏了一些东西,因为任何理智的人都不会选择手动将数百台打印机添加到 GPO 中。

理想情况下,我想找到一种使用 GPP 的编程方式,但在这种情况下,任何不涉及数十小时手动添加打印机的解决方案都会很棒。

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

Eva*_*son 8

在我看来,组策略的 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>
"@
Run Code Online (Sandbox Code Playgroud)

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

我实际上并没有尝试让 GPP CSE 解析这个 XML。XML 确实验证,至少。

我开始考虑使用Get-GPO并解析 GUID 来编写一些怪物以获取 SYSVOL 中 GPO 的文件系统路径,但是,鉴于今晚我需要做一些实际工作,我想我要离开了作为读者的练习。>smile< 不过应该是非常可行的。

  • Powershell 确实需要更多 GPO 选项。Get-Link、Set-Link、New-GPO 和 Set-GPORegistry 真的不够好...... (2认同)

Kat*_*ard 7

我非常努力地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)
}
Run Code Online (Sandbox Code Playgroud)

如果打印机被命名为逻辑事物,并且有一些逻辑方法来识别机器,那么您可能能够对其进行更多改进。例如,我曾经根据提取客户端 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>
Run Code Online (Sandbox Code Playgroud)