从powershell执行单向wcf服务操作

时间:2010-01-04 23:08:03

标签: .net wcf powershell

我有一个计划任务,每小时执行一次powershell脚本。 powershell脚本必须调用单向WCF服务操作。基本上它只需要启动一个操作。我的问题是我该怎么做呢?我认为只是执行url实际上会启动请求,但显然这是不正确的。

这是我想要做的事情:

$request = [System.Net.WebRequest]::Create("http://myserver.com/myservice/dosomething")
$request.GetResponse()

该操作不接受任何参数并返回void。

5 个答案:

答案 0 :(得分:8)

PowerShell 2.0使用New-WebServiceProxy cmdlet实现这一点:例如:

$zip = New-WebServiceProxy -uri http://www.webservicex.net/uszip.asmx?WSDL
$zip.getinfobyzip(20500).table

CITY      : Washington
STATE     : DC
ZIP       : 20500
AREA_CODE : 202
TIME_ZONE : E

答案 1 :(得分:7)

我认为问题在于您拥有的代码实际上是在创建HttpWebRequest,而不是WCF请求。 (换句话说,它只是在URL上执行HTTP GET请求,没有SOAP或.NET Remoting信息。)

您应该能够按照这些说明创建合适的端点:

http://msdn.microsoft.com/en-us/magazine/cc163647.aspx#S11

看起来应该是这样的:

$httpBinding = New-Object System.ServiceModel.BasicHttpBinding
$endpointAddress = New-Object System.ServiceModel.EndpointAddress 'http://myserver.com/myservice/dosomething'
$contractDescription = [System.ServiceModel.Description.ContractDescription]::GetContract([IYourInterface], $httpBinding, $endpointAddress)
$serviceEndpoint = New-Object System.ServiceModel.Description.ServiceEndpoint $contractDescription
$channelFactory = New-Object "System.ServiceModel.ChannelFactory``1[IYourInterface]" $serviceEndpoint
$webProxy = $channelFactory.CreateChannel();
$webProxy.yourServiceMethod();

请注意,您需要导入带有IYourInterface类的DLL才能生效:

[void] [Reflection.Assembly]::LoadFrom('path/to/your.dll')

或者,如果您为服务定义了WSDL,则可以按照这些更简单的说明访问该服务:

http://blogs.technet.com/heyscriptingguy/archive/2009/11/17/hey-scripting-guy-november-17-2009.aspx

或者,您可以确定HTTP SOAP请求的外观,并在HttpWebRequest内自行构建。

答案 2 :(得分:0)

我相信在尝试获取响应之前,您需要先设置HTTP方法。默认情况下,我认为 WebRequest 对象默认为 POST ,但您实际上需要将其设置为 GET

我没有多少使用PowerShell脚本,但根据您的示例,它看起来像这样:

$request = [System.Net.WebRequest]::Create("http://myserver.com/myservice/dosomething") 
$request.Method = "GET"
$request.GetResponse()

希望有所帮助!

答案 3 :(得分:0)

HTTP重播方法:

  1. 安装Fiddler,运行它并开始记录请求
  2. 使用“普通”客户端(记录请求)
  3. 调用WCF服务
  4. 使用Invoke-WebRequest - 重放XML SOAP请求主体和一些头文件,确保匹配头文件:Content-Type,SOAPAction,以及可能的其他文件
  5. 重复(3)并继续调整正文和标题,直到您有一个有效的SOAP请求
  6. 您不必使用WCF来调用WCF服务,您可以使用HTTP默认值进行3-4次更改来模仿。只是不要尝试自己构建SOAP信封。但是,通过“普通”HTTP重播Fiddler所需的一切是安全的。

答案 4 :(得分:0)

我喜欢jdmichal的答案,因为直接使它适用于参数为对象的输入......代码需要进行一些修改,这对我有用:

   <system.diagnostics>
      <sources>
            <source name="System.ServiceModel" 
                    switchValue="Critical, ActivityTracing"
                    propagateActivity="true">
            <listeners>
               <add name="traceListener" 
                   type="System.Diagnostics.XmlWriterTraceListener" 
                   initializeData= "C:\Logs\MyCriticalTraces.svclog" />
            </listeners>
         </source>
      </sources>
   </system.diagnostics>

更新: 我已经了解了如何将复合对象与New-WebServiceProxy cmdlet一起使用(感谢http://www.sqlmusings.com/2012/02/04/resolving-ssrs-and-powershell-new-webserviceproxy-namespace-issue/

[Reflection.Assembly]::LoadFrom("C:\.....\WcfService2.dll")
[Reflection.Assembly]::LoadWithPartialName("System.ServiceModel")

$httpBinding = New-Object System.ServiceModel.BasicHttpBinding
if($useNTLM){
    #passes the default creds
    $httpBinding.Security.Mode = "TransportCredentialOnly"
    $httpBinding.Security.Transport.ClientCredentialType = "Ntlm"
}
$endpointAddress = New-Object System.ServiceModel.EndpointAddress 'http://localhost:63600/Service1.svc'

$contractDescription = [System.ServiceModel.Description.ContractDescription]::GetContract([WcfService2.IService1])

$serviceEndpoint = New-Object System.ServiceModel.Description.ServiceEndpoint($contractDescription, $httpBinding, $endpointAddress)
$channelFactory = New-Object "System.ServiceModel.ChannelFactory``1[WcfService2.IService1]"($serviceEndpoint)

$webProxy = $channelFactory.CreateChannel();
$result = $webProxy.GetData(123);
Write-Output $result #prints 123
$comptype = new-object WcfService2.CompositeType
$comptype.BoolValue =$false
$comptype.StringValue = "whatever123zxcv"
$result = $webProxy.GetDataUsingDataContract($comptype);
Write-Output $result #prints whatever123zxcv