2013-11-28 81 views
1

我的代碼位於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); 

去除片斷清除所有的問題。

+1

StartDoc()不設置錯誤代碼,所以您從GetLastError()返回的內容沒有意義。該代碼段正在跳過所需的錯誤檢查,並且很難猜測哪些docInfo可能看起來像。測試你的理論的一個顯而易見的方法是從另一個程序打印,如記事本。如果那也失敗了,那麼你需要怪胎隊的幫助而不是程序員。還可以使用[GDI打印示例](http://archive.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=WindowsPrintSample&DownloadId=13936)並進行比較。 –

+0

我曾試過,其他程序可以在任何用戶下打印。你是對的,這個bug真的很奇怪 –

+0

對不起,我遺漏了docInfo的初始化。我已經包括它。至於錯誤檢查,在我的情況下,StartDoc在失敗時返回-1。爲了清晰起見,我刪除了錯誤檢查代碼。 –

回答

0

幾個月前,我們只有一位客戶(超過15000人)遇到了同樣的問題,而且我們在StackOverflow和其他開發人員論壇中找不到解決方案。

經過漫長的調查,我們發現問題是打印機HDC。而解決辦法是做當前StartDoc()調用,在錯誤的情況下,創建一個新的打印機DC指定具體pDeviceMode參數:

newPrinterDC = CreateDC(NULL, PrinterName, NULL, pDeviceMode); 

最後,我們所能做的再次使用newPrinterDCStartDoc()電話。

這解決了問題,並在100%的情況下正確運行。

我希望它能幫助你。

相關問題