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 dialogsusing 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;
}
}
}
}
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();
}
}
}