我的代碼位於32位Visual C++ 2010.這是通常的打印使用默認打印機之一,它是這樣的(這是確切的代碼減去錯誤處理程序):我的StartDoc()在Windows 7中失敗,在Windows XP中運行良好
// Get the length of the printer name.
GetDefaultPrinter(NULL, &size);
lpcPrinterName = new char[size];
// Get the printer name.
if(!GetDefaultPrinter(lpcPrinterName, &size)) {
// handle error
return false;
}
// Get a device context for the printer.
hdcPrint = CreateDC(NULL, lpcPrinterName, NULL, NULL);
// get printer parameters
iPrinterDPIX = GetDeviceCaps(hdcPrint, LOGPIXELSX); // x dpi
iPrinterDPIY = GetDeviceCaps(hdcPrint, LOGPIXELSY); // y dpi
iPrinterBPP = GetDeviceCaps(hdcPrint, BITSPIXEL); // bit per pixel
iPrinterHRes = GetDeviceCaps(hdcPrint, HORZRES); // x printable area in pixels. 0 maps to 0 here
iPrinterVRes = GetDeviceCaps(hdcPrint, VERTRES); // y printable area in pixels. 0 maps to 0 here
if (!OpenPrinter(lpcPrinterName, &printerHandle, NULL)) {
// handle error
return false;
}
// initialize docInfo
ZeroMemory(&docInfo, sizeof(docInfo));
docInfo.cbSize = sizeof(docInfo);
docInfo.lpszDocName = lpcstrDocName;
// ---> this is where it fails when run standalone on Windows 7, return value == -1
iPrintJobID = StartDoc(hdcPrint, &docInfo); // this starts a print job
if (iPrintJobID <= 0) {
// handle error
return false;
}
if (StartPage(hdcPrint) <= 0) { // this starts a new page
// handle error
return false;
}
{ // enclose in an inner scope to get graphics destroyed before deleting dc
Gdiplus::Graphics graphics(hdcPrint, printerHandle);
if (graphics.DrawImage(&bmp,x,y) != Ok)
// handle error
return false;
}
}
if (EndPage(hdcPrint) <= 0) { // ends the page (eject paper)
// handle error
return false;
}
if (EndDoc(hdcPrint) <= 0) { // end the print job (actually starts printing)
// handle error
return false;
}
ClosePrinter(printerHandle);
DeleteDC(hdcPrint);
delete[] lpcPrinterName;
我已經做了一些試錯與這些結果:
的代碼運行良好,在Windows XP(管理員和普通用戶)
當運行下Windows 7中,StartDoc失敗(返回-1),GetLastError()返回任何用戶(管理員,普通用戶,使用運行管理員的高架用戶,全部失敗)返回'Access is denied'錯誤。
代碼運行以及視窗7僅當以下:
- 從Visual C++運行,要麼開始與調試或不帶調試
- 並且僅當的Visual C++運行升高(運行作爲管理員)或以管理員帳戶登錄
爲了看到從程序的安全上下文中看到的那些條件之間的差異,我對用戶和組SID進行了窺視,對它們進行了比較,發現儘管它們在相同的用戶和組SID下運行, StartDoc仍然失敗。
我已經在實踐中使用過佳能iP3680,並且BullZip PDF打印機可以更容易地進行代碼調試,它們的反應完全相同。
任何人都可以幫助我找到一種方法讓Windows下的StartDoc成功?有沒有人遇到過相同或相關的問題?
補充:
我也試着服用閥芯/ Printers文件夾的所有權,沒有運氣。這似乎是圍繞Windows 7的安全問題展開的。我在這裏找到的一些其他打印案例設法解決這個問題,這就是爲什麼我試圖這樣做的原因
我忘記補充說,當我將打印機設置爲'直接打印到打印機'而不是使用打印機假脫機時,問題消失了。這暗示問題出在假脫機程序上。
解決:
我用的是防止通過實現一個空的DACL,像這樣被殺害我的應用程序的方法:
dwErr = SetSecurityInfo(hProcess, SE_KERNEL_OBJECT,
DACL_SECURITY_INFORMATION, NULL/*ownerpsid*/, NULL, pEmptyDacl, NULL);
去除片斷清除所有的問題。
StartDoc()不設置錯誤代碼,所以您從GetLastError()返回的內容沒有意義。該代碼段正在跳過所需的錯誤檢查,並且很難猜測哪些docInfo可能看起來像。測試你的理論的一個顯而易見的方法是從另一個程序打印,如記事本。如果那也失敗了,那麼你需要怪胎隊的幫助而不是程序員。還可以使用[GDI打印示例](http://archive.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=WindowsPrintSample&DownloadId=13936)並進行比較。 –
我曾試過,其他程序可以在任何用戶下打印。你是對的,這個bug真的很奇怪 –
對不起,我遺漏了docInfo的初始化。我已經包括它。至於錯誤檢查,在我的情況下,StartDoc在失敗時返回-1。爲了清晰起見,我刪除了錯誤檢查代碼。 –