2010-01-04 59 views
3

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

这是我要怎样做:

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

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

回答

7

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 
+0

如果脚本每天被调用很多次,读者可能会考虑使用C#编译WS代理,或者使用fiddler来记录请求并使用更轻量级的HTTP进行重放。 – yzorg 2013-08-01 23:38:56

0

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

我还没有使用PowerShell脚本很多,但基于把你的样品会是这个样子:

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

希望帮助!

+0

为了做到这一点就我只有用WebGet属性暴露操作暴露一个RESTful端点? – devlife 2010-01-04 23:53:13

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(); 

请注意,你需要导入的DLL与IYourInterface类这个工作:

​​

或者,如果你有服务定义的WSDL,您可以按照这些更容易说明访问服务:或者或者

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

,你能找出什么HTTP的SOAP请求需要看起来像,并且自己在HttpWebRequest之内形成它。

+0

没错。我不打算使用SOAP。理想情况下,我真的很想简单地以一种休息的方式执行一个url。这可能与WCF? – devlife 2010-01-04 23:54:36

+0

WCF通过SOAP公开服务。它还内置了.NET到.NET二进制后门,以消除XML转换的成本。 http://en.wikipedia.org/wiki/Windows_Communication_Foundation#Overview – jdmichal 2010-01-04 23:56:49

+0

巨大的代码示例是使用这个后门来避免XML转换。由于内置了New-WebServiceProxy cmdlet,在PowerShell中更好地支持使用SOAP接口。 – jdmichal 2010-01-04 23:59:10

0

HTTP重播方法:

  1. 安装小提琴手,运行它,并开始录制请求
  2. 使用 '正常' 客户端(记录的请求)
  3. 使用调用调用WCF服务-WebRequest-重播XML SOAP请求正文和一些头文件,一定要匹配头文件:Content-Type,SOAPAction和其他可能的文件
  4. 重复(3)并不断调整正文和头文件直到哟你有一个有效的SOAP请求

你不必使用WCF来调用WCF服务,你可以模仿一个带有3-4个HTTP默认值的变化。只是不要尝试自己构建SOAP信封。但是,通过'普通'HTTP重播您从Fiddler所需的所有内容是安全的。

0

我喜欢jdmichal的答案,因为它是直观的,使之成为其中的参数对象的输入工作...代码需要一些修改,这是对我工作:

[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 

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

$wsProxy = New-WebServiceProxy -uri http://localhost:63600/Service1.svc 
$wsProxy.UseDefaultCredentials = $true 
$namespace = $wsProxy.GetType().Namespace 
$myct = New-Object "$namespace.CompositeType" 
$myct.BoolValue = $true; 
$myct.StringValue = "asdfasdg"; 

$wsProxy.GetDataUsingDataContract($myct) 
$wsProxy.GetData(123,$true)