Click here to Skip to main content
15,887,676 members
Please Sign up or sign in to vote.
1.60/5 (2 votes)
Hello Friends...
I m involved in project creating 2 windows service
First service takes .csv file from FTP Folder then moves to Process/Working Folder. This service working fine.
Second Service takes .csv file from Process/Working Folder and change it format and move a file to Historian Folder. But this service working fine while debugging the service code with windows application using break point. But without break point it starts throwing an error as follows.

"The process cannot access the file because it is being used by another process."

Following is my second service code

C#
public partial class Form1 : Form
   {

       public static string workingfolderpath = "";
       public static string errorfolderpath = "";
       public static string historianfolderpath = "";
       public static string filepath = "";
       public System.Timers.Timer ObjTimer;

       public Form1()
       {
           InitializeComponent();

           NameValueCollection settings = ConfigurationManager.GetSection("customAppSettingsGroup/customAppSettings") as System.Collections.Specialized.NameValueCollection;
           workingfolderpath = settings["process"].ToString();
           errorfolderpath = settings["error"].ToString();
           historianfolderpath = settings["hist"].ToString();
           ObjTimer = new System.Timers.Timer();


           //ObjTimer.Elapsed += new ElapsedEventHandler(ObjTimer_Elapsed);
           ObjTimer.Interval = 60000;    //this is equal to 1 minute   i.e 1 minute= 60000 miliseconds
           ObjTimer.Enabled = true;
           ObjTimer.AutoReset = true;

       }


       public static void ProceesFile(string _filename)
       {
           List<string> ObjListFile = new List<string>();
           try
           {
               ObjListFile.Add(_filename);
               string[] file = _filename.Split('\\');
               StreamReader ObjStreamReader = new StreamReader(File.OpenRead(_filename));
               string[] line = ObjStreamReader.ReadLine().Split(';');
               string[] machinename = _filename.Split('_');
               for (int i = 2; i < line.Length; i++)
               {
                   line[i] = string.Concat(machinename[machinename.Length - 1].Remove(machinename[machinename.Length - 1].IndexOf(".csv")), "_", line[i].Trim('"'));
               }

               List<System.Collections.Generic.List<string>> ObjListColumns = new List<List<string>>();
               //here
               for (int i = 1; i < line.Length; i++)
               {
                   ObjListColumns.Add(new List<string>());
               }

               string[] values = null;
               while (!ObjStreamReader.EndOfStream)
               {
                   values = null;
                   values = ObjStreamReader.ReadLine().Split(';');
                   for (int i = 0; i < ObjListColumns.Count; i++)
                   {
                       ObjListColumns[i].Add(values[i + 1]);
                   }
               }
               ObjStreamReader.Close();
               ObjStreamReader.Dispose();
               GC.Collect();

               for (int i = 0; i < ObjListColumns[0].Count; i++)
               {
                   ObjListColumns[0][i] = ObjListColumns[0][i].Trim('"').Trim('\\').Trim('"');
               }
               for (int i = 0; i < ObjListColumns.Count; i++)
               {
                   for (int j = 0; j < ObjListColumns[i].Count; j++)
                   {
                       ObjListColumns[i][j] = ObjListColumns[i][j].Trim('"');
                   }
               }
               ObjListFile.Add(workingfolderpath + "\\w" + file[file.Length - 1]);
               FileStream ObjFileStream = new FileStream(workingfolderpath + "\\w" + file[file.Length - 1], FileMode.OpenOrCreate);
               StreamWriter ObjWriter = new StreamWriter(ObjFileStream);

               string text = null;
               ObjWriter.WriteLine("[Data]");
               ObjWriter.WriteLine("Tagname;TimeStamp;Value;DataQuality");
               string[] datetime = null;
               for (int i = 2; i < line.Length; i++)
               {
                   for (int j = 0; j < ObjListColumns[i - 1].Count; j++)
                   {
                       text = null;
                       //text=line[i].ToString()+";"+ObjListColumns[0][j].ToString()+";"+ObjListColumns[i - 1][j].ToString()+";"+"Good";
                       int sec = 1 + j;
                       datetime = ObjListColumns[0][j].ToString().Split(' ');
                       datetime[0] = DateTime.Now.AddDays(-1).ToShortDateString();
                       text = line[i].ToString() + ";" + datetime[0] + " " + datetime[1] + ";" + ObjListColumns[i - 1][j].ToString() + ";" + "Good";
                       //text = line[i].ToString() + ";" + DateTime.Now.AddMinutes(-sec).ToString("M/d/yyyy HH:mm:ss") + ";" + ObjListColumns[i - 1][j].ToString() + ";" + "Good";
                       ObjWriter.WriteLine(text);
                   }
               }
               ObjWriter.Flush();
               ObjFileStream.Flush();
               ObjWriter.Close();
               ObjWriter.Dispose();
               ObjFileStream.Close();
               ObjFileStream.Dispose();
               GC.Collect();
               Microsoft.Office.Interop.Excel.Application ObjApplication = new Microsoft.Office.Interop.Excel.Application();
               Microsoft.Office.Interop.Excel.Workbook ObjWorkBook = ObjApplication.Workbooks.Open(workingfolderpath + "\\w" + file[file.Length - 1], 0, false, 5, "", "", false, XlPlatform.xlWindows, ";", true, false, 0, true, false, false);
               Microsoft.Office.Interop.Excel.Worksheet ObjWorkSheet = ObjApplication.ActiveWorkbook.ActiveSheet;
               ObjApplication.Columns["A:A"].Select();
               ObjApplication.Selection.TextToColumns(ObjApplication.Range["A1"], XlTextParsingType.xlDelimited, XlTextQualifier.xlTextQualifierNone, Type.Missing, Type.Missing, true, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
               ObjWorkSheet.SaveAs(workingfolderpath + "\\c" + file[file.Length - 1], Microsoft.Office.Interop.Excel.XlFileFormat.xlCSV);
               //ObjWorkBook.Save();
               //ObjWorkBook.Close();
               //ObjApplication.SaveWorkspace();

               GC.Collect();

               Process[] proc = Process.GetProcessesByName("EXCEL");
               proc[0].Kill();
               proc[0].Dispose();
               //Call MoveToHistorian()
               ObjListFile.Add(workingfolderpath + "\\c" + file[file.Length - 1]);
               MoveToHistorian(workingfolderpath + "\\c" + file[file.Length - 1]);

           }
           catch (Exception Obj)
           {
               //Call MoveToError()
               string[] file = _filename.Split('\\');
               MoveToError(workingfolderpath + "\\c" + file[file.Length - 1], Obj.Message);
           }
           finally
           {
               //Delete all the temporary files what an application has created from the working folder
               foreach (string filename in ObjListFile)
               {
                   if (File.Exists(filename))
                   {
                       File.Delete(filename);
                   }
               }
           }
       }

       public static Boolean IsFileLocked(FileInfo file)
       {
           FileStream stream = null;
           try
           {
               stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
           }
           catch (IOException)
           {
               return true;
           }
           finally
           {
               if (stream != null)
                   stream.Close();
           }
           return false;
       }

       public static void FindFileInProcessFolder()
       {
           foreach (string file in Directory.GetFiles(workingfolderpath))
           {
               if (file.EndsWith(".csv"))
               {
                   FileInfo ObjFileInfo = new FileInfo(file);
                   FileInfo ObjFileInUse = new FileInfo(workingfolderpath + "\\" + ObjFileInfo.Name);
                   if (!IsFileLocked(ObjFileInUse))
                   {
                       ProceesFile(ObjFileInUse.FullName);
                       break;
                   }
               }
           }
       }

       public static void MoveToHistorian(string _filename)
       {
           //Move a file to Historian Folder
           string[] file = _filename.Split('\\');
           if (File.Exists(_filename))
           {
               Process[] proc = Process.GetProcessesByName("EXCEL");
               if (proc.Length > 0)
               {
                   proc[0].Kill();
                   proc[0].Dispose();
               }

               File.Move(_filename, historianfolderpath + "\\" + file[file.Length - 1]);
           }
       }

       public static void MoveToError(string _filename, string _errormessage)
       {
           //Move a file to Error Folder
           //And update a error file with message, filename and timestamp
           string[] file = _filename.Split('\\');
           if (File.Exists(_filename))
           {
               Process[] proc = Process.GetProcessesByName("EXCEL");
               if (proc.Length > 0)
               {

                   proc[0].Kill();
                   proc[0].Dispose();
               }
               if (File.Exists(errorfolderpath + "\\" + file[file.Length - 1]))
               {
                   File.Delete(errorfolderpath + "\\" + file[file.Length - 1]);
               }
               File.Move(_filename, errorfolderpath + "\\"+ file[file.Length - 1]);
           }
           FileStream ObjFileStream = new FileStream(errorfolderpath + "\\" + "error.txt", FileMode.Append, FileAccess.Write);
           StreamWriter ObjWriter = new StreamWriter(ObjFileStream);
           ObjWriter.WriteLine(errorfolderpath + "\\" + file[file.Length - 1] + " = : " + DateTime.Now.ToString() + " : " + _errormessage);
           ObjWriter.Close();
           ObjFileStream.Close();

           Process[] proc1 = Process.GetProcessesByName("EXCEL");
           if (proc1.Length > 0)
           {
               proc1[0].Kill();
               proc1[0].Dispose();
           }


       }

       private void button1_Click(object sender, EventArgs e)
       {
           Form1.FindFileInProcessFolder();
       }

   }


Help me to find out why does it happen while debugging without break point.
Thanks You.
Posted
Updated 12-Feb-18 21:25pm
Comments
lukeer 5-May-15 2:37am    
Breakpoints slow things down. I guess that is giving your processes time to sort themselves out. Without the breakpoint, they're running at machine speed and "historian service" kicks in at a time when "ftp service" has not yet finished using a file.

Show where exactly the error happens.

The error is pretty self explanatory, you are trying to to something to a file while it is being used by some other process (probably trying to move or delete etc.)

If you don't know what file then add logging to you code to write the exception and associated information to a text file which you can read, like : Mini Drop-in Replacement for log4net[^]
 
Share this answer
 
We have a number of issues here, first of all i'd like to advocate for the seperation of concerns.

So you're anchoring in a windows form that should display, then you're provinding minitoring handling of folders, that's another concern and Then you appear to be monitoring for csv files using ';' as listseperator and when you find such get the columns and then recreate a csv type file with a firstline of "[Data]" which you then write to a work folder.
Finally you move on the making a new excel workbook and sort of paste into that and store it in your working folder.

Beyond that you're doing a lot of explict handling of GC thread, which really shouldn't be done ... like ever. And tryig to kill excel as a process and stuff. Also shouldn't be necessary.

Therefore i think you should beging by refctoring the identifyable parts from each other. And when you release your interop COM objects, use System.Runtime.InteropServices.Marshal.ReleaseComObject(ObjApplication); after having called .Quit()

My first guess is that between your workbook handling doesn't release timely before you attempt to MoveToHistorian. Do not do any GetProcessByName + Kill stuff, you already have a COM handle so use that, and please do get all your domaine name specifics into using statements instead, you're making all of us cross-eyed trying to read the lines :D

Anyway so getting rid of your COM instance should read after your ObjWorkSheet.SaveAs...
C#
ObjApplication.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(ObjApplication);
//ObjWorkBook.Save();
//ObjWorkBook.Close();
//ObjApplication.SaveWorkspace();

//GC.Collect();

//Process[] proc = Process.GetProcessesByName("EXCEL");
//proc[0].Kill();
//proc[0].Dispose();
//Call MoveToHistorian()
ObjListFile.Add(workingfolderpath + "\\c" + file[file.Length - 1]);
MoveToHistorian(workingfolderpath + "\\c" + file[file.Length - 1]);


IMHO: You should really consider refactoring the entire thing, for instance your monitoring of directory could be using a FileSystemWatcher https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher%28v=vs.110%29.aspx[^]

Then the entire Excel handling and the usageof temp folders for it's own purposes should also sit in it's own sepearate class and finally your ui could subsribe to notifcations and perhaps own a (seperate?) class with a filesystemwatcher.
Currently you have a small program trying to do a lot at the same time which is unrelated to each other conceptually and then plumbing from apparent debugging like explicitly addressing garbage collector and process lifetime which should be removed.

I'm tempted to provide a rewrite, but i think these advice might just be enough to get you through

cheers!
 
Share this answer
 
 
Share this answer
 
I would suggest to check if the File is used by some process or not first before doing some operation on it.

Refer - Is there a way to check if a file is in use?[^]
 
Share this answer
 
The problem here is unfortunately the speed of your disk read-write aka System.IO.

When dealing with a physical file often you need to create a validation process to check if the file is used by another process which in your case is open, close, open close same file often. To do that you need something like this:

C#
public void Check_File_Access(string _path)
{
     FileInfo fi = new FileInfo(_path);

     lock (locker)
     {
          using (FileStream file = new FileStream(fi.FullName, FileMode.Append, FileAccess.Write, FileShare.Read))
          using (StreamWriter writer = new StreamWriter(file))
          {
               // You can add code here if file is accessible
          }
     }
}


It basically attempts to access the file until it gets access and then do what you need to do
 
Share this answer
 
we can use lock keyword for the method accessing the file, if file is locked a message can be shown to the user to try later as file is in use.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900