【问题标题】:PowerShell's Import-Clixml from a stringPowerShell 的 Import-Clixml 来自字符串
【发布时间】:2010-03-03 09:12:11
【问题描述】:

有没有办法在字符串或 XML 对象上运行 Import-Clixml cmdlet?

它需要文件路径作为输入来生成 PowerShell 对象,并且无法从 XML 对象获取输入。既然有将 PowerShell 对象序列化为 XML 对象的 ConvertTo-Xml cmdlet,为什么没有从 XML 转换,这会起到相反的作用?

我知道 System.Xml.Serialization.XmlSerializer 类可以做到这一点。但是,我想坚持使用 cmdlet 来执行此操作。

有没有办法使用 cmdlet(可能只使用 Import-Clixml)来执行此操作,而无需创建临时文件?

【问题讨论】:

  • 正如 Johannes 指出的那样,我认为没有办法避免文件。你能多谈谈你的场景吗?

标签: xml serialization powershell


【解决方案1】:

我是基于 ConvertFrom-CliXml 编写的。虽然我没有很彻底地测试它,但它似乎有效。

function ConvertFrom-CliXml {
    param(
        [parameter(position=0, mandatory=$true, valuefrompipeline=$true)]
        [validatenotnull()]
        [string]$string
    )
    begin
    {
        $inputstring = ""
    }
    process
    {
        $inputstring += $string
    }
    end
    {
        $type = [type]::gettype("System.Management.Automation.Deserializer")
        $ctor = $type.getconstructor("instance,nonpublic", $null, @([xml.xmlreader]), $null)
        $sr = new-object io.stringreader $inputstring
        $xr = new-object xml.xmltextreader $sr
        $deserializer = $ctor.invoke($xr)
        $method = @($type.getmethods("nonpublic,instance") | where-object {$_.name -like "Deserialize"})[1]
        $done = $type.getmethod("Done", [reflection.bindingflags]"nonpublic,instance")
        while (!$done.invoke($deserializer, @()))
        {
            try {
                $method.invoke($deserializer, "")
            } catch {
                write-warning "Could not deserialize object: $_"
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    短格式

    [Management.Automation.PSSerializer]::Deserialize($cliXmlString)
    

    长格式

    概念证明

    @{ a=1; b = 2,3,4; c = 3.14 } |  Export-Clixml -Path ~\Test.clixml
    $cliXmlString = ( Get-Content -Path ~\Test.clixml ) -join ''
    [Management.Automation.PSSerializer]::Deserialize($cliXmlString)
    

    预期和观察到的输出

    Name                           Value
    ----                           -----
    c                              3.14
    a                              1
    b                              {2, 3, 4}
    

    进一步阅读

    PSSerializer.Deserialize(String) Method

    【讨论】:

      【解决方案3】:

      显而易见的尝试是只给出变量的路径:

      PS Home:\> $xmldata = gci | ConvertTo-Xml
      PS Home:\> Import-Clixml Variable:\xmldata
      Import-Clixml : Cannot open file because the current provider (Microsoft.PowerShell.Core\Variable) cannot open a file.
      At line:1 char:14
      + Import-Clixml <<<<  Variable:\xmldata
          + CategoryInfo          : InvalidArgument: (:) [Import-Clixml], PSInvalidOperationException
          + FullyQualifiedErrorId : ReadWriteFileNotFileSystemProvider,Microsoft.PowerShell.Commands.ImportClixmlCommand
      

      ...遗憾的是失败了。所以我认为没有临时文件就没有真正可行的方法。

      ConvertTo-XML 的要点是允许在将对象转换为 XML 之后在 PowerShell 中进一步处理 XML。所以问题是为什么不能直接对对象进行更改而不是操作 XML 并将其转换回来?

      否则你仍然可以将临时文件的东西包装到一个函数中。

      【讨论】:

      • 我想将 XML 存储在其他地方而不是文件(可能是数据库),这就是为什么我希望能够使用其他输入而不是文件。不管怎样,谢谢你的回答,我只是觉得有一些我一开始没有想到的明显方法。
      【解决方案4】:

      有人写了ConvertTo-CliXml function

      所以应该可以用类似的方式编写一个 ConvertFrom-CliXml 函数。您应该检查 .NET Reflector 中的 Export-CliXml cmdlet,以确保没有其他需要做的事情。

      还有a bug report on Connect关于这个:

      我知道这并不能立即解决您的问题,但唯一的其他方法是使用临时文件作为 *-CliXml cmdlet 的输入和输出。

      【讨论】:

      • 为我正在从事的项目编写自己的函数将是矫枉过正并且可能容易出错。我会坚持使用临时文件。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-27
      • 2017-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-08
      相关资源
      最近更新 更多