another technical blog...technically

Monday, May 28, 2018

Why in the world i cannot get deferred item?

I was wondering why i could not get deferred items from a queue, so i drilled down just a little bit the BP Database in order to see all deferred items

Just watching the queue
So i dumped data before and after completion of the object just to understand how the DB row is updated

Old VS New
After that, we made a little action that inject SQL code from BP in order to get deferred items.

select
       *
       from
       BPAWorkQueue as q join BPAWorkQueueItem as i
       on q.id = i.queueid
       where q.name = 'QueueName'
       and i.deferred IS NOT NULL
       and i.completed IS NULL
       and i.exception IS NULL

And this is how Claudia Musio (thanks for everything) and me, solved the problem.

Monday, May 21, 2018

The KeepAlive problem

Sometimes, you just cannot ask to the IT department to disable screensaver or user lock screen, and personally i never understood why if we are dealing with virtualized machines, so you have to solve the problem somehow.

You can rely for sure on the LoginAgent VBO, which helps you to understand if the screen is locked and so you can login again, but if the screen is not locked, you can just move the mouse on the screen so the session remains alive.

I've tried some methods but only this worked, so in the global code you have to insert this piece of code


Private Shared Sub mouse_event(ByVal dwFlags As Integer, ByVal dx As Integer, ByVal dy As Integer, ByVal dwData As Integer, ByVal dwExtraInfo As Integer)
End Sub

Private Const MOUSEEVENTF_MOVE As Integer = 1
Private Const MOUSEEVENTF_LEFTDOWN As Integer = 2
Private Const MOUSEEVENTF_LEFTUP As Integer = 4
Private Const MOUSEEVENTF_RIGHTDOWN As Integer = 8
Private Const MOUSEEVENTF_RIGHTUP As Integer = 16
Private Const MOUSEEVENTF_MIDDLEDOWN As Integer = 32
Private Const MOUSEEVENTF_MIDDLEUP As Integer = 64
Private Const MOUSEEVENTF_ABSOLUTE As Integer = 32768

Public Shared Sub Move(ByVal xDelta As Integer, ByVal yDelta As Integer)
    mouse_event(MOUSEEVENTF_MOVE, xDelta, yDelta, 0, 0)
End Sub

After that yuo can create an action (eg. MouseMove) which randomly moves the mouse into the screen

Dim Randomizer As System.Random = New System.Random()
Dim x As Integer = Randomizer.Next(1, 640)
Dim y As Integer = Randomizer.Next(1, 480)

Move(x, y)

And that's it, another problem solved by Varro e Antonio Durante
Share:

Monday, May 14, 2018

Use BP Tags to do something more

What about tags?
I think tags can be used  to do more than simply tag an item to understand what kind of item the robot is working on.
Indeed we thank about a new way to use it, just replicating the .NET Dictionary ToString().

You can represent a dictionary as a set of key-value like this:

Key1:Value1;Key2:Value2;Key3:Value3;

And yeah using just a bit of code, you play with tags.
Look at this diagram, here we play with tags using a custom code


Dim patternTag As New Regex("(" + tagkey + ":)+([^;]){0,}")
Dim patternKey As New Regex("(" + tagkey + ":)+")
Dim match As Match
Dim value As String

match = patternTag.Match(tagString)

If match.Success Then
 valueTag = match.Value.TrimEnd(";")
 value = patternKey.Replace(valueTag, "")
 valueTag2 = valueTag.Replace(value, newValue)
 success = True
Else
 valueTag2 = tagKey + ":" + newValue
 success = False
End If

At first we get all data from tags from a particular item in the queue, and we look for all values of type Key1:whatever (note that, in our case is Key:Value and for BP is just one tag), so we delete pre-existing Key1:Value1 and we add Key1:NewValue.
It's clear that we assume that every tag of type Key-i:value is considered singleton.

With this configuration we can do interesting things, for example track technical statuses.
More generally, when you work with a process (expecially if attended), you have different phases, which can be matched with BP Item statuses.
In a singular phase, you can do lot of operations, and if the phase failed, it's normal to repeat the phase.
Sometimes you cannot redo some operations (maybe the robot is paying someone) and you don't want to split the original phase more phases (so not using the status) because of business rules.
So, assuming we are in Status S1, you do the Operation1 on a particular system and after that the robot crashes, when the robot retry the process, you can design the process so, if in state S1, the step Operation1 is skipped.

As usual, thanks to Antonio Durante and Raffaele Ecravino :-)

Monday, May 7, 2018

Scheduling processes and unregistered named pipe

Surprise surprise, a customer asked to start a robot at 7:00 AM, but if you generally work from 9AM to 9 PM like me, you'll find that start a robot at 7:00AM is... how can i say... not so beautiful.
So It's time to make the scheduler to work!

Let's assume the Resource PC we are using is configured to have the LoginAgent service listening on port 8081, and Resource PC ready to fire listening on port 8082.
When the LoginAgent is up and running, the Resource PC is not ready to start an automation, so we have to schedule this sequence of tasks:
  1. Login on 8081
  2. Run on 8082
  3. Logout on 8082
Da first configuration
It's also true that between 1 and 2, everything can happen, and you have to rely on resilience setting, but also, what can happen is that the Login fails because of unregistered named pipe.

Just the login agent log

I can see you asking yourself: WTF is named pipe?
Well, I read a lot about it but I don't remember a single word, but the concept is that the named pipe is a method for IPC (Inter Process Comunication), so i can assume is used when to resume LoginAgent.

Indeed, referring to the schedule above, if you observe the control room is that, when you see the resource PC connected on port 8081, the port 8082 results to be disconnected and vice versa, this means that LoginAgent is listening for login request while 8081 is connected and, until 8082 is in use (so until the logout), LoginAgent is not available.
Sometimes it happens that, even if LoginAgent service is available on port 8081, but the login failed because of the unregistered named pipe, so the solution is... surprise surprise...reboot the machine.
You can find all registered named pipes just with this PowerShell command
[System.IO.Directory]::GetFiles("\\.\\pipe\\")

And the output will be something like this


So the next action is to translate this code in a VBO action, so you can discover if the BP named pipe is registered or not, you can simply use this code to get all the named pipe and then just filter the output collectin

Dim listOfPipes As String() = System.IO.Directory.GetFiles("\\.\pipe\")
dt.Columns.Add("C1")
For Each s As String In listOfPipes
    dt.Rows.Add(s)
Next

Use VBO... use the force
Just the BP log after the cure

The next step is to integrate this new logic in the login task, so if the robot finds out that named pipe is not registered, it reboots the Resource PC.

And now login like this

.The final step is just to add a new task 2.Wait, this task will be:
  • Called if login failed
  • Calls login both in success and failure condition

A new day, a new design
With this little update, il login fails (and this is why i raise an exception after machine reboot), the wait process (it could be whatever, maybe also a void one) will use the resilience of BP to keep the scheduled task alive.
The pitfall of this technique is that you can generate a infinite loop, so take care.

So my friends, that's it, and thanks to my friend Antonio Durante for his time which helped us to work this out.

Me, myself and I

My Photo
I'm just another IT guy sharing his knowledge with all of you out there.
Wanna know more?