无法在响应数据协定中反序列化PSObject。耗尽线索

时间:2018-01-25 19:23:43

标签: c# powershell wcf serialization

背景

我工作的公司有一个通过WCF向网络公开的产品,特别是通过一个包含处理所有消息的单一方法的服务合同。在内部,产品解析SOAP标头和正文,加载服务插件,并将请求路由到该插件。

我已经编写了其中一个插件来托管PowerShell运行时,并提供了一个挂钩到该产品的某些内部管道的自定义主机。远程客户端可以向服务器发送任意脚本以执行,包括利用产品本身的功能。

要明确:我很清楚安全隐患。此插件仅用于诊断和原型设计,不适用于生产用途或部署。

问题:

在作为回复发回的数据合同中,我传递了一组PSObject个实例:

[DataContractAttribute]
public partial class RunScriptResponse
{
    [DataMember]
    public PSObject[] Output { get; set; }
}

根据this article,应支持PSObject;它实现ISerializable并拥有SerializableAttribute

响应数据合同正在由服务器进行序列化,并且正在被客户端无故接收 - 正如WCF可扩展性点所验证的那样。但是,当服务客户端尝试反序列化对象时,我点击了[1]:

Member 'CliXml' was not found.

然而,看看响应XML,它非常清楚,那个成员就在那里:

<RunScriptResponse xmlns="...">
  <RunScriptResult xmlns:d1p1="..." xmlns:e="..." xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <e:Output xmlns:d1p1="http://schemas.datacontract.org/2004/07/System.Management.Automation">
      <d1p1:PSObject>
        <CliXml i:type="d3p1:string" xmlns:d3p1="http://www.w3.org/2001/XMLSchema">
          &lt;Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04"&gt;

它表明在反序列化过程中发生某事PSObject无法找到<CliXml>元素,但我无法弄清楚为什么

此外,尝试访问此服务器的特定客户端本身就是PowerShell模块,通过反射从代理程序集动态生成。目的是您可以将脚本传递给服务器,返回一些PSObject实例,并在客户端上进行进一步处理。

鉴于其自动生成的性质,无法切换到其他序列化方案,例如序列化服务器上​​的PSObject实例,传递字符串数组,然后在其上反序列化它们客户。这将需要独特的一对一方法处理,这将使模块生成过程显着复杂化。

有没有人对如何进一步解决此问题或其他策略有任何建议?

谢谢!

[1]异常的堆栈跟踪:

   at System.Runtime.Serialization.SerializationInfo.GetElement(String name, Type& foundType)
   at System.Runtime.Serialization.SerializationInfo.GetValue(String name, Type type)
   at System.Management.Automation.PSObject..ctor(SerializationInfo info, StreamingContext context)
   at ReadPSObjectFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
   at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
   at ReadArrayOfPSObjectFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString , XmlDictionaryString , CollectionDataContract )
   at System.Runtime.Serialization.CollectionDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
   at ReadRunScriptResponseFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
   at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, String name, String ns)
   at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.DataContractSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.PartInfo.ReadObject(XmlDictionaryReader reader, XmlObjectSerializer serializer)
   at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.DeserializeParameterPart(XmlDictionaryReader reader, PartInfo part, Boolean isRequest)

20180129:我在客户端使用的代码是普通的WCF。我通过svcutil.exe从服务接口程序集导出WSDL和XSD,然后通过svcutil.exe运行它们以生成C#代理。从那里,一切都只是按原样调用代理:

// Utility code that wraps the programmatic generation of a proxy.
// Manually instantiates `WSHttpBinding` and `EndpointAddress`, then
// constructs an instance of the proxy client using those two objects.
//
var client = GenerateProxyClient<RunScriptRequest,
                                 IScriptingService, 
                                 ScriptingServiceClient, 
                                 RunScriptResponse>();

var response = client.RunScript(new RunScriptRequest
    {
        Script = @"Get-ChildItem C:\"
    });

0 个答案:

没有答案