2

I am using the following code to create a file at a temp path and then delete it after the print happened successfully. But after printing I try to dispose the file and when I try to delete the file, I still get an exception saying "The process cannot access the file 'Chart0.png' because it is being used by another process." Please help.

I also tried putting the deleting code in the finally block but still no luck.

public static bool PrintAllCharts(Dictionary<string, ILightningChartInterface> charts)
        {
            DirectoryInfo info = null;
            try
            {
                string FilePathWithoutFileName = string.Empty;
                info = Directory.CreateDirectory(@"C:\TempCharts");
                for (int i = 0; i < charts.Count; i++)
                {
                    KeyValuePair<string, ILightningChartInterface> kp = charts.ElementAt(i);
                    FilePathWithoutFileName = info.FullName;
                    string FullPath = string.Format("{0}/Chart{1}.png", FilePathWithoutFileName, i.ToString());
                    kp.Value.SaveChartToFile(FullPath);
                }
                var files = Directory.GetFiles(FilePathWithoutFileName);

                using (var pdoc = new PrintDocument())
                {
                    using (var pdi = new System.Windows.Forms.PrintDialog { Document = pdoc, UseEXDialog = true })
                    {
                        if (pdi.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                        {
                            pdoc.PrinterSettings = pdi.PrinterSettings;
                            pdoc.PrintPage += Pdoc_PrintPage;
                            foreach (var file in files)
                            {
                                pdoc.DocumentName = file;
                                pdoc.Print();
                            }
                        }
                    }
                }
                //Dispose the file after printing.
                foreach(var file in files)
                {
                    Image.FromFile(file).Dispose();
                    File.Delete(file); //This line gives an exception
                }

                foreach (DirectoryInfo dir in info.GetDirectories())
                {
                    dir.Delete(true);
                }
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        private static void Pdoc_PrintPage(object sender, PrintPageEventArgs e)
        {
            string file = ((PrintDocument)sender).DocumentName;
            System.Drawing.Image img = System.Drawing.Image.FromFile(file);
            Rectangle m = e.MarginBounds;

            if ((double)img.Width / (double)img.Height > (double)m.Width / (double)m.Height) // image is wider
            {
                m.Height = (int)((double)img.Height / (double)img.Width * (double)m.Width);
            }
            else
            {
                m.Width = (int)((double)img.Width / (double)img.Height * (double)m.Height);
            }
            e.Graphics.DrawImage(img, m);
        }
ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
nikhil
  • 1,578
  • 3
  • 23
  • 52

1 Answers1

4

The issue lies in your Pdoc_PrintPage method. You're using the following line to read the file:

System.Drawing.Image img = System.Drawing.Image.FromFile(file);

The docs for FromFile state:

The file remains locked until the Image is disposed.

So really you should write your code like this, so that the image is disposed of (and the file unlocked) after you're done with it:

string file = ((PrintDocument)sender).DocumentName;
using (System.Drawing.Image img = System.Drawing.Image.FromFile(file))
{
    Rectangle m = e.MarginBounds;

    if ((double)img.Width / (double)img.Height > (double)m.Width / (double)m.Height) // image is wider
    {
        m.Height = (int)((double)img.Height / (double)img.Width * (double)m.Width);
    }
    else
    {
        m.Width = (int)((double)img.Width / (double)img.Height * (double)m.Height);
    }
    e.Graphics.DrawImage(img, m);
}

Note that you have to dispose of the same image instance. You currently have this code in your delete loop:

Image.FromFile(file).Dispose();

That's simply trying to load a second copy of the file and then immediately dispose of it. Once you have implemented the above change, you should also remove this line from your delete loop.

ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
  • Thanks let me try it out,. But as for my reason to writing that code is from this post, if it lets you remove that down vote. https://stackoverflow.com/questions/26741191/ioexception-the-process-cannot-access-the-file-file-path-because-it-is-being – nikhil Aug 22 '18 at 00:29
  • Not really sure how I can remove [someone else's downvote](https://i.imgur.com/KOFyewn.jpg). – ProgrammingLlama Aug 22 '18 at 00:33
  • Hmm thats alright thanks John. I will accept the answer – nikhil Aug 22 '18 at 00:34