How to monitor windows service text output - c#

For my windows service, I have a procedure that outputs log entries to a text file. That all works well, but I can not see it live. As soon as I open the file to see the log, it stops writing to it, because the service can't write to an open file, I'm assuming.
My question: Is there a way to monitor this text output with something like the console? This solution will only be used for debugging purposes. I don't want a GUI or anything like that--just something simple to watch what my logger is doing.
Right now to write to the text file I'm doing:
RecordDataToLog("Log this");
private void RecordDataToLog(string txtData)
{
using (System.IO.StreamWriter file = new System.IO.StreamWriter(logFileDir, true))
file.WriteLine(txtData);
}
I tried to use Console like this, but it didn't work--no console window showed.
Console.WriteLine("Log this");
Or is there another text editor or text file type that supports writing to an open file?

I opened the file with notepad and Notepad++ and was still able to write to the file with StreamWriter, so it must be the editor you are opening the file with. Notepad doesn't refresh the contents at all. You need to reopen the file. Notepadd++ should prompt you and ask if you want to reload.
PowerShell v3 includes an option on the Get-Content cmdlet to open a file and print new content as it is added, similar to tail on *nix OSes:
Get-Content "C:\path\to\log\file" -Wait

You will reduce your pain in this area significantly by using a logging framework, such as log4net or NLog.
These will allow you to configure multiple output formats in a separate configuration file. I've converted a home-grown logging system to log4net. Took about half a day to do this - and this was a relatively large commercial application.

You can use Notepad++.
If you start it in the command-line by writing
notepad++.exe -ro "MyLogFile.txt"
then it will open the file in read-only mode.

You can use the Get-Content cmdlet from PowerShell to tail your log file

You can use also the "monitor" tool of NotePad++ (it's an icon with an eye).. doing so NotePad will automatically show you the updated file every time it will be modified by your app

Related

How to raise the event while double click on any file

I want to write/capture the event when I double click on my file located in Windows folder. Assume that we have some txt file located in D:\MyTest\Example1.txt
When I double click on the file, the file should not open whereas it should fire an event/trigger/service to execute some tasks.
I tried with FileSystemWatcher in C#. But, when I double click on the file, the file is getting opened.(It should not).
A simple requirement for your better understanding given below.
When you double click on any txt file in Windows, it should invoke a simple batch file (Example: a.bat) to display the today's date.
Conditions: When you double click on the file, the .bat file should run without opening the actual txt file.
FileSystemWatcher monitor specific path for any file add/remove/modification and not for file execution.
There are different solution based on your needs :
The simplest solution is to register your program for own file extension. by double clicking on file your program got executed and you can just log it and do nothing any more or open the requested file using actual program. for example "Notepad.exe 1.txt"
Write a hook module and load it into explorer's process and watch for file execution but the chief drawback of this solution is third party apps or tricks to open a file that make no sense in your program. for example using CMD.exe or PowerShell.exe to open text file because you monitor specific program.
You can inject your hook module into all executables but it is possible to make performance issues.
The beset solution is to write MiniFilter driver to monitor file system but it need to good system, user mode, c++ and driver development knowledge.
It's possible to implement a virtual file system and control everything over it and again it need to driver development but there is good C# ports for existing libraries, the best one for C# is Dokan .Net
Describe the simplest way to implement :
Write simple program without any form like this :
static void Main(string[] args)
{
if (!args.Any())
return;
foreach (string argument in args)
{
if (Path.GetExtension(argument) != "txt")
continue;
if (Path.GetDirectoryName(argument) == #"D:\MyTest\")
{
// Call your service event here
return;
}
Process.Start("Notepad.exe", argument);
}
}
Register your program for own file extension (in your case .txt) using registry configuration. Here is Microsoft documentation and maybe this topic help you.
Now by double clicking on a .txt file your program got executed and path of the file(s) passed to your program as arguments. program check each file and if you want you can call something or notify your service using different mechanisms like Pipes or Messages or etc.
If the file is not match you want the original application called (in my sample code "nodepad.exe") and the file open normal.

Using Excel as log reader. How to write to log file if Excel has it open?

I've come into a position where all the existing scheduled applications write their logs to .CSV files, so that people can open them in Excel. The problem comes when someone opens a log file and just leaves it open. The applications then can't write to their logs, and by rule, they die.
So the options are:
somehow get the users to open the files in Excel in a non-exclusive manner;
somehow be able to write to the log despite the users' rudeness;
write a kinder, gentler log reader (nope, the company runs on Excel and .csv files and they won't change);
???????
Or am I just missing a totally brainless way to deal with this?
Most of the apps are currently VBScript, but I've already managed to convert many of them to C# console apps, so answers in both styles are welcome.
If you set NTFS permissions on the folder containing the CSV files appropriately so that your users only have read access whilst the user your scheduled tasks are running as has full access, then Excel will open the files in Read Only mode.
This will prevent Excel from holding a lock on the files and allow your logging to continue unhindered.
You could potentially make use of a logging framework like Serilog.
When you configure Serilog, you can define multiple outputs (Serilog calls them Sinks). So, for example, you could configure your applications to write to a Windows Event Log as well as a CSV file. Your applications could continue to log to the Event Log even if someone has a CSV file open.
An example configuration could be:
var log = new LoggerConfiguration()
.WriteTo.File("log.csv")
.WriteTo.EventLog("My App")
.CreateLogger();
Then, to write to the log, you simply need:
log.Information("This is a sample log entry");
There are some other elements which need to be set up, but the documentation on their website is great and will get you started.
Serilog is very lightweight and quick to configure so it wouldn't take too much effort to update your applications to use it.
Here is the Serilog homepage: https://github.com/serilog/serilog/wiki
I'd highly recommend it as a logging framework.
(I am not involved in the project - just a big fan having used it multiple times in projects I've worked on).

Opening Word-document (.doc) using C# causes COMException due to File Block Settings

I'm trying to open a really old (binary) Word-file using C#/.NET and Microsoft.Office.Interop.Word. Whenever I try to open this file using the snippet below, it fails with a COMException telling me that "You are attempting to open a file type that is blocked by your File Block settings in the Trust Center."
This also used to happen when opening the same file in MS Word, but after adjusting the settings found in the Trust Center this now works just fine. However, I still cannot open the file using C#. Does anyone know if VS2010 caches these settings, or use its own settings somewhere? I have also tried to create a new project (after fixing the settings in Word) with the same snippet to see if that helped, but it did not.
Word.Application app;
string file = "<filename>";
app = new Word.Application();
try
{
app.Documents.Open(file);
}
catch (COMException e)
{
string s = e.Message;
}
This is implemented with an alternate data stream, supported by the NTFS file system. You access such a stream with the filename:stream syntax. The stream name that stores the info for the file blocking feature is Zone.Identifier:$DATA. It is written by whatever program copied the file, usually a browser.
You can see them with the DIR /R option. The SysInternals' Streams utility permits listing and deleting them. A silly way to get rid of it is copying it to a file system that doesn't support alternate data streams, like a .zip archive or a flash drive and copying it back.
You can look at the content of the stream or edit it with a command like notepad filename:zone.identifier, you'll see this:
[ZoneTransfer]
ZoneId=3
The ZoneId value identifies the origin of the file. Values are -1=unspecified, 0=local machine, 1=intranet, 2=trusted, 3=internet, 4=untrusted. What notepad can do is however not possible in .NET, it explicitly forbids using the : character in file names. The intention is for a human to deal with this, explicitly overriding the file blocking feature. Right-click the file in Explorer, Properties and click the Unblock button. That deletes the stream. Note the Powershell cmdlets mentioned in the first link.

Opening an image file in an executable I created

I just finished this tutorial - Create a Picture Viewer - on the MSDN site, and it all works well according to the tutorial specifications (although I did remove the unnecessary buttons).
At the moment, I can open an image file from within the program, which is fine.
However, I'd like to be able to open an image file from Windows Explorer, and have it open in my Image Viewer. (Using the Open With.. context menu).
I did try and open it via the Open With.. menu, but when the program loaded, the image didn't show up. The program just started up as it normally would.
What code do I need to put in, that allows me to open the program via an image file (if that makes sense)
You can use:
Environment.CommandLine
Which will contain stuff in the format of "..." "...", first being the path of your application, and in your case - second would be the path of the opened-with file.
Then, you can split that to get the second "..." and load the file as you normally do in you application.
You can also check to see whether the arguments of the application contain the path of the opened-with file. I'm not sure about that, but it should be very easy to check: Have an mbox which prints the parameters, then try opening a file with your program and see what shows up. Using the args[0] or args[1] or whatever will probably be easier than splitting Environment.CommandLine...

How to Display the Contents from StreamReader directly on Notepad?

Is there a way to display the contents from memory directly in a Notepad window?
I'm assuming that I understand your question. If the file already exists on the machine you can execute the following:
System.Diagnostics.Process.Start( "notepad.exe", "[PATH]\[FILE].txt");
If not then save the file locally and then run the above code.
Double-click on the file, making sure the association is set to Notepad.
If you want Notepad to show it without saving it to disk, you can open an instance of Notepad, get the handle for the window, then write the text directly into there. You will need to use Windows User APIs to do this.
The easiest way to accomplish this is to save the file and open it in notepad, however there are at least two other ways.
Open Notepad then copy what you want to the clipboard, then using DDE force Notepad to paste. This is bad, because it potentially overwrites what the user may have been doing in the clipboard.
The second way involves getting a window handle to the notepad Edit control, then doing a WM_SETTEXT to the window. This will not, however, work across privilege boundaries (such as for apps that run as administrator, but notepad runs as a normal user). This also involves getting down to Native level and doing P/Invokes. Not exactly an easy method.
Frankly, it's just easiest to save it to a file and load it.
Why do you need notepad to show some contents (which is in memory)?
If you are using winforms, you could put it in a textbox.
Sorry, if I have not understood your question correctly.
I would like to add to MrEdmundo's answer that the Isolated Storage is the right place to store the temporary txt file for Notepad.

Categories