问题
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