c# - 以空值将Powershell内容保存为JSON

标签 c# json powershell

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

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"

输出文件是这个(这是文件的一小部分)
        "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值和Count;在我的代码(C#)中,我编写此代码来读取我的JSON文件
string file = File.ReadAllText(MainWindow.path + @"\..\..\misc\json\FirewallRules.json");
List<GetSetFRules> rulesList = JsonConvert.DeserializeObject<List<GetSetFRules>>(file);

但有个问题; GetSetFRules类无法保存JSON的内容,因为JSON中的格式对于每个规则而言都不相同
 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; }
    }

所以,问题是,有没有办法像这样用空值保存每个规则?
[...]"LocalPort":  "Any",[...]

⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇⬇
[...]"LocalPort":  {
                          "value":  [
                                        "Any",
                                    ],
                          "Count":  1
                      }[...]

或这个
[...]"LocalPort":  {
                          "value":  [
                                        "",
                                    ],
                          "Count":  0
                      }[...]

最佳答案

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

@{
  Name='LocalPort'
  Expression={ , [array] ($PSItem | Get-NetFirewallPortFilter).LocalPort }
}
  • 强制转换[array]可以确保将命令输出视为数组,即使仅输出单个值(例如Any)也是如此。
  • 数组构造运算符,的一元形式将结果数组包装在aux中。临时数组,当将脚本块的({ ... })输出分配给Expression哈希表条目时,可以防止单个元素数组解包。

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

    上面的代码将始终为您提供所需的JSON表示形式,但是有一个警告:
    ConvertTo-Json通过对象为数组创建的JSON表示形式(包含数组元素的value属性和元素计数的count属性)应视为错误,因为数组应简单地表示为JSON数组:

    也就是说,类似:
    , (80, 443) | ConvertTo-Json
    

    应该产生:
    # OK: This is how it works in PowerShell v6+
    [
      80,
      443
    ]
    

    并不是:
    # BUG in Windows PowerShell v5.1
    {
        "value":  [
                      80,
                      443
                  ],
        "Count":  2
    }
    

    This answer讨论了详细信息,但是请注意,可以在给定的Windows PowerShell session 中运行以下命令一次来解决此问题:
    # Run this once per session, before calling ConvertTo-Json, to 
    # fix the JSON array serialization problem:
    Remove-TypeData System.Array -ErrorAction Ignore
    

    关于c# - 以空值将Powershell内容保存为JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59453502/

    相关文章:

    c# - 服务定位器模式下的单元测试

    iOS Swift 将具有奇怪格式的 JSON 响应转换为字典

    powershell - 使用PowerShell将GUID字符串转换为octetBytes

    json - 捕获json格式日志的两个时间戳之间的所有日志

    javascript - Jade/PUG JSON 插值

    powershell:坚持使用简单的 DateTime 脚本

    powershell - 将 "Visual Studio code"与交互式 Powershell 窗口(如 Powershell ISE)结合使用

    c# - ASP.NET MVC 查询在未请求时部署了应用程序服务器地址

    c# - 仅用正则表达式替换某些组

    c# - 关于 Visual Studio 和 MySQL 连接的问题