Ideas as to why file is locked

S

Snedker

Hi folks,

I've written a windows service that watches a specific (xml) file for
changes. If changes occur, the XML-file is being read and part of the
content written to an Access database (mdb).

First time the XML-file is changed everything runs well and data are
written to database. However, the second time I change the content of
the XML-file I get an IO exception: Process cannot access file 'bla
bla' because it being used by another proces.

The error occurs at line 43 (reader.Read();) in the file
http://files.getdropbox.com/u/175230/Code/XmlHandler.cs. The void
Execute() is called from line 66 in http://files.getdropbox.com/u/175230/Code/Service1.cs.

Any clues?

Thanks in advance for your time and efforts!

Kind regards
Morten Snedker
 
S

Snedker

Thanks for your reply Pete. And point taken in regards of the last
part of you reply.

The failing void (in a shortened version), which is failing on line
with the content: reader.Read();

public void Execute(string xmlFile)
{
XmlReader reader = new XmlTextReader(xmlFile);

using (reader)
{
reader.Read();

while (reader.Read())
{
reader.MoveToElement();
if (reader.HasAttributes)
{
for (int i = 0; i < reader.AttributeCount;
i++)
{
reader.MoveToAttribute(i);
switch (reader.Name)
{
case "Event":
mEvent = reader.Value; break;
//...
}
}
WriteToDatabase();
}
}
reader.Close();
} //using
}

So the "using" statement should close the file implicitly, but is also
closed explicitly - just to ensure some sort of delay is not the cause
of failure.


Regards /Snedker
 
P

Peter Duniho

[...]
So the "using" statement should close the file implicitly, but is also
closed explicitly - just to ensure some sort of delay is not the cause
of failure.

The Dispose() executed by the "using" statement happens immediately after
your call to Close(), and would happen exactly when the Close() happens,
were it not for the Close() being present. So it's not strictly useful to
do both (though I myself have even been known to anyway, because of my
lack of confort with the conflation of Dispose() and Close() by the .NET
API :) ).

In any case, if you are sure you're closing the file properly before
trying to reopen it, that only leaves some other application having it
open. Probably the application that makes the changes you're looking for
would be my guess. But without a concise-but-complete code example that
reliably demonstrates the problem, it's not possible to say for sure.

Pete
 
S

Snedker

In any case, if you are sure you're closing the file properly before  
trying to reopen it, that only leaves some other application having it  
open.  Probably the application that makes the changes you're looking for  
would be my guess.  But without a concise-but-complete code example that  
reliably demonstrates the problem, it's not possible to say for sure.

Thanks for your reply, Pete.

The entire project can be found at http://files.getdropbox.com/u/175230/Code/XMLService.zip.
The installation set can be found at http://files.getdropbox.com/u/175230/Code/XmlParser.zip.

The service expects the path C:\XmlParser\xmlparser.ini to be found.
To setup the service simply run ServiceSetup.cmd from the installation
set. This should be run with administrator rights.

To generate the error I've described earlier simply alter some of the
content of "MOJN_FM.xml", wait 15 seconds and alter some of the
content again. In my scenario VS asks to debug the failing code.

Thanks again to all of your replies - it's greatly appreciated!


Regards
Morten Snedker
 
S

Snedker

But without a concise-but-complete code example that  
reliably demonstrates the problem, it's not possible to say for sure.

PS: I am not all sure about what concise-but-complete is, so that's
why I have given link to the entire project (with the possibility of
dead links later on). Not out of dis-respect, but I am nut sure how to
make it precise enough. Would the proper way have been to post all of
the code here?

The problem is that I'm quite sure that the file is closed. I've also
tried to use a number of programs that can tell me if any processes
are locking the file. These state that nothing locks the file.

I simply open then XML-file with Notepad, alters the content and then
save/close the file. The second time I change the content I should get
an error - if it was because the service had not released the file.
But I CAN change the content of file the second time, and save it.

I thought this file notification would be a walk in the park, but by
now I've spent oceans of time with all sorts of weird problems (such
as the use of a timer out of necessity).

However, if I am using the usenet wrongly, please correct me.

Regards
Morten Snedker
 
S

Snedker

The Dispose() executed by the "using" statement happens immediately after 
your call to Close(), and would happen exactly when the Close() happens,  
were it not for the Close() being present.  So it's not strictly usefulto  
do both (though I myself have even been known to anyway, because of my  
lack of confort with the conflation of Dispose() and Close() by the .NET  
API :) ).

I don't know if it is semantics, but the XmlTextReader does not have a
Dispose() method. I don't suppose that changes your point of using
Close() when also have the use of "using"?

Regards
Morten Snedker
 
P

Peter Duniho

PS: I am not all sure about what concise-but-complete is, so that's
why I have given link to the entire project (with the possibility of
dead links later on). Not out of dis-respect, but I am nut sure how to
make it precise enough. Would the proper way have been to post all of
the code here?

All? No. But then, neither is a link to all of the code appropriate.

I find the words "concise" and "complete" to be quite descriptive. But if
you are still unsure, here are some links you may find helpful:
http://www.yoda.arachsys.com/csharp/complete.html
http://www.yoda.arachsys.com/csharp/incomplete.html
http://sscce.org/ (some Java-centric stuff, but mostly applicable to any
programming questions)
The problem is that I'm quite sure that the file is closed. I've also
tried to use a number of programs that can tell me if any processes
are locking the file. These state that nothing locks the file.

A file sharing access exception when you try to open the file only happens
when there's a file sharing access violation. That is, _something_ has
the file open when you try to open it.

Of the "number of programs" that you've tried, was any of those FileMon
from SysInternals? If not, it should have been. It can not only tell you
instantaneous status of a file, but more importantly it can log transient
file-related activity.

http://technet.microsoft.com/en-us/sysinternals/bb896642.aspx

(I see that the above page says that Process Monitor is now the tool to
use even for file-monitoring stuff...haven't had a chance to check it out
myself, but here's the link to that:
http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx)
I simply open then XML-file with Notepad, alters the content and then
save/close the file. The second time I change the content I should get
an error - if it was because the service had not released the file.
But I CAN change the content of file the second time, and save it.

I don't understand the above. Your previous posts suggests changing the
file "MOJN_FM.xml" and saving it to reproduce the problem. But the above
suggests that doing that doesn't cause any problem.

Of course, all this would be moot if you posted a concise-but-complete
code example, as the code example would automatically cause whatever
changes were necessary in order to reproduce the problem, without
requiring specific user actions.

But regardless, you'll have to post a much more specific and
self-contained question to get a useful answer. Given the information so
far, I can see no way to do anything except speculate.

Pete
 
S

Snedker

Having re-read the postings I suppose i did wrong.

This is the full code of "Service1.cs":

using System;
using System.IO;
using System.Timers;
using System.ServiceProcess;
using System.Diagnostics;

namespace WindowsService1
{
public partial class Service1 : ServiceBase
{
private FileSystemWatcher watcher;
private Timer timer;
private Paths paths = new Paths();

public Service1()
{
InitializeComponent();
}

protected override void OnStart(string[] args)
{
timer = new Timer();

watcher = new System.IO.FileSystemWatcher();

watcher.Path = paths.PathOnlyXmlFile;
watcher.IncludeSubdirectories = false;
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Filter = "MOJN_FM.xml";
watcher.Changed += new FileSystemEventHandler
(watcher_Changed);
watcher.EnableRaisingEvents = true;

StreamWriter sw = new StreamWriter(@"e:\log.log", true);
sw.WriteLine("xml-path: " + paths.PathOnlyXmlFile);
sw.WriteLine("database: " + paths.FullPathDatabase);
sw.Dispose();
}

protected override void OnStop()
{
timer.Dispose();
watcher.Dispose();
}

private void OnElapsedTime(object source, ElapsedEventArgs e)
{
timer.Stop();
watcher.EnableRaisingEvents = true;
}


private void watcher_Changed(object source,
FileSystemEventArgs e)
{
if (!timer.Enabled)
{
watcher.EnableRaisingEvents = false;

timer.Elapsed += new ElapsedEventHandler
(OnElapsedTime);
timer.Interval = 15000;
timer.Start();

XmlHandler xh = new XmlHandler();
xh.Execute(e.FullPath);

//StreamWriter sw = new StreamWriter(@"e:\log.log",
true);
//sw.WriteLine("xml-file: " + e.FullPath);
//sw.WriteLine("xml-path: " + paths.PathOnlyXmlFile);
//sw.WriteLine("database: " + paths.FullPathDatabase);
//sw.Dispose();
}
}
}
}

This is the full code of "XmlHandler.cs":
using System;
using System.IO;
using System.Xml;
using System.Text;
using System.Data.OleDb;
using System.Diagnostics;

namespace WindowsService1
{
class XmlHandler
{
#region Privates
private Paths paths = new Paths();
private static string EVENT_SOURCE = "dbConsult_XmlHandler";

private string mEvent = string.Empty;
private string mType = string.Empty;
private string mCategory = string.Empty;
private string mId = string.Empty;
private string mTitle = string.Empty;
private string mArtist = string.Empty;
private string mAlbum = string.Empty;
private string mComposer = string.Empty;
private string mMusicId = string.Empty;
private Int32 mDuration = 0;
private string mStartTime = string.Empty;
private DateTime mRealStartTime;
#endregion

public XmlHandler()
{ }


public void Execute(string xmlFile)
{
// Create an instance of XmlTextReader and call Read
method to read the file
XmlReader reader = new XmlTextReader(xmlFile);

//try
//{
using (reader)
{
reader.Read(); //
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx this is the failing line

// If the node has value
while (reader.Read())
{

// Move to fist element
reader.MoveToElement();
if (reader.HasAttributes)
{
for (int i = 0; i < reader.AttributeCount;
i++)
{
reader.MoveToAttribute(i);
switch (reader.Name)
{
case "Event":
mEvent = reader.Value; break;
case "Type":
mType = reader.Value; break;
case "Category":
mCategory = reader.Value;
break;
case "Id":
mId = reader.Value; break;
case "Title":
mTitle = reader.Value; break;
case "Artist":
mArtist = reader.Value; break;
case "Album":
mAlbum = reader.Value; break;
case "Composer":
mComposer = reader.Value;
break;
case "MusicId":
mMusicId = reader.Value;
break;
case "Duration":
mDuration = Convert.ToInt32
(reader.Value); break;
case "StartTime":
mStartTime = reader.Value;
mRealStartTime = ProperDate
(mStartTime); break;
}
}
WriteToDatabase();
}
}
reader.Close();
} //using
//}
//catch (Exception e)
//{
// EventLog myLog = new EventLog();
// if (!EventLog.SourceExists(EVENT_SOURCE))
// {
// myLog.Source = EVENT_SOURCE;
// }

// myLog.WriteEntry("Execute(): " + e.Message,
EventLogEntryType.Error);
//}
}
private void WriteToDatabase()
{
StringBuilder sql = new StringBuilder();

sql.Append("INSERT INTO tEntry
(EntryEvent,Type,Category,Id,IdNumeric,Title,Artist,Album,Composer,MusicId,DurationSeconds,StartTime)
");
sql.Append("VALUES (");
sql.Append("'" + mEvent + "',");
sql.Append("'" + mType + "',");
sql.Append("'" + mCategory + "',");
sql.Append("'" + mId + "',");
//try
//{
sql.Append(Convert.ToInt32(mId) + ",");
//}
//catch (Exception e)
//{
// EventLog myLog = new EventLog();
// if (!EventLog.SourceExists(EVENT_SOURCE))
// {
// myLog.Source = EVENT_SOURCE;
// }
// myLog.WriteEntry("WriteToDatabase;mId.ToInt32: " +
e.Message, EventLogEntryType.Error);
//}
sql.Append("'" + mTitle + "',");
sql.Append("'" + mArtist + "',");
sql.Append("'" + mAlbum + "',");
sql.Append("'" + mComposer + "',");
sql.Append("'" + mMusicId + "',");
//try
//{
sql.Append(Convert.ToInt32(mDuration) / 1000 + ",");
//}
//catch (Exception e)
//{
// EventLog myLog = new EventLog();
// if (!EventLog.SourceExists(EVENT_SOURCE))
// {
// myLog.Source = EVENT_SOURCE;
// }
// myLog.WriteEntry("WriteToDatabase;mDuration.ToInt32:
" + e.Message, EventLogEntryType.Error);
//}

sql.Append("#" + mRealStartTime + "#)");

OleDbConnection con = new OleDbConnection
("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
paths.FullPathDatabase + ";User Id=admin;Password=;");
con.Open();
OleDbCommand com = new OleDbCommand(sql.ToString(), con);

com.ExecuteNonQuery();
com.Dispose();

con.Close();
con.Dispose();
}

#region Helpers
private DateTime ProperDate(string input)
{

int mSecond = Convert.ToInt16(input.Substring(17, 2));
int mMinute = Convert.ToInt16(input.Substring(14, 2));
int mHour = Convert.ToInt16(input.Substring(11, 2));
int mDay = Convert.ToInt16(input.Substring(8, 2));
int mMonth = ProperMonth(input.Substring(4, 3));
int mYear = Convert.ToInt16(input.Substring(20, 4));

return new DateTime(mYear, mMonth, mDay, mHour, mMinute,
mSecond);

}
private int ProperMonth(string input)
{
switch (input)
{
case "Jan":
return 1;
case "Feb":
return 2;
case "Mar":
return 3;
case "Apr":
return 4;
case "May":
return 5;
case "Jun":
return 6;
case "Jul":
return 7;
case "Aug":
return 8;
case "Sep":
return 9;
case "Oct":
return 10;
case "Nov":
return 11;
case "Dec":
return 12;
}

return 0;
}

#endregion

}
}

Regards
Morten Snedker
 
I

Ignacio Machin ( .NET/ C# MVP )

Hi folks,

I've written a windows service that watches a specific (xml) file for
changes. If changes occur, the XML-file is being read and part of the
content written to an Access database (mdb).

First time the XML-file is changed everything runs well and data are
written to database. However, the second time I change the content of
the XML-file I get an IO exception: Process cannot access file 'bla
bla' because it being used by another proces.

The error occurs at line 43 (reader.Read();) in the filehttp://files.getdropbox.com/u/175230/Code/XmlHandler.cs. The void
Execute() is called from line 66 inhttp://files.getdropbox.com/u/175230/Code/Service1.cs.

Any clues?

Thanks in advance for your time and efforts!

Kind regards
Morten Snedker

Hi,

Is this a mobile device prorgram?

Try this, read the file to a memory stream (and make sure you are
closing the FileStream used to read it) then create your XmlStream
from the memory stream.

Also, are you sure the creator is closing the file?

Pd:
My firewall has getDropBox closed so I have not seen your code, so the
above suggestions are good guess only
 

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