CreateDC throws error on 203rd loop.

L

L

Hi guys,

I am writing some interop code to print graphics to an eps file
and I use adobe printer driver. The piece of code I have written is
working fine. but if I loop for more than 200 times, it is throwing an
error. Can anybody tell me why it throws an error or am I having memory
problems? I debuged through it and I see that createDC is returning 0
on 203rd loop and throws an exception. Why is createDC returning a 0?


This is the piece of code that does the interop.

using System;
using System.Drawing;
using System.IO;
using System.Drawing.Printing;
using System.Runtime.InteropServices;
using System.Drawing.Text;

namespace Printer
{
public class CPrinter
{
private Graphics pDC;
private IntPtr dc1;
private IntPtr hdevmode;

[StructLayout( LayoutKind.Sequential)]
public struct DOCINFO
{
[MarshalAs(UnmanagedType.LPWStr)]public string pDocName;
[MarshalAs(UnmanagedType.LPWStr)]public string pOutputFile;
[MarshalAs(UnmanagedType.LPWStr)]public string pDataType;
}

[DllImport(
"winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=false,
CallingConvention=CallingConvention.StdCall )]
public static extern long StartDocPrinter(IntPtr hPrinter, int Level,
ref DOCINFO pDocInfo);

[DllImport("gdi32.dll", EntryPoint="CreateDCA")]
public static extern IntPtr CreateDC(string lpDriverName, string
lpDeviceName,
string lpOutput, IntPtr pDevMode);

[DllImport("gdi32.dll")]
static extern bool DeleteDC(IntPtr hdc);

[DllImport("gdi32", EntryPoint="StartDocA")]
public static extern int StartDoc(IntPtr dc1, ref DOCINFO di);

[DllImport("gdi32")] public static extern int StartPage(IntPtr hDC);


[DllImport("gdi32")] public static extern int EndDoc(IntPtr hDC);

[DllImport("gdi32")] public static extern int EndPage(IntPtr hDC);

public CPrinter()
{
}
public void StartPrinter(string outputFile)
{
try
{
DOCINFO di = new DOCINFO();
di.pOutputFile = outputFile;
PrintDocument pd = new PrintDocument();
hdevmode = pd.PrinterSettings.GetHdevmode();
dc1 = CreateDC("","Acrobat Distiller 3x2",outputFile,hdevmode);
int result = StartDoc(dc1, ref di);
result = StartPage(dc1);
pDC = Graphics.FromHdc(dc1);
pDC.PageUnit = GraphicsUnit.Pixel;
}
catch(Exception ex)
{
throw(ex);
}
}

public void EndPrinter()
{
int result = EndPage(dc1);
result = EndDoc(dc1);
DeleteDC(dc1);
}
}
}

This is the piece of code where I loop :

using System;
using Printer;

namespace ConsoleApplication1
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
int i = 0;
try
{
while (true)
{
CPrinter AdobePrinter = new CPrinter();
AdobePrinter.StartPrinter("temp.wrk");
AdobePrinter.EndPrinter();
i++;
Console.WriteLine(i);
}
}
catch (Exception ex)
{
Console.WriteLine( i + " : " + ex);
}
}
}
}

Thanks,
Lalasa.
 
J

John Vottero

L said:
Hi guys,

I am writing some interop code to print graphics to an eps file
and I use adobe printer driver. The piece of code I have written is
working fine. but if I loop for more than 200 times, it is throwing an
error. Can anybody tell me why it throws an error or am I having memory
problems? I debuged through it and I see that createDC is returning 0
on 203rd loop and throws an exception. Why is createDC returning a 0?

You are using a Disposable object (Graphics) without disposing it.

This is the piece of code that does the interop.

using System;
using System.Drawing;
using System.IO;
using System.Drawing.Printing;
using System.Runtime.InteropServices;
using System.Drawing.Text;

namespace Printer
{
public class CPrinter
{
private Graphics pDC;
private IntPtr dc1;
private IntPtr hdevmode;

[StructLayout( LayoutKind.Sequential)]
public struct DOCINFO
{
[MarshalAs(UnmanagedType.LPWStr)]public string pDocName;
[MarshalAs(UnmanagedType.LPWStr)]public string pOutputFile;
[MarshalAs(UnmanagedType.LPWStr)]public string pDataType;
}

[DllImport(
"winspool.drv",CharSet=CharSet.Unicode,ExactSpelling=false,
CallingConvention=CallingConvention.StdCall )]
public static extern long StartDocPrinter(IntPtr hPrinter, int Level,
ref DOCINFO pDocInfo);

[DllImport("gdi32.dll", EntryPoint="CreateDCA")]
public static extern IntPtr CreateDC(string lpDriverName, string
lpDeviceName,
string lpOutput, IntPtr pDevMode);

[DllImport("gdi32.dll")]
static extern bool DeleteDC(IntPtr hdc);

[DllImport("gdi32", EntryPoint="StartDocA")]
public static extern int StartDoc(IntPtr dc1, ref DOCINFO di);

[DllImport("gdi32")] public static extern int StartPage(IntPtr hDC);


[DllImport("gdi32")] public static extern int EndDoc(IntPtr hDC);

[DllImport("gdi32")] public static extern int EndPage(IntPtr hDC);

public CPrinter()
{
}
public void StartPrinter(string outputFile)
{
try
{
DOCINFO di = new DOCINFO();
di.pOutputFile = outputFile;
PrintDocument pd = new PrintDocument();
hdevmode = pd.PrinterSettings.GetHdevmode();
dc1 = CreateDC("","Acrobat Distiller 3x2",outputFile,hdevmode);
int result = StartDoc(dc1, ref di);
result = StartPage(dc1);
pDC = Graphics.FromHdc(dc1);
pDC.PageUnit = GraphicsUnit.Pixel;
}
catch(Exception ex)
{
throw(ex);
}
}

public void EndPrinter()
{
int result = EndPage(dc1);
result = EndDoc(dc1);
DeleteDC(dc1);
}
}
}

This is the piece of code where I loop :

using System;
using Printer;

namespace ConsoleApplication1
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
int i = 0;
try
{
while (true)
{
CPrinter AdobePrinter = new CPrinter();
AdobePrinter.StartPrinter("temp.wrk");
AdobePrinter.EndPrinter();
i++;
Console.WriteLine(i);
}
}
catch (Exception ex)
{
Console.WriteLine( i + " : " + ex);
}
}
}
}

Thanks,
Lalasa.
 
L

L

I added the pDC.Dispose() to my EndPrinter() function and still I am
having the problem.

public void EndPrinter()
{
int result = EndPage(dc1);
result = EndDoc(dc1);
pDC.Dispose();
DeleteDC(dc1);
}

Thanks,
L.
 
M

Mattias Sjögren

Can anybody tell me why it throws an error or am I having memory
problems?

You're net freeing the handle returned by GetHDevmode.

public static extern long StartDocPrinter(IntPtr hPrinter, int Level,
^^^^

The return type should be (u)int.



Mattias
 
L

L

Can you tell me the method I should use to release the handle returned
by GetHDevmode? I am not able to find one.

Thanks,
Lalasa.
 
L

L

Hi,

Is there anything else I got to correct. Because I am having the
same error now after 1122 loops.
Here is my EndPrinter() function

public void EndPrinter()
{
int result = EndPage(dc1);
result = EndDoc(dc1);
pDC.Dispose();
Marshal.FreeHGlobal(hdevmode); // Frees the memory. You could also
free the memory by calling the native win32 globalfree method.
DeleteDC(dc1);
}

Thanks in advance
Lalasa.
 
M

Mattias Sjögren

Is there anything else I got to correct. Because I am having the
same error now after 1122 loops.

Well your DOCINFO struct doesn't look correct compared to the one in
the MSDN documentation.

Then I recommend that you use Task Manager to monitor the number of
GDI handles used in your application to ensure that you're not leaking
any.



Mattias
 
L

L

Well, I figured it out. The memory leak was happening in my main code
where I was using interop calls for creating fonts. I fixed my dispose
function to delete all the fonts and it is working in an end less loop
now. Thanks for the help.

Lalasa.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top