9

我在它自己的程序集中有一个手写的 WCF 代理,它非常简单:

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

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

我将其加载到 Powershell 脚本中:

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

然后,我尝试设置 App.config(根据SO 上的其他帖子),以便可以使用在配置中定义的端点来实例化客户端,而不是在脚本本身中:

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

我检查了 AppDomain 并将配置文件设置为其ConfigurationFile属性。

当我创建客户端实例时:

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

它倒下说:

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

有任何想法吗?我不想在脚本文件中手动创建端点——它需要从 config.xml 中读取。

4

5 回答 5

1

Powershell 和 Powershell ISE 处理此问题的方式似乎有所不同。

使用 ISE(至少是我正在使用的版本),您必须清除配置以强制重新加载。不过,我想您也可以将 .dll.config 文件的内容放入 powershell ISE 配置中。然而,这似乎很糟糕。下面发布的代码有效。我发现它的一部分在谷歌上搜索这个问题。

# $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
于 2015-11-25T21:51:34.790 回答
0

如果您发布完整的配置会更容易,但听起来您缺少以下部分。

<system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding">
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="ServiceAddress"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding"
        contract="MyService.Contracts.IMyService" name="MyServiceHttpEndpoint" />
    </client>
</system.serviceModel>

尽管您听起来很确定事实并非如此。

因此,让我们尝试确保您的 powershell 应用程序正确获取配置...

要确定 powershell 应用程序是否按预期拾取配置,请将以下内容添加到您的 powershell 文件中:

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

如果不是那么它不是配置问题,我认为我们可以就此达成一致。

那么dll可以看到配置中的设置吗?现在我们知道powershell可以看到配置并且可以调用你的dll。

配置是否与dll位于同一位置?

add-type 会做我们不期望的事情吗?查看 msdn 文档,它看起来像 add-type

将 Microsoft .NET Framework 类型(类)添加到 Windows PowerShell 会话。

如果该类现在处于 powershell 会话中,它是否可以像往常一样访问配置?我不知道。

也许尝试一下[Reflection.Assembly]::LoadFromadd-type看看这是否有什么不同?

恐怕我没有确切的答案,但我希望我的胡言乱语有些帮助。

于 2013-03-21T00:32:18.773 回答
0

您的程序集是作为 32 位还是 64 位目标构建的?

我在多种情况下遇到了 32/64 问题。

请注意,如果您在 64 位操作系统上运行,您有两个 PowerShell,一个 64 位(通常)和一个 32 位(当您需要 32 个外部程序集时很有趣)。

于 2013-03-20T04:31:01.313 回答
0

好像您缺少绑定类型,当您在 powershell 中时应该是 basicHttpBinding

使您的代码看起来像:

$endpointName = "MyServiceHttpEndpoint" 
$httpBinding = new-object System.ServiceModel.WSHttpBinding
$myclient = New-Object MyService.Client.MyServiceClient($httpBinding, $endpointName)
于 2013-03-25T13:45:06.503 回答
0

如果可能,我建议一起跳过配置文件。如果您的 api 提供 MEX 或 WSDL 端点,请尝试通过查询它们来创建您的代理,并用于WsdlImporter在内存中构建绑定配置。从那时起,您可以在必要时在内存中对其进行修改。

这就是我为我所从事的项目所做的,该项目在配置 WCF 服务方面非常繁重,因为它与使用WS-Trust.

对于类似的问题,我建议尝试使用图库中提供的WcfPS模块。因为与其他问题有重叠,所以我将引用其中的一部分。

该模块的代码是开源的,尽管它在脚本中,但它在很大程度上依赖于 .net 框架类和来自System.ServiceModel和程序集的System.IdentityModel程序集。我提到这一点是因为这些程序集中的大多数 api 在 .NET 标准 2 中不可用,因此该模块很遗憾无法在非 Windows 操作系统中运行。您还可以在我的文章WCFPS-PowerShell 模块中阅读有关它的更多信息,以使用 SOAP 端点。

这是自述文件中的示例

#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

使用这种方法,您不需要任何内联 .net 类型的导入,也不需要在 Visual Studio 上使用的代理,也不需要配置。很可能您将不得不根据您的用例对其进行调整。如果您可以改进模块的功能,请提交拉取请求。

于 2017-10-03T07:42:44.767 回答