How to use Memory Mapped Files with UiPath

Memory mapped files are an elegant way for interprocess communication. Memory mapped files defines an area in the memory and different processes can access to this sharable area as easy as to a file. In my opinion this could be very interesting for integration scenarios with UiPath. Especially when transferring larger amounts of data. Let us start with the test implementation.

We begin with a PowerShell script which creates a memory mapped file and stores a text in it. In the next step it reads the content of the memory mapped file. In PowerShell we use easily a StreamWriter and StreamReader.

#-Begin-----------------------------------------------------------------

$Text = @"
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit
amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
sed diam voluptua. At vero eos et accusam et justo duo dolores et ea
rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem
ipsum dolor sit amet.
"@

#-Sub Main--------------------------------------------------------------
Function Main {

  $Name = "UiPathRobot";
  $Size = 8192;
  [System.IO.MemoryMappedFiles.MemoryMappedFile]$MMF = `
    [System.IO.MemoryMappedFiles.MemoryMappedFile]::CreateNew($Name, $Size);
  If($Null -eq $MMF) {
    Return;
  }

  $Stream = $MMF.CreateViewStream();
  $StreamWriter = [System.IO.StreamWriter]::new($Stream);
  $StreamWriter.Write($Text);
  $StreamWriter.Dispose();
  $Stream.Dispose();

  $Stream = $MMF.CreateViewStream();
  $StreamReader = [System.IO.StreamReader]::new($Stream);
  $StreamReader.ReadToEnd().Replace("`0", "");
  $StreamReader.Dispose();
  $Stream.Dispose();

  $MMF.Dispose();

}

#-Main------------------------------------------------------------------
Main;

#-End-------------------------------------------------------------------

Now we switch to UiPath Studio and import System.IO.MemoryMappedFiles namespace.

Import

Now we define two variables and a tiny flowchart with three steps, two times Invoke Code and one Write Line.

Now let us look at the first Invoke Code to read the content of a memory mapped file. This is exactly the same procedure as in PowerShell. We open the memory mapped file, create a StreamReader and read the content.

'-Begin-----------------------------------------------------------------

Dim Name As String = "UiPathRobot"
Dim MMF As MemoryMappedFile
Dim MMFStream As MemoryMappedViewStream
Dim MMFStreamReader As StreamReader

Try
  MMF = MemoryMappedFile.OpenExisting(Name)
Catch
  Return
End Try

MMFStream = MMF.CreateViewStream
MMFStreamReader = New StreamReader(MMFStream)

Content = MMFStreamReader.ReadToEnd().Replace(Convert.ToChar(0), "")

MMFStreamReader.Dispose
MMFStream.Dispose
MMF.Dispose

'-End-------------------------------------------------------------------

Arguments

Now the second Invoke Code. It works nearly equal to read, but here we write new content with the StreamWriter.

'-Begin-----------------------------------------------------------------

Dim Name As String = "UiPathRobot"
Dim MMF As MemoryMappedFile
Dim MMFStream As MemoryMappedViewStream
Dim MMFStreamWriter As StreamWriter

Try
  MMF = MemoryMappedFile.OpenExisting(Name)
Catch
  Return
End Try

MMFStream = MMF.CreateViewStream
MMFStreamWriter = New StreamWriter(MMFStream)

MMFStreamWriter.Write(NewContent)
Try
  Do
    MMFStreamWriter.Write(Convert.ToChar(0))
  Loop
Catch
End Try

MMFStreamWriter.Dispose
MMFStream.Dispose
MMF.Dispose

'-End-------------------------------------------------------------------

Arguments

Now we can execute our test. We set a break point in line 33 and execute the PowerShell script.

It delivers exactly what we defined in the PowerShell variable.

Test002

Now we continue the execution and get the content from UiPath.

Great, it works :slightly_smiling_face:

Now we publish our UiPath process and use it with the UiRobot. Therefore we add the execution of the UiRobot instead a break point.

#-Begin-----------------------------------------------------------------

$Text = @"
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit
amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam
nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat,
sed diam voluptua. At vero eos et accusam et justo duo dolores et ea
rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem
ipsum dolor sit amet.
"@

#-Sub Main--------------------------------------------------------------
Function Main {

  $Name = "UiPathRobot";
  $Size = 8192;
  [System.IO.MemoryMappedFiles.MemoryMappedFile]$MMF = `
    [System.IO.MemoryMappedFiles.MemoryMappedFile]::CreateNew($Name, $Size);
  If($Null -eq $MMF) {
    Return;
  }

  $Stream = $MMF.CreateViewStream();
  $StreamWriter = [System.IO.StreamWriter]::new($Stream);
  $StreamWriter.Write($Text);
  $StreamWriter.Dispose();
  $Stream.Dispose();

  $UiPathRobot = "C:\Dummy\UiPath\app-18.4.2\UiRobot.exe";
  $Params = "-file C:\ProgramData\UiPath\Packages\BlankProcess.1.0.6951.15964.nupkg";

  Start-Process -FilePath $UiPathRobot -Argumentlist $Params -Wait -NoNewWindow;

  $Stream = $MMF.CreateViewStream();
  $StreamReader = [System.IO.StreamReader]::new($Stream);
  $StreamReader.ReadToEnd().Replace("`0", "");
  $StreamReader.Dispose();
  $Stream.Dispose();

  $MMF.Dispose();

}

#-Main------------------------------------------------------------------
Main;

#-End-------------------------------------------------------------------

And if we execute the script again, we get the same result.
Hint: For this test I changed Write Line with MessageBox.

Excellent :grinning:

Memory mapped files offers us fantastic possibilities to transfer data between different processes. You can define the size of a memory mapped file as you like. You can access via StreamReader and StreamWriter as well as BinaryReader and BinaryWriter.

My use case for this approach is easy to explain: We use SAP extended Computer Aided Testing Tool and in this context PowerShell. And I wanted to know if it is possible to use UiPath robot in this context also to get the full power of UiPath in the context of our testautomation. Often it is in this scenario necessary to transfer larger amounts of data and in this case to work with files is very unwieldy. Memory mapped files are a great way and if we can see it works seamlessly with UiPath.

3 Likes

Excellent :+1:

1 Like

Thank you very much @rahatadi :slightly_smiling_face:

Here the corresponding post in the SAP Community. It described the same way from the perspective of SAP eCATT. So you have the possibility to combine ABAP/eCATT with UiPath seamless.

How to use Memory Mapped Files with ABAP/eCATT

2 Likes

Hello,

Awesome post. I tried replicate the similar thing.

Issue is in my next iteration, The Data is getting over written instead of completely replacing the old value.

Iteration 1: I want to write value as 11111
Iteration2: I want to write value as 22

But After Iteration2 I am getting updated value as 22111 intead of 22.

Any idea how to resolve it?

Thanks,
Ajinkya

1 Like

Hello @AjinkyaCK,

I did not try that, but I would write the text with a final character 0. On this way you can mark the end of your stream and in your following step you read it up to this position.

Let us know if it worked on that way.

Best regards
Stefan

1 Like

Hi,

Thanks for response but the problem persist.

if we have two zeros then we will still get corrupted message.

May be instead of overwriting the stream I need to dispose and then create one with new message.

Thanks,
Ajinkya

1 Like

Hello @AjinkyaCK,

I tried it with the binary reader class, instead of stream reader class, and it works, here my approach:

$Stream = $MMF.CreateViewStream();
$StreamReader = [System.IO.BinaryReader]::new($Stream);
$i = 0;
While($StreamReader.ReadBytes(1) -ne 0) {
  $i += 1;
}
[Void]$StreamReader.BaseStream.Seek(0, [System.IO.SeekOrigin]::Begin);
$Bytes = [System.Byte[]]::CreateInstance([System.Byte], $i);
[Void]$StreamReader.Read($Bytes, 0, $i);
[System.Text.Encoding]::ASCII.GetString($Bytes);

With the while loop I detect the first 0 character and then I read the MMF up to this point. In the last line I get the string from the byte sequence.

Let us know if this approach works in your case.

Best regards
Stefan