javascript - 将Powershell对象传递给Node.JS/Electron并将其 package 在HTML标记中

标签 javascript node.js powershell object electron

我正在尝试用Electron写一个小工具来调用Powershell脚本。

我知道如何从此线程将Powershell输出输出到我的脚本中:

https://stackoverflow.com/a/10181488/3161671

所以我有

<script>
    var spawn = require("child_process").spawn,child;
    child = spawn("powershell.exe",["C:\\PowershellScript\\get-process.ps1"]);
    child.stdout.on("data",function(data){
        console.log("Powershell Data: " + data);
    });
    child.stderr.on("data",function(data){
        console.log("Powershell Errors: " + data);
    });
    child.on("exit",function(){
        console.log("Powershell Script finished");
    });
    child.stdin.end(); //end input
</script>

但是,我不太了解如何从PS输出(例如child.stdout.ProcessName)中调用对象成员。

我希望能够遍历输出并格式化表中的某些成员(如果这是合理的):
 <table>
  <tr>
    <th>CPU(s)</th>
    <th>Id</th>
    <th>ProcessName</th>
  </tr>
  <tr>
    <td>0,35</td>
    <td>1824</td>
    <td>conhost</td>
  </tr>
  <tr>
    <td>1.725</td>
    <td>3115</td>
    <td>firefox</td>
  </tr>
</table> 

什么是最干净的方法来实现这一目标?我见过人们在他们的Powershell脚本中嵌入HTML标记,但是我认为使用JavaScript进行对象到HTML和格式设置更有意义,不是吗?

最佳答案

根据我的理解,在这种情况下,标准输出将无法正常工作,因为它将具有自己的格式化显示方式。除了 native Powershell转换外,我几乎没有其他转换功能。您应该尝试使用它们,然后再解析输出。

干得好:

  • 转换为JsonIfAblePSObject

  • 为了便于理解,在注释部分中提到了用法。
    <#
    .SYNOPSIS
        Creates a new PSObject where all properties of the original object that are not able to be
        properly serialized to JSON are converted to a value which can be properly converted to JSON.
    
        This includes the following types:
        *   DateTime
    
        This conducts a deep property search
    .Example 
        Convert an custom PSObject to have parsable dates in Json
    
        $customObject = New-Object -TypeName PSobject -Property @{ Date = Get-Date; Number = 23; InnerDate = New-Object -TypeName PSObject -Property @{Date=Get-Date;} }
    
        ## BAD Json
        PS C:\dev> $customObject | ConvertTo-Json
        {
            "Date":  {
                         "value":  "\/Date(1410372629047)\/",
                         "DisplayHint":  2,
                         "DateTime":  "Wednesday, September 10, 2014 2:10:29 PM"
                     },
            "Number":  23,
            "InnerDate":  {
                              "Date":  {
                                           "value":  "\/Date(1410372629047)\/",
                                           "DisplayHint":  2,
                                           "DateTime":  "Wednesday, September 10, 2014 2:10:29 PM"
                                       }
                          }
        }
    
        ## Good Json
        PS C:\dev> $customObject | ConvertTo-JsonifiablePSObject | ConvertTo-Json
        {
            "Date":  "2014-09-10T14:10:29.0477785-04:00",
            "Number":  23,
            "InnerDate":  {
                              "Date":  "2014-09-10T14:10:29.0477785-04:00"
                          }
        }
    
    #>
    function ConvertTo-JsonifiablePSObject
    {
        param
        (
            [Parameter(Mandatory=$true, ValueFromPipeline=$true)]
            [PSObject]$Object
        )
    
        $newObjectProperties = @{}
    
        foreach ($property in $Object.psobject.properties)
        {
            $value = $property.Value
    
            if ($property.TypeNameOfValue -eq "System.Management.Automation.PSCustomObject")
            {
                $value = ConvertTo-JsonifiablePSObject -Object $property.Value
            }
            elseif ($property.TypeNameOfValue -eq "System.DateTime")
            {
                $value = $property.Value.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK")
            }
    
            $newObjectProperties[$property.Name] = $value
        }
    
        return New-Object -TypeName PSObject -Property $newObjectProperties
    }
    
    $json=$kbm | ConvertTo-Json
    
  • 转换为PSON
    function ConvertTo-PSON
    
    {
    <#
     .SYNOPSIS
       creates a powershell object-notation script that generates the same object data
     .DESCRIPTION
       This produces 'PSON', the powerShell-equivalent of JSON from any object you pass to it. It isn't suitable for the huge objects produced by some of the cmdlets such as Get-Process, but fine for simple objects
     .EXAMPLE
       $array=@()
       $array+=Get-Process wi* |  Select-Object Handles,NPM,PM,WS,VM,CPU,Id,ProcessName 
       ConvertTo-PSON $array
    
     .PARAMETER Object 
       the object that you want scripted out
     .PARAMETER Depth
       The depth that you want your object scripted to
     .PARAMETER Nesting Level
       internal use only. required for formatting
    #>
    
    [CmdletBinding()]
    param (
        [parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][AllowNull()] $inputObject,
        [parameter(Position = 1, Mandatory = $false, ValueFromPipeline = $false)] [int] $depth = 16,
        [parameter(Position = 2, Mandatory = $false, ValueFromPipeline = $false)] [int] $NestingLevel = 1,
        [parameter(Position = 3, Mandatory = $false, ValueFromPipeline = $false)] [int] $XMLAsInnerXML = 0
    )
    
    BEGIN { }
    PROCESS
    {
        If ($inputObject -eq $Null) { $p += '$Null'; return $p } # if it is null return null
        $padding = [string]'  ' * $NestingLevel # lets just create our left-padding for the block
        $ArrayEnd=0; #until proven false
        try
        {
            $Type = $inputObject.GetType().Name # we start by getting the object's type
            if ($Type -ieq 'Object[]') { $Type = "$($inputObject.GetType().BaseType.Name)" } # see what it really is
            if ($depth -ilt $NestingLevel) { $Type = 'OutOfDepth' } #report the leaves in terms of object type
            elseif ($Type -ieq 'XmlDocument' -or $Type -ieq 'XmlElement')
            {
                if ($XMLAsInnerXML -ne 0) { $Type = 'InnerXML' }
                else
                { $Type = 'XML' }
            } # convert to PS Alias
                # prevent these values being identified as an object
            if (@('boolean', 'byte', 'char', 'datetime', 'decimal', 'double', 'float', 'single', 'guid', 'int', 'int32',
            'int16', 'long', 'int64', 'OutOfDepth', 'RuntimeType', 'PSNoteProperty', 'regex', 'sbyte', 'string',
            'timespan', 'uint16', 'uint32', 'uint64', 'uri', 'version', 'void', 'xml', 'datatable', 'List`1',
            'SqlDataReader', 'datarow', 'ScriptBlock', 'type') -notcontains $type)
            {
                if ($Type -ieq 'OrderedDictionary') { $Type = 'HashTable' }
                elseif ($Type -ieq 'PSCustomObject') { $Type = 'PSObject' } #
                elseif ($inputObject -is "Array") { $Type = 'Array' } # whatever it thinks it is called
                elseif ($inputObject -is "HashTable") { $Type = 'HashTable' } # for our purposes it is a hashtable
                elseif (($inputObject | gm -membertype Properties | Select name | Where name -like 'Keys') -ne $null) { $Type = 'generic' } #use dot notation
                elseif (($inputObject | gm -membertype Properties | Select name).count -gt 1) { $Type = 'Object' }
            }
            write-verbose "$($padding)Type:='$Type', Object type:=$($inputObject.GetType().Name), BaseName:=$($inputObject.GetType().BaseType.Name) $NestingLevel "
            switch ($Type)
            {
                'ScriptBlock'{ "[$type] {$($inputObject.ToString())}" }
                'InnerXML'        { "[$type]@'`r`n" + ($inputObject.OuterXMl) + "`r`n'@`r`n" } # just use a 'here' string
                'DateTime'   { "[datetime]'$($inputObject.ToString('s'))'" } # s=SortableDateTimePattern (based on ISO 8601) local time
                'Boolean'    {
                    "[bool] $(&{
                        if ($inputObject -eq $true) { "`$True" }
                        Else { "`$False" }
                    })"
                }
                'string'     {
                    if ($inputObject -match '[\r\n]') { "@'`r`n$inputObject`r`n'@" }
                    else { "'$($inputObject -replace '''', '''''')'" }
                }
                'Char'       { [int]$inputObject }
                { @('byte', 'decimal', 'double', 'float', 'single', 'int', 'int32', 'int16', 'long', 'int64', 'sbyte', 'uint16', 'uint32', 'uint64') -contains $_ }
                { "$inputObject" } # rendered as is without single quotes
                'PSNoteProperty' { "$(ConvertTo-PSON -inputObject $inputObject.Value -depth $depth -NestingLevel ($NestingLevel))" }
                'Array'      { "`r`n$padding@(" + ("$($inputObject | ForEach {$ArrayEnd=1; ",$(ConvertTo-PSON -inputObject $_ -depth $depth -NestingLevel ($NestingLevel + 1))" })".Substring($ArrayEnd)) + "`r`n$padding)" }
                'HashTable'  { "`r`n$padding@{" + ("$($inputObject.GetEnumerator() | ForEach {$ArrayEnd=1; "; '$($_.Name)' = " + (ConvertTo-PSON -inputObject $_.Value -depth $depth -NestingLevel ($NestingLevel + 1)) })".Substring($ArrayEnd) + "`r`n$padding}") }
                'PSObject'   { "`r`n$padding[pscustomobject]@{" + ("$($inputObject.PSObject.Properties | ForEach {$ArrayEnd=1; "; '$($_.Name)' = " + (ConvertTo-PSON -inputObject $_ -depth $depth -NestingLevel ($NestingLevel + 1)) })".Substring($ArrayEnd) + "`r`n$padding}") }
                'Dictionary' { "`r`n$padding@{" + ($inputObject.item | ForEach {$ArrayEnd=1; '; ' + "'$_'" + " = " + (ConvertTo-PSON -inputObject $inputObject.Value[$_] -depth $depth -NestingLevel $NestingLevel+1) }) + '}' }
                'Generic'    { "`r`n$padding@{" + ("$($inputObject.Keys | ForEach {$ArrayEnd=1; ";  $_ =  $(ConvertTo-PSON -inputObject $inputObject.$_ -depth $depth -NestingLevel ($NestingLevel + 1))" })".Substring($ArrayEnd) + "`r`n$padding}") }
                'Object'     { "`r`n$padding@{" + ("$($inputObject | Get-Member -membertype properties | Select-Object name | ForEach {$ArrayEnd=1; ";  $($_.name) =  $(ConvertTo-PSON -inputObject $inputObject.$($_.name) -depth $NestingLevel -NestingLevel ($NestingLevel + 1))" })".Substring($ArrayEnd) + "`r`n$padding}") }
                'XML'        { "`r`n$padding@{" + ("$($inputObject | Get-Member -membertype properties | where name -ne 'schema' | Select-Object name | ForEach {$ArrayEnd=1; ";  $($_.name) =  $(ConvertTo-PSON -inputObject $inputObject.$($_.name) -depth $depth -NestingLevel ($NestingLevel + 1))" })".Substring($ArrayEnd) + "`r`n$padding}") }
                'Datatable'  { "`r`n$padding@{" + ("$($inputObject.TableName)=`r`n$padding @(" + "$($inputObject | ForEach {$ArrayEnd=1; ",$(ConvertTo-PSON -inputObject $_ -depth $depth -NestingLevel ($NestingLevel + 1))" })".Substring($ArrayEnd) + "`r`n$padding  )`r`n$padding}") }
                'DataRow'    { "`r`n$padding@{" + ("$($inputObject | Get-Member -membertype properties | Select-Object name | ForEach {$ArrayEnd=1; "; $($_.name)=  $(ConvertTo-PSON -inputObject $inputObject.$($_.name) -depth $depth -NestingLevel ($NestingLevel + 1))" })".Substring($ArrayEnd) + "}") }
                default { "'$inputObject'" }
            }
        }
        catch
        {
            write-error "Error'$($_)' in script $($_.InvocationInfo.ScriptName) $($_.InvocationInfo.Line.Trim()) (line $($_.InvocationInfo.ScriptLineNumber)) char $($_.InvocationInfo.OffsetInLine) executing $($_.InvocationInfo.MyCommand) on $type object '$($inputObject.Name)' Class: $($inputObject.GetType().Name) BaseClass: $($inputObject.GetType().BaseType.Name) "
        }
        finally { }
    }
    END { }
    }
    
  • 转换为YAML
    function ConvertTo-YAML
        {
    <#
     .SYNOPSIS
     creates a YAML description of the data in the object
     .DESCRIPTION
     This produces YAML from any object you pass to it. It isn't suitable for the huge objects produced by some of the cmdlets such as Get-Process, but fine for simple objects
     .EXAMPLE
       $array=@()
     $array+=Get-Process wi* |  Select-Object Handles,NPM,PM,WS,VM,CPU,Id,ProcessName 
     ConvertTo-YAML $array
    
     .PARAMETER Object 
     the object that you want scripted out
     .PARAMETER Depth
     The depth that you want your object scripted to
     .PARAMETER Nesting Level
     internal use only. required for formatting
    #>
    
       [CmdletBinding()]
       param (
            [parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)][AllowNull()] $inputObject,
            [parameter(Position = 1, Mandatory = $false, ValueFromPipeline = $false)] [int] $depth = 16,
            [parameter(Position = 2, Mandatory = $false, ValueFromPipeline = $false)] [int] $NestingLevel = 0,
            [parameter(Position = 3, Mandatory = $false, ValueFromPipeline = $false)] [int] $XMLAsInnerXML = 0
       )
    
       BEGIN { }
       PROCESS
       {
            If ($inputObject -eq $Null) { $p += 'null'; return $p } # if it is null return null
            if ($NestingLevel -eq 0) { '---' }
    
            $padding = [string]'  ' * $NestingLevel # lets just create our left-padding for the block
            try
            {
              $Type = $inputObject.GetType().Name # we start by getting the object's type
              if ($Type -ieq 'Object[]') { $Type = "$($inputObject.GetType().BaseType.Name)" } #what it really is
              if ($depth -ilt $NestingLevel) { $Type = 'OutOfDepth' } #report the leaves in terms of object type
              elseif ($Type -ieq 'XmlDocument' -or $Type -ieq 'XmlElement')
              {
                 if ($XMLAsInnerXML -ne 0) { $Type = 'InnerXML' }
                 else
                 { $Type = 'XML' }
              } # convert to PS Alias
              # prevent these values being identified as an object
              if (@('boolean', 'byte', 'char', 'datetime', 'decimal', 'double', 'float', 'single', 'guid', 'int', 'int32',
              'int16', 'long', 'int64', 'OutOfDepth', 'RuntimeType', 'PSNoteProperty', 'regex', 'sbyte', 'string',
              'timespan', 'uint16', 'uint32', 'uint64', 'uri', 'version', 'void', 'xml', 'datatable', 'List`1',
              'SqlDataReader', 'datarow', 'ScriptBlock', 'type') -notcontains $type)
              {
                 if ($Type -ieq 'OrderedDictionary') { $Type = 'HashTable' }
                 elseif ($Type -ieq 'PSCustomObject') { $Type = 'PSObject' } #
                 elseif ($inputObject -is "Array") { $Type = 'Array' } # whatever it thinks it is called
                 elseif ($inputObject -is "HashTable") { $Type = 'HashTable' } # for our purposes it is a hashtable
                 elseif (($inputObject | gm -membertype Properties |
                 Select name | Where name -like 'Keys') -ne $null) { $Type = 'generic' } #use dot notation
                 elseif (($inputObject | gm -membertype Properties | Select name).count -gt 1) { $Type = 'Object' }
              }
              write-verbose "$($padding)Type:='$Type', Object type:=$($inputObject.GetType().Name), BaseName:=$($inputObject.GetType().BaseType.Name) "
    
              switch ($Type)
              {
                 'ScriptBlock'{ "{$($inputObject.ToString())}" }
                 'InnerXML'     { "|`r`n" + ($inputObject.OuterXMl.Split("`r`n") | foreach{ "$padding$_`r`n" }) }
                 'DateTime' { $inputObject.ToString('s') } # s=SortableDateTimePattern (based on ISO 8601) using local time
                 'Boolean' {
                      "$(&{
                         if  ($inputObject -eq $true) { '`true' }
                         Else  { '`false' }
                       })"
                 }
                 'string' {
                      $String = "$inputObject"
                      if ($string -match '[\r\n]' -or $string.Length -gt 80)
                      {
                        # right, we have to format it to YAML spec.
                        ">`r`n" # signal that we are going to use the readable 'newlines-folded' format
                        $string.Split("`n") | foreach {
                             $bits = @(); $length = $_.Length; $IndexIntoString = 0; $wrap = 80
                             while ($length -gt $IndexIntoString + $Wrap)
                             {
                               $earliest = $_.Substring($IndexIntoString, $wrap).LastIndexOf(' ')
                               $latest = $_.Substring($IndexIntoString + $wrap).IndexOf(' ')
                               $BreakPoint = &{
                                    if ($earliest -gt ($wrap + $latest)) { $earliest }
                                    else { $wrap + $latest }
                               }
                               if ($earliest -lt (($BreakPoint * 10)/100)) { $BreakPoint = $wrap } # in case it is a string without spaces
                               $padding + $_.Substring($IndexIntoString, $BreakPoint).Trim() + "`r`n"
                               $IndexIntoString += $BreakPoint
                             }
                             if ($IndexIntoString -lt $length) { $padding + $_.Substring($IndexIntoString).Trim() + "`r`n" }
                             else { "`r`n" }
                        }
                      }
                      else { "'$($string -replace '''', '''''')'" }
                 }
                 'Char'  { "([int]$inputObject)" }
                 {
                      @('byte', 'decimal', 'double', 'float', 'single', 'int', 'int32', 'int16', `
                      'long', 'int64', 'sbyte', 'uint16', 'uint32', 'uint64') -contains $_
                 }
                 { "$inputObject" } # rendered as is without single quotes
                 'PSNoteProperty' { "$(ConvertTo-YAML -inputObject $inputObject.Value -depth $depth -NestingLevel ($NestingLevel + 1))" }
                 'Array'   { "$($inputObject | ForEach { "`r`n$padding- $(ConvertTo-YAML -inputObject $_ -depth $depth -NestingLevel ($NestingLevel + 1))" })" }
                 'HashTable'{
                      ("$($inputObject.GetEnumerator() | ForEach {
                        "`r`n$padding  $($_.Name): " +
                         (ConvertTo-YAML -inputObject $_.Value -depth $depth -NestingLevel ($NestingLevel + 1))
                       })")
                 }
                 'PSObject' { ("$($inputObject.PSObject.Properties | ForEach { "`r`n$padding $($_.Name): " + (ConvertTo-YAML -inputObject $_ -depth $depth -NestingLevel ($NestingLevel + 1)) })") }
                 'generic'  { "$($inputObject.Keys | ForEach { "`r`n$padding  $($_):  $(ConvertTo-YAML -inputObject $inputObject.$_ -depth $depth -NestingLevel ($NestingLevel + 1))" })" }
                 'Object' { ("$($inputObject | Get-Member -membertype properties | Select-Object name | ForEach { "`r`n$padding $($_.name): $(ConvertTo-YAML -inputObject $inputObject.$($_.name) -depth $NestingLevel -NestingLevel ($NestingLevel + 1))" })") }
                 'XML' { ("$($inputObject | Get-Member -membertype properties | where-object { @('xml', 'schema') -notcontains $_.name } | Select-Object name | ForEach { "`r`n$padding $($_.name): $(ConvertTo-YAML -inputObject $inputObject.$($_.name) -depth $depth -NestingLevel ($NestingLevel + 1))" })") }
                 'DataRow' { ("$($inputObject | Get-Member -membertype properties | Select-Object name | ForEach { "`r`n$padding $($_.name):  $(ConvertTo-YAML -inputObject $inputObject.$($_.name) -depth $depth -NestingLevel ($NestingLevel + 1))" })") }
                 #  'SqlDataReader'{$all = $inputObject.FieldCount; while ($inputObject.Read()) {for ($i = 0; $i -lt $all; $i++) {"`r`n$padding $($Reader.GetName($i)): $(ConvertTo-YAML -inputObject $($Reader.GetValue($i)) -depth $depth -NestingLevel ($NestingLevel+1))"}}
                 default { "'$inputObject'" }
              }
            }
            catch
            {
              write-error "Error'$($_)' in script $($_.InvocationInfo.ScriptName) $($_.InvocationInfo.Line.Trim()) (line $($_.InvocationInfo.ScriptLineNumber)) char $($_.InvocationInfo.OffsetInLine) executing $($_.InvocationInfo.MyCommand) on $type object '$($inputObject)' Class: $($inputObject.GetType().Name) BaseClass: $($inputObject.GetType().BaseType.Name) "
            }
            finally { }
       }
    
       END { }
    }
    

  • 注意:除了所有这些以外,还请尝试Convertto-json。

    希望能帮助到你...

    关于javascript - 将Powershell对象传递给Node.JS/Electron并将其 package 在HTML标记中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41353314/

    相关文章:

    javascript - Nodejs - Express - 我无法连接到 Socket IO 对象可能是什么问题?

    javascript - Jade 页面被多次渲染

    javascript - JS针对多个类并无限重复

    javascript - 多种图案的 Angular 管

    javascript - 具有序数 x 轴的多线图

    node.js - 如何优雅地重启node.js服务器?

    javascript - 在 angularjs 中查找变量是否为空

    powershell - 为什么我需要在我的 Powershell 配置文件中运行 `ssh-add`?

    windows - 如何批量获取未识别的网络适配器名称

    MySQL 查询异常从 Powershell v4 调用 "Fill"并使用 "2"参数