UCMA 3.0 アプリケーション開発 事始め (Startup)


環境 : Lync Server 2010, Lync 2010, UCMA 3.0 Runtime, Microsoft Speech Platform - Server Runtime Languages (ja-JP) 10.2, Visual Studio 2010, UCMA 3.0 SDK

UCMA 3.0 アプリケーション開発事始め

こんにちは。

UCMA 3.0 (Unified Communications Managed API 3.0) の環境構築や、開発チュートリアルについて頻繁に質問を受けるので、以下に Startup 用の手順を記載しておきます。

ややハードルは高いですが、UCMA を使用すると、下記で述べるような高度なエンドポイント接続 (B2BUA)、音声とテキストの連携 (ASR / TTS)、高度な IVR アプリケーション、Audio Routes などの高度な会議 (Conference) 機能の実装、独自の UI を持った Web アプリケーション (エージェントと連携したカスタム UI) など、非常に豊富なリアルタイム コミュニケーションのアプリケーション開発をおこなうことができます。

補足 :  番号プッシュで振り分けをおこなうような基本的な IVR (interactive voice response) 機能は、開発をおこなう必要はなく、Lync Server コントロールパネルの設定のみでおこなうことができます。

ランタイム環境のインストール

UCMA のインストール ユーザーは 必ずしも Lync Server の管理者である必要はないと思いますが、今回は、手順を簡素化するため、Lync Server をインストールした際に設定した Lync Server の管理者ユーザーを使用して、以降の設定 (インストール) 作業をおこないます。

まず、以下の手順で、UCMA のランタイム環境を、Lync Server とは別の新しいマシン (64 bit の Windows Server) にインストールします。

  • Windows Server (OS) の機能で、.NET Framework 3.5 の機能を追加 (インストール) します。(また、Windows PowerShell 2.0 がインストールされていることも確認しておきましょう!)
  • Lync Server がインストールされているドメインと同一のドメインにマシンを参加させます。(IP アドレス、デフォルト ゲートウェイ、DNS サーバーなども忘れず設定しておきましょう。)
  • Unified Communications Managed API 3.0 Runtime をインストールします。
  • 日本語の ASR / TTS を利用した開発をおこなう場合は、Microsoft Speech Platform - Server Runtime Languages (ja-JP) v10.2 をダウンロードしてインストールしておきましょう。
    なお、インストールするバージョンに注意してください。インストールされている Microsoft Server Speech Runtime のバージョンを確認し、このバージョンと揃えておきます。(今回は、Version 10.2 をインストールしています。)
  • インストール後にマシンの再起動が促されますので、再起動をおこないます。

補足 : ここでは、Lync Server 2010 のインストールについては述べません。(既にインストールされているものとします。) なお、Lync Server 2010 インストール時の注意点については、こちら に記載しました。

補足 : Lync Server 2010 にも UCMA 3.0 Runtime が入っています。ただし、Lync Server 2010 (RTM 版) がインストールする UCMA Runtime では、Speech Server Runtime などのバージョンが UCMA 3.0 SDK が使用するものと異なっていて、ダウンロード センターにある UCMA 3.0 SDK をインストールすることができない模様です。(試してみました。。。)
このため、UCMA 3.0 アプリケーションの開発サーバー (以降、UCMA サーバーと記載) は、Lync Server とは別の新しいサーバー環境に構築しています。

ここで、(特に英語圏でない方は、) まだ、UCMA 3.0 SDK をインストールしないよう注意してください。
UCMA 3.0 SDK をインストールすると、Lync Server Core Component が入っていない場合、言語やバージョンの異なる Lync Server Core Component をインストールしてしまう場合があるので、できれば、以下のランタイム環境の構成 (設定) の後で SDK をインストールしてください。

ランタイム環境の設定

つぎに、以下に述べる手順で、UCMA サーバー (アプリケーション サーバー) のランタイム環境を設定します。主に、Lync 用のプールの作成と、UCMA サーバーの Lync Server への登録をおこないます。
なお、以降で述べるステップは以下のドキュメントに詳しく記載されていますので、細かな点は、下記のドキュメントで確認しておいてください。

[MSDN] UCMA 3.0 : Activating a UCMA 3.0 Core Trusted Application

http://msdn.microsoft.com/en-us/library/gg437205.aspx

まず、UCMA Runtime のダウンロード ページ の指示にしたがって、以下のコマンドを実行し、ウィザードに従って構成します。
これにより、Lync Server Core Component が、UCMA サーバーにインストールされます。

%systemdrive%ProgramDataMicrosoftLync ServerDeploymentcache[Build version]SetupOCSCore.msi

つぎに、Lync Server のトポロジーに、この新しいコンピューター (UCMA サーバー) を登録します。(今回は、「MSDN : UCMA 3.0 - General Application Activation」に記載されている Windows PowerShell を使用した方法で設定します。)
[すべてのプログラム] - [Microsoft Lync Server 2010] - [Lync サーバー管理シェル] (Lync Server Management Shell) を 管理者権限 で起動します。以下のコマンドで、このドメイン (今回は、exmaple.jp) の Lync 環境における SiteId と Registrar サービスを取得します。(Lync Server コントロール パネルの [Topology] タブでも、これらの値を確認できます。)
今回の場合 (下記の出力結果を参照)、SiteId は「1」で、Registrar サービスは「kkdeveva01.example.jp」であることがわかります。

Get-CsSite

<出力結果>
Identity        : Site:Example Site 1
SiteId          : 1
Services        : {UserServer:kkdeveva01.example.jp, Registrar:kkdeveva01.examp
                  le.jp, UserDatabase:kkdeveva01.example.jp, FileStore:kkdeveva
                  01.example.jp...}
Pools           : {kkdeveva01.example.jp}
FederationRoute :
Description     :
DisplayName     : Example Site 1
SiteType        : CentralSite
ParentSite      :

補足 : 以降も、Lync Server Management Shell は必ず管理者権限で実行してください。

補足 : Lync Server Management Shell で使用可能なコマンドの一覧は、以下のコマンドで確認できます。(あとは、get-help コマンドで、各コマンドのシンタックスなどを確認してみてください。)
get-command -module Lync

上記の出力結果にしたがって、以下のコマンドを実行します。(今回は、kkdeveva03 のマシンに UCMA サーバーをインストールしています。)

New-CsTrustedApplicationPool -Identity kkdeveva03.example.jp -Registrar kkdeveva01.example.jp -Site 1

つぎに、表示されるメッセージにしたがって、以下のコマンドを実行します。(このコマンドを実行した際に、UCMA サーバーのトポロジーが構築されます。)

Enable-CsTopology

一般に、UCMA アプリケーションを構築した際には、トポロジーや Contact Object などの設定が毎回必要になります。
この設定には、手動で実行する方法と、自動で設定する方法 (auto-provisioning) があり、MSDN では自動設定 (auto-provisioning) を推奨しているので、今回は、以下の手順で Auto-Provisioning の構成をおこないましょう。

補足 : Lync Server で、Lync Server コントロール パネルの [Topology] タブを見ると、新規にプールが追加されているのがわかります。この際、Auto-Provisioning を構成していないと、下図の [Replication] 列 (赤く囲んだ箇所) が "X" になります。

まず、Replication Service (Windows のサービス) を UCMA サーバーにインストールし、Replication を有効にします。コマンド プロンプトを 管理者権限 で起動して以下を実行すると、サービスや、Store 用の SQL Server Express (インスタンス名は SqlExpressRtcLocal) などがインストールされます。

"%programfiles%Microsoft Lync Server 2010DeploymentBootstrapper.exe" /BootstrapLocalMgmt /MinCache

補足 : 実行結果は、%Temp% (%USERPROFILE%AppDataLocalTemp) に保存されます。エラーが発生した場合は、その内容に応じて適切に対処してください。

Lync Server Management Shell で、以下のコマンドを実行します。

Enable-CsReplica

続いて、Lync Server Management Shell で、以下のコマンドを実行します。
これにより、「Lync Server レプリカ レプリケーター エージェント」 (Windows サービス) が動作します。(以降は、マシンの起動と同時に自動実行されます。)

Start-Service Replica

Get-CsManagementStoreReplicationStatus コマンドで、レプリケーションの状態を確認できます。数分待つと UpToDate の値が True に変更されるので、これで完了です!

補足 : 完了すると、上図の Lync Server コントロール パネルの [Topology] タブで、[Replication] 列にチェックが付きます。

さいごに、以下の手順で、ドメインの証明機関 (CA) に Web サーバー用の証明書 (Certificate) を要求して、これを UCMA サーバーに設定します。
まず、下記のコマンドで要求をおこない、返された thumbprint (拇印) の文字列をコピーしておいてください。(なお、証明機関の名前 (下記の example-KKDEVEVA02-CA) や、発行された thumbprint などは、証明機関がインストールされたドメイン コントローラーの [管理ツール] - [証明機関] で、あとから確認できます。)

Request-CSCertificate -New -Type default -CA example.jpexample-KKDEVEVA02-CA -Verbose

<出力結果>
Issuer           : CN=example-KKDEVEVA02-CA, DC=example, DC=jp
NotAfter         : 2013/04/01 0:44:24
NotBefore        : 2011/04/02 0:44:24
SerialNumber     : 11049847000000000005
Subject          : CN=kkdeveva03.example.jp
AlternativeNames : {}
Thumbprint       : 7ECE8200DE1932BFE8C5A5FC4B89B9E558C7161C
Use              : Default

以下のコマンドで、上記の thumbprint (拇印) の文字列を使用して、UCMA サーバー用の Cert を設定します。

Set-CsCertificate -Type default -Thumbprint 7ECE8200DE1932BFE8C5A5FC4B89B9E558C7161C

開発環境の構築 (インストール)

上記で UCMA のランタイム環境が構成できましたので、つぎに、以下の手順で、開発環境をインストールします。

  • Visual Studio 2010 をインストールします。
  • UCMA 3.0 SDK (Unified Communications Managed API 3.0 Software Development Kit) をインストールします。(現在は、英語版しかありませんので、これをインストールしてください。)

アプリケーションの登録と開発

では、アプリケーションを開発し、実際に動かしてみましょう。

ここでは、Lync から使用可能なアプリケーション用のエンドポイントを作成します。
エンドポイントには、ユーザーエンド ポイント (UserEndpoint) とアプリケーション エンドポイント (ApplicationEndpoint) があります。アプリケーション エンドポイントは、Help Desk アプリケーションなど、サーバー上で実行され、多くのユーザーが使用するような一般的なサービスを実装するのに向いています。(複数の Conversation のハンドリング、接続のリカバリーなど、サービスに向いた機能が提供できます。) 一方、ユーザー エンドポイントは、一般のユーザーのように振舞います。(ユーザー エンドポイントは、Lync 上にユーザーとして登録され、AD 上のユーザーのごとく振舞います。) ユーザー エンドポイント (UserEndpoint) は、例えば、既存の Lync Web App のように、特定のユーザーを代表して動作させるようなアプリケーションに向いています。
ここでは、Help Desk 用のサンプル アプリケーションとして、アプリケーション エンドポイントを作成します。

まず、以下の手順で、アプリケーション エンドポイント (ApplicationEndpoint) を、上記で作成したアプリケーション プール (kkdeveva03.example.jp) に登録します。
[Lync サーバー管理シェル] (Lync Server Management Shell) を起動し、以下のコマンドを実行します。(繰り返しになりますが、常に、管理者権限で起動するのをお忘れなく !)
今回は、アプリケーション ID を「SmapleApp」、ポート番号を 10700 番とします。

New-CsTrustedApplication -ApplicationId SampleApp -TrustedApplicationPoolFqdn kkdeveva03.example.jp -Port 10700

なお、Get-CsTrustedApplication コマンドを実行すると、以下の通り、登録されているアプリケーションの Uri などを確認できます。

Identity                   : kkdeveva03.example.jp/urn:application:sampleapp
ComputerGruus              : {kkdeveva03.example.jp sip:kkdeveva03.example.jp@e
                             xample.jp;gruu;opaque=srvr:sampleapp:xjzL2FIN-lShf
                             Rr_Ho97aQAA}
ServiceGruu                : sip:kkdeveva03.example.jp@example.jp;gruu;opaque=s
                             rvr:sampleapp:xjzL2FIN-lShfRr_Ho97aQAA
Protocol                   : Mtls
ApplicationId              : urn:application:sampleapp
TrustedApplicationPoolFqdn : kkdeveva03.example.jp
Port                       : 10700
LegacyApplicationName      : sampleapp

つぎに、以下のコマンドで、上記で登録したアプリケーションのエンドポイントを登録します。今回は、sip アドレスを「SampleAppEndpoint@example.jp」とします。

New-CsTrustedApplicationEndpoint -ApplicationId urn:application:sampleApp -TrustedApplicationPoolFqdn kkdeveva03.example.jp -SipAddress sip:SampleAppEndpoint@example.jp -DisplayName "HelpDesk Sample"

では、Visual Studio で、アプリケーションを開発 (Development) して、このエンドポイントにバインドしましょう。

UCMA サーバー上で、Visual Studio を 管理者権限 で開き、[コンソール アプリケーション] を新規作成します。(ターゲットフレームワークは、[.NET Framework 3.5] とします。)

補足 : これから作成する UCMA アプリケーションは、管理者権限で起動する必要があります。このため、[デバッグ実行] (F5) で管理者としてアプリケーションを起動させるため、あらかじめ Visual Studio を管理者権限で起動しておきます。

作成されたプロジェクトで、以下を参照追加します。

%programfiles%Microsoft UCMA 3.0SDKCoreBinMicrosoft.Rtc.Collaboration.dll

まず、単に開始して終了するだけの簡単なアプリケーションを構築してみましょう。
UCMA アプリケーションでは、Collaboration Platform の開始 (Startup) と、Application Endpoint の確立 (Establish) という 2 段階の処理をおこないます。
以下のコードを作成し、この開始と確立をおこないます。UCMA で提供されるメソッドの多くは、下記の通り、Async パターンで実装されています。(なお、下記で、PresentityType を automaton にしているため、このプレゼンスは、常にオンライン (Available) で表示されます。)

. . .

using Microsoft.Rtc.Collaboration;

. . .

private CollaborationPlatform rtcPlatform;
private ApplicationEndpoint appEndpoint;

static void Main(string[] args)
{
    Program prog = new Program();
    prog.Run();
}

public void Run()
{
    // Start platform and establish endpoint
    ProvisionedApplicationPlatformSettings settings =
        new ProvisionedApplicationPlatformSettings("SampleApp", "urn:application:sampleapp");
    rtcPlatform = new CollaborationPlatform(settings);
    rtcPlatform.RegisterForApplicationEndpointSettings(this.ApplicationEndpointSettingsDiscovered);
    rtcPlatform.BeginStartup(this.PlatformStartupCompleted, null);
}

public void ApplicationEndpointSettingsDiscovered(object sender,
    ApplicationEndpointSettingsDiscoveredEventArgs e)
{
    Console.WriteLine("Called applicationEndpointSettingsDiscovered ...");
    ApplicationEndpointSettings settings = e.ApplicationEndpointSettings;
    settings.AutomaticPresencePublicationEnabled = true;
    settings.Presence.PresentityType = "automaton";
    settings.Presence.Description = "Hello help desk !";
    appEndpoint = new ApplicationEndpoint(rtcPlatform, settings);
    appEndpoint.BeginEstablish(this.EndpointEstablishCompleted, null);
}

public void PlatformStartupCompleted(IAsyncResult res)
{
    rtcPlatform.EndStartup(res);
    Console.WriteLine("Completed platform startup ...");
}

public void EndpointEstablishCompleted(IAsyncResult res)
{
    appEndpoint.EndEstablish(res);
    Console.WriteLine("Completed endpoint establish ...");
}

上記では、あらかじめ Lync Server Management Shell (PowerShell) で設定した Uri (SampleAppEndpoint.example.jp) などの設定を検出 (Discover) し、この設定を使って Endpoint の確立をおこなっています。(この他の実装方法もあります。)

つぎに、アプリケーションを正しく終了させるため、下記を追加しましょう。
同様に、Application Endpoint の終了 (Terminate) と、Collaboration Platform のシャットダウン (Shutdown) をおこないます。

. . .

using Microsoft.Rtc.Collaboration;
using System.Threading;
. . .

private CollaborationPlatform rtcPlatform;
private ApplicationEndpoint appEndpoint;
private AutoResetEvent shutdownEvent = new AutoResetEvent(false);
. . .

static void Main(string[] args)
{
    . . .
}

public void Run()
{
    // Start platform and establish endpoint
    . . .

    Thread.Sleep(10000);

    // Terminate endpoint and shutdown platform
    Console.WriteLine("Press enter to shutdown ...");
    Console.ReadLine();
    appEndpoint.BeginTerminate(this.EndpointTerminateCompleted, null);
}

public void EndpointTerminateCompleted(IAsyncResult res)
{
    appEndpoint.EndTerminate(res);
    Console.WriteLine("Completed endpoint terminate ...");
    rtcPlatform.BeginShutdown(this.PlatformShutdownCompleted, null);
}

public void PlatformShutdownCompleted(IAsyncResult res)
{
    rtcPlatform.EndShutdown(res);
    Console.WriteLine("Completed platform shutdown ...");
}
. . .

上記のアプリケーションを実行 (起動) すると、このアプリケーションは、Lync の利用者からは、下図のように表示されます。(上述の通り、常に Available になります。)

つぎに、<Enter> キーを押すと、Presence を動的に変更して、表示されるように変更してみましょう。

下記の通りコードを追加 (変更) します。

プレゼンスの発行・取得 (Publish / Subscribe) など、アプリケーション エンドポイントにユーザーのような振る舞いを追加したい場合には、下記のように UseRegistration を true に設定します。また、上述した PresentityType を autoattendant に変更し、プレゼンスの既定値を、今回は (Available ではなく) Offline にしています。(下記で、PresenceCategoryWithMetaData に渡す Container ID については、「MSDN : Introduction to Presence」を参照してください。)

注意 : なお、InitialPresence の情報などがキャッシュされていますので、いったん Remove-CsTrustedApplicationEndpoint、Remove-CsTrustedApplication でアプリケーションとエンドポイントを削除してから、再度、このアプリケーションとエンドポイントを登録しなおしてください。

. . .
using Microsoft.Rtc.Collaboration.Presence;
. . .

public void Run()
{
    . . .

    Thread.Sleep(10000);

    // Change Presence
    Console.WriteLine("Press enter to change presence ...");
    Console.ReadLine();
    List<PresenceCategoryWithMetaData> categoryList = new List<PresenceCategoryWithMetaData>();
    PresenceCategoryWithMetaData categoryItem = new PresenceCategoryWithMetaData(1, 0,
        new PresenceState(PresenceStateType.UserState,
            (int) PresenceAvailability.Busy,
            new PresenceActivity(new LocalizedString("Sorry, the desk is busy ..."))));
    categoryList.Add(categoryItem);
    appEndpoint.LocalOwnerPresence.BeginPublishPresence(categoryList,
        this.PublishPresenceCompleted, null);

    // Terminate endpoint and shutdown platform
    Console.WriteLine("Press enter to shutdown ...");
    Console.ReadLine();
    appEndpoint.BeginTerminate(this.EndpointTerminateCompleted, null);
}

. . .

public void ApplicationEndpointSettingsDiscovered(object sender, ApplicationEndpointSettingsDiscoveredEventArgs e)
{
    Console.WriteLine("Called applicationEndpointSettingsDiscovered ...");
    ApplicationEndpointSettings settings = e.ApplicationEndpointSettings;
    settings.UseRegistration = true;
    settings.AutomaticPresencePublicationEnabled = true;
    settings.Presence.PresentityType = "autoattendant";
    PresenceCategoryWithMetaData categoryItem = new PresenceCategoryWithMetaData(1, 0,
        new PresenceState(PresenceStateType.AggregateState,
            (int)PresenceAvailability.Offline,
            new PresenceActivity(new LocalizedString("Now is offline ..."))));
    settings.Presence.InitialPresenceState = new PresenceState(categoryItem);
    settings.Presence.Description = "Hello help desk !";
    appEndpoint = new ApplicationEndpoint(rtcPlatform, settings);
    appEndpoint.BeginEstablish(this.EndpointEstablishCompleted, null);
}

. . .

public void PublishPresenceCompleted(IAsyncResult res)
{
    appEndpoint.LocalOwnerPresence.EndPublishPresence(res);
}
. . .

このアプリケーションをサーバー側で実行し、<Enter> キーを 1 回押すと、実行結果は、下図の通りになります。(左はクライアント側、右は UCMA サーバー側です。)
それ以外の場合は、常に Offline になります。

つぎに、Help Desk に入ってきた IM (Instant Messaging) を検出し、この IM をヘルプデスク担当者の demouser2@example.jp (デモ次郎) と接続してみましょう。(これは、Back to Back Call と呼ばれる手法です。)
以下の通り追記します。

注意 : この際、Lync Server から、上記のプログラムに接続がおこなわれるため、UCMA サーバーのファイアウォール (Firewall) の設定で、上記のプログラムが受信可能となるように設定しておいてください。なお、Visual Studio でデバッグ実行している場合には、この実行プログラム (.exe) 以外に Visual Studio のホストも受信可能にしておく必要があります。(無論、Firewall をすべて無効にすれば大丈夫ですが、本番稼動時は、まめに設定しておきましょう。)

public void ApplicationEndpointSettingsDiscovered(object sender, ApplicationEndpointSettingsDiscoveredEventArgs e)
{
    . . .

    appEndpoint.RegisterForIncomingCall<InstantMessagingCall>(InstantMessagingReceived);
    appEndpoint.BeginEstablish(this.EndpointEstablishCompleted, null);
}
. . .

private BackToBackCall b2bCall;    // 下記の「注意」を参照 . . .

public void InstantMessagingReceived(object sender,
    CallReceivedEventArgs<InstantMessagingCall> e)
{
    // incoming
    BackToBackCallSettings inCallSettings =
        new BackToBackCallSettings(e.Call);

    // outgoing
    Conversation outCon = new Conversation(appEndpoint);
    InstantMessagingCall outCall = new InstantMessagingCall(outCon);
    BackToBackCallSettings outCallSettings =
        new BackToBackCallSettings(outCall, "sip:demouser2@example.jp");

    // execute b2b call
    b2bCall = new BackToBackCall(
        inCallSettings,
        outCallSettings);
    b2bCall.BeginEstablish(B2BCallEstablishCompleted, null);
}

public void B2BCallEstablishCompleted(IAsyncResult res)
{
    b2bCall.EndEstablish(res);
}
. . .

public void EndpointTerminateCompleted(IAsyncResult res)
{
    appEndpoint.EndTerminate(res);
    Console.WriteLine("Completed endpoint terminate ...");
    appEndpoint.UnregisterForIncomingCall<InstantMessagingCall>(InstantMessagingReceived);
    rtcPlatform.BeginShutdown(this.PlatformShutdownCompleted, null);
}
. . .

注意 : 上記では、可読性の観点から、変数 b2bCall をインスタンスの変数としていますが、複数のイベントが同時に発生した場合、b2bCall が書き変わってしまう可能性があるので注意してください。現実の開発では、メソッド内の変数として定義する (ラムダ式を使って BginEstablish の Async call を記述)、イベントが渡す引数を使用する など、考慮してプログラミングしてください。

デモ太郎 (demouser1) から、この Help Desk アプリケーションに対して IM をおこなうと、下図の通り、実際にはデモ次郎 (demouser2) と接続されます。(お互いは Help Desk アプリケーションと対話していますが、実際には、demouser1 と demouser2 の間で会話がおこなわれます。)

補足 : 一方、「転送」 をおこなうと、上記のような BackToBack エージェントによるバックエンドの接続ではなく、お互いの名前が表示され、フロントエンドで接続されます。転送をおこなうには、BeginTransfer メソッドを使用します。

上記は、もちろん、AudioVideoCall でも可能です。

例によって、例外処理や、プレゼンスの確認など、細かなコードは省略していますので、現実の開発では、こうした細かな処理もお忘れなく。。。(上述の通り、複数ユーザーで利用した場合にも配慮し、現実の開発では、Conversation や McuSession ごとにインスタンスを作成して処理すると良いでしょう。)

ここでは基本的なサンプルしか掲載しませんでしたが、この UCMA を使うと、冒頭で述べたように、非常に先進的なさまざまなアプリケーションが開発できます。また、UCMA 2.0 を使用されていた方は、UCMA 3.0 で、上記のようなアプリケーションが非常に簡単に構築できるようになっていることがおわかり頂けるでしょう。(いくつかの機能では、今までの XML 地獄からも解放されています。) また、「Lync 2010 クライアント開発 入門」で解説した CWE や Contextual Data とも連携できるため、「何について問い合わせているか」など、独自な情報とも連携できます。

UCMA 3.0 を使用したアプリケーション開発については、以下で紹介していますので、是非いろいろと試してみてください。

[MSDN] Unified Communications 2010 Training - Using the UCMA 3.0 SDK

http://msdn.microsoft.com/en-us/lync/gg581803

[MSDN] Unified Communications 2010 Training - Using the UCMA 3.0 Workflow SDK

http://msdn.microsoft.com/en-us/lync/gg581804

[MSDN] Unified Communications 2010 Training - Building Advanced Communications Solutions with UCMA 3.0

http://msdn.microsoft.com/en-us/lync/gg581805

 

関連ナンバー


Comments (0)

Skip to main content