来自字符串的PowerShell Import-Clixml

时间:2010-03-03 09:12:11

标签: xml serialization powershell

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

它需要一个文件路径作为输入来生成PowerShell对象,并且无法从XML对象获取输入。由于有ConvertTo-Xml cmdlet将PowerShell对象序列化为XML对象,为什么不能从XML转换,这会反过来呢?

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

有没有办法使用cmdlet(可能只有Import-Clixml),而不创建临时文件?

4 个答案:

答案 0 :(得分:1)

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

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并将其转换回来?

否则你仍然可以将临时文件包装到函数中。

答案 1 :(得分:1)

有人写了ConvertTo-CliXml function

因此应该可以以类似的方式编写ConvertFrom-CliXml函数。您应该检查.NET Reflector中的Export-CliXml cmdlet,以确保不需要执行任何其他操作。

关于此问题还有a bug report on Connect

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

答案 2 :(得分: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: $_"
            }
        }
    }
}

答案 3 :(得分:0)

简短表格

[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