Link to home
Start Free TrialLog in
Avatar of ITsolutionWizard
ITsolutionWizardFlag for United States of America

asked on

c#, file IO issue

I see alert message "Process cannot access the file because it is being used by another process".
when I click the button at third time. It seems reading is okay. but when i click the button to write something inside  to the xml.
it fails. how can i resolve this issue?

I know the  "Process cannot access the file because it is being used by another process". continue to happen the new message is sent.
sendMsg_Click(), but that does not mean the issues came from there.

And I check all controllers I used, and when the file is opened, it is closed immediately.

  protected void Page_Load(object sender, EventArgs e)
        {
            phoneNoList.DataSource = Utility.Controller.GetUniquePhoneNo(fromPhoneNo);
            phoneNoList.DataBind();
}

  protected void sendMsg_Click(object sender, EventArgs e)
        {
		 #region add a record to all message xml
                Domain.User u = new Domain.User();
                u.fullName = fullName.Text;
                u.from = "+1" + fromPhoneNo;
                u.to = "+1" + toPhoneNo.Text;
                u.body = body.Text;
                u.dateTimeSent = DateTime.Now.ToString();
                u.direction = "outbound-reply";
                string result = Utility.XML.Add(Utility.Controller.filePathUserMessagesAll, u);
                #endregion


}

  public static string Add(string inputFilePath,Domain.User u)
        {
            XDocument doc = XDocument.Load(inputFilePath);
            XElement user = new XElement("User",
                new XAttribute("PhoneNo",""),
                new XElement("FullName",u.fullName),
                new XElement("From",u.from),
                new XElement("To",u.to),
                new XElement("Body",u.body),
                new XElement("DateTimeSent",u.dateTimeSent),
                new XElement("Direction",u.direction),
                new XElement("Carrier",
                      new XElement("Name","Twilio"),
                      new XElement("SID",Utility.Controller.TwilioSID),
                      new XElement("Token",Utility.Controller.TwilioToken)));
            doc.Root.Add(user);
            doc.Save(inputFilePath);
            return "Added";
        }

    public static DataTable GetUniquePhoneNo(string accountPhoneNo)
        {
            string clientPhoneNo = string.Empty;
            string inputFilePath = filePathUserMessagesAll;
                //@"C:\Users\Documents\visual studio 2015\Projects\AppText\AppText\Data\UserMessagesAll.xml";
            DataTable dt = new DataTable();
            dt.Clear();
            dt.Columns.AddRange(new DataColumn[]
           {
                new DataColumn("PhoneNo",typeof(string)),
                new DataColumn("Client",typeof(string)),
                new DataColumn("DateCreated",typeof(string))
           });
            XDocument xdoc = null;
            using (XmlReader xr = XmlReader.Create(inputFilePath))
            {
                xdoc = XDocument.Load(xr);
                var query1 = from t in xdoc.Descendants("User")
                             where t.Element("From").Value.ToLower() == "+1" + accountPhoneNo.ToLower()
                             select new
                             {
                                 To = t.Element("To").Value,
                                 FullName = t.Element("FullName").Value,
                                 DateTimeSent = t.Element("DateTimeSent").Value
                                 //DateTime.Parse(txtDatepicker_end.Text).ToString("YYYY-MM-dd");
                             };
                var query2 = from t in xdoc.Descendants("User")
                             where t.Element("To").Value.ToLower() == "+1" + accountPhoneNo.ToLower()
                             select new
                             {
                                 To = t.Element("From").Value,
                                 FullName = t.Element("FullName").Value,
                                 DateTimeSent = t.Element("DateTimeSent").Value
                             };
                var query3 = query1.Concat(query2).OrderByDescending(z => z.DateTimeSent).GroupBy( z => z.To).Select(z=> z.First());
                foreach (var x in query3)
                {
                    dt.Rows.Add(x.To, x.FullName, (DateTime.Parse(x.DateTimeSent)).ToString("MM/dd/yy", System.Globalization.CultureInfo.InvariantCulture));
                }

               // string timeF = "2017-06-15T14:49:19-07:00";
               // DateTime dt = DateTime.Parse(timeF);
               // string timeS = dt.ToUniversalTime().ToString("MM/dd/yy hh:mm", System.Globalization.CultureInfo.InvariantCulture);


                // var messages2a = MessageResource.Read().Where(x => x.From.ToString() == "+1" + fromPhoneNo).GroupBy(x => x.To).Select(y => y.First());
                // var messages3a = MessageResource.Read().Where(y => y.To == "+1" + fromPhoneNo).GroupBy(x => x.To).Select(y => y.First());
                // var allz = messages2a.Concat(messages3a).OrderByDescending(z => z.DateCreated);
                return dt;
            }
        }

Open in new window

Avatar of HainKurt
HainKurt
Flag of Canada image

which line is creating that issue?
ASKER CERTIFIED SOLUTION
Avatar of zephyr_hex (Megan)
zephyr_hex (Megan)
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I am not sure about this is creating issue

XDocument doc = XDocument.Load(inputFilePath);

Open in new window


should not leave file open! MS does not say anything about it, and there is no close method here, meaning, it opens reads and closes...

XDocument.Load Method (String)
https://msdn.microsoft.com/en-us/library/bb343181(v=vs.110).aspx
Avatar of ITsolutionWizard

ASKER

doc is not inside of using statement. It won't work.
And what do you mean by closing the xdocument? Your code does not have it close?

XDocument doc;
using (FileStream fileStream = new FileStream(inputFilePath,FileMode.Open, FileAccess.Read, FileShare.Read))
{
     doc = XDocument.Load(filestream);
    //..and so on...
}
doc.Save(inputFilePath);

Open in new window

xdocument does not have close method

XDocument Class
https://msdn.microsoft.com/en-us/library/system.xml.linq.xdocument(v=vs.110).aspx

so, it means, we dont need to release or close anything, file should not be locked!

and you did not answer my question yet...

is issue happening on this line?

string result = Utility.XML.Add(Utility.Controller.filePathUserMessagesAll, u);

Open in new window


put a break point and go inside and see which line is causing the issue first...

Line 25 or 40???

            XDocument doc = XDocument.Load(inputFilePath); ???? here
            doc.Save(inputFilePath); ???? or here

or somewhere else...
Line 25
it actually points to  doc.Save(inputFilePath);
but that could be because the xml file is opened which is line 25
any helps?
try something like this

XDocument doc = XDocument.Load(inputFilePath);

Open in new window


>>>

XDocument doc;
using (var reader = XmlReader.Create(inputFilePath))
{
    doc = XDocument.Load(reader);
}

Open in new window

same issue is still occurred
ok, lets think something else!
copy it to a temp file and use it...
then overwrite the original one :)

XDocument doc = XDocument.Load(inputFilePath);

Open in new window


>>>

using (var tempFiles = new TempFileCollection())
{
  string tempFilePath = tempFiles.AddExtension("xml");
  // do something with the file here 
  File.Copy(inputFilePath, tempFilePath);
  XDocument doc = XDocument.Load(tempFilePath);
  ...
}

Open in new window

not working at all.
not working at all

meaning what? there is no reason for this not to work!

each time, you copy the file into a new temp file...
open it and work on it
then save as original!

so which line/code is giving error now?
and whats the message?
same line same error
Below is my original codes. you can modify if you can.

   public static string Add(string inputFilePath,Domain.User u)
        {
            WaitForFile(inputFilePath);
             XDocument doc;
            //XDocument doc = XDocument.Load(inputFilePath); 
            using (var reader = XmlReader.Create(inputFilePath))
            {             
                    doc = XDocument.Load(reader);
                    XElement user = new XElement("User",
                            new XAttribute("PhoneNo", ""),
                            new XElement("FullName", u.fullName),
                            new XElement("From", u.from),
                            new XElement("To", u.to),
                            new XElement("Body", u.body),
                            new XElement("DateTimeSent", u.dateTimeSent),
                            new XElement("Direction", u.direction),
                            new XElement("Carrier",
                                  new XElement("Name", "Twilio"),
                                  new XElement("SID", Utility.Controller.TwilioSID),
                                  new XElement("Token", Utility.Controller.TwilioToken)));
                    doc.Root.Add(user);
                    doc.Save(inputFilePath);
                    reader.Close(); 
            }
            return "Added";
        }
        public static bool WaitForFile(string fullPath)
        {
            int numTries = 0;
            while (true)
            {
                ++numTries;
                try
                {
                    // Attempt to open the file exclusively.
                    using (FileStream fs = new FileStream(fullPath,
                        FileMode.Open, FileAccess.ReadWrite,
                        FileShare.None, 100))
                    {
                        fs.ReadByte();

                        // If we got this far the file is ready
                        break;
                    }
                }
                catch (Exception ex)
                {
                 
                  

                    // Wait for the lock to be released
                    System.Threading.Thread.Sleep(500);
                }
            }
          
            return true;
        }

Open in new window

I added my suggestion to your 1st original code

public static string Add(string inputFilePath,Domain.User u) {
	using (var tempFiles = new TempFileCollection()) {
		string tempFilePath = tempFiles.AddExtension("xml");
		// do something with the file here 
		File.Copy(inputFilePath, tempFilePath);
		XDocument doc = XDocument.Load(tempFilePath);

		XElement user = new XElement("User",
			new XAttribute("PhoneNo",""),
			new XElement("FullName",u.fullName),
			new XElement("From",u.from),
			new XElement("To",u.to),
			new XElement("Body",u.body),
			new XElement("DateTimeSent",u.dateTimeSent),
			new XElement("Direction",u.direction),
			new XElement("Carrier",
			new XElement("Name","Twilio"),
			new XElement("SID",Utility.Controller.TwilioSID),
			new XElement("Token",Utility.Controller.TwilioToken)));
		doc.Root.Add(user);
		doc.Save(inputFilePath);
		return "Added";
	}
}

Open in new window

same issues
same issue? where?
maybe you open this file somewhere else in exclusive or write mode and never close it, and we just look at here hopelessly...
even i restart the web server. and the issue is still occurred with your codes
which line?
doc.Save(inputFilePath);
do you have access to that file/folder?
is file hidden/readonly/or system file?

change filename
change path
change drive

and try again...

we should think out box a bit :)
can you show me how?
maybe you dont have permission to write that folder
go to that folder and check permissions
give everyone full access to that folder

aaaaand try again :)
i already did longtime ago
in the last code, we are not even opening the file!
just copy to temp folder and work on copy!

how come we can get the file is in use!
This is what I used. it is base on your suggestion.

  public static string Add(string inputFilePath, Domain.User u)
        {
            XDocument doc;
            using (var tempFiles = new TempFileCollection())
            {
                string tempFilePath = tempFiles.AddExtension("xml");
                // do something with the file here 
                File.Copy(inputFilePath, tempFilePath);
                doc = XDocument.Load(tempFilePath);
            }

            XElement user = new XElement("User",
                new XAttribute("PhoneNo", ""),
                new XElement("FullName", u.fullName),
                new XElement("From", u.from),
                new XElement("To", u.to),
                new XElement("Body", u.body),
                new XElement("DateTimeSent", u.dateTimeSent),
                new XElement("Direction", u.direction),
                new XElement("Carrier",
                      new XElement("Name", "Twilio"),
                      new XElement("SID", Utility.Controller.TwilioSID),
                      new XElement("Token", Utility.Controller.TwilioToken)));
            doc.Root.Add(user);
            doc.Save(inputFilePath);
            return "Added";
        }

Open in new window

use the code @ ID: 42256294?
ok, open regedit and go to

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HTTP\Parameters\ListenOnlyList

what do you see here? do you have ListenOnlyList subkey?
by the way, whats the value of "inputFilePath" ???
no. see attached
e11a.jpg
public static string filePathUserMessagesAll { get { return @"C:\inetpub\UserMessagesAll.xml"; } }
who else is using this file?
check permissions on "C:\inetpub"
add everyone full permission and try again
if it does not solve anything, remove that permission...

or can you change the path to like "c:\temp\UserMessagesAll.xml"
and give everyone / full permission on "c:\path"
try this

doc.Save(inputFilePath);

Open in new window

>>>
doc.Save(inputFilePath.Replace(".xml",DateTime.Now.ToString(".yyyyMMdd.hhmmss")+".xml"));

Open in new window


this file will be unique...
lets see if it works
i have to use same file when it is saved.
just to test! I am assuming you added this to the file

using System.CodeDom.Compiler;

Open in new window


to be able to use TempFileCollection
maybe you are not changing the code file at all!!!
because you used non-working codes and keep saying same error!!!

looks like you keep changing different file and test the same code all the time :)
i sent you a private message, did you see that?
I can help you on skype if you wish
doc.Save(inputFilePath.Replace(".xml",DateTime.Now.ToString(".yyyyMMdd.hhmmss")+".xml"));

this one works if you just want to test.
works! means everytime it creates a new file! right?

no permission issue!
ok, try this now, Line 57

using (XmlReader xr = XmlReader.Create(inputFilePath))

Open in new window


>>>

XmlReaderSettings settings = new XmlReaderSettings();
settings.CloseInput = true;
using (XmlReader xr = XmlReader.Create(inputFilePath, settings))

Open in new window

that is just for test. again. i need to use same file
did you try ID: 42256353?
no. what is about?
it may be the solution that you are looking for :) click it, and try the code there
i do not understand what u want me to do with my codes. let me know if you can post it.
???

Line 57

using (XmlReader xr = XmlReader.Create(inputFilePath))

Open in new window


>>> replace it with

XmlReaderSettings settings = new XmlReaderSettings();
settings.CloseInput = true;
using (XmlReader xr = XmlReader.Create(inputFilePath, settings))

Open in new window

This is what you told me to use.

 public static string Add(string inputFilePath, Domain.User u)
        {
            XDocument doc;
            using (var tempFiles = new TempFileCollection())
            {
                string tempFilePath = tempFiles.AddExtension("xml");
                File.Copy(inputFilePath, tempFilePath);
                doc = XDocument.Load(tempFilePath);
            }
            XElement user = new XElement("User",
                new XAttribute("PhoneNo", ""),
                new XElement("FullName", u.fullName),
                new XElement("From", u.from),
                new XElement("To", u.to),
                new XElement("Body", u.body),
                new XElement("DateTimeSent", u.dateTimeSent),
                new XElement("Direction", u.direction),
                new XElement("Carrier",
                      new XElement("Name", "Twilio"),
                      new XElement("SID", Utility.Controller.TwilioSID),
                      new XElement("Token", Utility.Controller.TwilioToken)));
            doc.Root.Add(user);
            doc.Save(inputFilePath);           
            return "Added";
        }

Open in new window

I am not talking about this, the other code you posted originally...
I am talking about Line 57, @  "public static DataTable GetUniquePhoneNo(string accountPhoneNo)" method!!!
i see. hold on then. let me try
Save needs to be outside of the using statement.  This closes the stream automatically.

the structure should be as I stated earlier:
XDocument doc;
using (FileStream fileStream = new FileStream(inputFilePath,FileMode.Open, FileAccess.Read, FileShare.Read))
{
     doc = XDocument.Load(filestream);
    //..and so on...
}  //this will close the stream
doc.Save(inputFilePath);  //THEN save

Open in new window

@Hain : This general structure is per John Skeet, who pretty much is the same level of authority as MS.
I am talking about this code

XmlReaderSettings settings = new XmlReaderSettings();
settings.CloseInput = true;
using (XmlReader xr = XmlReader.Create(inputFilePath, settings))

Open in new window


we are not using stream but a filename instead...
and there are settings here that tells, close underlying stream on close...

XmlReaderSettings.CloseInput Property
https://msdn.microsoft.com/en-us/library/system.xml.xmlreadersettings.closeinput(v=vs.110).aspx
It's a filename, but the file can be read into filestream.  Please take a look at the John Skeet example I posted in my last comment ;)
will try thanks
It's a filename, but the file can be read into filestream.  Please take a look at the John Skeet example I posted in my last comment ;)

I know, but why we are creating stream if XmlReader.Create has a support for filename and option to close underlying objects automatically...
Filestream has the same support.  The "automatic" closing is actually a feature of classes that implement IDisposable.  Both filestream and xmlreader implement IDisposable.

It's actually a matter of preference, as to whether you use xmlreader or filestream.  For the OP's requirements, filestream will do the trick.  If there were low level inspection of nodes occurring, xmlreader would be the better choice.

Back to the point... is my original suggestion not working ?