Execute a one-way wcf service operation from powershell

后端 未结 5 1732
情歌与酒
情歌与酒 2021-02-06 12:52

I have a scheduled task which executes a powershell script every hour. The powershell script must make a call to a one-way WCF service operation. Essentially it just needs to

相关标签:
5条回答
  • 2021-02-06 13:27

    I think the problem is that the code you have is actually creating an HttpWebRequest, not a WCF request. (In other words, it's simply executing an HTTP GET request on the URL, with no SOAP or .NET Remoting information.)

    You should be able to follow these instructions to create a proper endpoint:

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

    It should look something like this:

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

    Note that you'll need to import the DLL with the IYourInterface class for this to work:

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

    Alternatively, if you have a WSDL defined for the service, you can follow these much easier instructions to access the service:

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

    Alternatively alternatively, you can figure out what the HTTP SOAP request needs to look like, and form it yourself within the HttpWebRequest.

    0 讨论(0)
  • 2021-02-06 13:29

    HTTP replay approach:

    1. Install Fiddler, run it and start recording requests
    2. invoke the WCF service using the 'normal' client (record the request)
    3. use Invoke-WebRequest - replay the XML SOAP request body and some headers, be sure to match the headers: Content-Type, SOAPAction, and possibly others
    4. repeat (3) and keep tweaking the body and headers until you have a valid SOAP request

    You don't have to use WCF to call a WCF service, you can mimic one with 3-4 changes from HTTP defaults. Just don't try to building the SOAP envelope yourself. But it's safe to replay everything you need from Fiddler over 'plain' HTTP.

    0 讨论(0)
  • 2021-02-06 13:34

    I like jdmichal's answer because it is intuitive to make it work for inputs where the parameters are objects... the code required some modifications, this is what worked for me:

    [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: I've found out how to use composite objects with the New-WebServiceProxy cmdlet (thanks to 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 讨论(0)
  • 2021-02-06 13:36

    PowerShell 2.0 makes this trivial with the New-WebServiceProxy cmdlet e.g.:

    $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 讨论(0)
  • 2021-02-06 13:42

    I believe that you'll need to set the HTTP method first before attempting to get a response. By default, I believe the WebRequest object defaults to POST, but you'll actually need to set it to GET.

    I haven't used PowerShell scripting much, but based off of your sample it would look something like this:

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

    Hope that helps!

    0 讨论(0)
提交回复
热议问题