0

当用户卸载应用程序时,我的应用程序会删除虚拟打印机。应用程序的安装和卸载可以使用用户交互(向导)或通过在 Windows server 2003 中设置组策略来完成(域管理员在服务器中设置策略,客户端 PC 中的域用户需要更新组策略并重新启动客户端 PC 进行安装或卸载应用程序)。应用程序中的以下代码在卸载应用程序时删除打印机和打印机驱动程序。

void CPrinterDriver::DeletePrinterIfExists()
{
// Delete old printer driver if existing
ControlSpoolService(TRUE);

HANDLE hPrinter = NULL;
PRINTER_DEFAULTS    pDefaults = { NULL, NULL, PRINTER_ALL_ACCESS };
// Ignore error codes
OpenPrinter(m_driverInfo.pName, &hPrinter, &pDefaults);
if (hPrinter)
{
// deleting jobs
SetPrinter(hPrinter, 0, NULL, PRINTER_CONTROL_PURGE);
// Delete printer
DeletePrinter(hPrinter);
// Get printer driver name and delete it
DWORD   dwNeeded = 0;
GetPrinter(hPrinter, 2, NULL, 0, &dwNeeded);
if (dwNeeded)
{
PRINTER_INFO_2  *pi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, sizeof(PRINTER_INFO_2)*dwNeeded);
if (pi2)
{
   GetPrinter(hPrinter, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded);
   DeletePrinterDriver(NULL, NULL, pi2->pDriverName);
   GlobalFree(pi2);
}
}
ClosePrinter(hPrinter);
}
}

上述代码在 Windows 7 的两种卸载情况下(用户交互式安装和使用组策略)都可以正常工作。在 Windows 8 中,它使用用户交互式安装和卸载运行良好。但在 Windows 8 中,上述 OpenPrinter() 正在返回 ERROR_INVALID_PRINTER_NAME。

我们发现 OpenPrinter() 是使用“SYSTEM”帐户调用的。请帮忙。

4

2 回答 2

0

我们发现在系统启动期间,组策略试图在填充 PC 中的可用打印机列表之前卸载打印机(列表填充在以下注册表项下。如果未填充列表,则以下项不存在)。

“HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers”

因此,我们在调用 openPrinter() 之前添加了 2 分钟(不少于 2 分钟)的延迟。延迟后,注册表项存在并且 OpenPrinter() 成功。这样我们就可以卸载打印机了。

注意:Microsoft 声称 Windows 8 启动时间对于某些受支持的硬件减少到 7 秒。但是 2 分钟的插入延迟会降低 Windows 8 PC 的启动性能。有关 Windwos 8 OS 启动时间改进的更多详细信息,请参阅以下链接。 http://blogs.msdn.com/b/b8/archive/2012/05/22/designing-for-pcs-that-boot-faster-than-ever-before.aspx 因此延迟 2 分钟可以被视为一种解决方法。需要检查 10/26 之后的 Windows 8 OS 版本中的行为。

于 2012-10-26T11:53:54.937 回答
0

如果您遇到以下问题:

  • 共享(网络)打印机的注册表项丢失并且
  • API 为您提供无效的打印机名称错误

然后您可以尝试通过完整的 UNC 路径打开打印机。

因此,当打开MYPRINTER不起作用时,将其打开为\\MYSERVER\MYPRINTER.

当然,这仍然假设您已经可以从其他应用程序正常打印到这台打印机!

于 2017-07-04T09:52:29.447 回答