2016-12-27 80 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:接受答案,如果它可以幫助你。 –

相關問題