# \[Perspective\] PowerShell Script + system.util.execute

**URL:** <https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718>\
**Category:** Ignition\
**Tags:** ignition81, scripting, perspective\
**Created:** [December 3, 2021, 9:23am UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718 "2021-12-03T09:23:02Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![Davide3i](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/davide3i/32/27811_2.png) [@Davide3i](https://forum.inductiveautomation.com/u/Davide3i)\
**Post date:** [December 3, 2021, 9:23am UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/1 "2021-12-03T09:23:02Z")

</div>

Hello.  
I’d like to know if there are any ways to receive a feedback from [`system.util.execute`](https://docs.inductiveautomation.com/display/DOC81/system.util.execute) after executing a PowerShell script.

If not, I suppose my best option will be to write the output to a _.log_ file and the read it with [`system.file.readFileAsString`](https://docs.inductiveautomation.com/display/DOC81/system.file.readFileAsString), right?

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [December 3, 2021, 9:47am UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/2 "2021-12-03T09:47:57Z")

</div>

That seems to be the way to go i guess

What kind of commands are you running tho that require feedback?

---

<div class="post-metadata">

**Author:** ![Davide3i](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/davide3i/32/27811_2.png) [@Davide3i](https://forum.inductiveautomation.com/u/Davide3i)\
**Post date:** [December 3, 2021, 9:49am UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/3 "2021-12-03T09:49:47Z")

</div>

We are using a RAID data storage system via Windows Storage Spaces and the project must show a pop-up if and when something messy is going on.

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [December 3, 2021, 9:57am UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/4 "2021-12-03T09:57:09Z")

</div>

You will have to delay the reading of the file probably if you are executing things like that that require time… i have no idea how you would now when a process is done 😕

---

<div class="post-metadata">

**Author:** ![Davide3i](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/davide3i/32/27811_2.png) [@Davide3i](https://forum.inductiveautomation.com/u/Davide3i)\
**Post date:** [December 3, 2021, 10:00am UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/5 "2021-12-03T10:00:26Z")

</div>

The script execution time is actually pretty immediate, to be honest. I’m probably going to put a small delay before reading the _.log_ file, just to be sure.

I’m pasting the PowerShell script if anyone is ever going to need it.

```auto
# Execute with:
# powershell "& ""path_to_file\raid_status.ps1"""
# powershell -File "path_to_file\raid_status"

# Write to log file.
#
# Parameters
# $Mode: if true, Write-File will log system messages.
# $FilePath: output file path.
# $Timestamp: current timestamp.
# $Value: output value.
function Write-File {
    param (
        [Parameter(Mandatory=$true, Position=0)]
        [bool]$Mode,
        [Parameter(Mandatory=$true, Position=1)]
        [string]$FilePath,
        [string]$Timestamp,
        [Parameter(Mandatory=$true, Position=3)]
        [string]$Value
    )

    if ($Mode) {
        Out-File -FilePath $FilePath -InputObject "[$Timestamp] $Value" -Append -Encoding ascii
    }
    else {
        Out-File -FilePath $FilePath -InputObject $Value -Encoding ascii
    }
}

# Log file path.
$LogFilePath = "$PSScriptRoot\storage_spaces.log"
# Status file path.
$StatusFilePath = "$PSScriptRoot\status.log"
# Current timestamp.
$Timestamp = Get-Date -Format "dd/MM/yyyy HH:mm:ss:fffffff K"

# Current physical disks' health status.
try {
    $BadDisks = get-physicaldisk | Where-Object {$_.HealthStatus -ne "Healthy"}
}
catch {
    $Message = "Command has failed: $($_.Exception.Message)"
    Write-File $true $LogFilePath -Timestamp $Timestamp $Message
	
    exit 1
}

if ($BadDisks) {
    $Message = "Check diagnostics: possible disk failure. | $BadDisks"
    Write-File $true $LogFilePath -Timestamp $Timestamp $Message
    Write-File $false $StatusFilePath $false
	
	return $false
}
else {
    $Message = "Healthy: no physical disk issues found."
    Write-File $true $LogFilePath -Timestamp $Timestamp $Message
    Write-File $false $StatusFilePath $true
}

# Current status of virtual drives.
try {
    $BadRAIDState = Get-VirtualDisk | where-object {$_.OperationalStatus -ne "OK"}
}
catch {
    $Message = "Command has failed: $($_.Exception.Message)"
    Write-File $true $LogFilePath -Timestamp $Timestamp $Message
	
    exit 1
}

if ($BadRAIDState) {
    $Message = "Check diagnostics: possible RAID system failure. | $BadRAIDState"
    Write-File $true $LogFilePath -Timestamp $Timestamp $Message
    Write-File $false $StatusFilePath $false
	
	return $false
}
else {
	$Message = "Healthy: no Windows Storage Spaces issues found."
    Write-File $true $LogFilePath -Timestamp $Timestamp $Message
    Write-File $false $StatusFilePath $true
	
	return $true
}

```

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [December 3, 2021, 1:57pm UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/6 "2021-12-03T13:57:36Z")

</div>

Ignition’s scripting functions target the common case, usually. In this case, you want to use the java [Process](https://docs.oracle.com/javase/8/docs/api/java/lang/Process.html) class directly. Full control over the created OS process, including the option to connect and work with standard pipes in parallel. So, no need for a log file. The process can just write to its standard output and the java side can read it.

---

<div class="post-metadata">

**Author:** ![Davide3i](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/davide3i/32/27811_2.png) [@Davide3i](https://forum.inductiveautomation.com/u/Davide3i)\
**Post date:** [December 3, 2021, 2:06pm UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/7 "2021-12-03T14:06:28Z")

</div>

Thank you for your insight: I’ll look into it to understand how to make it work. May I ask for any example made in Ignition Perspective?

---

<div class="post-metadata">

**Author:** ![ryanjmclaughlin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ryanjmclaughlin/32/4318_2.png) [@ryanjmclaughlin](https://forum.inductiveautomation.com/u/ryanjmclaughlin)\
**Post date:** [December 3, 2021, 2:41pm UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/8 "2021-12-03T14:41:16Z")

</div>

here is a simple example in python using subprocess, we use to execute powershell 7 via perspective.

```auto
def executePowerShell(commands):
    """
    Executes the given command(s) string in Windows PowerShell 7

    :param commands: The string of command(s) to execute.
        Example:
            '''
            hostname
            "test string"
            '''
        Yields:
            1ABCD-HOSTNAME
            test string
    :type commands: str
    :returns: The stdout and the return code from the PowerShell process.
        Example: ("ABCD-HOSTNAME\ntest string", 0)
    :rtype: tuple
    """
    import subprocess

    cmd = subprocess.Popen(['pwsh'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    stdout = cmd.communicate(commands)[0]
    return stdout, cmd.returncode

```

---

<div class="post-metadata">

**Author:** ![Davide3i](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/davide3i/32/27811_2.png) [@Davide3i](https://forum.inductiveautomation.com/u/Davide3i)\
**Post date:** [December 3, 2021, 2:49pm UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/9 "2021-12-03T14:49:32Z")

</div>

Thank you! I’m still pretty new to Ignition, so I’d like to understand a couple of things.

- This is a client script, right?
- By using `import subprocess` I don’t need to access Java `Process` class as suggested by @pturmel?

---

<div class="post-metadata">

**Author:** ![ryanjmclaughlin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ryanjmclaughlin/32/4318_2.png) [@ryanjmclaughlin](https://forum.inductiveautomation.com/u/ryanjmclaughlin)\
**Post date:** [December 3, 2021, 2:57pm UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/10 "2021-12-03T14:57:15Z")

</div>

> [@Davide3i](#):
>
> This is a client script, right?

Yes. It can be used anywhere you can run a script. You could add it to the project library or re-write it directly into an action script.

You don't necessarily need the function to wrap it, but as you learn Ignition you will find you should be organizing you scripts for re-use where needed. Its not obvious early on, but spending time thinking about the structure of your code/scripts etc. goes a long way to keep things sane as your project grow.

> [@Davide3i](#):
>
> By using `import subprocess` I don’t need to access Java `Process` class as suggested by @pturmel?

Correct, scripting uses jython, so you can use java functions in addition to jython functions. To me it comes down to what your comfortable with, but sometimes you need to evaluate performance as well. Sometimes the Java might be harder to write, but gives you more control and better performance. Sometimes it comes down to skill/comfort level. I just know python better and others know java better. You'll see both approaches debated all over the forums 🙂 I've learned a lot of java stuff from @pturmel over the years for sure!

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [December 3, 2021, 3:04pm UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/11 "2021-12-03T15:04:07Z")

</div>

> [@ryanjmclaughlin](#):
>
> Sometimes the Java might be harder to write, but gives you more control and better performance. Sometimes it comes down to skill/comfort level. I just know python better and others know java better. You’ll see both approaches debated all over the forums

jython has bugs and poor performing implementations scattered through its library. I've long advocated the use of java equivalents instead of jython wherever possible. Anything to do with network traffic, datetime, and proper handling of international strings/bytes streams in particular.

So, I strongly encourage using java's `Process` over jython's `subprocess`. Especially if character encoding on the traffic matters.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [December 3, 2021, 3:50pm UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/12 "2021-12-03T15:50:02Z")

</div>

`ProcessBuilder` example script:

> [@Procedure for installing python libraries from source](https://forum.inductiveautomation.com/t/procedure-for-installing-python-libraries-from-source/26022/16):
>
> Oh, right - system.util.execute is a 'fire-and-forget', it doesn't give you access to standard output. Try adapting this: from java.lang import ProcessBuilder, String pb = ProcessBuilder([r"C:\Users\pgriffith\AppData\Local\Microsoft\WindowsApps\python3.exe", r"C:\Users\pgriffith\Downloads\test.py"]) process = pb.start() output = String(process.getInputStream().readAllBytes()) print output (Note: This blocks until the process completes waiting on the input stream. It may or may not ever compl…

---

<div class="post-metadata">

**Author:** ![Davide3i](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/davide3i/32/27811_2.png) [@Davide3i](https://forum.inductiveautomation.com/u/Davide3i)\
**Post date:** [December 9, 2021, 8:33am UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/13 "2021-12-09T08:33:04Z")

</div>

Hello @paul-griffith.  
What **r"string"** means in Jython?  
Thank you!

---

<div class="post-metadata">

**Author:** ![victordcq](https://avatars.discourse-cdn.com/v4/letter/v/f6c823/32.png) [@victordcq](https://forum.inductiveautomation.com/u/victordcq)\
**Post date:** [December 9, 2021, 9:23am UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/14 "2021-12-09T09:23:09Z")

</div>

raw string.  
can be used so one wouldnt have to escape backslashes`\`

---

<div class="post-metadata">

**Author:** ![bkarabinchak.psi](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bkarabinchak.psi/32/83567_2.png) [@bkarabinchak.psi](https://forum.inductiveautomation.com/u/bkarabinchak.psi)\
**Post date:** [March 29, 2023, 7:16pm UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/15 "2023-03-29T19:16:12Z")

</div>

Trying this script right now in 7.9 and it doesn't work as from what I understand `.readAllBytes()` was not introduced yet. Trying `process.getInputStream().readAllBytes()` yields `AttributeError: 'java.io.BufferedInputStream' object has no attribute 'readAllBytes'`, I tried `process.getInputStream().toString()` but that is only giving me stuff like `java.io.BufferedInputStream@64418d37`. Do you know how can I do this in 7.9?

Edit:

I was able to accomplish it like this

```auto
from java.lang import ProcessBuilder
from java.io import ByteArrayOutputStream
import java.nio.charset.StandardCharsets as StandardCharsets
import jarray

commands = ['someCommandHere']
pb = ProcessBuilder(commands)
process = pb.start()

result = ByteArrayOutputStream()
buffer = jarray.zeros(1024, 'b')
while True:
    length = process.getInputStream().read(buffer)
    if length == -1:
        break
    result.write(buffer, 0, length)
print result.toString(StandardCharsets.UTF_8.name())

```

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [March 29, 2023, 8:15pm UTC](https://forum.inductiveautomation.com/t/perspective-powershell-script-system-util-execute/53718/16 "2023-03-29T20:15:11Z")

</div>

7.9 probably has IOUtils on the classpath; you could try one of these:  
[https://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/IOUtils.html#toByteArray-java.io.InputStream-](https://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/IOUtils.html#toByteArray-java.io.InputStream-)
