How to use a Windows Forms UI

In some cases, with attended bots, it could be necessary to input data into the automation workflow. As long as we work in desktop environments, we have everything aboard to enable such inputs on a simple way. In this post I describe an example of how to use Windows Forms UI.

Windows Forms UI DLL

Windows Forms is a UI framework to create rich desktop client apps for Windows. We can use Windows Forms for the compatibility modes Windows - Legacy (dotNET Framework 4.61 - x86 architecture) and Windows (dotNET 6 - x64 architecture). In my example I use a very easy one, a window with one label, one text box and one button.

The Windows Forms UI code is in a dynamic link library (DLL). Besides the definitions of the window and the UI controls, the DLL contains the event routines that are executed when the button is pressed or the window is closed. In both cases a JSON string is returned which contains the entered name. And last but not least the routine getValue which we call from UiPath.

//-Begin----------------------------------------------------------------

using System;
using System.Drawing;
using System.Windows.Forms;

namespace First {

  public class MyForm : Form {

    private static string retValue = String.Empty;
    private TextBox txtName = new TextBox();

    public MyForm() {
      InitComponents();
    }

    private void InitComponents() {

      //-Window---------------------------------------------------------
      Text = "UiPath example";
      ClientSize = new Size(640, 480);
      CenterToScreen();
      this.FormClosing += MyForm_FormClosing;

      //-Label Name-----------------------------------------------------
      Label lblName = new Label();
      lblName.Text = "Name";
      lblName.Left = 20;
      lblName.Top = 20;
      lblName.Width = 150;
      lblName.Height = 30;
      lblName.Font = new Font("Consoleas", 10);
      Controls.Add(lblName);

      //-Textbox Name---------------------------------------------------
      txtName.Left = 170;
      txtName.Top = 20;
      txtName.Width = 180;
      txtName.Height = 30;
      txtName.Font = new Font("Consoleas", 10);
      txtName.Text = "Stefan Schnell";
      Controls.Add(txtName);

      //-Button to quit ------------------------------------------------
      Button btnQuit = new Button();
      btnQuit.Text = "Click me to quit";
      btnQuit.Left = 6;
      btnQuit.Top = 444;
      btnQuit.Width = 628;
      btnQuit.Height = 30;
      btnQuit.BackColor = SystemColors.ButtonFace;
      btnQuit.Click += new System.EventHandler(click_btnQuit);
      Controls.Add(btnQuit);

    }

    //-Quit button click event------------------------------------------
    private void click_btnQuit(object sender, EventArgs e) {
      MessageBox.Show("Hello World from " + txtName.Text);
      retValue = "{\"name\": \"" + txtName.Text + "\"}";
      this.Close();
    }

    //-Windows Forms close event----------------------------------------
    private void MyForm_FormClosing(object sender, FormClosingEventArgs e) {
      retValue = "{\"name\": \"" + txtName.Text + "\"}";
    }

    //-Main-------------------------------------------------------------
    [STAThread]
    public string getValue() {
      #if NETCOREAPP
        Application.SetHighDpiMode(HighDpiMode.SystemAware);
      #endif
      Application.EnableVisualStyles();
      Application.Run(new MyForm());
      return retValue;
    }

  }

}

//-End------------------------------------------------------------------

To compile this code to a DLL use for dotNET Framework 4.61 this command …

csc.exe /target:library /platform:anyCPU /out:UiPathExample.dll UiPathExample.cs

… or with dotNET 6 SDK use this csproj …

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>

    <TargetFrameworks>net6.0-windows7.0;net461</TargetFrameworks>

    <OutputType>Library</OutputType>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <UseWindowsForms>true</UseWindowsForms>

  </PropertyGroup>


  <ItemGroup>

    <Reference Include="System.Windows.Forms" Condition="'$(TargetFramework)' == 'net461'">
      <HintPath>System.Windows.Forms.dll</HintPath>
    </Reference>

    <Reference Include="System.Windows.Forms" Condition="'$(TargetFramework)' == 'net6.0-windows7.0'">
      <HintPath>System.Windows.Forms.dll</HintPath>
      <HintPath>System.Windows.Forms.Primitives.dll</HintPath>
    </Reference>

  </ItemGroup>

</Project>

… and copy the DLL into your project directory.

Windows Forms with UiPath

After all these preparations are done, the library can now be used with UiPath. Here we use only a tiny Invoke Code activity, like I described it here about the using of dotNET assemblies.

System.Reflection.Assembly TestLibrary = System.Reflection.Assembly.LoadFrom(@"UiPathExample.dll");
dynamic Instance = TestLibrary.CreateInstance("First.MyForm");
strResult = Instance.getValue();

That’s all. :wink:

image

And in the context of the UiPath Assistant it works exactly like expected.

image

Conclusion

As we can see it is very easy to integrate rich client UIs, via Windows Forms, into the automation workflow. This allows us to build user interfaces and use the input from that, without any additional installations. For an attended bot that runs on the desktop and needs input certainly a good approach.

Addendum 19.09.2022: Tried successfully with UiPath Studio 22.8 in Windows compatibility mode (x64) with dotNET 6 SDK.

10 Likes

Hey @StefanSchnell

Awesome value add :boom:

Thanks for sharing.

#nK

1 Like

This is amazing. Thanks for sharing this another approach to fetch input from attended users.:+1:

1 Like

Thank you the quick overview @StefanSchnell!

I am curious, in the scenario of Attended Automations in a Desktop Environment; I can see when UiPath Apps might not be ideal, particularly if you don’t use Apps or unable to have an outbound network connection to leverage the service.

But what would your deciding factor be when comparing Windows Forms to the Form Activities [UiPath.Form.Activities] from UiPath?

1 Like

Why? UiPath has forms built in…

@codemonkee

Hello Tim,
if it is necessary to develop a new user interface in an RPA context then I would choose UiPath Form. The perspective changes when UIs exists, can be reused and the redevelopment would take much time. Another reason can be the use of external UI controls that cover special application areas or Windows UI possibilities, which can not be realized or used with UiPath Form. This approach is an alternative, simply another possibility to build an RPA UI.
Best regards
Stefan