2014-11-15 52 views
0

我想與netshpowershell。我希望看到導致該命令,如對象,但netsh的返回字符串:netsh結果powershell對象

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

我的腳本必須對系統工作,而本地化的,我不能使用-match用於解析字符串對象直接。

我該如何解決我的麻煩?

回答

2

你有幾個選擇,其中沒有一個很好。

1)將netsh輸出讀入string[],並使用自定義記錄解析器創建自己的對象。也就是說,查看不同語言環境的輸出,並確定是否Hosted newtork settings始終是第一個標題,後面跟着一堆-個字符。如果是這種情況,則假定數組中的下一個元素是Mode依此類推。這很容易出錯,但通常MS命令行工具只能翻譯消息,而不是他們的命令。

2)查找.Net API獲取相同的信息。有System.Net.NetworkInformation其中包含一堆連接的東西。這是一個開始,但我不確定它是否有你需要的信息。

3)如果以前的選項失敗,請使用P/Invoke撥打native Win32 API。這是很多工作,所以在滾動你自己的代碼之前查找預先存在的包裝庫。

1

我最近編寫了一個cmdlet來使用正則表達式來解析任意的多行文本,稱爲ConvertFrom-Text。 (如果你問我,不是很好的名字,但它符合PowerShell命名規則;歡迎提供建議!)所以假設你有這個cmdlet,這裏有一個可能的解決方案來解決你的問題。 (!買者自負給出從netsh的輸出的一個非常小的樣本得出的正則表達式,所以可能需要一些調整)

$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 

在我的測試系統,netsh wlan show hostednetwork返回此:

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

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

而且在上面的代碼中的變量$result的輸出產生這樣的:

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

所以$結果是對象的與section和陣列屬性,而後者是具有由netsh命令的輸出定義的屬性的對象。


當然,上面並沒有讓你很遠,沒有ConvertFrom-Text cmdlet的。所以這裏是實現。 (我有豐富的文檔和它的例子,這將是公開可用一次,我終於把它添加到我的開放源代碼的PowerShell庫)。

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 
} 
1
$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'