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
------------------------------

36 REPLIES 36

This looks great!

I'm having an issue though... If I run a script manually it works. I run it via this VBO and it gives me an error. 

The error is it cannot see a set of registry keys, if I check manually it works. Does PowerShell need to be run with elevated permissions?

------------------------------
Mat Hanley
------------------------------

I think it might be a limitation (or security feature) of how PowerShell works when another application invokes it? This is the message I get when I try to open powershell with a script manually using  "Run Process" action with the input of opening a script I created.
It's the same error I get if I run the script file or just the script text from your utility but I think it clips the rest of the error when it stores the result. 

12532.png


------------------------------
Mat
------------------------------

@Mat

Hello Mat,

thanks​ for your reply.

As far as I know PowerShell needs no elevated permissions.

I assume you have different execution policies for the scopes:
12536.png

You can find more information about execution policies of PowerShell here.
This could be a possible reason.

I tried different settings but in my case all works well without any differences.
Let us know your execution policy settings.

Addition:
Interesting is after I set the the execution policy of the scopes Process, CurrentUser and LocalMachine to Restricted the BP VBO works, but the process not.

12537.png
12538.png

It seems that the PowerShell Automation object works independently from the execution policies of the scopes. So this would no longer be a possible reason.

Best regards
Stefan

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

@StefanSchnell1

So, my execution policies are the same as yours. That doesn't seem to be the issue.

I have a colleague at work trying to help me with this.  We've not 'cracked' it yet.

I was hoping to use the Powershell module Smlets ( https://github.com/SMLets/SMLets ) in order to log jobs (create a ticket / incident) in Service Manager on behalf of the virtual worker. For example if an automation failed I wanted it to log an incident in Microsoft ​System Center Service Manager rather than sending an email. 

I've managed to create an incident using a powershell script if I run it manually. If I run it via the virtual worker using your VBO it errors.  Es ist sehr komisch!! 

I'm pretty new to powershell, and I only started working with Blue Prism in July. This VBO you've built though looks great I think it will be very useful to run PS scripts in the future too.

------------------------------
Mat
------------------------------

Vikash011
Staff
Staff
Hi Stefan,

I am getting the same error message when I have created a Blueprism object to execute a PowerShell command and capture the response. The process is running fine when I am trying to execute commands like Get-ADGroup, Get-Acl but it fail with the above error when I am executing the command as Get-QADGroup(Quest Commands for AD)etc.

Error : Could not load file or assembly 'System.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies.The system cannot find the file specified.

errorMessage="";
PowerShell ps = PowerShell.Create();
 ps.Commands.AddScript(Input);
 try{
Collection<PSObject> res = ps.Invoke();
 string tex="";
foreach (var x in res)
 {
tex=tex+"\n"+x;
}
output=tex;

if (ps.HadErrors)
{
foreach (ErrorRecord er in ps.Streams.Error)
 {
errorMessage=er.Exception.Message;
 }
 }
 }
catch (Exception e)
 {
 output="";
 errorMessage=e.Message;
 }

DLL used - System.dll
System.Data.dll
System.xml.dll
System.Drawing.dll
System.Collections.dll
System.Dynamic.dll
System.Core.dll
System.Linq.dll

Kindly let me know if you have any thought on this.

Regards,
Vikash

------------------------------
Vikash Anand
Senior Software Engineer
Ernst and Young
------------------------------

Vikash011
Staff
Staff
Hi Stefan,

Does this VBO also works with the Quest PowerShell? I can see it does not capture the response and still continue to the successful path whereas when I run the script directly in PowerShell it works as expected and return the output.

Regards,
Vikash

------------------------------
Vikash Anand
Senior Software Engineer
Ernst and Young
------------------------------

@Vikash Anand,

Are you talking about the packaged cmdlets Quest released that were subsequently purchased by Dell? As far as I know, Quest never built their own PowerShell.

Cheers,


------------------------------
Eric Wilson
Director, Partner Integrations for Digital Exchange
Blue Prism
------------------------------

@Vikash Anand

Hello Vikash,
thanks for your message.
Sorry but I can't answer your question. The last free release of Quest ActiveDirectory Cmdlets for PowerShell I found here is 1.5.1 from 2012 and it needs dotNET framework 3.5. As far as I read here are these Cmdlets deprecated and not longer available. If your requirements can be met with the Active Directory (AD) modules of Microsoft's RSAT (Remote Server Administration Tools), then you should use that.
Best regards
Stefan

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

Hi Stefan, 

Great work. And thank you for sharing.

Best regards,

Ben

------------------------------
Benjamin Anderson,
Senior Consultant,
UK
------------------------------
Benjamin Anderson, Senior Consultant, UK

Hello Ben,

thank you very much.

Best regards
Stefan

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