You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell GUI添加打印服务器ComboBox实现打印机列表联动

核心错误说明

你修改后的代码存在以下问题,导致功能无法正常运行:

  • 变量初始化顺序错误:脚本最顶部定义$printserver时,$cmbx_Server下拉框控件还未创建,且双引号内直接引用对象属性的写法不会被PowerShell正确解析,$printserver从初始化开始就是无效值
  • 事件逻辑缺失:下拉框的选中切换事件仅做了文本打印,没有实现「清空旧打印机列表→拉取选中服务器的打印机列表→填充到ListBox」的核心逻辑
  • 按钮事件语法错误:「Select Server」按钮的点击代码将PowerShell命令字符串错误作为参数传给下拉框属性,完全不会执行打印机查询操作
  • 启动逻辑错误:窗体加载阶段直接尝试读取未选中服务器的打印机列表,必然触发报错
  • 全局变量未动态更新:安装、设为默认打印机等事件中引用的$printserver始终是初始化时的无效值,不会随下拉框选择变化
修正后可运行完整代码
### Variables
# 定义打印服务器列表
$printServerList = @('Printserver1','Printserver2','Printserver3','Printserver4','Printserver5','Printserver6','Printserver7','Printserver8','Printserver9','Printserver0')

### Hide PowerShell Console
Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
$consolePtr = [Console.Window]::GetConsoleWindow()
[Console.Window]::ShowWindow($consolePtr, 0)

### GUI
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()

$Form                                = New-Object system.Windows.Forms.Form
$Form.ClientSize                     = '350,450'
$Form.text                           = "Printer Install Tool"
$Form.TopMost                        = $false

$lbl_Server                      = New-Object system.Windows.Forms.Label
$lbl_Server.text                 = "Print Server"
$lbl_Server.AutoSize             = $true
$lbl_Server.width                = 25
$lbl_Server.height               = 10
$lbl_Server.location             = New-Object System.Drawing.Point(11,16)
$lbl_Server.Font                 = New-Object System.Drawing.Font('Microsoft Sans Serif',10)

$cmbx_Server                     = New-Object system.Windows.Forms.ComboBox
$cmbx_Server.text                = "Choose Server"
$cmbx_Server.width               = 320
$cmbx_Server.height              = 30
$printServerList | ForEach-Object {[void] $cmbx_Server.Items.Add($_)}
$cmbx_Server.location            = New-Object System.Drawing.Point(11,46)
$cmbx_Server.Font                = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
$cmbx_Server.DropDownStyle       = 'DropDownList'

$btn_Cancel                          = New-Object system.Windows.Forms.Button
$btn_Cancel.text                     = "Close"
$btn_Cancel.width                    = 100
$btn_Cancel.height                   = 30
$btn_Cancel.location                 = New-Object System.Drawing.Point(225,410)
$btn_Cancel.Font                     = 'Microsoft Sans Serif,10'

$btn_Install                         = New-Object system.Windows.Forms.Button
$btn_Install.text                    = "Install printer"
$btn_Install.width                   = 100
$btn_Install.height                  = 30
$btn_Install.location                = New-Object System.Drawing.Point(10,410)
$btn_Install.Font                    = 'Microsoft Sans Serif,10'

$btn_Default                         = New-Object system.Windows.Forms.Button
$btn_Default.text                    = "Set as Default"
$btn_Default.width                   = 100
$btn_Default.height                  = 30
$btn_Default.location                = New-Object System.Drawing.Point(117,410)
$btn_Default.Font                    = 'Microsoft Sans Serif,10'

$txtBox_Location                     = New-Object system.Windows.Forms.TextBox
$txtBox_Location.multiline           = $false
$txtBox_Location.width               = 147
$txtBox_Location.height              = 20
$txtBox_Location.location            = New-Object System.Drawing.Point(179,110)
$txtBox_Location.Font                = 'Microsoft Sans Serif,8'
$txtBox_Location.ReadOnly            = $true

$listBox_Printers                    = New-Object system.Windows.Forms.ListBox
$listBox_Printers.text               = "listBox"
$listBox_Printers.width              = 159
$listBox_Printers.height             = 250
$listBox_Printers.location           = New-Object System.Drawing.Point(11,110)

$lbl_ChoosePrinter                   = New-Object system.Windows.Forms.Label
$lbl_ChoosePrinter.text              = "Choose a printer"
$lbl_ChoosePrinter.AutoSize          = $true
$lbl_ChoosePrinter.width             = 25
$lbl_ChoosePrinter.height            = 10
$lbl_ChoosePrinter.location          = New-Object System.Drawing.Point(11,90)
$lbl_ChoosePrinter.Font              = 'Microsoft Sans Serif,10'

$lbl_PrinterLoc                      = New-Object system.Windows.Forms.Label
$lbl_PrinterLoc.text                 = "Printer location"
$lbl_PrinterLoc.AutoSize             = $true
$lbl_PrinterLoc.width                = 25
$lbl_PrinterLoc.height               = 10
$lbl_PrinterLoc.location             = New-Object System.Drawing.Point(179,90)
$lbl_PrinterLoc.Font                 = 'Microsoft Sans Serif,10'

$Form.controls.AddRange(@($btn_Cancel,$btn_Install,$txtBox_Location,$listBox_Printers,$lbl_ChoosePrinter,$lbl_PrinterLoc,$btn_Default,$lbl_Server,$cmbx_Server))


### Eventhandlers 
# 下拉框选中服务器时自动加载对应打印机列表
$cmbx_Server.Add_SelectedIndexChanged({
    # 清空旧列表
    $listBox_Printers.Items.Clear()
    $txtBox_Location.Clear()
    $selectedServer = $cmbx_Server.SelectedItem.ToString()
    
    try {
        # 拉取选中服务器的打印机
        $printers = Get-Printer -ComputerName $selectedServer -ErrorAction Stop | Select-Object -Property Location, Name
        foreach($printer in $printers){
            [void]$listBox_Printers.Items.Add($printer.Name)
        }
    }
    catch {
        [System.Windows.Forms.MessageBox]::Show("无法连接到打印服务器 $selectedServer : $_", "连接错误", "OK", "Error")
    }
})

$listBox_Printers.Add_SelectedIndexChanged({ 
    if ($listBox_Printers.SelectedItem -and $cmbx_Server.SelectedItem) {
        $printName = $listBox_Printers.SelectedItem.ToString()
        $selectedServer = $cmbx_Server.SelectedItem.ToString()
        $txtBox_Location.Text = (Get-Printer -ComputerName $selectedServer -Name $printName).Location
    }
})

$btn_Default.Add_Click({ 
    if (-not $cmbx_Server.SelectedItem -or -not $listBox_Printers.SelectedItem) {
        [System.Windows.Forms.MessageBox]::Show("请先选择打印服务器和打印机", "提示", "OK", "Warning")
        return
    }
    $selectedServer = $cmbx_Server.SelectedItem.ToString()
    $printName = $listBox_Printers.SelectedItem.ToString()
    # 兼容新旧版本Windows的默认打印机设置逻辑
    Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Windows' -Name "LegacyDefaultPrinterMode" -Value 1 -ErrorAction SilentlyContinue
    (New-Object -ComObject WScript.Network).SetDefaultPrinter("\\$selectedServer\$printName")
    [System.Windows.Forms.MessageBox]::Show("已将 $printName 设置为默认打印机", "操作成功", "OK", "Information")
})

$btn_Cancel.Add_Click({ 
    $Form.Close() 
})

$btn_Install.Add_Click({ 
    if (-not $cmbx_Server.SelectedItem -or -not $listBox_Printers.SelectedItem) {
        [System.Windows.Forms.MessageBox]::Show("请先选择打印服务器和打印机", "提示", "OK", "Warning")
        return
    }
    $selectedServer = $cmbx_Server.SelectedItem.ToString()
    $printName = $listBox_Printers.SelectedItem.ToString()
    try {
        Add-Printer -ConnectionName "\\$selectedServer\$printName" -ErrorAction Stop
        [System.Windows.Forms.MessageBox]::Show("打印机 $printName 安装成功", "操作成功", "OK", "Information")
    }
    catch {
        # 兼容旧系统用rundll32方式安装
        rundll32 printui.dll,PrintUIEntry /in /n "\\$selectedServer\$printName"
    }
})

[void]$Form.ShowDialog()
改动说明
  • 移除了多余的「Select Server」按钮,选中下拉框选项后自动加载对应打印机列表,操作更顺畅
  • 所有事件中动态获取当前选中的服务器,不再依赖初始化时的全局无效变量
  • 增加了空选择校验、服务器连接错误提示、操作成功提示,交互更友好
  • 修复了原修改版中重复的打印服务器列表项,将下拉框设为仅可选择不可编辑,避免输入无效值
  • 兼容新旧版本Windows的打印机安装、默认打印机设置逻辑
  • 位置文本框设为只读,避免用户误修改

内容的提问来源于stack exchange,提问作者PCMedicJAX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 00:54:26