Executing a UiPath activity from C# causes null pointer exception

For UiPath version 18.2.3 I successfully created a new logging activity. The idea is, while logging everything in Orchestrator , the new activity would in addition log in a file as well. Coming up our organization will upgrade to UiPath 2019.4.3 and my activity did not work, so I needed to upgrade the UiPath references to current dlls (e.g. UiPath.Core.Activities.dll to UiPath.System.Activities.dll). Doing that gives me a compilable code, but the activity causes a null-pointer exception during execution. Why?

This is my code:

using System;
using System.Activities;
using System.Activities.Presentation.Metadata;
using System.ComponentModel;
using System.IO;
using System.Text;
using UiPath.Core.Activities;

namespace CustomCode.Log
{
    /// <summary>
    /// Designer attribute gives a look & feel like UiPaths own LogMessage activity
    /// </summary>
    [Designer(typeof(UiPath.Core.Activities.Design.LogDesigner))]
    public class LogMessage : CodeActivity, IRegisterMetadata
    {
        [Category("Input")]
        public CurentLogLevel Level { get; set; }

        [Category("Input")]
        public InArgument<System.String> Message { get; set; }

        [Category("Input")]
        public InArgument<System.String> LogFilePath { get; set; }

        /// <summary>
        /// UiPath Log Message object reference
        /// </summary>
        private UiPath.Core.Activities.LogMessage _LogMessage { get; set; }

        /// <summary>
        /// Constructor
        /// </summary>
        public LogMessage()
        {
            DisplayName = "Extended Log Message";            
            Level = CurentLogLevel.Trace; // default setting
        }

        /// <summary>
        /// declare dummy register metadata class to force UiPath to load this assembly
        /// </summary>
        public void Register()
        {
            // intentionally empty
        }

        /// <summary>
        /// First log as if done by native UiPath then log to the file specified
        /// </summary>
        /// <param name="context"></param>
        protected override void Execute(CodeActivityContext context)
        {
            // first do the usual UiPath logging...
            string message = Message.Get(context);
            //bool isNew = false;

            #region log as UiPath standard
            // it is necessary to create new objects every time. 
            // reassigning property values causes errors when logging is frequent...
            _LogMessage = new  UiPath.Core.Activities.LogMessage
            {
                Level = this.Level,
                Message = new InArgument<string>(message),
            };

            // do UiPath log 
            try
            {
                WorkflowInvoker.Invoke(_LogMessage); // NULL POINTER EXCEPTION HERE
            }
            catch (Exception ex)
            {
                throw new Exception("Internal UiPath Invoke Exception ", ex);
            }
            #endregion

            string logFilePath = LogFilePath.Get(context);

            // log to file if path is specified...
            if (logFilePath != null)
            {
                LogToFile(logFilePath, message, Level.ToString());
            }
        }

        /// <summary>
        /// Method to write a line in the log file
        /// </summary>
        /// <param name="filename">the file to which to log</param>
        /// <param name="message">the log message</param>
        /// <param name="level">the log level</param>
        private void LogToFile(string filename, string message, string level)
        {
            StringBuilder LogLine = new StringBuilder(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            LogLine.Append("\t");
            LogLine.Append(level);
            LogLine.Append("\t");

            LogLine.Append("\t - ");
            LogLine.Append(message);
            LogLine.Append(Environment.NewLine);

            try
            {
                // append the log line
                File.AppendAllText(filename, LogLine.ToString());
            }
            catch (Exception ex)
            {
                // try to log the exception in UiPath
                _LogMessage.Message = new InArgument<string>(ex.Message + Environment.NewLine + ex.StackTrace);
                throw new Exception("Internal append to log file exception", ex);
            }
        }
    }
}
2 Likes

Hi Lars,

In 2018.3, the UiPath.Core.Activities package was eliminated and split into the UiPath.UIAutomation and UiPath.System packages. We don’t support their use in other activities, however.

3 Likes

Thank you for your reply. It would be nice if extensions to native activities were allowed.

Is there a way to accomplish what I wish to do by a different approach? E.g. is there an API to append to Orchestrator log at runtime or a webservice etc.?

Hi Dean,

Please suggest if there is any other option from which, we can extend/override this activity? Since I need two activities for logging

  1. Log in orchestrator
  2. Log in API.

Since we are performing logging in every step, require to override this activity if allowed.