I have created a simple Windows service, following these youtube videos:
https://www.youtube.com/watch?v=cp2aFNtcZfk.
This works, so long as I don't try to do any logging. If I call my logging function:
public static void LogMsg(LogMsgTypes msgType, string msg)
{
string path = AppDomain.CurrentDomain.BaseDirectory;
string logFileName = string.Format("{0}Recalculator{1:yyyyMMdd}.log",path, DateTime.Now);
var file = System.IO.File.AppendText(logFileName);
file.WriteLine(string.Format("{0} {1,-9} : {2}", DateTime.Now.ToString(), msgType, msg));
file.Close();
}
then the service crashes and I get an Unauthorized Access Exception error in the Windows Event Log. I know I should be logging to the Event Log anyway, but I gather I will have to create the source manually first and I would really like to be able to write to a file if possible. On the youtube tutorial I am following, the guy gets no errors at all.
I think the correct answer is probably that I should do it 'right' by creating a source in the Windows Event Log and then writing to there instead of to a custom log file.
For now, I have just installed the service to run under Local System.
Related
As the title suggested, is it possible to print out info for web API? I understand there is the option of logging but I am just trying to look for a simple print. I tried console.writeline() but my WEB API do not have a console.
I publish the API to an IIS server, and I would call the API for various functions through a webpage. However, there is no logging setup yet therefore I am trying to find a quick and easy way to print info such as the value of a variable etc. For instance, I would console.log() when I do a quick troubleshoot on my webpage, how can I achieve this for WEB API?
There are a couple of options.
If you use a typical logging framework like Log4Net or Serilog or similar, you can easily write to files. This is easy to set up and recommended.
If you need it now, and are using windows, you could use the event log to write data to it.
See: https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.eventlog?view=dotnet-plat-ext-6.0
// Create an EventLog instance and assign its source.
EventLog myLog = new EventLog();
myLog.Source = "MySource";
// Write an informational entry to the event log.
myLog.WriteEntry("Writing to event log.");
And look for it in the windows event log.
See this on how to access it.
I just noticed writing to a txtfile would be the easiest for me, if I were to avoid setting up logging, basically I will just call as something below when needed.
private void fakeLogging (string data)
{
string logpath = #"C:\path\to\file.txt";
if (!System.IO.File.Exists(logpath))
{
FileStream fs = System.IO.File.Create(logpath);
fs.Close();
}
System.IO.File.AppendAllText(logpath, DateTime.Now + " " + data + Environment.NewLine);
}
I try to copy the EventLog "Application" to another folder on my PC but always get the error that
"....Could not find a part of the path
'C:\Windows\System32\winevt\Logs\Application.evtx..."
I use the code:
public void collectEventLogsFromSystem(string RequestedlogName,string newFolderPath)
{
string combinedLogToFind = "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Eventlog\\" + RequestedlogName;
string LogEventsPath = (string)Registry.GetValue(combinedLogToFind, "File", null);
if (LogEventsPath != null)
{
System.IO.File.Copy(LogEventsPath, newFolderPath +"\\"+ RequestedlogName, true);
}
}//collectEventLogsFromSystem method
Even if i use explicit folder path it won't work:
System.IO.File.Copy(#"C:\Windows\System32\winevt\Logs\Application.evtx", "c:\\ttt\\Application.evtx", true);
any idea?
I found this answer on StackOverflow which will probably solve your problem. I have a 64 bit machine which exhibited the same behavior. This post by John Rasch solved the issue and explains why it failed.
If you are trying to get the log file while the program is running, the way above will not work. This post Export Event Log (.evtx) without "run as administrator" will allow you to backup the event log, even if you are currently using the event log in your application.
I am trying to use System.Diagnostics.XmlWriterTraceListener to log to a local file. I start by creating a source and adding a new XmlWriterTraceListener to it, like so:
public class Logger
{
const string LOG_ERR_FMT = "<message><![CDATA[{0}]]></message>{2}";
TraceSource tSource = new TraceSource(
"MyApp",
SourceLevels.Verbose | SourceLevels.ActivityTracing
);
public Logger() {
tSource.Listeners.Add(
new XmlWriterTraceListener("C:\\app_path\\app_tracelog.svclog", "LocalListener")
);
}
public static Logger defLogger = new Logger();
public static Logger Default {
get {return defLogger; }
set { if (value != null) defLogger = value; }
}
public void LogError(string msg, string extraXmlData) {
tSource.TraceEvent(TraceEventType.Error, 0, LOG_ERR_FMT, logMsg, extraXmlData);
}
}
I've simplified the log format in the sample above. The actual LogError method takes an Exception object and inserts some xml-serialized data about it into the message, but that's not needed to show what my problem is here.
Anyways, any other part of my app can now log an error to the "app_tracelog.svclog" file with a simple line like, oh say...
Logger.Default.LogError(
"Error parsing response from web service \"someservice.com\".",
"<RequestBody><![CDATA[" + responseBody + "]]></RequestBody>"
);
All is well until I open up app_tracelog.svclog. First of all, when I try to open it with Microsoft Service Trace Viewer, that program behaves like it's empty, and gives me a message of "There is no trace loaded from the file."
Second, I open the file with good old Notepad++ and find that my app DID INDEED log to it. I select all and tell XmlTools to pretty it up, and the tool tells me it can't do it because there's errors in the XML.
So, I start formatting it manually. All goes well at first, until I get to the actual application message that I logged. Here, I find that this STUPID ##$ class has screwed up all my nested XML by replacing brackets and such with encoded XML/HTML entities!
All my '<'s have become "<", All my '>'s have become ">", etc... So the log message that SHOULD have looked like:
<message><![CDATA[Error parsing response from web service "someservice.com".]]></message><RequestBody...
Now looks like:
<message><![CDATA[Error parsing response from web service "someservice.com".]]></message><RequestBody...
So the big question is: How can I FORCE XmlWriterTraceListener to stop trashing my message when I log? I know what I'm doing when I put in special XML characters, and it thinks it knows better! --OR- Is there another listener class that will log to a local XML file the way I want?
I'm trying to get my .Net Windows Service to right to a custom event log. I'm using EventLogInstaller to create the event log and source when the application is installed. I read here that it takes a while for Windows to register the source so they reccomend you restart the application before trying to write to the log.
As this is a Windows Service I didn't want to have to force a computer restart or get the user to manually start the service up, so I use this code to wait for the log to exist and then start the service automatically.
while (!(EventLog.Exists("ManageIT") || EventLog.SourceExists("ManageIT Client Service")))
{
Thread.Sleep(1000);
}
System.ServiceProcess.ServiceController controller = new System.ServiceProcess.ServiceController("ManageIT.Client.Service");
controller.Start();
My problem is that events from the service are still written to the Application Log and although I can see my custom log in the Registry Editor it does not show up in the Windows 7 Event Viewer.
Any help will be much appreciated.
By default when a service is installed, the source gets associated with the Application Log.
If we change this association at a later point, the system needs a restart.
We can however prevent the association of the service with the application log, by setting autolog property to false in the service class (class which inherits from servicebase) constructor.
http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicebase.autolog.aspx
Try this snippet:
edit - caveat: if the user running the code does not have administrator rights, this will throw an exception. Since this is the case (and if the user will not have these rights) best practices should be to assume the log exists, and simply write to it. see: The source was not found, but some or all event logs could not be searched
if (!EventLog.SourceExists("MyApplicationEventLog"))
{
EventSourceCreationData eventSourceData = new EventSourceCreationData("MyApplicationEventLog", "MyApplicationEventLog");
EventLog.CreateEventSource(eventSourceData);
}
using (EventLog myLogger = new EventLog("MyApplicationEventLog", ".", "MyApplicationEventLog"))
{
myLogger.WriteEntry("Error message", EventLogEntryType.Error);
myLogger.WriteEntry("Info message", EventLogEntryType.Information);
}
It sounds like you are writing to the event log like this:
EventLog.WriteEntry("Source", "Message");
This will write to the application log.
If you use the code in simons post with the creation of myLogger, you can specify the name of the Log.
I did something like this:
var logName = EventLog.LogNameFromSourceName("MyApp", Environment.MachineName);
//delete the source if it associated with the wrong Log
if (!string.IsNullOrEmpty(logName) & logName != "MyLog")
{
EventLog.DeleteEventSource("MyApp", Environment.MachineName);
}
if (!EventLog.SourceExists("MyApp"))
{
EventLog.CreateEventSource("MyApp", "MyLog");
}
I would like to print some traces during the requests processing.
But when I make Console.WriteLine("something") in this environment, nothing is shown.
What is missing, what do I need to do in order to use console to print these traces?
Use Debug.Write() and and watch the results come out through the debugger output window in the IDE.
Alternatively, use the ASP.NET trace feature, which is quite powerful. Once you have enabled tracing, you can navigate to the trace.axd page in your web app's root directory. This page will show the trace messages for your app.
In addition to the methods already mentioned you can simply write to a log file:
File.AppendAllText(#"c:\log.txt", #"Debug Message Here!" + Environment.NewLine);
Of course you could use Server.MapPath to write the file in your web directory.
I know this is late, but you can write to your Javascript console from your C# script using the following class
public static class Javascript
{
static string scriptTag = "<script type=\"\" language=\"\">{0}</script>";
public static void ConsoleLog(string message)
{
string function = "console.log('{0}');";
string log = string.Format(GenerateCodeFromFunction(function), message);
HttpContext.Current.Response.Write(log);
}
public static void Alert(string message)
{
string function = "alert('{0}');";
string log = string.Format(GenerateCodeFromFunction(function), message);
HttpContext.Current.Response.Write(log);
}
static string GenerateCodeFromFunction(string function)
{
return string.Format(scriptTag, function);
}
}
That way you can see your log messages in real time as you click through the site, just as you would in js.
You can use Response.Write to write output to your page for debugging, or use alert in javascript, or even write to a log file. There are many ways to get debugging output. There's also a log4net for .Net that you can use (similar to log4j)
Given that it's an ASP.NET application, I would do:
Page.Trace.Write ("Something here");
Then enable trace either for the page or the application and then just go to ~/Trace.axd to see the results (they can also be at the end of the page output, depending on the configuration option that you choose).
Where are you looking for the output?
Console.WriteLine() writes to the command line - not to the webpage. Either use Response.Write() to write onto the webpage or start up your application in the Visual Studio debugger to look at the command line output.