netsh result to powershell object

流过昼夜 提交于 2019-12-02 15:32:34

问题


I am trying to work with netsh from powershell. I want see result from this command such as object, but netsh return string:

netsh wlan show hostednetwork | Get-Member
   TypeName: System.String
...

My script must work on system with rather localization, and I can't use -match for parse string to object directly.

How I can solve my trouble?


回答1:


You got a few alternatives, none of which are nice.

1) Read the netsh output into a string[] and use a custom record parser to create your own object. That is, look at the output on different locales and find out if, say, Hosted newtork settings is always the first header followed by bunch of - characters. If that's the case, assume that next element in array is Mode and so on. This is very error prone, but usually MS command line tools only translate messages, not their order.

2) Look for .Net API for the same information. There is System.Net.NetworkInformation which contains a bunch of connection things. It's a start, though I am not sure if it has info you need.

3) Failing the previous options, use P/Invoke to call native Win32 API. It's a lot of work, so look for pre-existing wrapper libraries before rolling your own.




回答2:


I recently wrote a cmdlet to parse arbitrary, multi-line text using regular expressions, called ConvertFrom-Text. (Not a great name, if you ask me, but it conforms to the PowerShell naming rules; suggestions are welcome!) So assuming you have that cmdlet, here is one possible solution to your question. (Caveat emptor! The regular expression given was derived from a very small sample of netsh output, so may need some tuning.)

$regex = [regex] '(?ms)(?:^\s*$\s*)?^(?<section>.*?)\s*-+\s*(?<data>.*?)\s*^\s*$'
$result = netsh wlan show hostednetwork | Out-String |
    ConvertFrom-Text -pattern $regex -multiline
$result | % {
    $dataObj = [PsCustomObject]@{}
    $_.Data -split "`r`n" | % {
        $element = $_ -split '\s*:\s*'
        Add-Member -InputObject $dataObj -MemberType NoteProperty -Name $element[0].Trim() -Value $element[1].Trim()
    }
    $_.Data = $dataObj # Replace data text with data object
}
$result

On my test system, netsh wlan show hostednetwork returns this:

Hosted network settings
-----------------------
    Mode                   : Allowed
    Settings               : <Not configured>

Hosted network status
---------------------
    Status                 : Not available

And the output of the $result variable in the code above yields this:

section                   data
-------                   ----
Hosted network settings   @{Mode=Allowed; Settings=<Not configured>}
Hosted network status     @{Status=Not available}

So $result is an array of objects with section and data properties, and the latter is an object with properties defined by the output of the netsh command.


Of course, the above does not get you very far without the ConvertFrom-Text cmdlet. So here is the implementation. (I have copious documentation and examples for it, which will be publicly available once I eventually add it to my open-source PowerShell library.)

filter ConvertFrom-Text
{
    [CmdletBinding()]
    Param (
    [Parameter(Mandatory=$true,Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
    [string[]]$InputObject,

    [Parameter(Mandatory=$true,Position=1)]
    [regex]$Pattern,

    [switch]$RequireAll,
    [switch]$Multiline
    )

    if ($Multiline) {
        $dataString = $InputObject -join "`n"
        IterateByMatch $dataString $Pattern
    }
    else {
        IterateByLine $InputObject $Pattern
    }
}

function IterateByLine([string[]]$data, [regex]$regex)
{
    $data | ForEach-Object {
        if ($PSItem -match $regex)
        {
            New-Object PSObject -Property (GetRegexNamedGroups $matches)
        }    
        elseif ($RequireAll) {
            throw "invalid line: $_"
        }
    }
}  

function IterateByMatch([string[]]$data, [regex]$regex)
{
  $regex.matches($data) | Foreach-Object {
    $match = $_
    $obj = new-object object
    $regex.GetGroupNames() |
    Where-Object {$_ -notmatch '^\d+$'} |
    Foreach-Object {
      Add-Member -InputObject $obj NoteProperty `
          $_ $match.groups[$regex.GroupNumberFromName($_)].value
    }
    $obj
  }
}

function Get-RegexNamedGroups($hash)
{
    $newHash = @{};
    $hash.keys | ? { $_ -notmatch '^\d+$' } | % { $newHash[$_] = $hash[$_] }
    $newHash 
} 



回答3:


$netshResult = Invoke-Command -Computername localhost {netsh int tcp show global}
$result = @{}
$netshObject = New-Object psobject -Property @{
    ReceiveSideScalingState = $Null
    ChimneyOffloadState = $Null
    NetDMAState = $Null
} 
$netshResult = $netshResult | Select-String : #break into chunks if colon  only
$i = 0
while($i -lt $netshResult.Length){
    $line = $netshResult[$i]
    $line = $line -split(":")
    $line[0] = $line[0].trim()
    $line[1] = $line[1].trim()
    $result.$($line[0]) = $($line[1])
    $i++
    }
$netshObject.ReceiveSideScalingState = $result.'Receive-Side Scaling State'
$netshObject.ChimneyOffloadState = $result.'Chimney Offload State'
$netshObject.NetDMAState = $result.'NetDMA State'


来源:https://stackoverflow.com/questions/26943777/netsh-result-to-powershell-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!