2

グラフィックスを印刷するために、GDI 印刷 API への Win32 呼び出しを使用しています。

特定の PCL 印刷キューで、印刷時に GDI メモリがリークすることに気付きました。私が知る限り、すべてが適切に処分されています。私の会社の管理者ではないので、印刷キューが使用しているドライバーを特定するのはかなり困難です。PCL6 ドライバーが主な原因のようです。私が見た他の一見無関係な問題:

System.ComponentModel.Win32Exception: システム コールに渡されたデータ領域が小さすぎます System.ComponentModel.Win32Exception: 操作は正常に完了しました

var hdc = GdiPrintWin32.CreateDC(IntPtr.Zero, printerName, IntPtr.Zero, IntPtr.Zero);
if (hdc == IntPtr.Zero)
    throw GetError("Device context failed for {0}", printerName);

try
{
    if (GdiPrintWin32.StartDoc(hdc, ref doc) <= 0)
        throw GetError("Failed to start print job");

このロジックは現在、Windows サービス内でホストされている WCF で実行されています。インスタンスモードをシングルに設定してハンマーで叩くと、最初の数回の呼​​び出ししか取得できません。インスタンス モードを呼び出しごとに設定すると、再現がはるかに簡単になります。

また、基本的に約 20 分間サービスに通話を発信できず、修正するには再起動が必要になるというエラーも確認しました。サービスを停止した後、次のような Windows イベント ログがあることに気付きました。

2 つのユーザー レジストリ ハンドルが \Registry\User... から漏洩しました: プロセス 3792 (\Device\HarddiskVolume1\Windows\System32\rundll32.exe) がキー \REGISTRY\USER を開きました... プロセス 3792 (\Device\HarddiskVolume1\Windows\ System32\rundll32.exe) がキー ...\Software\Hewlett-Packard\HP SSNP を開きました

基本的に、それは私たちにとって悪夢に他なりません。誰もこのような経験をしたことがありますか?

印刷に使用しているコードの中身は次のとおりです。

var doc = new Docinfo { DocName = printJobName };

// create a device-context 
var hdc = GdiPrintWin32.CreateDC(IntPtr.Zero, printerName, IntPtr.Zero, IntPtr.Zero);
if (hdc == IntPtr.Zero)
    throw GetError("Device context failed for {0}", printerName);

try
{
    if (GdiPrintWin32.StartDoc(hdc, ref doc) <= 0)
        throw GetError("Failed to start print job");


    foreach (PrintingMetafile metafile in pages)
    {
        var bytes = metafile.GetBytes();

        // load the bytes to a memory location and get the pointer
        var inMemRef = GdiPrintWin32.SetEnhMetaFileBits((uint)bytes.Length, bytes);

        if (inMemRef == IntPtr.Zero)
            throw GetError("Failed to create EMF in memory");

        // Get the pixel coordinates of the paper
        var x = 0; // GdiPrintWin32.GetDeviceCaps(hdc, HORZSIZE);
        var y = 0; // GdiPrintWin32.GetDeviceCaps(hdc, VERTSIZE);
        var hres = GdiPrintWin32.GetDeviceCaps(hdc, HORZRES);
        var vres = GdiPrintWin32.GetDeviceCaps(hdc, VERTRES);

        var rect = new Rect { Left = x, Top = y, Right = hres, Bottom = vres };

        if (GdiPrintWin32.StartPage(hdc) <= 0)
            throw GetError("StartPage failed");


        if (GdiPrintWin32.PlayEnhMetaFile(hdc, inMemRef, ref rect) == 0)
            throw GetError("PlayEnhMetaFile failed");

        if (GdiPrintWin32.EndPage(hdc) <= 0)
            throw GetError("EndPage failed");


        if (inMemRef != IntPtr.Zero)
        {
            GdiPrintWin32.DeleteEnhMetaFile(inMemRef);
        }
    }

    if (GdiPrintWin32.EndDoc(hdc) <= 0)
        throw GetError("Failed to finish print job");
}
finally
{
    GdiPrintWin32.DeleteDC(hdc);
}
4

0 に答える 0