Out-String and Invoke-Expression

More PowerShell work today…

I’ve been working with the output from a Ruby script that we use to access Solr indexes for customer data. As I wrote previously, I’ve been able to use the ISE to create command lines to feed job names to this Ruby script and determine whether the job in question was successfully ingested into Solr when it was first ingested.

Using the ISE, I was able to assemble scripts – well, I say scripts. More like lists of command lines – but it still saved a lot of work to use the PowerShell ISE’s command pane to write script lines to the script pane above, then save the script pane as a PowerShell script on the server where the command needed to be run.

But I want more.

Today, I started work on scripting a tool to take a specified day (which would default to the current day) and call the Ruby script itself for all the jobs processed on the specified day. I started with a script to look up just one job (the job name was hardcoded into the script) while I figured out how to invoke the Ruby script, get the output from the Ruby script, and search the output for the information I needed.

I discovered that the PowerShell tool I needed to capture the output of the Ruby script was Out-String

Specifically, the heart of the new functionality involves a script line like this:

 $result = jruby.exe PARAM1 PARAM2 PARAM3 “20160923 <job#>” | Out-String

The part of the line in blue is the same command line format as the individual lines of the query scripts I’ve been writing. The addition of the Out-String command captures the jruby output and introduces it into the PowerShell pipeline, and setting $result equal to that routes that pipeline output into the $result variable, where I can search for the number of hits.

I then wrapped the the essential parts of this code inside a Get-ChildItem | ForEach-Object cycle. Instead of having the Ruby command line as a line of the script, I build up a string expression and used Invoke-Expression to call it:

Get-ChildItem <local\path\to\job\data\directories | ForEach-Object {
$expression = ‘jruby.exe PARAM1 PARAM2 PARAM3 ‘ +
‘”20160923 ‘+ $_.PSChildName.ToString() + ‘”‘ + “`n”
$result = Invoke-Expression $expression | Out-String
<code to parse $result and extract the number of Solr hits>

I added the extracted hits data to a variable called $Body, which I could use after the main part of the script was done as the -Body of an email to be sent through our processing mail server.

I also created an empty array before starting the Get-ChildItem | ForEach-Object cycle. Inside the cycle, whenever I found a line of output that showed 0 bytes returned from Solr, I added the associated job number to a list of $zeroByteJobs, then at the end used the job numbers to find the information needed for file of Solr addonly command lines, that I then assembled into another script that I ran separately to add those jobs to Solr.

I do have one really nagging problem – the Ruby script burps out a recommendation to use ansicon to improve the Ruby command-line experience. This output was not captured by the $result = … | Out-String combination. Thinking about it after I got home, though, it occurs to me that it might be generated as an error, and if so the way to deal with it will be to redirect it using PowerShell error stream redirection.


Leave a Reply

Your email address will not be published. Required fields are marked *