Выполнить одностороннюю операцию службы wcf из powershell - PullRequest
4 голосов
/ 05 января 2010

У меня есть запланированное задание, которое выполняет сценарий powershell каждый час. Сценарий powershell должен выполнить вызов односторонней операции службы WCF. По сути, это просто нужно начать операцию. Мой вопрос: как мне это сделать? Я думал, что просто выполнение url на самом деле вызовет запрос, но, очевидно, это не правильно.

Вот что я пытался сделать:

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

Операция не принимает параметров и возвращает void.

Ответы [ 5 ]

8 голосов
/ 05 января 2010

PowerShell 2.0 делает это тривиальным с помощью командлета New-WebServiceProxy, например ::100100

$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
7 голосов
/ 05 января 2010

Мне кажется, проблема в том, что ваш код создает HttpWebRequest , а не запрос WCF. (Другими словами, он просто выполняет HTTP-запрос GET к URL-адресу без информации 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, чтобы это работало:

[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.

0 голосов
/ 28 января 2016

Мне нравится ответ 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

UPDATE: Я узнал, как использовать составные объекты с командлетом New-WebServiceProxy (спасибо 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)
0 голосов
/ 02 августа 2013

HTTP-подход к воспроизведению:

  1. Установите Fiddler, запустите его и начните запись запросов
  2. вызов службы WCF с использованием «обычного» клиента (запишите запрос)
  3. используйте Invoke-WebRequest - воспроизведите тело запроса XML SOAP и некоторые заголовки, убедитесь, что они совпадают с заголовками: Content-Type, SOAPAction и, возможно, другими
  4. повторите (3) и продолжайте настраивать тело и заголовки, пока у вас не будет действительного запроса SOAP

Вам не нужно использовать WCF для вызова службы WCF, вы можете имитировать ее с 3-4 изменениями по умолчанию по умолчанию HTTP. Только не пытайтесь создать конверт SOAP самостоятельно. Но безопасно воспроизвести все, что вам нужно, из Fiddler по «обычному» HTTP.

0 голосов
/ 05 января 2010

Я считаю, что вам нужно сначала установить метод HTTP, прежде чем пытаться получить ответ. По умолчанию, я полагаю, что объект WebRequest по умолчанию равен POST , но вам действительно нужно будет установить его на GET .

Я не очень много использовал сценарии PowerShell, но, исходя из вашего примера, это выглядело бы примерно так:

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

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...