WCF LOB アダプター SDK を使用して配置パッケージを作成する
開発サイクル中は、Visual Studio 内でアダプターをビルド、デバッグ、実行できます。 アダプター ソリューションの出力は DLL アセンブリです。 Visual Studio IDE を使用してアダプター ソリューションをビルドすることも、devenv.exe スクリプトを使用してアダプター アセンブリを作成することもできます。 アダプターが開発され、アダプター コンシューマーの環境内で使用できる状態になったら、テスト環境と運用環境にアダプターをインストールできるようにする展開パッケージを作成する必要があります。
ソリューション内に Visual Studio のセットアップと配置プロジェクトを含めることができます。 これは、ソリューション ビルドの一部として .msi ファイルを自動的に生成するために使用できます。
Note
Visual Studio .NET 内の ([ビルド] メニューの) Configuration Managerを使用してソリューションを除外することで、ローカル ワークステーションでソリューションをビルドするたびに、セットアップおよび配置プロジェクトがビルドされないようにすることができます。 このメソッドを使用してソリューション ビルドからプロジェクトを除外した場合、ソース管理ソリューション ファイルには影響しません。 変更は、ソース管理下ではなく開発者固有のソリューション ユーザー オプション ファイル内で保持されます。
ソリューションに新しいプロジェクトが追加されるたびに、新しいプロジェクトの出力が .msi ファイルに含まれ、プロジェクト固有のインストール手順が実行されるように、配置プロジェクトを更新して構成する必要があります。
アダプター プロジェクトの出力をユーザーのコンピューターにインストールするだけでは十分ではありません。 アダプターはグローバル アセンブリ キャッシュ (GAC) にインストールする必要があり、WCF にアダプターを登録するには、machine.config ファイルを更新する必要があります。
WCF でアダプターを登録または登録解除するために使用できるカスタム アクションの例を次に示します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Reflection;
using System.ServiceModel.Configuration;
using System.Diagnostics;
using System.Configuration;
namespace Microsoft.Adapters.Samples.EchoV2
{
//Custom action to register the adapter with WCF configuration in machine.config
//<system.serviceModel>
// <extensions>
// <bindingElementExtensions>
// <add name="{BINDINGELEM_NAME}" type="{BINDINGELEM_TYPE}, {Assembly Information}" />
// </bindingElementExtensions>
// <bindingExtensions>
// <add name="{BINDING_NAME}" type="{BINDING_TYPE}, {Assembly Information}" />
// </bindingExtensions>
// </extensions>
// <client>
// <endpoint binding="{BINDING_NAME}" contract="IMetadataExchange" name="{BINDING_SCHEME}" />
// </client>
//</system.serviceModel>
[RunInstaller(true)]
public partial class WCFLOBAdapterInstaller : Installer
{
private Assembly adapterAssembly;
private Type bindingSectionType;
private Type bindingElementExtensionType;
const string INSTALLER_PARM_INSTALLDIR = "INSTALLDIR";
const string BINDING_ASSEMBLY_NAME = "Microsoft.Adapters.Samples.EchoV2.EchoAdapter.dll";
const string BINDINGELEM_NAME = "echoAdapterV2";
const string BINDINGELEM_TYPE = "Microsoft.Adapters.Samples.EchoV2.EchoAdapterBindingElementExtensionElement";
const string BINDING_NAME = "echoAdapterBindingV2";
const string BINDING_TYPE = "Microsoft.Adapters.Samples.EchoV2.EchoAdapterBindingCollectionElement";
const string BINDING_SCHEME = "echov2";
/// <summary>
/// Constructor - initialize the components and register the event handlers
/// </summary>
public WCFLOBAdapterInstaller()
{
InitializeComponent();
this.AfterInstall += new InstallEventHandler(AfterInstallEventHandler);
this.BeforeUninstall += new InstallEventHandler(BeforeUninstallEventHandler);
}
/// <summary>
/// Add the WCF configuration information in machine.config when installing the adapter.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AfterInstallEventHandler(object sender, InstallEventArgs e)
{
try
{
Debug.Assert(this.Context != null, "Context of this installation is null.");
string path = this.Context.Parameters[INSTALLER_PARM_INSTALLDIR] + BINDING_ASSEMBLY_NAME;
adapterAssembly = Assembly.LoadFrom(path);
Debug.Assert(adapterAssembly != null, "Adapter assembly is null.");
bindingSectionType = adapterAssembly.GetType(BINDING_TYPE, true);
Debug.Assert(bindingSectionType != null, "Binding type is null.");
bindingElementExtensionType = adapterAssembly.GetType(BINDINGELEM_TYPE, true);
Debug.Assert(bindingElementExtensionType != null, "Binding element extension type is null.");
AddMachineConfigurationInfo();
}
catch (Exception ex)
{
throw new InstallException("Error while adding adapter configuration information. " + ex.InnerException.Message);
}
}
/// <summary>
/// Registers the adapter with the WCF configuration
/// NOTE: The
/// </summary>
public void AddMachineConfigurationInfo()
{
System.Configuration.Configuration config = ConfigurationManager.OpenMachineConfiguration();
Debug.Assert(config != null, "Machine.Config returned null");
// add <client><endpoint>
ServiceModelSectionGroup sectionGroup = config.GetSectionGroup("system.serviceModel") as ServiceModelSectionGroup;
if (sectionGroup != null)
{
bool channelEndpointElementExists = false;
// this call can throw an exception if there is problem
// loading endpoint configurations - e.g. each endpoint
// tries to load binding which in turn loads the DLL
ClientSection clientSection = sectionGroup.Client;
foreach (ChannelEndpointElement elem in clientSection.Endpoints)
{
if (elem.Binding.Equals(BINDING_NAME, StringComparison.OrdinalIgnoreCase) && elem.Name.Equals(BINDING_SCHEME, StringComparison.OrdinalIgnoreCase) && elem.Contract.Equals("IMetadataExchange", StringComparison.OrdinalIgnoreCase))
{
channelEndpointElementExists = true;
break;
}
}
if (!channelEndpointElementExists)
{
Debug.WriteLine("Adding ChannelEndpointElement for : " + BINDING_NAME);
ChannelEndpointElement elem = new ChannelEndpointElement();
elem.Binding = BINDING_NAME;
elem.Name = BINDING_SCHEME;
elem.Contract = "IMetadataExchange";
sectionGroup.Client.Endpoints.Add(elem);
Debug.WriteLine("Added ChannelEndpointElement for : " + BINDING_NAME);
}
// add <bindingElementExtension>
if (!sectionGroup.Extensions.BindingElementExtensions.ContainsKey(BINDINGELEM_NAME))
{
ExtensionElement ext = new ExtensionElement(BINDINGELEM_NAME, bindingElementExtensionType.FullName + "," + bindingElementExtensionType.Assembly.FullName);
sectionGroup.Extensions.BindingElementExtensions.Add(ext);
}
// add <bindingExtension>
if (!sectionGroup.Extensions.BindingExtensions.ContainsKey(BINDING_NAME))
{
ExtensionElement ext = new ExtensionElement(BINDING_NAME, bindingSectionType.FullName + "," + bindingSectionType.Assembly.FullName);
sectionGroup.Extensions.BindingExtensions.Add(ext);
}
config.Save();
}
else throw new InstallException("Machine.Config doesn't contain system.serviceModel node");
}
/// <summary>
/// Remove the machine configuration information when uninstalling the adapter
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BeforeUninstallEventHandler(object sender, InstallEventArgs e)
{
try
{
RemoveMachineConfigurationInfo();
}
catch (Exception ex)
{
throw new InstallException("Error while removing adapter configuration information" + ex.InnerException.Message);
}
}
/// <summary>
/// Unregisters the adapter with WCF configuration
/// </summary>
public void RemoveMachineConfigurationInfo()
{
System.Configuration.Configuration config = ConfigurationManager.OpenMachineConfiguration();
Debug.Assert(config != null, "Machine.Config returned null");
ServiceModelSectionGroup sectionGroup = config.GetSectionGroup("system.serviceModel") as ServiceModelSectionGroup;
ChannelEndpointElement elemToRemove = null;
if (sectionGroup != null)
{
// Remove <client><endpoint>
foreach (ChannelEndpointElement elem in sectionGroup.Client.Endpoints)
{
if (elem.Binding.Equals(BINDING_NAME, StringComparison.OrdinalIgnoreCase) && elem.Name.Equals(BINDING_SCHEME, StringComparison.OrdinalIgnoreCase) && elem.Contract.Equals("IMetadataExchange", StringComparison.OrdinalIgnoreCase))
{
elemToRemove = elem;
break;
}
}
if (elemToRemove != null)
{
Debug.WriteLine("Removing ChannelEndpointElement for : " + BINDING_NAME);
sectionGroup.Client.Endpoints.Remove(elemToRemove);
Debug.WriteLine("Removed ChannelEndpointElement for : " + BINDING_NAME);
}
// Remove <bindingExtension> for this adapter
if (sectionGroup.Extensions.BindingExtensions.ContainsKey(BINDING_NAME))
{
sectionGroup.Extensions.BindingExtensions.RemoveAt(BINDING_NAME);
}
// Remove <bindingElementExtension> for this adapter
if (sectionGroup.Extensions.BindingElementExtensions.ContainsKey(BINDINGELEM_NAME))
{
sectionGroup.Extensions.BindingElementExtensions.RemoveAt(BINDINGELEM_NAME);
}
config.Save();
}
else
{
throw new InstallException("Machine.Config doesn't contain system.serviceModel node");
}
}
/// <summary>
/// Use this for testing outside of the Setup project
/// </summary>
/// <param name="assemblyDirectory">Directory where the adapter assembly is located</param>
public static void TestAddConfiguration(string assemblyDirectory)
{
WCFLOBAdapterInstaller action = new WCFLOBAdapterInstaller();
InstallContext context = new InstallContext();
// In the Setup project, this is set by selecting custom action
// and in Properties setting /INSTALLDIR="[TARGETDIR]\" for CustomActionData
context.Parameters.Add("INSTALLDIR", assemblyDirectory);
action.Context = context;
action.AfterInstallEventHandler(null, null);
}
/// <summary>
/// Use this for testing outside of the Setup project
/// </summary>
/// <param name="assemblyDirectory">Directory where the adapter assembly is located</param>
public static void TestRemoveConfiguration(string assemblyDirectory)
{
WCFLOBAdapterInstaller action = new WCFLOBAdapterInstaller();
InstallContext context = new InstallContext();
// In the Setup project, this is set by selecting custom action
// and in Properties setting /INSTALLDIR="[TARGETDIR]\" for CustomActionData
context.Parameters.Add("INSTALLDIR", assemblyDirectory);
action.Context = context;
action.BeforeUninstallEventHandler(null, null);
}
}
}
展開パッケージを使用してサンプル アダプターを調べる場合は、テスト コードとインストール スクリプトを含む完成したエコー アダプターをダウンロードできます。 このサンプルは、 または \BizTalk Server\ASDK_x64\Program Files\WCF LOB Adapter SDK\Documents\Samples
の BizTalk インストール ファイルに\BizTalk Server\ASDK_x86\Program Files\WCF LOB Adapter SDK\Documents\Samples
含まれています。
参照
WCF LOB アダプター SDK を使用してアダプターをデプロイする
WCF LOB アダプター SDK を使用してアダプターを展開解除する