【发布时间】:2019-07-24 02:26:55
【问题描述】:
我正在尝试在 Windows Server 2012 R2 Standard 上的打印机队列中获取作业的域用户名。下面的代码 sn-p 在 Delphi 中。 OpenPrinter 和 EnumJobs 是 Windows 后台处理程序 API 的一部分。
更新! 将 maxJobs 设置为 4 的更高倍数允许枚举队列中的更多作业。例如。设置 maxJobs=8 允许两个作业,但不是三个。 maxJobs=12 允许三个作业。
已解决! 看来我可以忽略 EnumJobs 的返回值,只需查看它返回的作业数是否 > 0(调用时的最后一个参数)。这似乎适用于下面列出的所有实例,包括通过共享的打印机。
const
maxJobs = 4;
var
h : THandle;
jia : array [1..maxJobs] of JOB_INFO_1;
jiz, jic : DWord; // size of jia, count of jia
begin
if OpenPrinter('DocTest', h, nil) then
begin
if EnumJobs(h, 0, maxJobs, 1, @jia, SizeOf(jia), jiz, jic) then
[...]
EnumJobs 根据下面列出的不同条件返回 true 或 false。如果它在以下任何一种情况下返回 false,我正在检索的错误消息是“系统错误。代码:5。访问被拒绝”。
显然是权限问题。我已在打印机安全设置中将打印、管理此打印机和管理文档分配给每个人。分配这些设置后,所有作业均已提交。我的程序正在以域管理员身份登录的会话中运行。
- 如果我从运行此程序的同一会话中打印作业,并且队列中只有一个作业,则 EnumJobs 将返回 TRUE。 (有关更改,请参阅上面的更新)
- 如果我以任何用户身份从服务器上的另一个会话(它安装了终端服务)打印,并且队列中只有一个作业,则 EnumJobs 返回 TRUE。 (有关更改,请参阅上面的更新)
- 如果队列中有多个作业,EnumJobs 将返回 FALSE。作业是否针对同一用户并不重要。 (有关更改,请参阅上面的更新)
- 如果我将作业从另一台服务器打印到打印机共享,EnumJobs 将返回 FALSE。两台服务器都在同一个域中。哪个用户打印作业都没有关系,包括域管理员。
这里发生了什么,特别是在一次枚举超过 (maxJobs / 4) 个作业时访问被拒绝?
【问题讨论】:
-
程序是否有权访问
C:\Windows\System32\spool目录? -
@Drake 确实如此,毕竟它是以域管理员身份运行的。获取上述作业信息后,它会扫描 spool 文件夹的 *.spl 文件中的作业内容以获取更多信息,然后再删除作业。