2010-01-04 36 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)