最近在做Lync相关的开发,刚接触到MSPL应用程序,MSPL(Microsoft SIP Processing Language)是Lync开发中很重要的一种脚本语言,它属于Lync Server SDK包,主要用来用来过滤和路由SIP消息。它开发的脚本是嵌在Lync Server 2010应用程序中应用程序清单(manifests)中。MSPL不支持算术运算,类型定义和除foreach外的循环。
本次不讲具体的MSPL语法和应用,因为关于MSPL部署的资料比较少,很多刚接触MSPL开发的朋友,可能和本人一样,在MSPL应用程序部署的问题花了不少时间。因此,作为预备知识,先讲一下怎么部署MSPL应用程序到Lync Server,其实这个过程并不复杂。
我们以SDK中自带的案例(FilteringApp和Archiver)来做部署说明:
案例一般在C:\Program Files\Microsoft Lync Server 2010\SDK\Samples目录下,FilteringApp是一个只有脚本(ScriptOnly)的服务器应用程序,Archiver是一个编译的服务器应用程序。
MSPL服务器应用程序可以部署在以下服务器上:
Standard Edition Server
Director
Front End Server
A/V Conferencing Server
Mediation Server
Edge Server
Archiving Server
Monitoring Server
Archiving and Monitoring Server
Survivable Branch Server
我们先来讲ScriptOnly的应用程序FilteringApp的部署
1. 将应用程序目录FilteringApp复制到服务器上,如C:/lync目录下,在C:/Lync/FilteringApp目录上有两个文件:
1) Filtering.am 脚本文件(应用程序清单文件,xml格式)

< r:applicationManifest
r:appUri ="http://www.microsoft.com/LC/SDK/Samples/Filter"
xmlns:r ="http://schemas.microsoft.com/lcs/2006/05" >
<!--
- Handle all IMs
-->
< r:requestFilter methodNames ="ALL"
strictRoute ="true"
registrarGenerated ="false"
domainSupported ="false" />
<!--
- Ignore all responses.
-->
< r:responseFilter reasonCodes ="NONE" />
<!--
- Don't proxy by default.
-->
< r:proxyByDefault action ="false" />
<!--
- Script-only application.
-->
< r:scriptOnly />
<!--
-
- policy.txt:
-
- The IM policy database file. Contains three whitespace-delimited
- columns, formatted as follows:
-
- user@domain policy value
-
- where user@domain is the user's full request-uri, and policy is one
- of the following:
-
- allow: deliver all IMs sent to this user.
- filter: deliver all IMs to this user, provided the word in
- the value column is not in the message body.
- drop: reject all IMs sent to this user.
-
-->
< r:file name ="policyTable" path ="policy.txt" delimitedBy ="whitespace" keyColumnName ="uri" >
<!-- Policy applies to this URI. -->
< r:column name ="uri" />
<!-- The policy verb describing action to be taken (see above description) -->
< r:column name ="policy" />
<!-- The filter string applied to messages (for "filter" policy) -->
< r:column name ="value" />
</ r:file >
< r:splScript > <![CDATA[
/*++
Copyright (C) 2004 Microsoft Corporation.
Script:
Filter.am.
Abstract:
This sample demonstrates a simple user-based IM filtering policy. The
policy data is read from a structured flat file; see above for a
description of this file's contents. Note that the file is reread if
modified; alternatively, a static="true" attribute in the <file> tag
changes this behavior.
Features demonstrated:
- Flat file access
--*/
thisScript = "Filter.am :: ";
/*
* Banner
*/
Log("Debug", false, "");
Log("Debug", false, "Entering Filter.am");
Log("Debug", false, "New ", sipRequest.Method, " request for ", GetUserAtHost(sipRequest.To));
/*
* Get user@domain string for the user in the To: header.
*/
userUri = GetUri(sipRequest.To);
userAtHost = GetUserAtHost(userUri);
/*
* Look up the policy for this user.
*/
policy = policyTable[userAtHost].policy;
/*
* Act on the policy verb.
*/
switch (policy)
{
case "allow":
/*
* Proxy this request.
*/
ProxyRequest("");
Log("Debug", false, thisScript, "[allow] Proxying ", sipRequest.Method);
break;
case "filter":
/*
* Proxy this request, if the content body doesn't contain the specified
* forbidden text.
*/
if (IndexOfString(sipRequest.Content, policyTable[userAtHost].value) == -1)
{
/*
* Content body doesn't match filter string. Proxy.
*/
Log("Debug", false, thisScript, "[filter] Proxying " , sipRequest.Method);
ProxyRequest("");
}
else
{
/*
* Content matched filter string -- reject this request.
*/
Log("Debug", false, thisScript, "[filter] Rejecting ", sipRequest.Method);
Respond(403, "Forbidden (Message filtered)");
}
break;
case "drop":
/*
* Drop all requests sent to this user.
*/
Log("Debug", false, thisScript, "[drop] Rejecting ", sipRequest.Method);
Respond(403, "Forbidden (Message filtered)");
break;
default:
/*
* Unknown policy verb -- by default, reject
*/
Log("Debug", false, thisScript, "No policy verb for user ", userAtHost, " -- dropping ", sipRequest.Method);
Respond(403, "Forbidden (Invalid policy verb)");
break;
}
]]> </ r:splScript >
</ r:applicationManifest >
其中:r:appUri="http://www.microsoft.com/LC/SDK/Samples/Filter"表示应用程序Uri,在后面的安装脚本中要用到
2)Policy.txt,此应用程序中用到内flat file.作用大家看一内容就清楚
user2@myhost.com filter confidential
user3@myhost.com drop
2. 在Lync Server命令行管理程序中执行PowerShell的安装脚本:
其中:
registrar:lyncserver.corp.itime.biz/FilteringApp 是要部署的应用程序标识,其中是lyncserver.corp.itime.biz服务器的FQDN,FilteringApp 是应用程序名称,应修改为实际的值。
http://www.microsoft.com/LCS/Samples/Filtering 是应用程序的Uri,在am文件中定义,应修改为和am文件一致,FilteringApp.am文件后会贴出。
-Critical $False 表示是否关键项,如果为True,则程序会自动启动,并且如果该应用程序的失败会导致整个服务崩溃。
-Enabled $True 表示安装后是否启用。
-ScriptName "C:\lync\FilteringApp\Filter.am" 脚本位置,一般ScriptOnly应用程序需要,这里修改为实际的am文件位置
然后以管理员身份运行 Lync Server命令行管理程序,执行以上脚本,如下图所示:



< r:applicationManifest
r:appUri ="http://www.microsoft.com/LCS/Samples/Archiver"
xmlns:r ="http://schemas.microsoft.com/lcs/2006/05" >
<!--
- Handle all IMs, including those with strict routes
- and those with request URIs that don't match this server's
- domain.
-->
< r:requestFilter methodNames ="MESSAGE,INVITE,ACK,BYE"
strictRoute ="true"
domainSupported ="false" />
<!--
- Handle all responses.
-->
< r:responseFilter reasonCodes ="ALL" />
< r:splScript > <![CDATA[
/*++
Script:
Archiver.am
Abstract:
This script dispatches incoming requests and responses to the
managed part of the archiver sample, found in Archiver.cs.
--*/
/*
* Dispatch all requests to the managed part of this application.
*/
if (sipRequest)
{
Dispatch("OnRequest");
}
else
{
Dispatch("OnResponse");
}
]]> </ r:splScript >
</ r:applicationManifest >



