2013-03-14 1 views
8

J'ai une procuration WCF écrite à la main dans son propre montage, il est très simple:Comment utiliser un proxy WCF personnalisé dans un script Powershell avec un fichier de configuration?

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

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

Je chargeais ceci dans un script Powershell:

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

Je suis alors en train de mettre l'App .config (selon other posts sur SO) de telle sorte que le client peut être instancié avec un point d'extrémité défini dans la configuration, plutôt que dans le script lui-même:

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

I avez vérifié l'AppDomain et le fichier de configuration est défini comme sa propriété ConfigurationFile.

Lorsque je crée une instance du client:

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

Il tombe en disant:

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

Toutes les idées? Je ne veux pas créer manuellement le point de terminaison dans le fichier de script - il doit être lu à partir de la configuration.

+1

L'erreur est: il a regardé dans le fichier de configuration et n'a pas pu trouver un point de terminaison nommé "MyServiceHttpEndpoint". Vous devrez poster le fichier de configuration réel si vous voulez une aide significative. – ErnieL

+0

Il indique également 'Cela peut être dû au fait qu'aucun fichier de configuration n'a été trouvé pour votre application' - quel est le problème. Le fichier de configuration est bon, il fonctionne en dehors de Powershell sans problèmes. – MalcomTucker

+0

J'ai vérifié l'AppDomain et le fichier de configuration est présent et correct dans 'AppDomain.La propriété ConfigurationFile, donc il est trouvé, je ne peux pas simplement lier le fichier de configuration au proxy client consommateur. Ajout de la config ... – MalcomTucker

Répondre

0

Vos assemblys sont-ils construits en tant que cibles 32 bits ou 64 bits?

J'ai rencontré le problème 32/64 dans plusieurs cas. Faites juste attention à ce que si vous utilisez un OS 64 bits, vous avez deux PowerShells à 64 bits (habituel) et à 32 bits (interressant quand vous avez besoin de 32 assemblages externes).

0

Ce serait plus facile si vous aviez posté votre config complète, mais il semble que vous manquiez la section suivante. Bien que vous sembliez assez sûr que ce n'est pas le cas.

permet donc d'essayer et assurez-vous que votre application powershell capte la config correctement ...

Pour être sûr que l'application powershell capte la config comme prévu d'ajouter quelque chose comme ceci dans votre fichier powershell:

Get-Content $LocalPath\MyService.Client.dll.config | foreach {Write-Output $_} 

Si ce n'est pas alors un problème de configuration, je pense que nous pouvons nous entendre là-dessus.

Donc, la DLL peut-elle voir les paramètres dans la configuration? A présent, nous savons que PowerShell peut voir la config et peut appeler votre DLL.

La configuration est-elle au même emplacement que la DLL?

Est-ce que ajouter-type fait quelque chose que nous n'attendons pas? En regardant les documents msdn il ressemble add type

Ajoute un type Microsoft .NET Framework (une classe) à une session Windows PowerShell .

Si la classe est maintenant dans une session PowerShell, a-t-elle accès à la configuration comme elle le ferait normalement? Je ne sais pas.

Peut-être essayer plutôt [Reflection.Assembly]::LoadFrom et add-type pour voir si cela fait une différence?

Je n'ai pas de réponse exacte J'ai peur, mais j'espère que mes divagations seront utiles.

0

On dirait que vous manquez type de reliure, il devrait être BasicHttpBinding lorsque vous êtes dans powershell

Faites votre look code comme:

$endpointName = "MyServiceHttpEndpoint" 
$httpBinding = new-object System.ServiceModel.WSHttpBinding 
$myclient = New-Object MyService.Client.MyServiceClient($httpBinding, $endpointName) 
0

Il semble y avoir une différence dans la façon dont Powershell et Powershell ISE gère cela. Avec ISE (au moins la version que j'utilise), vous devez effacer la configuration pour la forcer à recharger. Bien que, je suppose que vous pourriez également mettre le contenu de votre fichier .dll.config dans la config ISE powershell. Cependant, cela semble méchant. Le code affiché ci-dessous fonctionne. J'ai trouvé certaines parties de googler ce problème.

# $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 
0

Je suggère de sauter le fichier de configuration tous ensemble si possible. Si votre API fournit un point de terminaison MEX ou WSDL, essayez de créer vos proxys en les interrogeant et utilisez WsdlImporter pour créer la configuration de liaison en mémoire. À partir de ce moment, vous pouvez le modifier en mémoire si nécessaire.

C'est ce que je fais pour le projet sur lequel je travaille qui a un très lourd en termes de service de configuration WCF car il est intégré à un service de jeton de sécurité utilisant WS-Trust.

Pour un question similaire, j'ai suggéré d'utiliser le module WcfPS disponible sur la galerie. Parce qu'il y a chevauchement avec l'autre question, j'en cite une partie.

Le code pour le module est open source et bien que son dans le script, il dépend fortement des classes du framework .net et des assemblées des assemblées System.ServiceModel et System.IdentityModel. Je mentionne cela parce que la plupart des API à l'intérieur de ces assemblys ne sont pas disponibles à partir de .NET standard 2, donc le module ne fonctionnera malheureusement pas avec des systèmes d'exploitation autres que Windows. Vous pouvez également en lire plus à ce sujet dans mon article WCFPS - PowerShell module to work with SOAP endpoints.

C'est l'exemple de la README

#region Initialize the channel/client 
$svcEndpoint="http://myserviceprovider/Service1.svc" 

$wsImporter=New-WcfWsdlImporter -Endpoint $svcEndpoint -HttpGet 
$proxyType=$wsImporter | New-WcfProxyType 

# select the endpoint and implicitly the binding from the imported configuration 
$endpoint=$wsImporter | New-WcfServiceEndpoint -Endpoint $svcEndpoint 
$channel=New-WcfChannel -Endpoint $endpoint -ProxyType $proxyType 
#endregion 

#region Use the channel/client 
$channel.Method1() 
$channel.Method2() 
#endregion 

Avec cette méthode, vous n'avez pas besoin d'importation de types de ligne .net, ni les proxy que vous utilisez sur Visual Studio et aucune configuration. Très probablement, vous devrez l'ajuster à votre cas d'utilisation. Si vous pouvez améliorer la fonctionnalité du module, veuillez soumettre une demande d'extraction.

Questions connexes