I'm having issues with random FileNotFoundExceptions when i'm creating a FileStream. The filepath is correct, the file exist, still i get FileNotFoundException at random times. How can i debug this more in detail? I'm running a Windows Mobile 6 project and this is the exception:
System.IO.FileNotFoundException: Could not find file '\Program Files\xxx\xxx\xxx-11133.bin'.
at System.IO.__Error.WinIOError(Int32 errorCode, String str)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, Boolean useAsync, String msgPath)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access)
This is the method that throws the exception:
internal static FInstance ReadAndDecrypt(string key, string fiId)
{
FileInfo fileInfo = new FileInfo(FullFilePath(fiId));
FileStream fileStream = null;
CryptoStream cryptoStream = null;
GZipInputStream zipStream = null;
try
{
int time = Environment.TickCount;
fileStream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read);
var serializer = new XmlSerializer(typeof(FInstance));
var FInstance = (FInstance)serializer.Deserialize(fileStream);
return Instance;
}
catch (Exception e)
{
Log.Error(e);
return null;
}
finally
{
if (fileStream != null)
fileStream.Close();
}
}
I can't think of anything that could cause this, is there any way to debug this deeper?
Debugging this should be straightforward. Add the following into your code right before your try/catch block:
if((!fileInfo.Exists) && (Debugger.IsAttached))
{
Debugger.Break();
}
This will get you to the state where the file isn't there. You should be checking for existence before opening the file in your production code anyway to protect against things like the file being deleted or in use while you app is already running.
Related
I have an Azure Function (HttpTrigger) which creates a tar.gz file in my Azure Storage.
When I trigger it one time, the file is succesfully created. but if I hit it again I have an error:
[Info] The process cannot access the file
'D:\local\Temp\myDir\tarArchive.tar.gz' because it is being used by
another process.
I have to restart the function in the Azure Portal to be able to create another file.
here is my code:
FileStream fs = new FileStream(myDir+"/firstFile", FileMode.Create);
fs.Write(bytesToCompress, 0, bytesToCompress.Length);
fs.Dispose();
FileStream sfs = new FileStream(myDir + "/secondfile", FileMode.Create);
sfs.Dispose();
DirectoryInfo DirectoryOfFilesToBeTarred = new DirectoryInfo(myDir);
FileInfo[] filesInDirectory = DirectoryOfFilesToBeTarred.GetFiles();
string tarArchiveName = myDir + "/tarArchive.tar.gz";
using (Stream targetStream = new GZipOutputStream(File.Create(tarArchiveName)))
{
using (TarArchive tarArchive = TarArchive.CreateOutputTarArchive(targetStream, TarBuffer.DefaultBlockFactor))
{
foreach(FileInfo fileToBeTarred in filesInDirectory)
{
log.Info(fileToBeTarred.FullName);
TarEntry entry = TarEntry.CreateEntryFromFile(fileToBeTarred.FullName);
tarArchive.WriteEntry(entry, true); // Error thrown here
}
}
}
I thought fileToBeTarred was still in use when the function is called again (am I wrong?) but I've tried to create a stream from this FileInfo in order to Dispose() it, but didn't fix my problem. I've also tried to Delete() it, without any effect.
Is someone seeing what I don't see ?
Thanks for your help
UPDATE
Here is the corected code given by Wim Coenen
using (Stream fileStream = File.Create(tarArchiveName))
using (Stream targetStream = new GZipOutputStream(fileStream))
using (TarArchive tarArchive = TarArchive.CreateOutputTarArchive(targetStream, TarBuffer.DefaultBlockFactor))
{
foreach (FileInfo fileToBeTarred in filesInDirectory)
{
log.Info(fileToBeTarred.FullName);
TarEntry entry = TarEntry.CreateEntryFromFile(fileToBeTarred.FullName);
tarArchive.WriteEntry(entry, true); // Error thrown here
}
}
And the log of the error (e = Exception object)
e.message =>
2018-08-01T11:59:46.887 [Info] The process cannot access the file
'D:\local\Temp\myDir\tarArchive.tar.gz' because it is being used by
another process.
e.ToString() =>
2018-08-01T11:59:47.152 [Info] System.IO.IOException: The process
cannot access the file 'D:\local\Temp\myDir\tarArchive.tar.gz'
because it is being used by another process.
at System.IO.__Error.WinIOError(Int32 errorCode, String
maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess
access, Int32 rights, Boolean useRights, FileShare share, Int32
bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String
msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode,
FileAccess access, FileShare share)
at ICSharpCode.SharpZipLib.Tar.TarArchive.WriteEntryCore(TarEntry
sourceEntry, Boolean recurse)
at ICSharpCode.SharpZipLib.Tar.TarArchive.WriteEntry(TarEntry
sourceEntry, Boolean recurse)
at UploadFileFromBCText.Function1.d__4.MoveNext()
It looks like you are not creating it in Azure Storage, but on the local disk of a Function App instance. That's probably not a good idea, since instances are short-lived and won't preserve your files for long.
Instead, have a look at Azure Blob Storage Output binding - its purpose is to store file in Azure Storage without using low-level File API or SDKs.
The problem is that you are not disposing the stream returned by File.Create(tarArchiveName)). Fixed version:
using (Stream fileStream = File.Create(tarArchiveName))
using (Stream targetStream = new GZipOutputStream(fileStream))
using (TarArchive tarArchive = TarArchive.CreateOutputTarArchive(targetStream, TarBuffer.DefaultBlockFactor))
{
foreach(FileInfo fileToBeTarred in filesInDirectory)
{
log.Info(fileToBeTarred.FullName);
TarEntry entry = TarEntry.CreateEntryFromFile(fileToBeTarred.FullName);
tarArchive.WriteEntry(entry, true);
}
}
I've just find what was the problem:
In fact when I hit for the first time the trigger, myDir is empty. So I create at this time the two files
FileStream fs = new FileStream(myDir+"/firstFile", FileMode.Create);
fs.Write(bytesToCompress, 0, bytesToCompress.Length);
fs.Dispose();
FileStream sfs = new FileStream(myDir + "/secondfile", FileMode.Create);
sfs.Dispose();
With these files, I create a tar.gz archive with the files in the directory, which doesn't exists yet.
The second time I hit the trigger the tar.gz file exists, and belongs to the directory. So when I do
foreach(FileInfo fileToBeTarred in filesInDirectory)
{
log.Info(fileToBeTarred.FullName);
TarEntry entry = TarEntry.CreateEntryFromFile(fileToBeTarred.FullName);
tarArchive.WriteEntry(entry, true);
}
At a moment, it works with the tar.gz file ..!
filesInDiretory is filled by this method:
FileInfo[] filesInDirectory = DirectoryOfFilesToBeTarred.GetFiles();
So I solve this issue by:
Checking if the file exists. If it is, I delete it.
Fill filesInDirectory AFTER
So my complete code looks like this now:
DirectoryInfo DirectoryOfFilesToBeTarred = new DirectoryInfo(myDir);
string tarArchiveName = myDir + "/tarArchive.tar.gz";
if (File.Exists(tarArchiveName))
{
log.Info("file exists");
File.Delete(tarArchiveName);
}
FileInfo[] filesInDirectory = DirectoryOfFilesToBeTarred.GetFiles();
using (Stream fileStream = File.Create(tarArchiveName))
using (Stream targetStream = new GZipOutputStream(fileStream))
using (TarArchive tarArchive = TarArchive.CreateOutputTarArchive(targetStream, TarBuffer.DefaultBlockFactor))
{
foreach (FileInfo fileToBeTarred in filesInDirectory)
{
Directory.SetCurrentDirectory(Path.GetTempPath() + "/myDir");
log.Info(fileToBeTarred.Name);
log.Info(fileToBeTarred.FullName);
TarEntry entry = TarEntry.CreateEntryFromFile(fileToBeTarred.FullName);
tarArchive.WriteEntry(entry, true);
}
}
Guys can some one tell me why i have such error ....
2013-08-11 18:44:28 - NPMessage: DEBUG: Dispatching a RPCStorageWriteUserFileMessage
2013-08-11 18:44:28 - RPCStorageWriteUserFileMessage: INFO: Got a request for writing 8192 bytes to file iw4.stat for user alhpons.
2013-08-11 18:44:28 - ProfileData: INFO: Handling profile update request for alhpons
2013-08-11 18:44:28 - ProfileData: ERROR: Exception: System.IO.IOException: The process cannot access the file 'D:\IW4M\NpServer\data\priv2\00\000\alhpons\iw4.stat' because it is being used by another process.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
at System.IO.File.ReadAllBytes(String path)
at NPx.ProfileData.Handle(UpdateRequest request)
at NPx.ProfileData.Run()
Edit:
i use my App on windows server 2008 and some files need to read / write permission for my application but i have such error so i need to fix that problem and my source is:
public override void Process(NPHandler client)
{
var fileName = Message.fileName;
var fileData = Message.fileData;
var npid = (long)Message.npid;
var fsFile = StorageUtils.GetFilename(fileName, npid);
_client = client;
_fileName = fileName;
_npid = npid;
if (!client.Authenticated)
{
ReplyWithError(1);
return;
}
if (client.NPID != (long)npid)
{
ReplyWithError(1);
return;
}
if (!Directory.Exists(Path.GetDirectoryName(fsFile)))
{
Directory.CreateDirectory(Path.GetDirectoryName(fsFile));
}
// are we allowed to write this type of file?
if (!_fileHooks.ContainsKey(fileName))
{
ReplyWithError(1);
return;
}
string backupFile = null;
int result = _fileHooks[fileName](fileData, fsFile, out backupFile);
if (result > 0)
{
ReplyWithError(result);
return;
}
Log.Info(string.Format("Got a request for writing {0} bytes to file {1} for user {2}.", fileData.Length, fileName, npid.ToString("X16")));
try
{
var stream = File.Open(fsFile, FileMode.Create, FileAccess.Write);
stream.BeginWrite(fileData, 0, fileData.Length, WriteCompleted, stream);
if (backupFile != null)
{
var backupStream = File.Open(backupFile, FileMode.Create, FileAccess.Write);
backupStream.BeginWrite(fileData, 0, fileData.Length, BackupWriteCompleted, backupStream);
}
}
catch (Exception ex)
{
Log.Error(ex.ToString());
ReplyWithError(2);
}
}
Yes, the very program that gives you this message may be the program that is locking the file. Make sure to practice good housekeeping by closing each data stream after it has been used.
var stream = File.Open(fsFile, FileMode.Create, FileAccess.Write);
Where do you close this stream again?
The process cannot access the file xxx because it is being used by another process.
The Microsoft programmer that wrote this message was a trust-hearty soul. He did not want to assume that you got it wrong. When you are debugging your code, that message should however have ended with "is being used by a process". It includes your own.
Also note that you made the same mistake with backupStream. Since you are already using File.ReadAllBytes() to read the file, you might just as well use File.WriteAllBytes() to write it. If you can't afford the delay then you'll need to ensure it is closed in the WriteCompeted callback method.
If you already do this, then consider that the file might actually be in use by another process. Which does happen.
I'm getting an exception: The process cannot access the file.
Here's the code:
if (!Monitor.TryEnter(lockObject))
return;
try
{
watcher.EnableRaisingEvents = false;
try
{
XmlDocument xdoc = new XmlDocument();
xdoc.Load(FileName);
xdoc = null;
}
catch (XmlException xe)
{
using (StreamWriter w = File.AppendText(FileName))
{
Console.WriteLine(xe);
w.WriteLine("</test>");
w.WriteLine("</testwrapper>");
}
}
System.Threading.Thread.Sleep(2000);
XPathDocument myXPathDoc = new XPathDocument(new StreamReader(FileName, System.Text.Encoding.GetEncoding("windows-1256")));
XslCompiledTransform myXslTrans = new XslCompiledTransform();
myXslTrans.Load("D:/GS/xsl/test.xsl");
XmlTextWriter myWriter = new XmlTextWriter(destinationFile, null);
myWriter.Formatting = Formatting.Indented;
myWriter.Indentation = 4;
myXslTrans.Transform(myXPathDoc, null, myWriter);
myWriter.Close();
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
finally
{
Monitor.Exit(lockObject);
watcher.EnableRaisingEvents = true;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
The code was working perfectly before I added these lines. These are mainly for testing if the xml file is without the closing tags (which) I normally get then add the tags. After I added the following code it started giving me this exception.
try
{
XmlDocument xdoc = new XmlDocument();
xdoc.Load(FileName);
xdoc = null;
}
catch (XmlException xe)
{
using (StreamWriter w = File.AppendText(FileName))
{
Console.WriteLine(xe);
w.WriteLine("</test>");
w.WriteLine("</testwrapper>");
}
}
What could be wrong here ?
EDIT: Error I'm getting
The process failed: System.IO.IOException: The process cannot access the file 'z
:\TF_B1BBA.xml' because it is being used by another process.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, I
nt32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions o
ptions, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolea
n useLongPath)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access,
FileShare share, Int32 bufferSize)
at System.Xml.XmlDownloadManager.GetStream(Uri uri, ICredentials credentials,
IWebProxy proxy, RequestCachePolicy cachePolicy)
at System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofO
bjectToReturn)
at System.Xml.XmlTextReaderImpl.OpenUrlDelegate(Object xmlResolver)
at System.Threading.CompressedStack.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCl
eanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.CompressedStack.Run(CompressedStack compressedStack, Cont
extCallback callback, Object state)
at System.Xml.XmlTextReaderImpl.OpenUrl()
at System.Xml.XmlTextReaderImpl.Read()
. at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean prese
veWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.Load(String filename)
at GSelInterface.Program.convert(Object source, FileSystemEventArgs f) in C:\
Documents and Settings\Administrator\Desktop\ConsoleApplication1\ConsoleApplicat
ion1\Program.cs:line 178
In your try block you have opened the file. You need to close it.
XmlDocument xdoc = new XmlDocument();
xdoc.Load(FileName);
Follow this example.
http://msdn.microsoft.com/en-us/library/zcsyk915.aspx
It may be because of the watcher (then FileShare.ReadWrite is the important part).
Try:
XmlDocument xdoc = new XmlDocument();
FileStream fs = new FileStream(FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
xdoc.Load(fs);
You are trying to write on "Filename" file that is already open in the try block.
Edit 1:
It seems the lock is set by the process that is saving the file.
When convert() is fired, filesystem has still not finished to save the file.
It happens expecially if you have a big xml.
If you add a sleep just before trying to write the file, exception is not raised.
This is a quick&dirty patch.
If xml files are saved with an high frequency, you need to add some kind of lock to the xml file changed.
Edit 2:
Try also to remove watcher's event before doing stuff, and add again after everything is done, so you prevent multiple events to be fired.
Not so sure that EnableRaisingEvents = false will work in the right way.
See this post also:
EnableRaisingEvents (enabling and disabling it)
try
{
watcher.EnableRaisingEvents = false;
//Edit2: Remove the watcher event
watcher.Changed -= new FileSystemEventHandler(convert);
try
{
XmlDocument xdoc = new XmlDocument();
xdoc.Load(FileName);
}
catch (XmlException xe)
{
System.Threading.Thread.Sleep(1000); //added this line
using (StreamWriter w = File.AppendText(FileName))
{
Console.WriteLine(xe);
w.WriteLine("</test>");
w.WriteLine("</testwrapper>");
}
}
}
/*
Here all xslt transform code
*/
//Edit2: Add again the watcher event
watcher.Changed += new FileSystemEventHandler(convert);
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
The solution to this problem is right at this link:
Exception during xml processing
This was another question I raised. Thank you all of you who spent their time in helping me out.
Make sure the file does not exist.
I had to recreate my build configuration and the old file still existed. Once I deleted the old transform I was able to recreate the new transform.
The following line is throwing an exception. I have no idea why.
using (var output = new FileStream(sftpFile.Name, FileMode.Create,FileAccess.ReadWrite))
Exception is:
Error: System.UnauthorizedAccessException: Access to the path 'C:\Users\roberth\
Programming_Projects\Common\UI\bin\Debug' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access,
Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions
options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy,
Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access)
at CWD.Networking.DownloadFromSftp(String hostname, String user, String passw
ord, Int32 port, String localPath, String remotePath, String filename) in c:\Use
rs\roberth\Programming_Projects\Common\Common\Common.cs:line 566
Line 566 is the using statement above.
Can anyone shed some light as to why I may be triggering an error? I have full permissions to the directory, no compilation issues, I can create new files and folders manually in that directory as well.
--Edit--
I tried running VS as administrator as suggested with no resolution.
The UnauthorizedAccessException error message tells you what file it is you're trying to open:
C:\Users\roberth\Programming_Projects\Common\UI\bin\Debug
This looks like a directory name: you can't open a directory as a file.
You've presumably forgotten to append a filename:
string filename = Path.Combine(sftpFile.Name, "SomeFile.dat");
using (var output = new FileStream(filename,...)
{
...
}
You need to use something similar to the following:
private bool EnviarArchivoSFTP(string PuertoSFTP, string UrlFTP, string CarpetaFTP, string UsuarioFTP, string PasswordFTP, string FicheroFTP, string nombreArchivo)
{
bool archivoEnviado = false;
using (var client = new SftpClient(UrlFTP, int.Parse(PuertoSFTP), UsuarioFTP, PasswordFTP))
{
client.ConnectionInfo.Timeout = TimeSpan.FromSeconds(1);
client.OperationTimeout = TimeSpan.FromSeconds(1);
client.Connect();
client.ChangeDirectory(CarpetaFTP);
string dataPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
string appFile = Path.Combine(dataPath, FicheroFTP, nombreArchivo);//Se brindan permisos full sobre la carpeta
using (var fileStream = new FileStream(appFile, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
client.BufferSize = 4 * 1024; // bypass Payload error large files
client.UploadFile(fileStream, Path.GetFileName(nombreArchivo));
archivoEnviado = true;
}
}
return archivoEnviado;
}
I have the following logics below that get called once every 20 minutes via a Timer, it serializes the content of the object into a file path, The filePath i see is \hard disk\logs\applicationstate.xml , please note I confirm this is a valid path..
It works most of the time but every now and then I get the System.IO.IOeException on the line this.StreamWriter = new StreamWriter(filePath); with the following stack stack trace:
at System.IO.__Error.WinIOError(Int32 errorCode, String str)\r\n at
System.IO.FileStream..ctor(String path, FileMode mode, FileAccess
access, FileShare share, Int32 bufferSize, Boolean useAsync, String
msgPath)\r\n at System.IO.FileStream..ctor(String path, FileMode
mode, FileAccess access, FileShare share, Int32 bufferSize)\r\n at
System.IO.StreamWriter.CreateFile(String path, Boolean append)\r\n
at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding
encoding, Int32 bufferSize)\r\n at
System.IO.StreamWriter..ctor(String path)\r\n at
Shs.ScanPanel.CA.DataManager.DataManagercr.CopyData(Object data)\r\n
at System.Threading.Timer.ring()\r\n"
When it happens I see \hard disk\logs\applicationstate.xml exists but it has 0 byte.
So my question is, could the StreamWriter cause this 0 byte file to be generated in the first place? I read up on the IOException under StreamWriter on MSDN and it says the following
IOException
path includes an incorrect or invalid syntax for file name, directory name, or volume label syntax.
This confused me, is it because it tries to open a stream writer to a 0 byte file? could this 0 byte generated in the last time this code runs where a null object was being serialized into the file? if so why didn't I see that exception in Visual Studio?
if (filePath != string.Empty)
{
if (this.StateObject == null)
{
this.StateObject = new State();
}
//Do something to my StateObject object
this.StreamWriter = new StreamWriter(filePath);
this.Serializer = new XmlSerializer(typeof(State));
this.Serializer.Serialize(this.StreamWriter, this.StateObject);
}
else
{
if (this.log != null)
{
this.log.Write(LogLevel.Error, this.componentName, "CopyData : Unable to initilize State Object");
}
}
}
else
{
if (this.log != null)
{
this.log.Write(LogLevel.Error, this.componentName, "CopyData : Error while retrieving Current working directory");
}
}
}
catch (Exception ex)
{
if (this.log != null)
{
this.log.Write(ex, this.componentName);
}
}
finally
{
if (this.StreamWriter != null)
{
this.StreamWriter.Close();
}
}
I recommend using this.StreamWriter.Flush() to make sure all the contents are written.
However you exception appears to be complaining that the path is incorrect.
Edit: Opps I missed the WinCE tag
So I wrote up a little program and I confirmed that the line that makes the file to have 0 byte is right at the this.StreamWriter = new StreamWriter(filePath);
But what really boggle my mind is that it successfully wipe out the file so that new data can be serialized into it but yet at the same time it throws exception. I'm thinking this is a lower layer of the StreamWriter api or it could be something with the flash drive.... after all I'm running this program on WINDOW CE