One service appends to and another one truncates a file - c#

I have a service that controls an RS-232 device and logs actions to a file. I am to write another service which will read the log file line by line and run some queries on a database then delete all the logs.
My concern is about read and write conflicts on the file. For example, the logger service open the file to append a new line at the same time the replicator service opens the file and write "" so truncate its content.
Any suggestions to clarify my situation?

How about modifying the "read" service to rename the file first (putting a "_" in front of it is what I usually do). And then it can delete it when done. The write service should create the log file if it does not exist. This way you should have zero data loss.

If your are not tied to use a file, the use case would suggest a message queue for handing over your log messages.

Related

Add log to my application that can write from different EXE files at same time

i have Command Line application that received file from user (DOC, PDF), this file is locate on the same machine and my application copy this file to specific folder and return 0 is this operation passed and 1 otherwise.
This command line exe file can open several times concurrency and there is no problem with it.
Now i want to add to my application a Log that will locate in the application folder and this Log will write each file name and if the operation passed or failed.
Now i wonder how to achieve that in case i have several open processes and how to avoid situation that 2 exe files try to write to my log at the same time.
can i using lock in such case although i am using several exe files in the same time ?
You can create named system mutex to control access to log file
// Set this variable to false if you do not want to request
// initial ownership of the named mutex.
bool requestInitialOwnership = true;
bool mutexWasCreated;
// Request initial ownership of the named mutex by passing
// true for the first parameter. Only one system object named
// "MyMutex" can exist; the local Mutex object represents
// this system object. If "MyMutex" is created by this call,
// then mutexWasCreated contains true; otherwise, it contains
// false.
Mutex m = new Mutex(requestInitialOwnership, "MyMutex", out mutexWasCreated);
To ensure there are named mutex you can use Mutex.TryOpenExisting("MyMutex", resultMutex) and if it exists you can Wait, Log and Release it
resultMutex.WaitOne();
Log("success");
resultMutex.ReleaseMutex();
More info availible in MSDN: http://msdn.microsoft.com/en-us/library/System.Threading.Mutex(v=vs.110).aspx
Do not make a log file. Use ETW and log to the windows mechanisms. It is not like the event log is new (it is there for a long time) and ETW is now fully supported via nuget packages.
ETW also is kernel based.
If you don't care too much about the log's cleanliness, you can open the log file in a way that allows multiple processes to write to it:
private static Stream CreateFile(string path, bool checkHost)
{
var mode = FileMode.Append;
return new FileStream(path, mode, FileAccess.Write, FileShare.ReadWrite, 4096, FileOptions.SequentialScan, Path.GetFileName(path), false, false, checkHost);
}
The drawback is that if two processes write to the file concurrently then you'll get a mess that will look like this:
2014-11-26 11:32:93 Suc2014-11-26 11:32:93 Failed: file "Some.doc"
seeded: file "Other.doc"
I.e. the processes race each other and you end up with intermingled log entries. If you don't have too many processes writing to the same log file, and if each process writes infrequently, you should have very few collisions like this.
There are several ways around it. One is to open the file in read-only mode in each process, and wait on other processes until the file is available; the crudest way to do this is to try-catch a File.AppendAllText() in a while-loop until you succeed. There are other options listed in questions like this one.
Another alternative is to write log to multiple files, or to something other than file, e.g. to a DB.
One of the cleanest and SOA based approach would be to a use a separate logging service which your process ( or processes) will call to log information. Log4Net provides a mechanism for both client and server to post and consume messages respectively. Look at https://log4netremotelogging.codeplex.com/ for further details.

How to generate the Log File at End of the program Execution

I have Developed a console application (using C# and oracle) which will read some data from the Database generate a Excel sheet and send the mail to respective Address. In my application I generate a log file and put log in every steps. When my application start running it is creating the Log file and start writing the Log. And my Log file Name is Like:
logFileName = "XYZ"+ "_" + System.DateTime.Today.Date.Day.ToString() + "." + System.DateTime.Today.Date.Month.ToString() + "." + System.DateTime.Today.Date.Year.ToString() + "" + System.DateTime.Now.Hour.ToString()+ ".txt";
This file is generate onetime in a hour and every Execution it is just override the Data. But now I want to generate separate log file for Each Execution of program. If I am trying to add in file name (min,sec) and start writing log file every sec it is generating a new log file in middle of program execution. So I want to Write Total log in End of the program execution or any error encounter to terminate the program. So where should i store the initial log data and finally i need to write it.
I know there are some relevant post but i did not find the relevant to my concern. Please help me out to find the solution.
You can do logging by hand, but I would recommend a logging library like NLOG, which supports your scenario out of the box and is well tested.
http://nlog-project.org/
Add the hour to the end of the file name. That will create the new file.
You can also try File.Create:
Creating an empty file in C#
using (File.Create(filename)) ;
EDIT: You can also just use a stringbuilder to build up the log data, then write to a file at the end.
I would use logging tool like log4net and do the configuration to create log file on each execution
check log4net one file per run and Log4Net basics with a Console Application (c#)

how to refresh/reload app.config file before a function or method executes

I have a windows service that send out emails at a particular hour of the a particular day. The and hour on when the email should be send out along with information like the SMTP server to use are stored in the app.config file.
When i open the app.config file in notepad and change those values, my service does not pick the changes even when i call ConfigurationManager.RefreshSection("configuration");
How can i make sure that every time my email sending function executes, it must first query the app.config for the latest changes/values. Must i restart the service first?
Instead of modifying the app.config, try modifying the appname.exe.config file with this refresh section.
Refer this. Hope it helps. Thanks

Delete Nlog log file after it was successfully emailed

I want to delete my Nlog logfile between each application run only if it was emailed to me successfully otherwise it should keep adding to the logfile. I am using Outlook to email the file. I don't want to use Smtp since some networks block port 25 and then it does not get emailed to me.
The problem is when I try to delete the logfile with File.Delete(logfile) is says that the the file is in use by aonther process. How do I unlock or close the file in order for me to email it using Outlook (and then re-open it fo further logging)?
I was thinking of making a copy of the logfile and emailing that, but I'm not sure if its the best way to do it.
Thx for any ideas.
It's not Outlook which prevents the deletion of the file - your application is still running and logging to that file is still active, hence it is the Nlog part of your application which prevents the deletion.
Tell nlog to use a different log file, or not to log at all (you may resume logging later on).
By default nlog doesn't keep files open (file target, keepFileOpen). So either you try to delete file when your application is writing data, or outlook still using the file.
First, you may want to send it via outlook a copy of the log file. So you'd be sure that original file is not locked by an external process.
Second, you'll be able to reconfigure current file target to write to another file (log(n+1).txt or something. There are some hints about programmatic configuration at Add, enable and disable NLog loggers programmatically). So you'll be sure that application isn't logging to the file.
Then you'll be able to remove it, I think.
Option 1 :
if(chkLogger.Checked){
NLog.Config.SimpleConfigurator.ConfigureForFileLogging("Logfile.log",NLog.LogLevel.Trace);
}
else
{
NLog.Config.SimpleConfigurator.ConfigureForFileLogging("Logfile.log", NLog.LogLevel.Off);
}
Option 2 : LogManager.DisableLogging() and LogManager.EnableLogging()
from website Stopping-Starting-NLog-on-runtime

ASP.Net: Writing chunks of file..HTTP File upload with resume

Please refer to question: Resume in upload file control
Now to find a solution for the above question, I want to work on it and develop a user control which can resume a HTTP File Upload process.
For this, I'm going to create a temporary file on server until the upload is complete. Once the uploading is done completely then will just save it to the desired location.
The procedure I have thought of is:
Create a temporary file with a unique name (may be GUID) on the server.
Read a chunk of file and append it to this temp file on the server.
Continue step 1 to 3 until EOF is reached.
Now if the connection is lost or user clicks on pause button, the writing of file is stopped and the temporary file is not deleted.
Clicking on resume again or uploading the same file again will check on the server if the file exists and user whether to resume or to overwrite. (Not sure how to check if it's the same file. Also, how to step sending the chunks from client to server.)
Clicking on resume will start from where it is required to be uploaded and will append that to the file on the server. (Again not sure how to do this.)
Questions:
Are these steps correct to achieve the goal? Or need some modifications?
I'm not sure how to implement all these steps. :-( Need ideas, links...
Any help appreciated...
What you are trying is not easy, but it is doable. Follow these guidelines:
Write 2 functions on the client side using ajax:
getUploadedPortionFromServer(filename) - This will ask the server if the file exists, and it should get an xml response from the server with the following info:
boolean(exist/not exist), size(bytes), md5(string)
The function will also run an md5 on the same size it got from the server on the local file,
If the md5 is the same, you can continue sending from the point it was stopped,
elseif not the same or size == 0, start over.
uploadFromBytes(x) - Will depend on the 1st function.
On the server you have to write matching functions, which will check the needed stuff, and send the response via XML to the client.
In order to have distinct filenames, you should use some sort of user tagging.
Are users logged in to your server? if so, use a hash of thier username appended to the filename, this will help you distinguish between the files.
If not, use a cookie.

Categories

Resources