[英]How can I speed up powershell to get firewall rules on windows 10?
我需要使用 PowerShell 枚舉 Windows 10 上的所有防火牆規則。 我從netsh
切換到 PowerShell,因為一些內置規則的名稱很有趣,例如@{microsoft.windows.shellexperiencehost_10.0.17134.1_neutral_neutral_cw5n1h2txyewy?ms-resource://microsoft.windows.shellexperiencehost/resources/pkgdisplayname}
而我無法使用使用netsh
管理。 切換到 PowerShell 顯示真實名稱是一個 UID 並解決了我的問題,但代碼運行起來真的很慢:
PS C:\Users\vagrant\Desktop> Measure-Command {.\ps-slow.ps1 show}
Seconds : 48
...
與Measure-Command {show-netfirewallrule}
:
...
Milliseconds : 644
和netsh
:
PS C:\Users\vagrant\Desktop> Measure-Command { netsh advfirewall firewall show rule all verbose}
...
TotalSeconds : 1.0588127
通過注釋掉腳本的Get-NetFirewall*Filter
部分,它會全速運行,但當然缺少我想要的所有數據。 這個想法是收集所有防火牆規則的詳細信息,然后將批次輸出為 JSON。
有誰知道如何優化它? 我是 PowerShell 菜鳥,所以我希望我錯過了一些明顯的東西。 完整的腳本是:
Show-NetFirewallRule | `
Where-Object { $_.cimclass.toString() -eq "root/standardcimv2:MSFT_NetFirewallRule" } | `
ForEach-Object { `
$af = $_ | Get-NetFirewallAddressFilter | Select-Object -First 1; # Assumes only one filter
$appf = $_ | Get-NetFirewallApplicationFilter | Select-Object -First 1; # Assumes only one filter
$pf = $_ | Get-NetFirewallPortFilter | Select-Object -First 1; # Assumes only one filter
$if = $_ | Get-NetFirewallInterfaceTypeFilter | Select-Object -First 1; # Assumes only one filter
New-Object -Type PSCustomObject -Property @{
Name = $_.Name
DisplayName = $_.DisplayName
Description = $_.Description
Enabled = $_.Enabled.toString()
Action = $_.Action.toString()
Direction = $_.Direction.toString()
EdgeTraversalPolicy = $_.EdgeTraversalPolicy.toString()
Profile = $_.Profile.toString()
DisplayGroup = $_.DisplayGroup
# Address Filter
LocalAddress = $af.LocalAddress
RemoteAddress = $af.RemoteAddress
LocalIp = $af.LocalIp
RemoteIp = $af.RemoteIp
# Port Filter
LocalPort = $pf.LocalPort
RemotePort = $pf.RemotePort
Protocol = $pf.Protocol
IcmpType = $pf.IcmpType
# Application Filter
Program = $appf.Program
# Interface Filter
InterfaceType = $if.InterfaceType.toString()
}
} | Convertto-json
好的,感謝所有發帖的人。 最初的問題是netsh
留下未解析的名稱,例如:
@{Microsoft.Todos_1.41.12842.0_x64__8wekyb3d8bbwe?ms-resource://Microsoft.Todos/Resources/app_name_ms_todo}
@{Microsoft.Todos_1.41.12842.0_x64__8wekyb3d8bbwe?ms-resource://Microsoft.Todos/Resources/app_name_ms_todo}
在只能由 PowerShell 解析的輸出中,使用原始腳本。 這種方法的問題是速度非常慢(幾分鍾)。
關於這個線程和同事的建議是:
@FirewallAPI.dll,-25427
到引用的任何資源)New-Object -ComObject HNetCfg.FwPolicy
(與netsh
有相同的輸出問題)綜上所述,如果不犧牲我想要的數據,我想要的優化是不可能的。 我將在大部分時間嘗試使用更快的 COM API/netsh,但在別無選擇時切換到使用 powershell API(當未解析的名稱迫使我們這樣做時)
這種方法更快,因此,您可能會采用不同的方法來獲取相同的信息。
param
(
[switch]$Local,
[switch]$GPO
)
# If no switches are set the script will default to local firewall rules
if (!($Local) -and !($Gpo))
{ $Local = $true }
$RegistryKeys = @()
if ($Local) {$RegistryKeys += 'Registry::HKLM\System\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\FirewallRules'}
if ($GPO) {$RegistryKeys += 'Registry::HKLM\Software\Policies\Microsoft\WindowsFirewall\FirewallRules'}
Foreach ($Key in $RegistryKeys)
{
if (Test-Path -Path $Key)
{
(Get-ItemProperty -Path $Key).PSObject.Members |
Where-Object {
(@('PSPath','PSParentPath','PSChildName') -notcontains $_.Name) -and
($_.MemberType -eq 'NoteProperty') -and
($_.TypeNameOfValue -eq 'System.String')} |
ForEach-Object {
# Prepare hashtable
$HashProps = @{
NameOfRule = $_.Name
RuleVersion = ($_.Value -split '\|')[0]
Action = $null
Active = $null
Dir = $null
Protocol = $null
LPort = $null
App = $null
Name = $null
Desc = $null
EmbedCtxt = $null
Profile = $null
RA4 = $null
RA6 = $null
Svc = $null
RPort = $null
ICMP6 = $null
Edge = $null
LA4 = $null
LA6 = $null
ICMP4 = $null
LPort2_10 = $null
RPort2_10 = $null
}
# Determine if this is a local or a group policy rule and display this in the hashtable
if ($Key -match 'HKLM\\System\\CurrentControlSet')
{ $HashProps.RuleType = 'Local' }
else
{ $HashProps.RuleType = 'GPO' }
# Iterate through the value of the registry key and fill PSObject with the relevant data
ForEach ($FireWallRule in ($_.Value -split '\|'))
{
switch (($FireWallRule -split '=')[0])
{
'Action' {$HashProps.Action = ($FireWallRule -split '=')[1]}
'Active' {$HashProps.Active = ($FireWallRule -split '=')[1]}
'Dir' {$HashProps.Dir = ($FireWallRule -split '=')[1]}
'Protocol' {$HashProps.Protocol = ($FireWallRule -split '=')[1]}
'LPort' {$HashProps.LPort = ($FireWallRule -split '=')[1]}
'App' {$HashProps.App = ($FireWallRule -split '=')[1]}
'Name' {$HashProps.Name = ($FireWallRule -split '=')[1]}
'Desc' {$HashProps.Desc = ($FireWallRule -split '=')[1]}
'EmbedCtxt' {$HashProps.EmbedCtxt = ($FireWallRule -split '=')[1]}
'Profile' {$HashProps.Profile = ($FireWallRule -split '=')[1]}
'RA4' {[array]$HashProps.RA4 += ($FireWallRule -split '=')[1]}
'RA6' {[array]$HashProps.RA6 += ($FireWallRule -split '=')[1]}
'Svc' {$HashProps.Svc = ($FireWallRule -split '=')[1]}
'RPort' {$HashProps.RPort = ($FireWallRule -split '=')[1]}
'ICMP6' {$HashProps.ICMP6 = ($FireWallRule -split '=')[1]}
'Edge' {$HashProps.Edge = ($FireWallRule -split '=')[1]}
'LA4' {[array]$HashProps.LA4 += ($FireWallRule -split '=')[1]}
'LA6' {[array]$HashProps.LA6 += ($FireWallRule -split '=')[1]}
'ICMP4' {$HashProps.ICMP4 = ($FireWallRule -split '=')[1]}
'LPort2_10' {$HashProps.LPort2_10 = ($FireWallRule -split '=')[1]}
'RPort2_10' {$HashProps.RPort2_10 = ($FireWallRule -split '=')[1]}
Default {}
}
}
# Create and output object using the properties defined in the hashtable
New-Object -TypeName 'PSCustomObject' -Property $HashProps
}
}
}
# Partial results
Action : Allow
LPort2_10 :
RuleType : Local
LPort : 135
Edge :
LA6 :
Dir : In
Desc : @icsvc.dll,-710
ICMP4 :
RA4 :
Name : @icsvc.dll,-709
LA4 :
App : %SystemRoot%\system32\svchost.exe
ICMP6 :
Protocol : 6
RuleVersion : v2.0
NameOfRule : vm-monitoring-dcom
RPort :
Svc : RpcSs
RA6 :
Profile :
EmbedCtxt : @icsvc.dll,-700
RPort2_10 :
Active : FALSE
Get-NetFirewallRule
滿足您的需求嗎?
$MyRules = Get-NetFirewallRule
foreach ($rule in $MyRules) {
[the rest of your code]
}
我不認為這很好理解,但 get-netfirewall*filter 命令旨在更快地完成任務。 只需將第一個管道與第二個管道進行比較。 這就像在 get-childitem 或 get-wmiobject 等其他命令中使用 -filter 選項一樣。 我認為即使是在線幫助的作者也無法理解這一點。 就像 powershell 只有 80% 的文檔。
Get-NetFirewallRule |
Get-NetFirewallPortFilter |
Where LocalPort -eq 3389 | Get-NetFirewallRule |
Set-NetFirewallRule -RemoteAddress 192.168.1.1 -WhatIf
Get-NetFirewallPortFilter |
Where LocalPort -eq 3389 | Get-NetFirewallRule |
Set-NetFirewallRule -RemoteAddress 192.168.1.1 -WhatIf
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.