You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用BinaryFormatter序列化PowerShell类时遇SerializationException问题求助

解决PowerShell中BinaryFormatter序列化自定义TreeNode类的SerializationException问题

这个报错的核心原因是:你用PowerShell原生class关键字定义的类型,会被PowerShell自动注入一些和会话状态绑定的内部成员(比如System.Management.Automation.SessionStateInternal),这些成员本身是不可序列化的,当BinaryFormatter尝试遍历对象的所有成员进行序列化时,就会触发这个异常。

下面给你几个可行的解决方案,按推荐优先级排序:

方案1:用Add-Type定义纯C#类(最稳妥)

PowerShell的class语法会在后台添加很多PowerShell特有的属性,而用Add-Type定义的C#类是标准的.NET类型,不会附带这些额外成员,所以可以直接被BinaryFormatter序列化:

Add-Type @"
[Serializable]
public class TreeNode {
    // 这里添加你的树形结构所需的成员,比如名称、子节点列表等
    public string NodeName { get; set; }
    public System.Collections.Generic.List<TreeNode> ChildNodes { get; set; } = new System.Collections.Generic.List<TreeNode>();
}
"@

# 创建树形结构实例
$rootNode = New-Object TreeNode
$rootNode.NodeName = "Root"

$childNode = New-Object TreeNode
$childNode.NodeName = "Child 1"
$rootNode.ChildNodes.Add($childNode)

# 执行序列化
$fileStream = New-Object System.IO.FileStream 'storage.bin', ([System.IO.FileMode]::Create)
$binaryFormatter = New-Object System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
$binaryFormatter.Serialize($fileStream, $rootNode)
$fileStream.Close()

方案2:实现ISerializable接口手动控制序列化(保留PowerShell类)

如果你一定要用PowerShell的class语法,可以通过实现ISerializable接口,手动指定需要序列化的成员,排除PowerShell注入的不可序列化属性:

using namespace System.Runtime.Serialization
using namespace System.Security.Permissions

[Serializable()]
class TreeNode : ISerializable {
    # 自定义成员
    [string]$NodeName
    [System.Collections.Generic.List[TreeNode]]$ChildNodes = @()

    # 无参构造函数(反序列化必须)
    TreeNode() {}

    # 反序列化构造函数
    protected TreeNode([SerializationInfo]$info, [StreamingContext]$context) {
        $this.NodeName = $info.GetString("NodeName")
        $this.ChildNodes = $info.GetValue("ChildNodes", [System.Collections.Generic.List[TreeNode]])
    }

    # 控制序列化的成员
    [SecurityPermission(SecurityAction.Demand, SerializationFormatter=$true)]
    void GetObjectData([SerializationInfo]$info, [StreamingContext]$context) {
        # 只添加你需要序列化的自定义成员
        $info.AddValue("NodeName", $this.NodeName)
        $info.AddValue("ChildNodes", $this.ChildNodes)
    }
}

# 测试序列化
$root = [TreeNode]::new()
$root.NodeName = "Root Node"

$fileStream = New-Object System.IO.FileStream 'storage.bin', ([System.IO.FileMode]::Create)
$binaryFormatter = New-Object System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
$binaryFormatter.Serialize($fileStream, $root)
$fileStream.Close()

方案3:改用更安全的序列化方式(推荐替代BinaryFormatter)

BinaryFormatter已经被.NET官方标记为不安全(存在远程代码执行风险),如果你的场景不需要二进制格式,推荐用JSON或XML序列化,PowerShell原生支持,而且完全避免这类问题:

# 定义PowerShell树形类
class TreeNode {
    [string]$NodeName
    [System.Collections.Generic.List[TreeNode]]$ChildNodes = @()
}

# 构建树形结构
$root = [TreeNode]::new()
$root.NodeName = "Root"
$child1 = [TreeNode]::new()
$child1.NodeName = "Child 1"
$root.ChildNodes.Add($child1)

# 序列化到JSON文件(指定Depth确保深层结构被序列化)
$root | ConvertTo-Json -Depth 10 | Out-File "tree_storage.json" -Encoding UTF8

# 反序列化回对象
$deserializedTree = Get-Content "tree_storage.json" -Encoding UTF8 | ConvertFrom-Json

内容的提问来源于stack exchange,提问作者Rabash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:21:00