Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a custom WCF proxy in a Powershell script with a config file?

I have a hand-written WCF proxy in it's own assembly, it's very simple:

public class MyServiceClient : ClientBase<IMyService>, IMyService
{
    public MyServiceClient()
    {
    }

    public MyServiceClient(string endpointConfigurationName) :
        base(endpointConfigurationName)
    {
    }
}

I am loading this into a Powershell script:

Add-Type -Path "$LocalPath\MyService.Client.dll"
Add-Type -Path "$LocalPath\MyService.Contracts.dll"

I am then trying to set the App.config (as per other posts on SO) so that the client can be instantiated with an Endpoint defined in config, rather than in the script itself:

[System.AppDomain]::CurrentDomain.SetData("APP_CONFIG_FILE", "$LocalPath\MyService.Client.dll.config")

I have checked the AppDomain and the config file is set as its ConfigurationFile property.

When I create an instance of the client:

$endpointName = "MyServiceHttpEndpoint" # defined in the app.config file
$myclient = New-Object MyService.Client.MyServiceClient($endpointName)

It falls over saying:

Exception calling ".ctor" with "1" argument(s): "Could not find endpoint element with name 'MyServiceHttpEndpoint' and contract 'MyService.Contracts.IMyService' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this name could be found in the client element."

Any ideas? I don't want to manually create the endpoint in the script file - it needs to be read from config.

like image 707
jimmy_terra Avatar asked Mar 14 '13 16:03

jimmy_terra


1 Answers

There seems to be a difference in the way that Powershell and Powershell ISE handle this.

With ISE (at least the version I'm using) you have to clear out the configuration to force it to reload. Though, I guess you could also put the contents of your .dll.config file into the powershell ISE config. However, that seems nasty. The code posted below works. I found parts of it googling this issue.

# $dllPath is the path to the dll we want to load
# first point to the correct config file
[System.AppDomain]::CurrentDomain.SetData("APP_CONFIG_FILE", "$dllPath.config")

# PowerShell ISE is a PITA we have to override the config
if ($psISE -ne $null) {
    Add-Type -AssemblyName System.Configuration
    [Configuration.ConfigurationManager].GetField("s_initState", "NonPublic, Static").SetValue($null,0)
    [Configuration.ConfigurationManager].GetField("s_configSystem", "NonPublic, Static").SetValue($null,$null)
    ([Configuration.ConfigurationManager].Assembly.GetTypes() | where {$_.FullName -eq "System.Configuration.ClientConfigPaths"})[0].GetField("s_current", "NonPublic, Static").SetValue($null, $null)
}

#Now load the DLL
$null = [Reflection.Assembly]::LoadFrom($dllPath)

# DLL and Config should be loaded - test
like image 119
Steve L Avatar answered Oct 24 '22 16:10

Steve L