Create a simple PC SDK application
Overview
To get started with programming, create a simple application that displays all the virtual and real controllers on the network. It should then be possible to log on to a controller and start RAPID execution.
Caution
Remote access to controllers must be handled carefully. Make sure you do not unintentionally disturb a system in production.
Setting up the project
Use this procedure to set up a PC SDK project using Windows Forms:
On the File menu in Visual Studio, select New and click Project.
Select Windows Forms App (.NET Framework) to target .NET Framework 4.8, or Windows Forms App to target .NET 10.Select a name, location and target framework for the project and click Create.
Add a reference to the PC SDK assembly, ABB.Robotics.Controllers.PC.dll, to the project. The default location of this assembly is in the installation directory under the folder
net48ornet10.0, depending on your target framework.For a standalone application, additional runtime assemblies must be copied to the application directory.
To achieve this, add the following to the project.csprojfile (replacenet10.0withnet48for a .NET Framework project):
<ItemGroup>
<Content Include="C:\Program Files (x86)\ABB\SDK\PCSDK 2026\net10.0\RobotStudio.Services.RobApi.Desktop.dll"
Visible="False" CopyToOutputDirectory="Always"/>
<Content Include="C:\Program Files (x86)\ABB\SDK\PCSDK 2026\net10.0\RobotStudio.Services.RobApi.dll"
Visible="False" CopyToOutputDirectory="Always"/>
</ItemGroup>
Open Form1.cs and add the needed namespace statements at the top of the source code page:
using ABB.Robotics.Controllers.PC; using ABB.Robotics.Controllers.Discovery; using ABB.Robotics.Controllers.RapidDomain;In the Solution Explorer right-click Form1.cs and select View Designer. Create the Graphical User Interface according to the instruction in the next section.
Create the user interface
The following screenshot shows the running PC SDK application that we will create. As you see both virtual and real controllers on the network are included in a network scan.

Use this procedure to create the user interface of the application:
Change the Text property of the form to Network scanning window.
Change its Size to 850; 480.
Add a
ListViewcontrol to the form. Set the following properties to get a similar look as in the figure above:FullRowSelect - True
GridLines - True
View - Details
Add the columns for IPAddress, ID, Availability, Virtual, System name, RobotWare Version and Controller name and adjust the width of the columns.
Add a
Panelwith aButtonunder the listview. Set theTextof the button.
Implement network scanning
To find all controllers on the network we start by declaring these member variables in the class:
private NetworkScanner scanner = null;
private Controller controller = null;
private Task[] tasks = null;
private NetworkWatcher networkwatcher = null;
As the application is supposed to scan the network as soon as it is started, we can put the code for it in the event handler, like this:
this.scanner = new NetworkScanner();
this.scanner.Scan();
ControllerInfoCollection controllers = scanner.Controllers;
ListViewItem item = null;
foreach (ControllerInfo controllerInfo in controllers)
{
item = new ListViewItem(controllerInfo.IPAddress.ToString());
item.SubItems.Add(controllerInfo.Id);
item.SubItems.Add(controllerInfo.Availability.ToString());
item.SubItems.Add(controllerInfo.IsVirtual.ToString());
item.SubItems.Add(controllerInfo.SystemName);
item.SubItems.Add(controllerInfo.Version.ToString());
item.SubItems.Add(controllerInfo.ControllerName);
this.listView1.Items.Add(item);
item.Tag = controllerInfo;
}
Add a network watcher
By implementing a NetworkWatcher the application can supervise the network and detect when controllers are lost or added.
This example shows how to program network supervision, and how to add a detected controller to the listview.
After having added a NetworkWatcher object to the FormLoad event handler, we add a subscription to its Found event.
this.networkwatcher = new NetworkWatcher(scanner.Controllers);
this.networkwatcher.Found += new EventHandler<NetworkWatcherEventArgs>(HandleFoundEvent);
this.networkwatcher.Lost += new EventHandler<NetworkWatcherEventArgs>(HandleLostEvent);
this.networkwatcher.EnableRaisingEvents = true;
Note
In C# the event handler skeleton is auto generated using the Tab key twice after “+=” in the above statements. If you prefer, you can use a simplified syntax when using generic event handlers:
networkwatcher.Found += HandleFoundEvent;
Handle event
As the events will be received on a background thread and should result in an update of the user interface the Invoke method must
be called in the event handler. For more information on how to force execution from background to GUI thread,
see Invoke method.
void HandleFoundEvent(object sender, NetworkWatcherEventArgs e)
{
this.Invoke(new
EventHandler<NetworkWatcherEventArgs>(AddControllerToListView),
new Object[] { this, e });
}
This event handler updates the user interface:
private void AddControllerToListView(object sender, NetworkWatcherEventArgs e)
{
ControllerInfo controllerInfo = e.Controller;
ListViewItem item = new ListViewItem(controllerInfo.IPAddress.ToString());
item.SubItems.Add(controllerInfo.Id);
item.SubItems.Add(controllerInfo.Availability.ToString());
item.SubItems.Add(controllerInfo.IsVirtual.ToString());
item.SubItems.Add(controllerInfo.SystemName);
item.SubItems.Add(controllerInfo.Version.ToString());
item.SubItems.Add(controllerInfo.ControllerName);
this.listView1.Items.Add(item);
item.Tag = controllerInfo;
}
Establish connection to controller
When you double-click a controller in the list, a connection to that controller must be established and you must be logged on. Use the following procedure to implement this functionality.
- Generate
DoubleClickevent of theListView. - In the event handler create a
Controllerobject that represents the selected robot controller. - Log on to the selected controller.
- For controllers running RobotWare 8 and later, register the control station. For more information, see the code sample of Implement event handler.
Implement event handler
This example shows the code of the ListView.DoubleClick event handler:
ListViewItem item = this.listView1.SelectedItems[0];
if (item.Tag != null)
{
ControllerInfo controllerInfo = (ControllerInfo)item.Tag;
if (controllerInfo.Availability == Availability.Available)
{
if (this.controller != null)
{
this.controller.Logoff();
this.controller.Dispose();
this.controller = null;
}
this.controller = ControllerFactory.CreateFrom(controllerInfo);
this.controller.Logon(UserInfo.DefaultUser);
if (this.controller.RobotWareVersion >= new Version(8, 0))
{
this.controller.ControlStation.Register("Example ControlStation", $"{Guid.NewGuid().ToString()}", 1234, true);
}
}
else
{
MessageBox.Show("Selected controller not available.");
}
}
Note
The check to see whether the Controller object already exists is important, as you should explicitly log off and dispose of any
existing controller object before creating a new one. The reason is that a logon session allocates resources that should not be
kept longer than necessary.
Start program execution
The Click event handler of the Start RAPID Program button should start program execution of the first RAPID task.
Starting RAPID execution in manual mode can only be done from the FlexPendant so we need to check that the controller is in automatic mode before trying. We also need to check if the controller is in the Motors On state. Finally, we need to check the version of RobotWare running on the controller. RobotWare 8 controllers come with changes regarding how write access is obtained hence the mastership concept does not work for those controllers (see Control Station and Write Access).
For controllers running RobotWare 8 and later, we first must ensure that the external control is enabled (this setting, if true, allows remote control stations to take write access). Then we need to check if the motion control is enabled and, if not, enable it (this tells the robot controller that the control station in question is allowed to send commands that can make the robot move). Finally we can request write access and perform the RAPID start command. When the start command finishes executing write access should be released.
For controllers running RobotWare 7 and earlier, we need to request mastership of Rapid and call the Start method.
If mastership is already held by ourselves or another client, an InvalidOperationException will be thrown.
For further information, see Mastership.
It is necessary to release mastership whether or not the start operation succeeds. This can be done by applying the using mechanism.
private void button1_Click(object sender, EventArgs e)
{
try
{
if (controller == null)
{
return;
}
if (controller.OperatingMode != ControllerOperatingMode.Auto)
{
MessageBox.Show(
"Automatic mode is required to start execution from a remote client.");
return;
}
if (controller.State != ControllerState.MotorsOn)
{
MessageBox.Show("Motors On is required to start execution.");
return;
}
if (controller.RobotWareVersion >= new Version(8, 0))
{
if (!controller.ControlStation.WriteAccessStatus.ExternalControlEnabled)
{
MessageBox.Show("External control must be enabled on the FlexPendant.");
return;
}
if (!controller.ControlStation.MotionControlEnabled)
{
MessageBox.Show("Enabling motion control. Ensure that emergency stop is within reachable "
+ "distance of the operator and other saftey measures are in place.")
controller.ControlStation.MotionControlEnabled = true;
}
try
{
controller.ControlStation.RequestWriteAccess();
controller.Rapid.Start();
}
finally
{
controller.ControlStation.ReleaseWriteAccess();
}
}
else
{
using (Mastership m = Mastership.Request(controller.Rapid))
{
controller.Rapid.Start();
}
}
}
catch (WriteAccessHeldException ex)
{
MessageBox.Show("Write access is held by another client." + ex.Message);
}
catch (System.InvalidOperationException ex)
{
MessageBox.Show("Mastership is held by another client." + ex.Message);
}
catch (System.Exception ex)
{
MessageBox.Show("Unexpected error occurred: " + ex.Message);
}
}