EncompDEV
LoanDebugger2

Encompass Auto Start

Click here to download this application with source code    

This program allows to auto-login into Encompass 20.2 and above with command-line parameters -s -u -p as Encompass allowed in prior versions. It's a stand-alone executable that starts Encompass and then automates Encompass login dialog.

Auto-login is implemented via UIAutomation framework which works safely across process boundaries. It cannot be a Plugin since Plugins are loaded after user logs into Encompass.

Code used for this project:

Form1.cs - main form that shows status "Connecting to Encompass..." and has a timer checking/processing Encompass dialogs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Windows.Automation;

using System.IO;
using System.Diagnostics;

namespace EncompassAutoStart
{
    public partial class Form1 : Form
    {
        // params from command line
        string sEXE = "";       // -e - location of Encompass EXE.  Alternatively, you can put EncompassAutoStart in Encompass.exe dir
        string sServer = "";    // -s - server.  Can be https://TEBE12345678.ea.elliemae.net$TEBE12345678 or just TEBE12345678
        string sUID = "";       // -u - user id
        string sPWD = "";       // -p - password


        // Encompass process that we start
        Process pENCOMPASS = null;

        private bool ClientIDDialog_Handled = false;
        private bool LoginDialog_Handled = false;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                lblError.Text = "";

                // parse params from command-line
                sEXE = Utils2.ParseCommandLineParam("-e");
                sServer = Utils2.ParseCommandLineParam("-s");
                sUID = Utils2.ParseCommandLineParam("-u");
                sPWD = Utils2.ParseCommandLineParam("-p");

                // adjust server from full https if it was specified as full
                int i1 = sServer.LastIndexOf("$");
                if (i1 > 0)
                {
                    sServer = sServer.Substring(i1 + 1);
                }

                if (String.IsNullOrEmpty(sServer) ||
                    String.IsNullOrEmpty(sUID))
                {
                    throw new Exception("Please specify -s and -u parameters.  -e and -p are optional.");
                }
                else
                {
                    lblStarting.Text = "Starting Encompass " + sServer + " as " + sUID;
                }
            }
            catch (Exception ex)
            {
                Utils2.MsgBox_ErrorOK("Error: " + ex.Message);
                this.Close();
            }
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            try
            {
                StartEncompassExe();

                // start checking for Login window
                timerCheck.Enabled = true;
            }
            catch (Exception ex)
            {
                Utils2.MsgBox_ErrorOK("Error: " + ex.Message);
                this.Close();
            }
        }

        private void StartEncompassExe()
        {
            // if EXE was not specified - use current directory
            if (String.IsNullOrEmpty(sEXE))
            {
                sEXE = Path.Combine(Utils2.AppPath(), "Encompass.exe");
            }

            if (!File.Exists(sEXE))
            {
                throw new Exception("File not found: " + sEXE);
            }

            ProcessStartInfo si = new ProcessStartInfo();
            si.FileName = sEXE;

            // version
            FileVersionInfo info = FileVersionInfo.GetVersionInfo(sEXE);
            string s = info.FileVersion;
            if (s.StartsWith("18") ||
                s.StartsWith("19") ||
                s.StartsWith("20.0") ||
                s.StartsWith("20.1"))
            {
                // old version - pass command-line params
                si.Arguments = "-s https://" + sServer + ".ea.elliemae.net$" + sServer + " -u " + sUID;
                if (!String.IsNullOrEmpty(sPWD))
                {
                    si.Arguments += " -p " + sPWD;
                }
            }
            else
            {
                // Encompass 20.2 and above don't use commpand-line
            }

            si.CreateNoWindow = false;
            si.UseShellExecute = true;
            si.WindowStyle = ProcessWindowStyle.Normal;
            pENCOMPASS = Process.Start(si);
        }

        private void timerCheck_Tick(object sender, EventArgs e)
        {
            try
            {
                timerCheck.Enabled = false;

                // sanity check
                if (pENCOMPASS == null)
                {
                    this.Close();
                    return;
                }

                pENCOMPASS.Refresh();

                // sanity check
                if (pENCOMPASS.HasExited)
                {
                    this.Close();
                    return;
                }

                IntPtr ptr = pENCOMPASS.MainWindowHandle;
                if (ptr != IntPtr.Zero)
                {
                    AutomationElement frm = AutomationElement.FromHandle(ptr);

                    if (CheckForClientIDDialog(frm))
                    {
                        // first dialog handled - continue to the next one
                    }
                    else if (CheckForLoginDialog(frm))
                    {
                        // success - we just logged in - stop
                        this.Close();
                        return;
                    }
                    else if (CheckForMainWindow(frm))
                    {
                        // we somehow got to main window - stop
                        this.Close();
                        return;
                    }
                }

                // fallthrough - restart timer again
                timerCheck.Enabled = true;
            }
            catch (Exception ex)
            {
                timerCheck.Enabled = false;
                Utils2.MsgBox_ErrorOK("Error: " + ex.Message);
                this.Close();
            }
        }

        private bool CheckForClientIDDialog(AutomationElement frm)
        {
            // don't throw errors
            try
            {
                if (!ClientIDDialog_Handled)
                {
                    if (frm.Current.AutomationId.Equals("AuthenticationForm", StringComparison.OrdinalIgnoreCase) &&
                        frm.Current.Name.StartsWith("Encompass", StringComparison.OrdinalIgnoreCase))
                    {
                        AutomationElement cmbBoxUserid = Utils2.FindElement(frm, "cmbBoxUserid");
                        if (cmbBoxUserid != null)
                        {
                            Utils2.SetText(cmbBoxUserid, sServer);
                            AutomationElement btnLogin = Utils2.FindElement(frm, "btnLogin");
                            Utils2.InvokeClick(btnLogin);
                            ClientIDDialog_Handled = true;
                            return true;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }

            // fallthrough - not handled
            return false;
        }

        // return TRUE if we login
        private bool CheckForLoginDialog(AutomationElement frm)
        {
            // don't throw errors
            try
            {
                if (!LoginDialog_Handled)
                {
                    if (frm.Current.AutomationId.Equals("ThinThickForm", StringComparison.OrdinalIgnoreCase) &&
                        frm.Current.Name.StartsWith("Encompass", StringComparison.OrdinalIgnoreCase))
                    {
                        // find "webBrowser1"
                        AutomationElement webBrowser1 = Utils2.FindElement(frm, "webBrowser1");

                        // find "instanceId", "userId", "password", "Log In"
                        AutomationElement instanceId = Utils2.FindElement(webBrowser1, "Instance ID");
                        AutomationElement userId = Utils2.FindElement(webBrowser1, "User ID");
                        AutomationElement password = Utils2.FindElement(webBrowser1, "password");

                        // set values
                        Utils2.SetText(instanceId, sServer);
                        Utils2.SetText(userId, sUID);

                        if (!String.IsNullOrEmpty(sPWD))
                        {
                            Utils2.SetText(password, sPWD);
                            AutomationElement btn = Utils2.FindElement(webBrowser1, "Log In");
                            Utils2.InvokeClick(btn);
                        }

                        LoginDialog_Handled = true;
                        return true;
                    }
                }
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }

            // fallthrough - not logged in
            return false;
        }

        private bool CheckForMainWindow(AutomationElement frm)
        {
            // don't throw errors
            try
            {
                if (frm.Current.AutomationId.Equals("MainForm", StringComparison.OrdinalIgnoreCase))
                {
                    return true;
                }
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }

            // fallthrough - not logged in
            return false;
        }

        private void HandleError(Exception ex)
        {
            if (ex is ElementNotAvailableException)
            {
                // ignore - form disappeared
            }
            else
            {
                lblError.Text = ex.Message;
            }
        }

    }
}

Utils2.cs - various utility functions
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Windows.Forms;

using System.Windows.Automation;

namespace EncompassAutoStart
{
    public class Utils2
    {
        // app path with backslash
        public static string AppPath()
        {
            return FileDir(Application.ExecutablePath);
        }

        // return backslashed
        public static string FileDir(string sFile)
        {
            int last_slash = sFile.LastIndexOf('\\');
            if (last_slash >= 0) return sFile.Substring(0, last_slash + 1);
            else return sFile;
        }

        public static void MsgBox_ErrorOK(string s)
        {
            // Form w = Form.ActiveForm; 
            MessageBox.Show(s, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }

        public static string ParseCommandLineParam(string sParam)
        {
            // 1) split cmd line
            string[] args = Environment.GetCommandLineArgs();
            for (int i = 1; i < args.Length - 1; i++)
            {
                if (args[i].Equals(sParam, StringComparison.OrdinalIgnoreCase))
                {
                    return args[i + 1];
                }
            }
            // fallthrough - not found
            return "";
        }

        public static void SetText(AutomationElement element, string s)
        {
            object patternObj;
            if (element.TryGetCurrentPattern(ValuePattern.Pattern, out patternObj))
            {
                ValuePattern valuePattern = (ValuePattern)patternObj;
                if (valuePattern != null)
                {
                    valuePattern.SetValue(s);
                    return;
                }
            }
            // fallthrough - value not set
            throw new Exception("Cannot set element value '" + element.Current.Name + "'");
        }

        public static AutomationElement FindElement(AutomationElement el1, string sNameOrID)
        {
            // 1) check by ID
            TreeScope scope = TreeScope.Descendants;
            Condition condition = new PropertyCondition(AutomationElement.AutomationIdProperty, sNameOrID, PropertyConditionFlags.IgnoreCase);
            AutomationElement el2 = el1.FindFirst(scope, condition);
            if (el2 == null)
            {
                // 2) check by Name
                condition = new PropertyCondition(AutomationElement.NameProperty, sNameOrID, PropertyConditionFlags.IgnoreCase);
                el2 = el1.FindFirst(scope, condition);
            }
            return el2;
        }

        public static void InvokeClick(AutomationElement el)
        {
            InvokePattern ip = el.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
            ip.Invoke();
        }


    }
}