0

我有一个安装打印机驱动程序的可执行文件,然后使用所述驱动程序创建打印机。我使用从 server 2003 资源工具包中生成的 tlbimp 托管版本的 prnadmin。

在 Windows XP 上,我必须将打印处理器设置为 MS_XPS。默认处理器是 WINPRINT。这个片段就是这样做的。

  static string winxpPrinterProcessor = "MS_XPS";
  if (isWinXP() && pPrinter.PrintProcessor != winxpPrinterProcessor)
  {
    Console.WriteLine("Oh No, the printer exists, but the processor isn't XPS. Setting now. It's currently " + pPrinter.PrintProcessor);
    pPrinter.PrintProcessor = winxpPrinterProcessor;
    Console.WriteLine("Set the processor to " + winxpPrinterProcessor);
    if (updateOnly)
    {
      pMaster.PrinterSet(pPrinter);
    } else { //else we're adding
      pMaster.PrinterAdd(pPrinter);
    }

当我自己运行程序时,通过双击,它可以完美运行。当它作为 MSI 自定义操作运行时,它不起作用。一切正常(安装打印机、驱动程序、设置端口)但设置打印处理器。Windows 只是忽略处理器设置。

MSI 以 SYSTEM 用户身份启动自定义操作(它是一个控制台应用程序)进程。当我手动启动它时,它在我的域管理员帐户下运行。

我还应该注意手动安装打印机也可以正常工作,因为 xp 从 INF 文件中获取处理器。使用 prnadmin dll 时它会忽略该设置。

我度过了一个非常令人沮丧的早晨。有什么想法吗?或者更好的方法来安装打印机?

4

1 回答 1

0

好的,从来没有弄清楚为什么它在那种特定情况下会失败,但我确实想出了一个更好的解决方法。如果有人可以回答我最初的问题,我会给你答案。

背景:我们选择使用 prnadmin 包装器来做所有事情,因为我们必须创建一个端口,而这似乎是最简单的方法。

我们现在不再使用托管代码创建打印机,而是向 PrintUI 发送命令。我们可以用PrintUI设置端口,windows XP在使用PrintUI时会选择INF文件中指定的处理器,所以一石二鸟。

public static string PrinterDriverName = "MyPrinter.INF";
public static string portOutputFileName = "nul:";

/// <summary>
/// Installs a printer and driver from an INF file, setting the 
/// port to portOutputFileName ('nul:' in this case)
/// </summary>
private static void CreatePrinterPrintUI()
{
  string sCommand = String.Format(@"rundll32 printui,PrintUIEntry /if /K /m '{0}' /n '{0}' /r '{2}' /f '{1}'"
    ,PrinterDriverName,Path.Combine(Application.StartupPath,PrinterDriverInf)
    ,portOutputFileName).Replace("'","\""); //it fails on single quotes
  execCmd(sCommand);
}

public static void execCmd(string _sCmd)
{
  try
  {
    System.Diagnostics.ProcessStartInfo p = new ProcessStartInfo("cmd", "/c " + _sCmd);
    p.RedirectStandardOutput = true;
    p.UseShellExecute = false;
    p.CreateNoWindow = true;
    System.Diagnostics.Process proc = new System.Diagnostics.Process();
    proc.StartInfo = p;
    proc.Start();
    string sResult = proc.StandardOutput.ReadToEnd();
    Console.WriteLine(sResult);
  }
  catch (Exception e)
  {
    sErr += e.ToString();
  }
}
于 2012-05-16T22:32:20.837 回答