cancel
Showing results for 
Search instead for 
Did you mean: 

VBO to Invoke PowerShell Files

StefanSchnell1
Level 7

Hello Community,

these days I tried to build my first own VBO. I thought a Code Stage that executes a PowerShell script might be a good example. So I developed a small routine that reads and executes a PowerShell script. It also offers the possibility to pass parameters to the script. Here the code:

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

//-Initialization of output variables-----------------------------------
ErrorMessage = "";
Result = "";

//-Check if file exists-------------------------------------------------
if(!File.Exists(PowerShellFileName)) {
  ErrorMessage = "File not found";
  return;
}

//-Read the content of the file and check-------------------------------
string PSCode = File.ReadAllText(PowerShellFileName);
if(System.String.IsNullOrEmpty(PSCode)) {
  ErrorMessage = "Code missed";
  return;
}

//-Checking the Separator-----------------------------------------------
if(System.String.IsNullOrEmpty(Separator)) {
  Separator = ",";
}

//-Read parameters and add it to a list---------------------------------
object[] Params = null;
if(!System.String.IsNullOrEmpty(Parameters)) {
  string[] partsParam = Parameters.Split(new char[] {Separator[0]});
  Params = new List<string>(partsParam).ToArray();
}

//-Open the runspace----------------------------------------------------
Runspace runspace;

try {

  runspace = RunspaceFactory.CreateRunspace();
  if(STA == true) {
    runspace.ApartmentState = System.Threading.ApartmentState.STA;
  } else {
    runspace.ApartmentState = System.Threading.ApartmentState.MTA;
  }
  runspace.ThreadOptions = PSThreadOptions.ReuseThread;
  runspace.Open();

} catch(System.Exception ex) {
  ErrorMessage = ex.Message;
  return;
}

//-Create PowerShell----------------------------------------------------
System.Management.Automation.PowerShell PS;

try {

  PS = System.Management.Automation.PowerShell.Create();
  PS.Runspace = runspace;
  PS.AddScript(PSCode);

} catch(System.Exception ex) {
  runspace.Close();
  ErrorMessage = ex.Message;
  return;
}

//-Add parameters to PowerShell-----------------------------------------
if(Params != null) {
  foreach(string PSParam in Params) {
    string[] partsPSParam = PSParam.Split('=');
    PS.AddParameter(partsPSParam[0].Trim(), partsPSParam[1].Trim());
  }
}

//-Invoke PowerShell----------------------------------------------------
try {

  Collection<PSObject> Ret = PS.Invoke();
  runspace.Close();

  //-Set Result---------------------------------------------------------
  StringBuilder stringBuilder = new StringBuilder();
  foreach(PSObject oPS in Ret) {
    stringBuilder.AppendLine(oPS.ToString());
  }
  Result = stringBuilder.ToString();

} catch(System.Exception ex) {
  runspace.Close();
  ErrorMessage = ex.Message;
  return;
}

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

There are the input parameters

  • PowerShellFileName = Path and name of the PowerShell script which should be executed.
  • Parameters = Parameters of the PowerShell script, if available.
  • Separator = The separator between the parameters, default is a comma.
  • STA = Single-Threaded Apartment if true, Multi Threaded Apartment if false, default is true.

There are the output parameters

  • Result = Output of the PowerShell script.
  • ErrorMessage = In case of error an explanatory text.

12672.png

To test it I use this PowerShell script example, with a few parameters and an output:

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

Param (
  [String]$var1,
  [String]$var2,
  [String]$desc,
  [Int]$i
)

$varHost = Get-Host;

$Ret = $Null;
For($j = 1; $j -le $i; $j++) {
  $Ret += "PowerShell greets " + $j + "`r`n";
}
$Ret += "Hello World via " + $var1 + " version " + $var2 + " from ";
$Ret += $varHost.Name + " " + $varHost.Version + "`r`n";
$Ret += $desc;
$Ret | Out-String;

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

12673.png

It works as expected. As far as I can see, this should make it easier to integrate PowerShell into Blue Prism processes. Since the basis is available with Windows, this approach should be executable without additional installations. In some cases, such integration can be very profitable, for example if consolidated scripts already exist and can be further used.

Best regards
Stefan



------------------------------
Stefan Schnell
Senior Systems Engineer at BWI GmbH
------------------------------

38 REPLIES 38

Hello Community,
I tried the PowerShell VBO with Blue Prism 7.01 in an Windows 11 environment, all works well and as expected.
Best regards
Stefan

------------------------------
Stefan Schnell
Senior Systems Engineer at BWI GmbH
------------------------------

Yes Stefan. It takes a few seconds.

Cheers

jack

------------------------------
Jack Look
Sr Product Consultant
Blue Prism
------------------------------

RushabhDedhia
Level 4

Hey @StefanSchnell1,

We were facing an issue whenever we were calling the PowerShell script to get information related to ADGroup we were not getting all properties in the result string.
@Manish Chhugani has made some code changes, where we will get all properties into the Result Collection as a "Key-Value" pair. (Set the Result output as a Collection)

Below is the code for the same:

//-Blue Prism Begin-----------------------------------------------------

           DataTable dt = new DataTable();
            dt.Columns.Add("Name", typeof(string));
            dt.Columns.Add("Data", typeof(DataTable));
            //-Initialization of output variables-----------------------------------
            string ErrorMessage = "";
            string Result = "";
            string PSCode = "";

           if (System.String.IsNullOrEmpty(PowerShellFileName))
            {
                PSCode = PowerShellCode;
            }
            else
            {
                //-Check if file exists-----------------------------------------------
                if (!File.Exists(PowerShellFileName))
                {
                    ErrorMessage = "File not found";
                    return;
                }
                //-Read the content of the file---------------------------------------
                PSCode = File.ReadAllText(PowerShellFileName);
            }

           //-Check if code is available-------------------------------------------
            if (System.String.IsNullOrEmpty(PSCode))
            {
                ErrorMessage = "Code missed";
                return;
            }

           ////-Checking the Separator-----------------------------------------------
            if (System.String.IsNullOrEmpty(Separator))
            {
                Separator = ",";
            }

           ////-Read parameters and add it to a list---------------------------------
            object[] Params = null;
            if (!System.String.IsNullOrEmpty(Parameters))
            {
                string[] partsParam = Parameters.Split(new char[] { Separator[0] });
                Params = new List<string>(partsParam).ToArray();
            }

           //-Open the runspace----------------------------------------------------
            Runspace runspace;

           try
            {

               runspace = RunspaceFactory.CreateRunspace();
                if (STA == true)
                {
                    runspace.ApartmentState = System.Threading.ApartmentState.STA;
                }
                else
                {
                    runspace.ApartmentState = System.Threading.ApartmentState.MTA;
                }
                runspace.ThreadOptions = PSThreadOptions.ReuseThread;
                runspace.Open();

           }
            catch (System.Exception ex)
            {
                ErrorMessage = ex.Message;
                return;
            }

           //-Create PowerShell----------------------------------------------------
            System.Management.Automation.PowerShell PS;

           try
            {

               PS = System.Management.Automation.PowerShell.Create();
                PS.Runspace = runspace;
                PS.AddScript(PSCode);

           }
            catch (System.Exception ex)
            {
                runspace.Close();
                ErrorMessage = ex.Message;
                return;
            }

           ////-Add parameters to PowerShell-----------------------------------------
            if (Params != null)
            {
                foreach (string PSParam in Params)
                {
                    string[] partsPSParam = PSParam.Split('=');
                    PS.AddParameter(partsPSParam[0].Trim(), partsPSParam[1].Trim());
                }
            }

           //-Invoke PowerShell----------------------------------------------------
            try
            {

               Collection<PSObject> Ret = PS.Invoke();
                runspace.Close();

               //-Set Result---------------------------------------------------------
                //StringBuilder stringBuilder = new StringBuilder();
                foreach (PSObject oPS in Ret)
                {
                    //stringBuilder.AppendLine(oPS.ToString());
                    DataTable dtChild = new DataTable();
                    dtChild.Columns.Add("KEY", typeof(string));
                    dtChild.Columns.Add("VALUE", typeof(string));
                    foreach (PSPropertyInfo pSProperty in oPS.Properties)
                    {
                        dtChild.Rows.Add(pSProperty.Name, pSProperty.Value);
                    }
                    dt.Rows.Add(oPS.ToString(), dtChild);
                }
                Result = dt;
            }
            catch (System.Exception ex)
            {
                runspace.Close();
                ErrorMessage = ex.Message;
            }
            //-Blue Prism End-------------------------------------------------------


Thanks & Regards
Rushabh Dedhia



------------------------------
Rushabh Dedhia
Founder,
Biznessology (https://www.linkedin.com/company/biznessology/)
+91 9428860307
------------------------------
Rushabh Dedhia Founder, Biznessology (https://www.linkedin.com/company/biznessology/) +91 9428860307

Hello @Rushabh Dedhia,
thank you very much, excellent.
Best regards
Stefan​​

------------------------------
Stefan Schnell
Senior Systems Engineer at BWI GmbH
------------------------------

@Stefan Schnell, @Rushabh Dedhia,

Would this make a good change overall to the published VBO, or are there cases where having the data returned as a string is still a better approach?

Cheers,​​

------------------------------
Eric Wilson
Director, Integrations and Enablement
Blue Prism Digital Exchange
------------------------------

Hi @ewilson

I think it would be best ​if we can get all properties as collection rather getting single property in string. It may also help users to filter any specific property they are looking for.

@Rushabh Dedhia Looking for your inputs/thoughts​.​​​

------------------------------
Manish Chhugani
Technical Lead
WonderBotz
------------------------------

Hello Stefen,

We are facing an issue with ARSQuest command via PowerShell. It's working with Windows PowerShell ISE as expected, but not with Blue Prism for the same script. We have tried the VBO recommended by you, but still it's getting fail at the Get-QADUser command.

Kindly advise, if we need to make some changes in the code stages.

FYI: We have raised the request with Blue Prism. (https://support.blueprism.com/helpdesk/tickets/246105)

Thank you.



------------------------------
Simanchala Pattanayak
Lead Solution Advisor
Deloitte USI
Bangalore
------------------------------

mmostaquim
Level 4

Hi @StefanSchnell1,

I have written a powershell script where I want to provide a PDF file path as input, and as output I need a specific value that can be extracted using a regex pattern. I have seen your solution. It is really a helpful solution. But I am a bit confused about how to execute the code. Could you please help me?

Powershell Code:

Param (
[String]$var1,
)

[System.Reflection.Assembly]::LoadFrom("C:\Users\mnm\powershell\itextsharp.dll")
[System.Reflection.Assembly]::LoadFrom("C:\Users\mnm\powershell\BouncyCastle.Crypto.dll")
$pdfread = New-Object iTextSharp.text.pdf.PdfReader("$var1")
for($page = 1; $page -le $pdfread.NumberOfPages; $page++) {
$content += [iTextSharp.text.pdf.parser.PdfTextExtractor]::GetTextFromPage($pdfread,$page)
}
$pattern = "qtpv-.*"
$matches = [regex]::Matches($content, $pattern)
if ($matches.Count -gt 0) {
Write-Output "Found match: $($matches[0].Value)"
} | Out-String;

else {
Write-Output "No match found." } | Out-String;
$pdfread.Close()

mmostaquim_1-1719929693482.png

 

 

 

If I define the path of the PDF file in the parameter, the code does not work. But if I use the file path within the code, it works perfectly. What could be the reason? for example:

"Param (
[String]$var1
)

[System.Reflection.Assembly]::LoadFrom(""C:\Users\mnm\powershell\itextsharp.dll"");
[System.Reflection.Assembly]::LoadFrom(""C:\Users\mnm\powershell\BouncyCastle.Crypto.dll"");

$var1 = ""c:/downloads/ddfg.pdf""
$pdfread = New-Object iTextSharp.text.pdf.PdfReader(""$var1"")
for($page = 1; $page -le $pdfread.NumberOfPages; $page++) {
$content += [iTextSharp.text.pdf.parser.PdfTextExtractor]::GetTextFromPage($pdfread,$page)
}
$pattern = ""qtpv-.*""
$matches = [regex]::Matches($content, $pattern)
if ($matches.Count -gt 0) {
$code = ""$($matches[0].Value)""

$code | Out-String;
}

else {
$code =""No match found."" };

$code | Out-String;
$pdfread.Close()"