So basically I write a windows service that scans any given directory for a zip file and then uploads it to an FTP server. I added a tracing method that suppose to write into a txt file and keep a log of everything. The problems comes when I release the service into windows I get a error message in the Event Viewer( I added a LogEvent using EventLog class) that returns
System.IO.IOException: The process cannot access the file
'C:\Windows\system32\traceLog.txt' because it is being used by another
process.
The code that does the tracing is the following
private void EscribirTrace(string mensaje)
{
if (Tracing)
{
try
{
using (FileStream archivo2 = new FileStream(string.Format("{0}\\traceLog.txt", Environment.CurrentDirectory), FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
{
mensaje = string.Format("{0} - {1} \r\n", DateTime.Now, mensaje);
StreamWriter writer = new StreamWriter(archivo2);
writer.WriteLine(mensaje);
writer.Flush();
writer.Dispose();
}
}
catch (Exception ex)
{
LogEvent("Error en escribir tracing", ex);
}
}
}
Any ideas would be appreciated
Edit So after some research I figure that that system32 is not the best place for the file. My intention was to have that log file at the path were the service was installed. After some research I replaced the
Enviroment.CurrentDirectory
for
Path.GetFullPath(System.Reflection.Assembly.GetExecutingAssembly().Location).Replace(
Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().Location)
Formated into a string.
The rest just worked pretty well.
Thank you for the responses !
Its because your using statement has not released the file yet. You have it open in the steam so you can't write to it until you close your stream.
If you want to simply write text to a file just use:
File.WriteAllText(FILEPATH, TEXTDATA);
That call will open the file, write to it, and then close it.
if it throws on the using ...make sure all other streams on the file are closed properly ...
if it throws on the streamwriter constructor
change the using to be the stream writer with the new filestream in the constructor
/Windows/system32 requires admin access. Your application probably isn't running with the proper privileges. You should try writing the log to a different (less restrictive) location. If you need to write to system32 ensure that your service is running with admin privileges.
Related
try
{
string directory = #"D:/user/user.txt";
FileStream FS = new FileStream(directory, FileMode.Append);
StreamWriter SW = new StreamWriter(FS);
string register;
register = $"{generateID()};{txtfirstName.Text};{txtLastName.Text};{txtUser.Text};{txtEmail.Text};{txtPersonalID.Text}";
SW.WriteLine(register);
SW.Close();
FS.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
I run this code in c# windows forms .NET framework and constanly i get the same message. I am in university and i am pretty new in programming so i have no idea what could be wrong. What are your thoughs? Any idea?
Your question is a little confusing. First of all, you shouldn't name your variable directory because in the end it is a file name and used as such.
(I'll ignore the difference between the image "D:\user\user.txt" and the code "D.:\user\user.txt" and will assume you actually ment and did use the first).
Most likely, the D:\User directory does not exist and the FileStream class will not create it for you. It will simply assume that all (sub) directories up to the specified file name exist and fail otherwise.
So make sure that the directory exists, either outside your application, or like so:
string fileName = #"D:\user\user.txt";
string directory = Path.GetDirectoryName(fileName);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
FileStream FS = new FileStream(fileName, FileMode.Append);
// ... rest of code
You are running the application on a windows machine. In windows, the file path needs to be given like
string directory = #"D:\user\user.txt";
Also, make sure this file path exists and the application you are running has permission to write on this file.
If you are running a test application then give permission as FullControl to Everyone. AS below
If you are sure about the path, check if you run VS as an administrator
I need some help.
My application works with Outlook files.
For example, I have a MSG format file is stored at my PC.
Let's imagine that I haven't got any running Outlook processes on my PC.
var myProcess = new Process { ProcessInfo = new ProcessStartInfo {FileName = targetPath}}
where targetPath is full path to my file.
Then I start process:
myProcess.Start();
At this moment Outlook runs at OS. Looking into TaskManager I see this process, and it's unique PID.
And there is my first question: why this PID is different from myProcess.Id ?
Moving on. I need to check is my file still opening at Outlook. I resolve this issue by trying to open this file in my application for a certain time.
var iterations = 3600;
while (iterations > 0 ) {
Thread.Sleep(1000);
var fInfo = new FileInfo(targetPath);
FileStream stream = null;
try {
stream = fInfo.Open(FileMode.Open, FileAccess.Read | FileAccess.Write, FileShare.None);
} catch {
//I expect if exception occurs then file is not lock and can send it to server.
}
finally{
if(stream != null)
stream.Close();
}
iteration--;
}
I think, while my MSG file is using by Outlook, I my application cant open file. In that way I decide that cant save my file and send it to server. But! If I add attachment but NOT close this e-mail at Outlook, my application CAN open this file. And I don't understand why Outlook change Read/Write attribute of this file? And how I can solve this issue?
Unfortunately, I haven't any idea why it happens and how to make it work.
I was looking on any info at web that can help to solve my issue, but has no result :(
Thank you for your time.
Firstly, Outlook is a singleton - if you start a new instance of outlook.exe, it will simply switch control to the already running instance and exit.
Outlook internally caches / references open MSG files, there is really northing you can do about that.
Here is the code I have that writes to a couple of files:
StreamWriter writer = new StreamWriter(#"C:\TotalStock\data\points\" + stockName.ToUpper() + ".txt");
for(int i = 0; i < lines; i++)
{
writer.WriteLine(lineData[i]);
postGui.Send((object state) =>
{
progressBar2.PerformStep();
}, null);
}
writer.Close();
When I delete the text files and run the code there is no issue, but then when I close the application and run it once more the program gives me the following error. What is it that causes this error and what can I do to stop it?
Error:
An unhandled exception of type 'System.IO.IOException' occurred in mscorlib.dll
Additional information: The process cannot access the file 'C:\TotalStock\data\points\IBM.txt' because it is being used by another process
As marc_s pointed out, the error occurs because the file you are trying to edit is opened by another application. If you are certain that you don't have the file opened in any other editor/viewer, the problem may the program itself.
If several instances of the same code run concurrently and require access to the same file, say in a multithread environement.
Does another component in your application read from the text file while you are trying to write to the file?
Does your application hang, and the second instance requires the same file?
Do you run the same tests each time?
Probably the problem is that you open the file but do not close it when you exit the program. i see you are using StreamWriter to write the data to the file.
might by you get an exception and therefor does not close the file. when playing with files you should always do:
try
{
// Your code with files
}
catch
{
}
finally
{
writer.Close();
}
other reasons might be that you are using some other File/Stream/etc. please be sure that you close all the members that need to be closed before close the program.
please share all your code if you want us to check if you forgot something else
as Sayse Is saying another way to make sure you close your writers is a using statement:
using(StreamWriter writer = new StreamWriter(#"C:\TotalStock\data\points\" + stockName.ToUpper() + ".txt");)
{
// Your code of playing with files
}
I face weird problem with IOException on different servers. Here is my story:
I have win server (C#) that monitors folder for file changes. Also, a FTP server (WinSSHD) is pointed on same folder. When someone uploads a file WinService checks is write complete or not. If file is uploaded WinService renames it via File.Move method.
Is write complete check is made by File.Open method. Like this:
public static bool IsWriteComplete(string filePath)
{
bool isWriteComplete;
FileStream stream = null;
try
{
stream = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite|FileShare.Delete);
isWriteComplete = true;
}
catch (IOException)
{
isWriteComplete = false;
}
catch (Exception ex)
{
isWriteComplete = false;
}
finally
{
if (stream != null) { stream.Close(); }
}
return isWriteComplete;
}
For some reason on one server it works perfectly (Win2003SP2) and on another one (Win2003SP1) is not working at all. The IsWriteComplete method says True, WinServer tries to move file and dies by IOException later. I haven't found any references regarding such issue.
To fix the issue I replaced File.Open by File.Move.
Before:
stream = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite|FileShare.Delete);
After:
File.Move(filePath, filePath);
And now it works on second server (Win2003SP1) and doesn't work on first one (Win2003SP2).
Does anybody know why it works as such?
When you use File.Open you have a "race condition", even if you use FileShare.None - after you close the file, another thread/process can sneak in and lock the file (open it) before you call File.Move. This other process might not be the FTP server, but could be something you are not even aware of, such as a virus checker. Thus you should use File.Move instead of File.Open, and catch the IOException if the File.Move fails, and then retry, until it succeeds.
When you use FileShare.ReadWrite|FileShare.Delete, you allow other processes to read, write or delete the file while you're opening it. On the other side, you can open the file while others also access it. So, try FileShare.None to open the file exclusively, which should fail as long as the file is in use by the FTP server.
Also, you should use FileAccess.ReadWrite to make sure that you have full access to the file. You do not know how the FTP server locks the file, maybe it allows other processes to open the file in read-mode and declines write mode while the upload is still in process. So, FileAccess.ReadWrite is better.
MSDN reference: http://msdn.microsoft.com/en-us/library/system.io.fileshare.aspx and http://msdn.microsoft.com/en-us/library/system.io.fileaccess.aspx
About your code:
catch (IOException)
{
isWriteComplete = false;
}
catch (Exception ex)
{
isWriteComplete = false;
}
The catch block for IOException is not neccessary if you also catch Exception...
Alternatively, you can check in other way then open method.
FileInfo fileInfo = new FileInfo(filePath);
bool isNormal = ((fileInfo.Attributes & FileAttributes.Normal) == FileAttributes.Normal);
//or
bool isReadOnly = ((fileInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly);
You can find the method in either way in order to understand whether file is available or not. And you can continue based upon the status.
Please let me know if you are looking for some other things.
Found the root cause of the behavior.
There was different FTP service installed: Techia. For some reason Tectia doesn't set write lock on uploading files. That's why File.Open(filePath, FileAccess.Write) doesn't throw IOException.
I am struggling with this for some time now. I can not access a file after I call File.Copy method. Here is what I tried:
File.Copy(sourceFile, destinationFile, true);
FileStream fs = File.Open(destinationFile, FileMode.Open);
I am getting UnauthorizedAccessException on the second line. It says: Access to the path ... is denied. I have also tried suggestion stated here but that didn't work.
Any help is appreciated.
EDIT: Here is what I found out. If I do this:
File.Copy(sourceFile, destinationFile, true);
FileStream fs = File.Open(destinationFile, FileMode.Open, FileAccess.Read);
It doesn't throw exception. The file I am trying to access is read only. So, I tried to remove read only attribute like this:
File.Copy(sourceFile, destinationFile, true);
FileInfo fileInfo = new FileInfo(destinationFile);
fileInfo.IsReadOnly = false;
FileStream fs = File.Open(destinationFile, FileMode.Open, FileAccess.ReadWrite);
And I get the same exception as before. By the way, I checked if I can open file manually and edit it, and I can. Of course, when I uncheck read only check box. I have also checked file attributes in windows explorer while debugging, right after the third line, and the file is no longer read only. Having all that in checked, I don't understand why is the exception being thrown on the fourth line.
Are you sure it's ONLY files copied using File.Copy that you can't open, and not every file in the target folder? And is this a regular NTFS folder, or network share?
If you are running an antivirus or security software, try disabling it. After a file is created they will often open a file to scan it.
Update
According to http://msdn.microsoft.com/en-us/library/b9skfh7s.aspx - UnauthorizedAccessException thrown by File.Open will not give the message 'Access to the path... is denied'. (edit: I can't see that message for File.Copy either, so this might be wrong)
I suspect it is your File.Copy that fails with that exception, and you don't have rights to read the source file, or write the target file. You're probably looking at the highlighted source code line, which shows the next line to be exectued.
So - maybe your copy fails, not the File.Open ?
Try this!
private bool CheckFileHasCopied(string FilePath)
{
try
{
if (File.Exists(FilePath))
{
using (File.OpenRead(FilePath))
{
return true;
}
}
else
{
return false;
}
}
catch (Exception)
{
Thread.Sleep(2000);
return CheckFileHasCopied(FilePath);
}
}
if (CheckFileHasCopied(destinationFile)) { File.Delete(sourceFile); }