2016-12-27 79 views
0

我正在试图在Electron中编写一个调用Powershell脚本的工具。将PowerShell对象传递给Node.JS/Electron并将它们包装在HTML标记中

我知道如何让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用于Object-to-HTML和格式更有意义,不是吗?

+0

'stdout'不会成为它的对象的格式化版本。转换为JSON可能会为您提供更有用的JavaScript格式(我假设您可以解析它)。你这样做'Get-Process -Name WmiPrvSE | ConvertTo-Json -Depth 2'。所以你只能得到JSON,当你调用'powershell.exe','-NoLogo'时,你需要添加下面的开关。尽量保持深度尽可能浅。过程对象具有许多丰富的属性。如果您将其中的很多事件序列化为事件深度2,则需要一些时间。 – TravisEz13

+0

听起来不错,它回答了问题的一部分。我如何解析它在Javascript中获取对象并在HTML中设置它们的格式?我试过'JSON.parse(child)',但是这给了我一个错误。 – 30000MONKEYS

回答

0

根据我的理解,标准输出不会在这种情况下工作,因为它将有自己的格式化显示方式。除了本机PowerShell转换之外,我除了几个​​转换功能之外。你应该尝试一下,然后你应该解析输出。

在这里你去:

  • 的ConvertTo-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 
  • 的ConvertTo-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 
        [email protected]() 
        $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`[email protected](" + ("$($inputObject | ForEach {$ArrayEnd=1; ",$(ConvertTo-PSON -inputObject $_ -depth $depth -NestingLevel ($NestingLevel + 1))" })".Substring($ArrayEnd)) + "`r`n$padding)" } 
          'HashTable' { "`r`[email protected]{" + ("$($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`[email protected]{" + ($inputObject.item | ForEach {$ArrayEnd=1; '; ' + "'$_'" + " = " + (ConvertTo-PSON -inputObject $inputObject.Value[$_] -depth $depth -NestingLevel $NestingLevel+1) }) + '}' } 
          'Generic' { "`r`[email protected]{" + ("$($inputObject.Keys | ForEach {$ArrayEnd=1; "; $_ = $(ConvertTo-PSON -inputObject $inputObject.$_ -depth $depth -NestingLevel ($NestingLevel + 1))" })".Substring($ArrayEnd) + "`r`n$padding}") } 
          'Object'  { "`r`[email protected]{" + ("$($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`[email protected]{" + ("$($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`[email protected]{" + ("$($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`[email protected]{" + ("$($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 { } 
    } 
    
  • 的ConvertTo-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 
        [email protected]() 
    $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也除了所有这些。

希望它有帮助...

+0

哇,很好的功能。现在我只需要知道如何获得输出到我的Javascript;) – 30000MONKEYS

+0

@ 30000MONKEYS:高兴地帮助..Goodluck –

+0

@ 30000MONKEYS:接受答案,如果它可以帮助你。 –

相关问题