Writing to An Event Log in a Visual Studio Tools Customization

Patrick Roth - Click for blog homepageSo you are writing your top notch, one-of-a-kind Visual Studio Tools for Microsoft Dynamics GP customization.

You've covered all the bases for any potential errors and just in case you miss any and an exception is thrown, you are catching the exception to write into an event log.

This works great until you test this on a Vista, Windows 7, or Windows 2008 machine.  Then your code fails and actually causes another exception trying to write to the log.

This was the issue posed to me in a case a few days ago logged as a Visual Studio Tools case by one of our ISV's.

While I explained to the ISV that this is more of C# or Visual Studio case since there isn't anything "Visual Studio Tools" about writing to an event log, it did sound interesting enough to take a look at.

After some a bit of testing, what I found was that writing to the event log wasn't what was causing the failure (as he termed it) of his code.

Instead the exception was thrown by trying to register an event source.  The error was:

Exception: The source was not found, but some or all of the event logs could not be
searched. Inaccessible logs: Security.
 

 

As I noted previously, it wasn't writing to the event log that caused this.  Instead it was the checking of the event source that caused this specific error:

Event Log Source Example

 str sSource = "vsTools dotNET Sample";
str sLog = "Dynamics";

if (!EventLog.SourceExists(sSource)) //this is the line that throws this exception
    EventLog.CreateEventSource(sSource, sLog);

From a bit of research, the specific issue is that when this method checks through the registry for the event logs to see if this source exists, it also tries to parse the Security log which a non Administrator does not have access to.  Note that even if the user does have Administrator rights on the machine, if the Dynamics.exe process (which a VSTools app runs under) isn't run with elevated permissions you'll still get this error.

There are a couple of ways to deal with this issue.

My first suggestion is that if the ISV wished to have a registered source that he create an installation application to install his VSTools application.  Run the installation application with elevated permissions and have it create the desired event source as well as put the customization in the Addins folder.

The second option would be to put the code to create the event source in the VSTools code.  However since that Dynamics isn't typically run elevated, the ISV would document that "On each machine a local admin has to run Dynamics GP with elevated permissions at least once."  So that is an option as well.

While I would advocate for creating the event source during an installation, below is an example of the second option since it is more easily shown in this article.

C# VSTools 2010 Code Example

         public void Initialize()
        {
            //Create trigger after user logs in to record the user/company/time of login to event log
            Dynamics.Procedures.AddSuccessfulLoginRecord.InvokeAfterOriginal += 
                 new Microsoft.Dexterity.Applications.DynamicsDictionary.AddSuccessfulLoginRecordProcedure.InvokeEventHandler(AddSuccessfulLoginRecord_InvokeAfterOriginal);
        }

        void AddSuccessfulLoginRecord_InvokeAfterOriginal(object sender, Microsoft.Dexterity.Applications.DynamicsDictionary.AddSuccessfulLoginRecordProcedure.InvokeEventArgs e)
        {
            string sSource;
            string sLog;
            string sEvent;

            sSource = "VSTools dotNET Sample";
            sLog = "Dynamics";
            sEvent = Dynamics.Globals.UserId.Value + " has logged into company " + Dynamics.Globals.CompanyName.Value + " at " + DateTime.Now.ToString();

            try
            {
                if (!EventLog.SourceExists(sSource))
                    EventLog.CreateEventSource(sSource, sLog);
            }
            catch (Exception ee)
            {
                //Catch exception silently.
                //Likely just don't have permissions to check the event source.
            }

            try
            {
                EventLog.WriteEntry(sSource, sEvent, EventLogEntryType.Information, 1234);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Exception: " + ex.Message);
            }
        }

Assuming that Dynamics GP has been launched by a local Administrator with elevated permissions, the first try block code will execute successfully and create the event source of "VSTools dotNET Sample" for the Dynamics event log.  After the event source is created, any ordinary user can write to the event log successfully.

Then as shown in the picture below, the User ID, Company Name, and current Date & Time will be entered in the Dynamics event log.

Best Regards,
Patrick Roth
Developer Support

// Copyright © Microsoft Corporation. All Rights Reserved.
// This code released under the terms of the
// Microsoft Public License (MS-PL, https://opensource.org/licenses/ms-pl.html.)