我有一个应用程序根据用户请求执行一些中央文件生成。创建文件后,我希望能够将它们放在该用户的打印队列中(在该组织中有一个中央打印队列,因此用户负责打印自己的文档),这样他们就可以了用户准备好后打印出来。
通过在.net中使用System.Printing
程序集,我可以将作业添加到我自己的打印队列中,所以我听起来就是这个部分。我的打印代码如下所示:
private void RunPrintJob( string myFileName )
{
PrintServer ps = new PrintServer(@"\\printatron");
PrintQueue queue = new PrintQueue(ps, "psandqueues");
try
{
PrintSystemJobInfo pj = queue.AddJob(myFileName);
Stream myStream = pj.JobStream;
Byte[] myByteBuffer = GenerateBufferFromFile(myFileName); myStream.Write(myByteBuffer, 0, myByteBuffer.Length);
myStream.Close();
}
catch (Exception ed)
{
Debug.WriteLine(ed.Message);
if (ed.InnerException != null)
{
Debug.WriteLine(" -> " + ed.InnerException);
}
result = false;
}
queue.Commit();
}
所以我拥有集中创建的文档,我知道哪个用户负责创建它们,我可以将它们发送到打印机。
我现在需要的是一种将创建它们的用户设置为打印机的方法。有没有办法通过打印队列执行此操作?我知道它可以从PrintSystemJobInfo.Submitter
属性中读取,但这是只读的。如果没有,我是否必须通过模拟来实现,如果是这样,在后一种情况下,我可以做些什么来避免必须存储一堆用户密码并且每次用户更改密码时软件都会失败?这似乎是一种非常笨拙的操作方式,但由于此活动目前尚未以交互方式执行,我还有其他选择吗?
答案 0 :(得分:3)
我正在做类似的事情。如果进程具有足够的权限来获取您需要的模拟级别(例如模仿或委派与识别),则模拟也不算太糟糕。
以下是我冒充的方法:
public static bool GetImpersonationToken(string UPN, out IntPtr dupToken)
{
dupToken = IntPtr.Zero;
WindowsImpersonationContext impersonationContext = null;
bool result = false;
try
{
WindowsIdentity wid = new WindowsIdentity(UPN);
impersonationContext = wid.Impersonate();
result = DuplicateToken(wid.Token, 2, ref dupToken) != 0;
}
finally
{
if (impersonationContext != null)
impersonationContext.Undo();
}
return result;
}
注意:清理该令牌句柄是调用方法的责任。
我根据用户的电子邮件从LDAP查询中解析UPN(通常它们是相同的,但通常都不是)。
但是我遇到了一些我传入的字节数组的问题。我尝试了File.ReadAllBytes,但这会导致打印机吐出乱码。是否需要在GenerateBufferFromFile中发生一些特殊的编码?
**更新**
看起来有很多关于直接使用JobStream的问题:
Is PrintSystemJobInfo.JobStream broken?
所以我只是要写文件,虽然我希望避免这种情况。