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

Windows服务下Java RDP会话筛选当前用户重定向打印机

Windows服务下筛选当前用户专属打印机的方案

问题根源

Windows服务以系统账户运行时,默认会枚举所有登录用户会话里的打印机资源。要筛选出当前进程所属用户的打印机,关键是把打印机和Windows会话ID关联匹配。

具体实现步骤

1. 获取当前进程的会话ID

Java标准库没提供直接拿会话ID的方法,得用JNA调用Windows API:

import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;

public class SessionHelper {
    public static int getCurrentSessionId() {
        WinNT.HANDLE processHandle = Kernel32.INSTANCE.GetCurrentProcess();
        int[] sessionId = new int[1];
        Kernel32.INSTANCE.ProcessIdToSessionId(Kernel32.INSTANCE.GetProcessId(processHandle), sessionId);
        return sessionId[0];
    }
}

2. 查询打印机对应的会话ID并筛选

通过WMI查询每个打印机的会话ID属性,再和当前进程的会话ID匹配:

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.management.MBeanServerConnection;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class PrinterFilter {
    public static List<String> getCurrentSessionPrinters() throws Exception {
        int targetSessionId = SessionHelper.getCurrentSessionId();
        List<String> matchedPrinters = new ArrayList<>();

        // 连接本地WMI服务
        JMXServiceURL wmiUrl = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/wmi");
        JMXConnector connector = JMXConnectorFactory.connect(wmiUrl);
        MBeanServerConnection mBeanConn = connector.getMBeanServerConnection();

        // 查询所有Win32_Printer实例
        ObjectName printerMBean = new ObjectName("Win32_Printer");
        Set<ObjectInstance> allPrinters = mBeanConn.queryMBeans(printerMBean, null);

        for (ObjectInstance printer : allPrinters) {
            ObjectName objName = printer.getObjectName();
            Integer printerSessionId = (Integer) mBeanConn.getAttribute(objName, "SessionId");
            String printerName = (String) mBeanConn.getAttribute(objName, "Name");

            if (printerSessionId != null && printerSessionId == targetSessionId) {
                matchedPrinters.add(printerName);
            }
        }

        connector.close();
        return matchedPrinters;
    }
}

3. 整合到原有代码

修改你原来的findPrinters方法,加入筛选逻辑:

public void findPrinters() {
    try {
        List<String> sessionPrinters = PrinterFilter.getCurrentSessionPrinters();
        
        PrintService[] allServices = PrinterJob.lookupPrintServices();
        for (PrintService service : allServices) {
            if (sessionPrinters.contains(service.getName())) {
                log.info("当前会话打印机: {}", service.getName());
            }
        }
    } catch (Exception e) {
        log.error("筛选打印机失败", e);
    }
}

注意点

  • 要引入JNA依赖(比如net.java.dev.jna:jna-platform)才能调用Windows API。
  • Windows服务得有足够权限访问WMI,不然查不到打印机的会话信息。
  • 本地打印机的SessionId可能是0,要是你的场景包含这类打印机,得调整匹配逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 11:37:33