Event logger in Windows 10 Universal Apps - c#

I am trying to create an event log for a Windows Universal Application.
Earlier we had System.Diagnostics EventLog to log events, but I could not find anything similar on the Windows 10 Universal Apps platform.
Is it possible to create logs for Windows 10 and can these logs be written to a file for accessing it later?
I searched a lot, but could not find anything.

FileLoggingSession
Since Windows 8.1 there are FileLoggingSession and LoggingChannel classes in the Windows.Foundation.Diagnostics namespace, which can perform logging to files when configured to do so. You can read more in the official documentation.
Initialization, usage and retrieving the log file can be done like in the following snippet, of course you need to create interfaces, singletons etc. to make it usable:
// Initialization
FileLoggingSession fileLoggingSession = new FileLoggingSession("session");
var loggingChannel = new LoggingChannel("channel");
fileLoggingSession.AddLoggingChannel(loggingChannel);
// Log messages
loggingChannel.LogMessage("error message", LoggingLevel.Error);
// When file is needed
var file = await fileLoggingSession.CloseAndSaveToFileAsync();
// Do anything with file
LoggingSession
Just as FileLoggingSession writes logs to a file but the main difference is that FileLoggingSession writes logs immediately to the file, and LoggingSession does not, and you need to manually request writing the logs to a file with the SaveToFileAsync method. From the documentation:
The FileLoggingSession class sends logged messages to disk files as they are logged. The FileLoggingSession class uses sequential logging, which means that all messages are sent to a disk file, and a sequential history of messages is retained. This is distinct from the LoggingSession class, which sends logged messages to disk on-demand, and this happens when there's a problem and the immediate history of in-memory messages is needed for analysis.
MetroLog
You have another alternatives if you do not wan't to use FileLoggingSession or LoggingSession classes. One good solution is MetroLog which has a FileStreamingTarget target that makes it very simple to log in a Windows/Phone app.
You create the logger when you need it, for example in a page:
public sealed partial class LogSamplePage : Win8Sample.Common.LayoutAwarePage
{
private ILogger Log = LogManagerFactory.DefaultLogManager.GetLogger<LogSamplePage>();
}
Then you can use it in the page like this:
// flat strings...
if (this.Log.IsInfoEnabled)
this.Log.Info("I've been navigated to.");
// formatting...
if (this.Log.IsDebugEnabled)
this.Log.Debug("I can also format {0}.", "strings");
// errors...
try
{
this.DoMagic();
}
catch(Exception ex)
{
if (this.Log.IsWarnEnabled)
this.Log.Warn("You can also pass in exceptions.", ex);
}
MetroEventSource
The second solution is this logging sample on MSDN sample gallery by Can Bilgin where you have the MetroEventSource class. You can log messages for example an error like this:
MetroEventSource.Log.Error("Here is the error message");
If you use this logger don't forget to initialize it on application run, as described in the sample project.

Related

How to send log to Cloud Watch in C# application

I want to be able to send application logs to Cloud Watch Log. and I got to know that there is a Cloud Watch Agent service that runs in the background and reads logs from log file and send only the delta (extra logs) to Cloud Watch Log. All this makes sense to me. Then I got to know about NLog a C# logging framework, and wrote below POC to send logs.
static void Main(string[] args)
{
ConfigureNLog();
var logger = NLog.LogManager.GetCurrentClassLogger();
logger.Info("Hello World");
logger.Log(LogLevel.Info, "Sample informational message");
}
static void ConfigureNLog()
{
var accessKey = ConfigurationManager.AppSettings.Get("AWSAccessKey");
var secretKey = ConfigurationManager.AppSettings.Get("AWSSecretKey");
var config = new LoggingConfiguration();
var awsTarget = new AWSTarget()
{
LogGroup = "NLog.ProgrammaticConfigurationExample",
Region = "us-east-1",
Credentials = new BasicAWSCredentials(accessKey, secretKey)
};
config.AddTarget("aws", awsTarget);
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, awsTarget));
LogManager.Configuration = config;
}
Now when I run above code, I am able to send log to Cloud Watch. But I am confused now, where is the significance of Cloud Watch Agent?
Since I am directly sending log data, does that mean I don't need Cloud Watch Agent in my scenario?
In case I want to use Cloud Watch Agent then I need to use FILE as a target for logs by NLog and then tell Cloud Watch Agent to send that log file to Cloud Watch Log??
Is my understanding correct? Please help me in understanding the flow.
Is below flow correct?
NLog write log to File -> Cloud Agent read log from there -> Send log
to Cloud Watch
Question: How to use Cloud Watch Agent in above POC to send data via NLog?
Cloud Watch Agent runs on your server and can watch logs files that are produced. These log files can be anything, IIS Logs, Time Logs, Event Log, Etc. When the log file is updated, CWA will grab the updates and send to Cloud Watch. This is the generic behavior of the CWA and is great for Event Logs and OS logging.
By modifying the AWS.EC2.Windows.CloudWatch.json CWA json file, you can configure it to watch log files for certain formats and send changes to CW outside the standard/example ones it does by default. You can update the json to your NLog entry layout format and have it watch for that specific format in the file. CW Does have a delay sending.
Now you have Nlog which writes log files. You can have NLog send the log entries to a file and have the Cloud Watch Agent watch that file, pick up the change and send it or you can have NLog send the entries directly to CW. Since you are writing directly to CW through a NLog target, you don't need the Cloud Agent for your NLog files. I suggest keeping CWA for other log files like IIS or event logs.
I guess it is a matter a preference on how you do it. I think NLog Targets with layouts is easier than dealing with the CloudWatch json file to try and match the log format. I only use CWA to send log files I have no control over and use a NLog Target to send my NLog entries.
I can post an example CWA json snippet for a 3rd party log file I monitor with CWA if you need an example.
When an application just have to write to a file, then it lives a very simple life with few problems.
When an application suddenly have to handle network traffic (with timeouts, disconnects, retries, connectivity, latency, etc.) then it suddenly will have issues with things queuing up, taking memory, using sockets, causing garbage collections, stalls, etc. (And loosing all pending logevents on crash)
Depending on the lifetime of your application and the critically of your applications, then it can be useful to give it a simple life. And let a friend like Cloud Watch Agent worry about the network-stuff.
See also https://github.com/NLog/NLog.Extensions.Logging/wiki/NLog-cloud-logging-with-Azure-function-or-AWS-lambda

When is a Kofax Workflow Agent run?

When are workflow agents actually called?
I've installed my own workflow agent (this one) and write to a log on the second line in ProcessWorkflow (the first one being the log4net XmlConfigurator.Configure call with a newly created FileInfo instance.
The log is always written after the KTM Server module. This WOULD make sense, because I read a configuration which prompts the WFA to do something with the workflow data. But after the KTM Validation module (where the WFA is also configured to do something) the log is not written.
Is there an explanation, why I don't see any log entries? I've checked the kofax logs too, but I found no evidence there.
The exact code snippet looks like this:
public void ProcessWorkflow(ref IACWorkflowData workflowData)
{
XmlConfigurator.Configure(new FileInfo(#"C:\Program Files (x86)\Kofax\CaptureSS\ServLib\Configuration Files\log4net.config"));
log.Info("Workflow Agent started ...");
// rest of the code
So, since I kind of figured out how to use Workflow Agents, I decided to answer this question for future reference.
A Workflow Agent is being run every time a module has been executed. IIRC this includes viewing the properties with Batch Manager. The Workflow Agent will be called on the site where the module has been executed. So if you execute your automatic modules (i.e. PDF Generator, Export) on a server and Scan and Validation on client sites, the Workflow Agent will be executed on the server or the client station which executed the module respectively.
I actually forgot what didn't work in my original question, but I also ran into problems because I didn't register the DLL using RegAsm.exe. See my other Kofax-related question for more information about this: How to correctly install Workflow Agents in Kofax?
You can also use this in your code so that it only runs the logic when you want it to:
if (workflowData.CurrentModule.Name != "Scan" || workflowData.get_NextState().Name != "Ready")
{
return;
}

Converting Microsoft EWS StreamingNotification Example to a service

I've been working to try and convert Microsoft's EWS Streaming Notification Example to a service
( MS source http://www.microsoft.com/en-us/download/details.aspx?id=27154).
I tested it as a console app. I then used a generic service template and got it to the point it would compile, install, and start. It stops after about 10 seconds with the ubiquitous "the service on local computer started and then stopped."
So I went back in and upgraded to C# 2013 express and used NLog to put a bunch of log trace commands to so I could see where it was when it exited.
The last place I can find it is in the example code, SynchronizationChanges function,
public static void SynchronizeChanges(FolderId folderId)
{
logger.Trace("Entering SynchronizeChanges");
bool moreChangesAvailable;
do
{
logger.Trace("Synchronizing changes...");
//Console.WriteLine("Synchronizing changes...");
// Get all changes since the last call. The synchronization cookie is stored in the
// _SynchronizationState field.
// Only the the ids are requested. Additional properties should be fetched via GetItem
//calls.
logger.Trace("Getting changes into var changes.");
var changes = _ExchangeService.SyncFolderItems(folderId, PropertySet.IdOnly, null, 512,
SyncFolderItemsScope.NormalItems,
_SynchronizationState);
// Update the synchronization cookie
logger.Trace("Updating _SynchronizationState");
the log file shows the trace message ""Getting changes into var changes." but not the "Updating _SynchronizationState" message.
so it never gets past var changes = _ExchangeService.SyncFolderItems
I cannot for the life figure out why its just exiting. There are many examples of EWS streaming notifications. I have 3 that compile and run just fine but nobody as far as I can tell has posted an example of it done as a service.
If you don't see the "Updating..." message it's likely the sync threw an exception. Wrap it in a try/catch.
OK, so now that I see the error, this looks like your garden-variety permissions problem. When you ran this as a console app, you likely presented the default credentials to Exchange, which were for your login ID. For a Windows service, if you're running the service with one of the built-in accounts (e.g. Local System), your default credentials will not have access to Exchange.
To rectify, either (1) run the service under the account you did the console app with, or (2) add those credentials to the Exchange Service object.

C# Windows Service Textwriter

I've created a standard windows service that uses the LocalSystem account. For the log files I use textwriter to write to a specified file within C:\Users\useraccount directory. The problem is, when running as a service under LocalSystem, it doesn't want to create or write to the file at all.
string dir = #"C:\Users\useraccount\log.txt";
StreamWriter sw = File.AppendText(dir);
As you can see, the directory is hardcoded in so there isn't any base directory conflicts seeing as LocalSystem would start in System32 or something of that nature. The permissions on the folder lets the System account access it fully (windows 7) so why am I not able to create/write to that file?
Thanks for any input!
Edit:
Apparently the logging program thread is running as LocalSystem as well, when I really need it to be running as a standard user. So how do I execute a threaded process from the service to run under the local user account instead of under LocalSystem.
I use Thread.new(process) where process is an additional program. The process program needs to receive input before it writes anything, and it isn't receiving input because it's on the wrong account. How would I fix this?
Should do the same trick as using(...) but did you try:
sw.Close();
Without it there's just an empty file but it throws no exceptions..
Try this code and check what exception reports:
try
{
using (StreamWriter sw = File.AppendText(dir))
{
sw.WriteLine("test");
}
}
catch (Exception ex)
{
Debug.Print(ex.Message);
}
Just a note: it's a good idea to use using(...) with all classes implementing IDisposable interface, so you can be sure they are freed when exiting block!
First of all I would use Log4Net instead of rolling your own logging mechanism, unless there is a good reason not to. This way you can create the log file you want but also (via a config or code) add log appenders such as windows event log. Then I would make sure I log any and all exceptions. You say no exception is being thrown, I expect there is an exception being thrown on the logging thread which is not 'bubbling' up, so catch it and log it (Log.Error(ex)). You can then see these exceptions in your event log if you have configured an event log appender.
Lastly, I'm not sure how you would assume the security context of the logged on user. Sounds like that would be a big securtity hole, unless you write something that prompts the user to enter their credentials or grant the process the right to impersonate/assume the user security context.. Perhaps that is the answer, the service responds to a user logon by prompting the user to grant this right. I'll have a look around for a better answer to this point.

How to log user operations for a asp.net application?

How can we log user operations for a asp.net application. Further what is the approach for saving the log data ? Kindly guide.
I recommend to use a logging framework like log4net or NLog. These frameworks allow you to log to many destinations and more importantly they allow you to make the decision after you finished your application i.e. you can configure where the log messages are written.
Personally I would log to a database in case of web applications.
or, you could use the Common Logging infrastructure to hide the implementation and switch between loggers at will
http://netcommon.sourceforge.net
Where you store the logging is largely dictated by how you will consume the logging data(i.e. read and interpret the logging data, take action if needed). If the person who analyzes the logging data has access to the machine and it's not business-critical, just log to file. If the machine is critical to your business you probably have some sort of monitoring software and publishing the logging to event logs or WMI becomes interesting.
If you log to file, consider how long you need the logging data and how much of it you need at one time. You can use rolling log files to make sure they don't become gigantically large and consume half your hard disk space. You can also use filters or priorities to log only errors when there is nothing wrong, and open the filter to debug or verbose when investigating a problem.
IIRC log4net and/or enterprise library can log to a format that is readable by the WCF service trace viewer, see http://msdn.microsoft.com/en-us/library/ms732023.aspx (but i'm not sure about that one). Log4net has a dashboard, though.
There are two methods: either you save the log details into the database or create a simple text file so that you can track the events.
Here I am the giving just simple code to how to track the event and maintain the log details and save the log details into the text file. It may help you solve your problem.
First of all you have to import name space:
using System.IO;
I had created the small function to track the log details-
public void LogEntry(string msg, string path)
{
try
{
//It will open the file, append the your message and close the file
File.AppendAllText(path,msg);
}
catch (Exception ex)
{
ex.GetBaseException();
}
}
In this function you have to pass the two parameters
Message
Path of your text File
For example
string logmsg;
logmsg = "** " + DateTime.Now.ToString() + "||" + "User:" + UserName + "||" + " EventDesc: Login Attempt Failed";
l1.LogEntry(logmsg, Server.MapPath("LoginEvent.txt"));
Here the LoginEvnet.txt is the name of the text file where I am storing the log details.
logmsg-It is the message you have to track the or store in the log file

Categories