首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将powershell内容保存为带有空值的JSON

将powershell内容保存为带有空值的JSON
EN

Stack Overflow用户
提问于 2019-12-23 10:13:05
回答 3查看 331关注 0票数 2

我必须使用命令Get-NetFirewallRule保存一些信息,并将它们保存在一个.JSON文件中。我就是这样做的

代码语言:javascript
复制
Get-NetFirewallRule  |
select-object -Property Name,
DisplayName,
DisplayGroup,
@{Name='Protocol';Expression={($PSItem | Get-NetFirewallPortFilter).Protocol}},
@{Name='LocalPort';Expression={($PSItem | Get-NetFirewallPortFilter).LocalPort}},
@{Name='RemotePort';Expression={($PSItem | Get-NetFirewallPortFilter).RemotePort}},
@{Name='RemoteAddress';Expression={($PSItem | Get-NetFirewallAddressFilter).RemoteAddress}},
Enabled,
Profile,
Direction,
Action |
ConvertTo-Json | Out-File "C:\Users\Administrator\Desktop\firewall.txt"

输出文件如下(这是文件的一小部分)

代码语言:javascript
复制
        "Name":  "Microsoft-Windows-PeerDist-WSD-Out",
        "DisplayName":  "BranchCache Peer Discovery (WSD-Out)",
        "DisplayGroup":  "BranchCache - Peer Discovery (Uses WSD)",
        "Protocol":  "UDP",
        "LocalPort":  "Any",
        "RemotePort":  "3702",
        "RemoteAddress":  "LocalSubnet",
        "Enabled":  2,
        "Profile":  0,
        "Direction":  2,
        "Action":  2
    },
    {
        "Name":  "Microsoft-Windows-PeerDist-HostedServer-In",
        "DisplayName":  "BranchCache Hosted Cache Server (HTTP-In)",
        "DisplayGroup":  "BranchCache - Hosted Cache Server (Uses HTTPS)",
        "Protocol":  "TCP",
        "LocalPort":  {
                          "value":  [
                                        "80",
                                        "443"
                                    ],
                          "Count":  2
                      },
        "RemotePort":  "Any",
        "RemoteAddress":  "Any",
        "Enabled":  2,
        "Profile":  0,
        "Direction":  1,
        "Action":  2
    }

如您所见,powershell以两种不同的方式保存LocalPort :第一种使用1值,第二种使用2值和计数;在我的代码(C#)中,我编写了以下代码来读取JSON文件

代码语言:javascript
复制
string file = File.ReadAllText(MainWindow.path + @"\..\..\misc\json\FirewallRules.json");
List<GetSetFRules> rulesList = JsonConvert.DeserializeObject<List<GetSetFRules>>(file);

但是有一个问题:类GetSetFRules无法保存JSON的内容,因为JSON中的格式对于每个规则都不一样

代码语言:javascript
复制
 class GetSetFRules
    {
        public string Name { get; set; }
        public string DisplayName { get; set; }
        public string DisplayGroup { get; set; }
        public string Protocol { get; set; }
        public Localport LocalPort { get; set; }
        public string RemotePort { get; set; }
        public string RemoteAddress { get; set; }
        public int Enabled { get; set; }
        public int Profile { get; set; }
        public int Direction { get; set; }
        public int Action { get; set; }
    }

    public class Localport
    {
        public string[] value { get; set; }
        public int Count { get; set; }
    }

那么,问题是,是否有一种方法可以像这样保存每个空值的规则?

代码语言:javascript
复制
[...]"LocalPort":  "Any",[...]

⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇

代码语言:javascript
复制
[...]"LocalPort":  {
                          "value":  [
                                        "Any",
                                    ],
                          "Count":  1
                      }[...]

或者这个

代码语言:javascript
复制
[...]"LocalPort":  {
                          "value":  [
                                        "",
                                    ],
                          "Count":  0
                      }[...]
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-12-23 18:38:53

您需要确保计算出的($PSItem | Get-NetFirewallPortFilter).LocalPort属性中的LocalPort输出是数组类型的,可以确保如下所示:

代码语言:javascript
复制
@{
  Name='LocalPort'
  Expression={ , [array] ($PSItem | Get-NetFirewallPortFilter).LocalPort }
}

  • Cast [array]确保将命令输出作为数组处理,即使只有一个值(如Any )被输出。数组构造操作符,的一元形式
  • 将结果数组包装在aux中。当脚本块({ ... })的输出分配给Expression哈希表条目时,防止单个元素数组被打开的临时数组.

顺便说一句:正如Theo指出的那样,in his answer和一个优化一样,对同一个输入对象多次调用Get-NetFireWallPortFilter,跨越多个计算的属性,效率很低,并且降低了命令的速度。

上面的内容将始终如一地为您提供所需的JSON表示,但是有一个警告

ConvertTo-Json通过一个对象为数组创建的JSON表示形式(包含带有数组元素的value属性和带有元素计数的count属性)应该被视为一个bug,因为数组应该简单地表示为JSON数组

也就是说,就像:

代码语言:javascript
复制
, (80, 443) | ConvertTo-Json

应该屈服:

代码语言:javascript
复制
# OK: This is how it works in PowerShell v6+
[
  80,
  443
]

而不是

代码语言:javascript
复制
# BUG in Windows PowerShell v5.1
{
    "value":  [
                  80,
                  443
              ],
    "Count":  2
}

This answer讨论了详细信息,但请注意,在给定的PowerShell会话中运行以下一次可用于修复问题:

代码语言:javascript
复制
# Run this once per session, before calling ConvertTo-Json, to 
# fix the JSON array serialization problem:
Remove-TypeData System.Array -ErrorAction Ignore
票数 0
EN

Stack Overflow用户

发布于 2019-12-23 13:42:48

我想我找到了解决办法

将类GetSetFRules替换为类dynamic

代码语言:javascript
复制
List<dynamic> rulesList = JsonConvert.DeserializeObject<List<dynamic>>(file);
票数 0
EN

Stack Overflow用户

发布于 2019-12-23 14:48:09

在我的Win10机器上,使用Powershell代码还显示了RemotePortProtocol的数组输出。我认为最好不要尝试调整所有的项,使其具有这样的输出,而是将所有的规则对象按原样列出,这样它们都有这些属性的一个值。

另外,您可以通过不多次执行Get-NetFirewallPortFilter来加快速度:

代码语言:javascript
复制
# Retrieve every firewall rule object as single object.
# All of these objects will have properties 'LocalPort', RemotePort, 'Protocol'
# listed as single string values; not as array values in the output
Get-NetFirewallRule | ForEach-Object {
    $portFilter = $_ | Get-NetFirewallPortFilter
    $_ | Select-Object -Property Name,
    DisplayName,
    DisplayGroup,
    @{Name='Protocol';Expression={$portFilter.Protocol}},
    @{Name='LocalPort';Expression={$portFilter.LocalPort}},
    @{Name='RemotePort';Expression={$portFilter.RemotePort}},
    @{Name='RemoteAddress';Expression={($_ | Get-NetFirewallAddressFilter).RemoteAddress}},
    Enabled,
    Profile,
    Direction,
    Action 
} | Sort-Object DisplayName | ConvertTo-Json | Out-File "C:\Users\Administrator\Desktop\firewall.txt"

部分产出:

{“名称”:“{56BC733-582E-45e8-9249-F88002B598E9}”、"DisplayName":"Microsoft管理控制台“、"DisplayGroup":null、”协议“:"TCP”、"LocalPort":“任意”、"RemotePort":“任意”、"RemoteAddress":“任意”、“启用”:1。“配置文件”:4,“指示”:1,“操作”:4 },{“名称”:"{C3F4E91A-65F5-4805-8F6B-86C6ECA5F4EE}","DisplayName":“”,"DisplayGroup":null,"Protocol":"UDP","LocalPort":"Any","RemotePort":"Any","RemoteAddress":"Any","Enabled":1,"Profile":4,“RemotePort”:1,"Action":4 },{ "Name":"UDP Query RemotePort“"DisplayName":"DisplayGroup":null,“协议”:"UDP","LocalPort":“任意”,"RemotePort":“任何”,"RemoteAddress":“任意”,“启用”:1,“配置文件”:2,“方向”:1,“操作”:2 },{“名称”:"TCP查询User{C99F0EF2-8891-4B2D-B389-4A3F8B66638A}C:\windows\system32\mmc.exe",“DisplayName:"Microsoft管理控制台”、"DisplayGroup":null、“DisplayGroup”:"TCP“、"LocalPort":”Any“、"RemotePort":"Any","RemoteAddress":“任意”,“启用”:1,“配置文件”:2,“方向”:1,“操作”:2}

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59453502

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档