gpt4 book ai didi

c++ - 如何在 Win x64 上使用 WinAPI 正确安装虚拟打印机?

转载 作者:可可西里 更新时间:2023-11-01 09:31:10 26 4
gpt4 key购买 nike

我正在尝试使用 WinAPI 调用从 C++ 控制台程序安装虚拟打印机。它在 Windows XP 上运行良好,但在 Windows 7 x64 上有一些进程将文件锁定在系统文件夹中,这是安装所必需的。我认为它们只出现在 x64 Windows 系统上,但我没有在 Windows XP x64 上测试过。

这些是进程 splwow64.exe 和 PrintIsolationHost.exe。我试图以编程方式杀死它们,结果很好(好吧,为了终止 PrintIsolationHost.exe,我设置了一个调试权限,'因为它是系统进程)但我开始认为我的代码可能有问题,如果它没有以这种方式工作。显然必须有某种安装方式而不终止任何系统进程。

代码是这样的:

BOOL res = FALSE;
printf("Run install:\n\n");

// Set debug privilages to current process
HANDLE hTokenThis( NULL );
OpenProcessToken( GetCurrentProcess(), TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hTokenThis );
SetPrivilege( hTokenThis, SE_DEBUG_NAME, TRUE );

printf("Stop spooler service...\r\n");
if(!StopService("spooler"))
return FALSE;

// Stop splwow64.exe and PrintIsolationHost.exe - it can prevent some files to be copied
HANDLE process = GetProcessByName( "splwow64.exe" );
if (process)
TerminateProcess( process, 0 );

// Stop PrintIsolationHost.exe (it runs under SYSTEM and requires debug rights to be stopped)
process = GetProcessByName( "PrintIsolationHost.exe" );
if (process)
TerminateProcess( process, 0 );

// Continue install
printf("Copy driver file...\r\n");
if(!CopyInstFile())
{
return FALSE;
}
printf("Start spooler service...\r\n");
if(!StartServices("spooler"))
return FALSE;

printf("Add Port...\r\n");
res = AddPort();
ERROR_CHECK_EXIT(res)

printf("Add Driver...\r\n");
res = AddDriver();
ERROR_CHECK_EXIT(res)

printf("Add print Processor...\r\n");
res = AddProcessor();
ERROR_CHECK_EXIT(res)

printf("Add printer...\r\n");
res = AddPrint();
ERROR_CHECK_EXIT(res)

安装各种东西的函数:

BOOL CPrintInstal::AddDriver()
{
DRIVER_INFO_3 driverInfo;
memset(&driverInfo,0,sizeof(driverInfo ));
driverInfo.cVersion = 3;
driverInfo.pName = PRINTERDRIVERNAME;
driverInfo.pEnvironment = NULL;//"Windows NT x86";
driverInfo.pDriverPath="UNIDRV.DLL";
driverInfo.pDataFile=PDFCONVERTED_GPD;
driverInfo.pConfigFile= "UNIDRVUI.DLL";
driverInfo.pHelpFile= "UNIDRV.HLP";
driverInfo.pDependentFiles = NULL;
driverInfo.pDefaultDataType=NULL;

return AddPrinterDriver(NULL,3,(LPBYTE)&driverInfo);
}

BOOL CPrintInstal::AddPrint()
{
PRINTER_INFO_2 printInfo;
memset(&printInfo,0,sizeof(PRINTER_INFO_2));
printInfo.pServerName=NULL;
printInfo.pPrinterName=PRINTERNAME;
printInfo.pShareName=NULL;
printInfo.pPortName=PORTNAME_A;
printInfo.pPrintProcessor =PRINTPROCESSORNAME;
printInfo.pDatatype = "NT EMF 1.008";
printInfo.pDriverName =PRINTERDRIVERNAME;
printInfo.Attributes = PRINTER_ATTRIBUTE_LOCAL | PRINTER_ATTRIBUTE_QUEUED | PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS;
SetLastError(0);
HANDLE handle = AddPrinter(NULL,2,(LPBYTE)&printInfo);
if(handle == NULL)
{
if(GetLastError()!=1802)
return FALSE;
}
ClosePrinter(handle);
return TRUE;
}

还有很多,有些真的很长,不需要的话就不贴了。

有什么方法可以防止系统锁定文件并强制安装打印机?

附言我在复制文件时停止后台处理程序服务,然后在调用 WinAPI 之前运行它。
P.P.S 这不是我的代码。这是我们需要为客户维护的遗留代码。

最佳答案

不,没有办法防止文件被锁定。即使您停止了假脱机程序、splwow64 和您能想到的所有其他东西,其他程序仍有可能打开您的 DLL 之一。这一点尤其正确,因为您正在使用 UNIDRV,因为它被许多其他打印机驱动程序使用。

MoveFileEx功能是唯一可靠的解决方案。如果您的任何文件拷贝由于访问被拒绝错误而失败,请使用带有 MOVEFILE_DELAY_UNTIL_REBOOT 选项的 MoveFileEx 并提示用户重新启动。您还可以将安装程序放入注册表的 RunOnce 键(以感叹号为前缀)以保证它会在重新启动后继续安装。这将是对您的安装程序的重大更改,但这是唯一可靠的方法。

关于c++ - 如何在 Win x64 上使用 WinAPI 正确安装虚拟打印机?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7771413/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com