Windows Service creates a text file but won't let go

  • Thread starter Thread starter stuart.jones
  • Start date Start date
S

stuart.jones

Dear all

I have a Windows Service that retrieves some data as XML, applies an
XSLT to produce a CSV which is saved to the filesystem as a text file.
This all works fine. Depending upon the configuration, this file is
then
1. copied to another location
2. attached to an e-mail message
3. FTPed to a particular location

Problem is that the FTPing is failing with the "being used by another
process" error.

I assume that the file has finished being written as steps 1 and 2 are
successful. If I try and delete the file manually through Explorer I'm
unable to do so - until I stop the Windows Service.

Why does the Windows Service appear to keep a handle on the created
file?

Any help is greatly appreciated.
Regards
Stuart
 
Sounds to me like you aren't closing the filestream after you finish writing
the file.
If you want, post a short-but-complete code sample and somebody will verify
it for you.

Peter
 
But isn't it odd that the file can be copied locally, or attached to an
e-mail?

I'll post up the code just as soon as I'm back from my holiday!

Thanks
Stuart
 
OK, here's the code, with a bit of explanation. I appreciate any help!


In the main routine I call a method to perform the transformation,
followed by a method to transfer the generated file via FTP:

sErrorMsg = objRecipient.Transform();
sErrorMsg = objRecipient.OutputToFTP();


The Transform() method is as follows:

internal string Transform()
{
if (dsResults.Tables.Count > 0)
{
// Convert to XML
string xmlResultsFilePath = String.Empty;
XmlDataDocument xmlResults = new XmlDataDocument(dsResults);
string xmlResultsFilename = Path.ChangeExtension("Data", ".xml");
string xmlResultsFilePath = Path.Combine(repository,
xmlResultsFilename);
xmlResults.Save(xmlResultsFilePath);

// Determine the path to the installation
Module mod = Assembly.GetExecutingAssembly().GetModules()[0];
string fullPath = mod.FullyQualifiedName;
string myInstallPath = Path.GetDirectoryName(fullPath);

// Transform each output object
for (int i = 0; i < outputs.Count; i++)
{
Output o = (outputs as Output);

// Create the XsltSettings object with document() and scripting
enabled
XsltSettings settings = new XsltSettings(true, true);

// Execute the transform
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(Path.Combine(myInstallPath, o.Transformation),
settings, new XmlUrlResolver());
xslt.Transform(xmlResultsFilePath, Path.Combine(repository,
o.OutputFilename));
}
}
return String.Empty;
}


The OutputToFTP() method is as follows. It uses an Indy component to do
the FTPing (the code is pre-.NET 2.0):

internal string OutputToFTP()
{
for (int i = 0; i < outputs.Count; i++)
{
Output o = (outputs as Output);
if (o.OutputToFtp)
{
FileInfo fi = new FileInfo(Path.Combine(repository,
o.OutputFilename));

if (fi.Exists)
{
FTP indyFTP = new FTP();
try
{
indyFTP.Host = o.FtpHost;
indyFTP.Username = o.FtpUsername;
indyFTP.Password = o.FtpPassword;
indyFTP.Connect();
indyFTP.ChangeDir("in");
indyFTP.Put(Path.Combine(repository, o.OutputFilename),
o.OutputFilename, false);
}
catch (Exception e)
{
return String.Format("Error: {0} " +
"when trying to FTP to: {1}. ",
e.Message, o.FtpHost);
}
finally
{
indyFTP.Disconnect();
}
}
}
}
return String.Empty;
}


If the filestream is still open this suggests a problem with the
Transform() method (though the code was converted from an example in
the VS Help).

Thanks in advance,
Stuart.
 
I solved this by converting the file to a FileStream object, and using
this in the overloaded Put() method (thanks go to the newsgroup
atozedsoftware.indy.protocol.ftp).

I'd still like to know why the Service keeps a hold of the file but I
guess this question is destined to be left hanging...

OK, here's the code, with a bit of explanation. I appreciate any help!


In the main routine I call a method to perform the transformation,
followed by a method to transfer the generated file via FTP:

sErrorMsg = objRecipient.Transform();
sErrorMsg = objRecipient.OutputToFTP();


The Transform() method is as follows:

internal string Transform()
{
if (dsResults.Tables.Count > 0)
{
// Convert to XML
string xmlResultsFilePath = String.Empty;
XmlDataDocument xmlResults = new XmlDataDocument(dsResults);
string xmlResultsFilename = Path.ChangeExtension("Data", ".xml");
string xmlResultsFilePath = Path.Combine(repository,
xmlResultsFilename);
xmlResults.Save(xmlResultsFilePath);

// Determine the path to the installation
Module mod = Assembly.GetExecutingAssembly().GetModules()[0];
string fullPath = mod.FullyQualifiedName;
string myInstallPath = Path.GetDirectoryName(fullPath);

// Transform each output object
for (int i = 0; i < outputs.Count; i++)
{
Output o = (outputs as Output);

// Create the XsltSettings object with document() and scripting
enabled
XsltSettings settings = new XsltSettings(true, true);

// Execute the transform
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(Path.Combine(myInstallPath, o.Transformation),
settings, new XmlUrlResolver());
xslt.Transform(xmlResultsFilePath, Path.Combine(repository,
o.OutputFilename));
}
}
return String.Empty;
}


The OutputToFTP() method is as follows. It uses an Indy component to do
the FTPing (the code is pre-.NET 2.0):

internal string OutputToFTP()
{
for (int i = 0; i < outputs.Count; i++)
{
Output o = (outputs as Output);
if (o.OutputToFtp)
{
FileInfo fi = new FileInfo(Path.Combine(repository,
o.OutputFilename));

if (fi.Exists)
{
FTP indyFTP = new FTP();
try
{
indyFTP.Host = o.FtpHost;
indyFTP.Username = o.FtpUsername;
indyFTP.Password = o.FtpPassword;
indyFTP.Connect();
indyFTP.ChangeDir("in");
indyFTP.Put(Path.Combine(repository, o.OutputFilename),
o.OutputFilename, false);
}
catch (Exception e)
{
return String.Format("Error: {0} " +
"when trying to FTP to: {1}. ",
e.Message, o.FtpHost);
}
finally
{
indyFTP.Disconnect();
}
}
}
}
return String.Empty;
}


If the filestream is still open this suggests a problem with the
Transform() method (though the code was converted from an example in
the VS Help).

Thanks in advance,
Stuart.


But isn't it odd that the file can be copied locally, or attached to an
e-mail?

I'll post up the code just as soon as I'm back from my holiday!

Thanks
Stuart
 

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

Back
Top