『求助』在Webpage上调用Windows Messenger API
最近在工作中遇到一个在WebPage上调用Windows Messenger API的需求,于是到MSDN上大搜一番,还是有所收获。相关链接如下:http://www.microsoft.com/china/MSDN/library/WebServices/WebServices/nacwebteam09032001.mspx?pf=true
其中包含了一段MSN Instant Messenger代码。首先要提出的一个大家容易混淆的概念:Windows Messenger 与 MSN Messenger 到底有什么区别和联系?
·MSN Messenger不是系统自带的,而Windows Messenger在非Windows 2003的Microsoft系统上都已经作为默认组件安装,这里我们要使用到的就是Windows Messenger API
·MSN Messenger只能用.Net Passport这个微软统一身份验证来登陆,也就意味着它只能在一台联入了互联网的电脑上登陆使用。而Windows Messenger则有三种登陆方式:a. Exchange身份验证 b. .Net Passport身份验证 c. SIP身份验证。其中c. SIP身份验证不太常用。而现在很多企业都已经建立了内部Exchange服务器,这样就经常会采用Windows Messenger的Exchange身份验证来进行登录后内部员工IM联系。而如果使用b. .Net Passport身份验证则功能上与MSN Messenger完全一样。
·Windows Messenger可以同时使用三种身份验证登陆,换句话说就是我可以同时登陆企业内网的Windows Messenger IM以及互联网上的MSN Messenger。其中的联系人列表是整合的。就有点像MyIM能整合MSN以及QQ、Yahoo IM等等IM软件一样。而MSN Messenger不行
·MSN Messenger的聊天记录可以保存,且通讯功能更加强大,如最新的7.5版本“传情动漫”以及“手写”功能已经完全超越了QQ等同类IM软件。而Windows Messenger聊天记录在关闭聊天窗口后消失不自动保存,只集成了一些最基本的通信方式。可以算作是简化版的MSN Messenger
有了以上的信息,我们已经可以开始试验了。将MSDN上的那段MSN Instant Messenger代码复制到本地,保存成.html文件,用IE打开。嗯。一切正常。请看下图(由于本人在台企上班,公司要求使用繁体操作系统,请大家见谅):
图一
然后,我们把这个文件复制到wwwroot发布目录下。再通过 http://172.18.77.60/ (我电脑的IP地址)前缀来访问。如下图所示:
图二
大家可以看到。同样一段代码。直接访问与发布后访问执行结果不同。我本想将此功能制作成一个WebPart以便在SharePoint上的任意地点引用。但是现在的问题是,只有我直接双击该html文件才能正常显示“联系人名单”,而我无论使用http://127.0.0.1/ 或者 http://localhost/ 或者 http://我的电脑IP地址/ 三种方式访问,联系人列表都会发生错误。但是通过点击“undefined”链接是可以实现对话功能的,通过查看源代码得知,其是通过枚举id来实现的,所以这里仅仅是一个显示上的问题。
下面让我们来看看完整的代码,完全使用JavaScript调用Windows Messenger API来实现。
作为代码本身是很简单的,不用过多解释,整个实现的原理就是:首先new了两个Windows Messenger实例,分别为oMsgrObj以及oMsgrApp。然后通过对好友列表oList = oMsgrObj.List(0);循环枚举,并利用DOM技术塞入新的Element来列出好友名称oNewElement.innerText = oContact.FriendlyName; 以及好友状态switch (oContact.State)。最后通过function sendMessage()函数来实现OnClick事件,调用对应的Windows Messenger实例弹出好友对话框。整段代码是清晰明了也很容易懂的。这里我们主要看看造成上面图二错误的代码段:
function populateContacts()
{
var oList = oMsgrObj.List(0);
var oContact;
var i;
for (i = 0; i < oList.Count; i++)
{
oContact = oList.Item(i);
oNewElement = document.createElement("DIV");
oNewElement.innerText = oContact.FriendlyName;
接着我换了一个思路去做这个功能,直接在VS.Net中新建一个工程,引入COM中的MessengerAPI类,然后加入以下测试代码都会报错,不知道为什么。
我百思不得其解,同样的方法难道只能在本地使用?那这段代码不就没有意义了吗?恳请各位大虾指点迷津。m(_ _)m 拜..
附Windows Messenger下载地址:
http://nj.onlinedown.net/soft/3366.htm
其中包含了一段MSN Instant Messenger代码。首先要提出的一个大家容易混淆的概念:Windows Messenger 与 MSN Messenger 到底有什么区别和联系?
·MSN Messenger不是系统自带的,而Windows Messenger在非Windows 2003的Microsoft系统上都已经作为默认组件安装,这里我们要使用到的就是Windows Messenger API
·MSN Messenger只能用.Net Passport这个微软统一身份验证来登陆,也就意味着它只能在一台联入了互联网的电脑上登陆使用。而Windows Messenger则有三种登陆方式:a. Exchange身份验证 b. .Net Passport身份验证 c. SIP身份验证。其中c. SIP身份验证不太常用。而现在很多企业都已经建立了内部Exchange服务器,这样就经常会采用Windows Messenger的Exchange身份验证来进行登录后内部员工IM联系。而如果使用b. .Net Passport身份验证则功能上与MSN Messenger完全一样。
·Windows Messenger可以同时使用三种身份验证登陆,换句话说就是我可以同时登陆企业内网的Windows Messenger IM以及互联网上的MSN Messenger。其中的联系人列表是整合的。就有点像MyIM能整合MSN以及QQ、Yahoo IM等等IM软件一样。而MSN Messenger不行
·MSN Messenger的聊天记录可以保存,且通讯功能更加强大,如最新的7.5版本“传情动漫”以及“手写”功能已经完全超越了QQ等同类IM软件。而Windows Messenger聊天记录在关闭聊天窗口后消失不自动保存,只集成了一些最基本的通信方式。可以算作是简化版的MSN Messenger
有了以上的信息,我们已经可以开始试验了。将MSDN上的那段MSN Instant Messenger代码复制到本地,保存成.html文件,用IE打开。嗯。一切正常。请看下图(由于本人在台企上班,公司要求使用繁体操作系统,请大家见谅):
图一
然后,我们把这个文件复制到wwwroot发布目录下。再通过 http://172.18.77.60/ (我电脑的IP地址)前缀来访问。如下图所示:
图二
大家可以看到。同样一段代码。直接访问与发布后访问执行结果不同。我本想将此功能制作成一个WebPart以便在SharePoint上的任意地点引用。但是现在的问题是,只有我直接双击该html文件才能正常显示“联系人名单”,而我无论使用http://127.0.0.1/ 或者 http://localhost/ 或者 http://我的电脑IP地址/ 三种方式访问,联系人列表都会发生错误。但是通过点击“undefined”链接是可以实现对话功能的,通过查看源代码得知,其是通过枚举id来实现的,所以这里仅仅是一个显示上的问题。
下面让我们来看看完整的代码,完全使用JavaScript调用Windows Messenger API来实现。
1
<HTML>
2
<HEAD>
3
<TITLE>Embedding MSN Messenger Test</TITLE>
4
5
<OBJECT CLASSID="clsid:F3A614DC-ABE0-11d2-A441-00C04F795683"
6
CODEBASE="#Version=2,0,0,83"
7
CODETYPE="application/x-oleobject" ID="oMsgrObj" WIDTH="0"
8
HEIGHT="0" OnUserStateChanged="alert();">
9
</OBJECT>
10
<OBJECT CLASSID="clsid:FB7199AB-79BF-11d2-8D94-0000F875C541"
11
CODETYPE="application/x-oleobject"
12
ID="oMsgrApp" WIDTH="0" HEIGHT="0">
13
</OBJECT>
14
15
<STYLE>
16
BODY
17
{
18
FONT-FAMILY: Verdana, Arial, Helvetica;
19
FONT-SIZE: 8pt;
20
}
21
INPUT
22
{
23
FONT-FAMILY: Verdana, Arial, Helvetica;
24
FONT-SIZE: 8pt;
25
}
26
.clsHeading
27
{
28
FONT-WEIGHT: bolder;
29
FONT-SIZE: 10pt;
30
}
31
.clsContact
32
{
33
PADDING: 2px;
34
CURSOR: hand;
35
}
36
</STYLE>
37
</HEAD>
38
39
<BODY onLoad="body_onLoad();">
40
41
<SCRIPT LANGUAGE="JScript">
42
43
// Here are the definitions for the Messenger enumerated values we use
44
45
var MSTATE_OFFLINE = 1;
46
var MSTATE_ONLINE = 2;
47
var MSTATE_BUSY = 10;
48
var MSTATE_BE_RIGHT_BACK = 14;
49
var MSTATE_IDLE = 18;
50
var MSTATE_AWAY = 34;
51
52
function body_onLoad()
53
{
54
// First, we need to make sure that the Messenger controls got instantiated correctly
55
56
if ("undefined" != typeof(oMsgrObj) && null != oMsgrObj.object && "undefined"
57
!= typeof(oMsgrApp) && null != oMsgrApp.object)
58
{
59
// If so, let's check to see if we're online and (if so) populate our contacts UI
60
61
if (oMsgrObj.LocalState == MSTATE_ONLINE)
62
{
63
populateContacts();
64
}
65
else if (oMsgrObj.LocalState == MSTATE_OFFLINE)
66
{
67
btnLogon.disabled = false;
68
}
69
}
70
else
71
{
72
// Uh, oh - the controls didn't get instantiated correctly;
73
// the user probably needs to install Messenger
74
75
alert("You need to install the latest version of MSN Messenger!\nGo to http://messenger.msn.com right now!");
76
}
77
}
78
79
function populateContacts()
80
{
81
var oList = oMsgrObj.List(0);
82
var oContact;
83
var i;
84
85
// To populate our contact list, we're going to iterate throught the
86
// default list collection, check the state of each contact,
87
// and add a DIV with the approppriate appearance to our UI
88
89
for (i = 0; i < oList.Count; i++)
90
{
91
oContact = oList.Item(i);
92
93
oNewElement = document.createElement("DIV");
94
oNewElement.innerText = oContact.FriendlyName;
95
96
switch (oContact.State)
97
{
98
case MSTATE_ONLINE:
99
// Don't need to do anything
100
break;
101
case MSTATE_OFFLINE:
102
oNewElement.innerText += " (Offline)";
103
oNewElement.style.color = "graytext";
104
break;
105
case MSTATE_BUSY:
106
oNewElement.innerText += " (Busy)";
107
break;
108
case MSTATE_BE_RIGHT_BACK:
109
oNewElement.innerText += " (Be Right Back)";
110
break;
111
case MSTATE_IDLE:
112
oNewElement.innerText += " (Idle)";
113
break;
114
case MSTATE_AWAY:
115
oNewElement.innerText += " (Away)";
116
break;
117
default:
118
oNewElement.innerText += "(Just plain not around!)";
119
oNewElement.style.color = "graytext";
120
break;
121
}
122
oNewElement.className = "clsContact";
123
124
// To enable us to respond to the onclick event,
125
// we're programmatically setting the event
126
// handler AND we're defining an expando property
127
// on the contact DIV whose value is set to
128
// the index of the contact in the default list (so we can find them later)
129
130
oNewElement.onclick = sendMessage;
131
oNewElement.setAttribute("CONTACTID", i.toString());
132
133
divContacts.appendChild(oNewElement);
134
}
135
}
136
function doLogon()
137
{
138
// To logon, we just ask Messenger to display its logon UI
139
140
if (oMsgrObj.LocalState == MSTATE_OFFLINE)
141
{
142
btnLogon.disabled = true;
143
oMsgrApp.LaunchLogonUI();
144
}
145
}
146
147
function sendMessage()
148
{
149
// To send a message, we likewise just ask Messenger to do the heavy
150
// lifting (we just have to
151
// pass it a contact from the default list)
152
153
var nContactID = parseInt(window.event.srcElement.getAttribute("CONTACTID"));
154
if (!isNaN(nContactID))
155
{
156
var oContact = oMsgrObj.List(0).Item(nContactID);
157
oMsgrApp.LaunchIMUI(oContact);
158
}
159
}
160
161
</SCRIPT>
162
163
<SCRIPT LANGUAGE="JScript" EVENT="onLocalStateChangeResult(hr)" FOR="oMsgrObj">
164
165
if (hr == 0)
166
{
167
if (oMsgrObj.LocalState == MSTATE_ONLINE)
168
{
169
// Now we're online
170
171
window.setTimeout("populateContacts();", 3000);
172
}
173
else if (oMsgrObj.LocalState == MSTATE_OFFLINE)
174
{
175
// Now we're offline
176
177
divContacts.innerHTML = "";
178
btnLogon.disabled = false;
179
}
180
}
181
182
</SCRIPT>
183
184
<DIV CLASS="clsHeading">Contacts (click on a contact to send a message!)</DIV>
185
<DIV ID="divContacts" STYLE="MARGIN-TOP: 8px;
186
MARGIN-BOTTOM: 8px; BORDER: 1px solid steelblue"></DIV>
187
<INPUT TYPE="BUTTON" ID="btnLogon" VALUE="Logon" onClick="doLogon();" DISABLED="yes">
188
189
</BODY>
190
</HTML>
<HTML>2
<HEAD>3
<TITLE>Embedding MSN Messenger Test</TITLE>4

5
<OBJECT CLASSID="clsid:F3A614DC-ABE0-11d2-A441-00C04F795683" 6
CODEBASE="#Version=2,0,0,83"7
CODETYPE="application/x-oleobject" ID="oMsgrObj" WIDTH="0" 8
HEIGHT="0" OnUserStateChanged="alert();">9
</OBJECT>10
<OBJECT CLASSID="clsid:FB7199AB-79BF-11d2-8D94-0000F875C541" 11
CODETYPE="application/x-oleobject"12
ID="oMsgrApp" WIDTH="0" HEIGHT="0">13
</OBJECT>14

15
<STYLE>16
BODY17
{18
FONT-FAMILY: Verdana, Arial, Helvetica;19
FONT-SIZE: 8pt;20
}21
INPUT22
{23
FONT-FAMILY: Verdana, Arial, Helvetica;24
FONT-SIZE: 8pt;25
}26
.clsHeading27
{28
FONT-WEIGHT: bolder;29
FONT-SIZE: 10pt;30
}31
.clsContact32
{33
PADDING: 2px;34
CURSOR: hand;35
}36
</STYLE>37
</HEAD>38

39
<BODY onLoad="body_onLoad();">40

41
<SCRIPT LANGUAGE="JScript">42

43
// Here are the definitions for the Messenger enumerated values we use44

45
var MSTATE_OFFLINE = 1;46
var MSTATE_ONLINE = 2;47
var MSTATE_BUSY = 10;48
var MSTATE_BE_RIGHT_BACK = 14;49
var MSTATE_IDLE = 18;50
var MSTATE_AWAY = 34;51

52
function body_onLoad()53
{54
// First, we need to make sure that the Messenger controls got instantiated correctly55

56
if ("undefined" != typeof(oMsgrObj) && null != oMsgrObj.object && "undefined" 57
!= typeof(oMsgrApp) && null != oMsgrApp.object)58
{59
// If so, let's check to see if we're online and (if so) populate our contacts UI60

61
if (oMsgrObj.LocalState == MSTATE_ONLINE)62
{63
populateContacts();64
}65
else if (oMsgrObj.LocalState == MSTATE_OFFLINE)66
{67
btnLogon.disabled = false;68
}69
}70
else71
{72
// Uh, oh - the controls didn't get instantiated correctly; 73
// the user probably needs to install Messenger74

75
alert("You need to install the latest version of MSN Messenger!\nGo to http://messenger.msn.com right now!");76
}77
}78

79
function populateContacts()80
{81
var oList = oMsgrObj.List(0);82
var oContact;83
var i;84

85
// To populate our contact list, we're going to iterate throught the 86
// default list collection, check the state of each contact,87
// and add a DIV with the approppriate appearance to our UI88

89
for (i = 0; i < oList.Count; i++)90
{91
oContact = oList.Item(i);92

93
oNewElement = document.createElement("DIV");94
oNewElement.innerText = oContact.FriendlyName;95

96
switch (oContact.State)97
{98
case MSTATE_ONLINE:99
// Don't need to do anything100
break;101
case MSTATE_OFFLINE:102
oNewElement.innerText += " (Offline)";103
oNewElement.style.color = "graytext";104
break;105
case MSTATE_BUSY:106
oNewElement.innerText += " (Busy)";107
break;108
case MSTATE_BE_RIGHT_BACK:109
oNewElement.innerText += " (Be Right Back)";110
break;111
case MSTATE_IDLE:112
oNewElement.innerText += " (Idle)";113
break;114
case MSTATE_AWAY:115
oNewElement.innerText += " (Away)";116
break;117
default:118
oNewElement.innerText += "(Just plain not around!)";119
oNewElement.style.color = "graytext";120
break;121
}122
oNewElement.className = "clsContact";123

124
// To enable us to respond to the onclick event, 125
// we're programmatically setting the event126
// handler AND we're defining an expando property127
// on the contact DIV whose value is set to128
// the index of the contact in the default list (so we can find them later)129

130
oNewElement.onclick = sendMessage;131
oNewElement.setAttribute("CONTACTID", i.toString());132

133
divContacts.appendChild(oNewElement);134
}135
}136
function doLogon()137
{138
// To logon, we just ask Messenger to display its logon UI139

140
if (oMsgrObj.LocalState == MSTATE_OFFLINE)141
{142
btnLogon.disabled = true;143
oMsgrApp.LaunchLogonUI();144
}145
}146

147
function sendMessage()148
{149
// To send a message, we likewise just ask Messenger to do the heavy150
// lifting (we just have to151
// pass it a contact from the default list)152

153
var nContactID = parseInt(window.event.srcElement.getAttribute("CONTACTID"));154
if (!isNaN(nContactID))155
{156
var oContact = oMsgrObj.List(0).Item(nContactID);157
oMsgrApp.LaunchIMUI(oContact);158
}159
}160

161
</SCRIPT>162

163
<SCRIPT LANGUAGE="JScript" EVENT="onLocalStateChangeResult(hr)" FOR="oMsgrObj">164

165
if (hr == 0)166
{167
if (oMsgrObj.LocalState == MSTATE_ONLINE)168
{169
// Now we're online170

171
window.setTimeout("populateContacts();", 3000);172
}173
else if (oMsgrObj.LocalState == MSTATE_OFFLINE)174
{175
// Now we're offline176

177
divContacts.innerHTML = "";178
btnLogon.disabled = false;179
}180
}181

182
</SCRIPT>183

184
<DIV CLASS="clsHeading">Contacts (click on a contact to send a message!)</DIV>185
<DIV ID="divContacts" STYLE="MARGIN-TOP: 8px; 186
MARGIN-BOTTOM: 8px; BORDER: 1px solid steelblue"></DIV>187
<INPUT TYPE="BUTTON" ID="btnLogon" VALUE="Logon" onClick="doLogon();" DISABLED="yes">188

189
</BODY>190
</HTML>作为代码本身是很简单的,不用过多解释,整个实现的原理就是:首先new了两个Windows Messenger实例,分别为oMsgrObj以及oMsgrApp。然后通过对好友列表oList = oMsgrObj.List(0);循环枚举,并利用DOM技术塞入新的Element来列出好友名称oNewElement.innerText = oContact.FriendlyName; 以及好友状态switch (oContact.State)。最后通过function sendMessage()函数来实现OnClick事件,调用对应的Windows Messenger实例弹出好友对话框。整段代码是清晰明了也很容易懂的。这里我们主要看看造成上面图二错误的代码段:
function populateContacts()
{
var oList = oMsgrObj.List(0);
var oContact;
var i;
for (i = 0; i < oList.Count; i++)
{
oContact = oList.Item(i);
oNewElement = document.createElement("DIV");
oNewElement.innerText = oContact.FriendlyName;
其中由oList变量得到oMsgrObj的实例后枚举oList的各个Item并存放到oContact变量中。种种现象表明oMsgrObj以及oMsgrApp两个实例已经创建成功,否则无法调用其内部方法如 oMsgrObj.List(0) 以及 oList.Count,但是现在出问题的方法是 oContact.FriendlyName。图二现象表明如果使用IP访问该网页则 oContact.FriendlyName 方法无法正常得到联系人名称,所以会显示为 undefined。而直接通过IE打开该页面则一切正常。
有些朋友说是安全性的问题,我已经把几个地址都加入“信任的网站”了,问题依旧。请看下图:
接着我换了一个思路去做这个功能,直接在VS.Net中新建一个工程,引入COM中的MessengerAPI类,然后加入以下测试代码都会报错,不知道为什么。
1
using System;
2
using System.Collections;
3
using System.ComponentModel;
4
using System.Data;
5
using System.Drawing;
6
using System.Web;
7
using System.Web.SessionState;
8
using System.Web.UI;
9
using System.Web.UI.WebControls;
10
using System.Web.UI.HtmlControls;
11
using MessengerAPI;
12
13
namespace WebMessenger
14
{
15
/// <summary>
16
/// WebForm1 的摘要说明。
17
/// </summary>
18
public class WebForm1 : System.Web.UI.Page
19
{
20
private void Page_Load(object sender, System.EventArgs e)
21
{
22
// 在此处放置用户代码以初始化页面
23
getMsgrObj();
24
}
25
26
Web 窗体设计器生成的代码
46
47
private void getMsgrObj()
48
{
49
MessengerAPI.MessengerClass oMsgr = new MessengerAPI.MessengerClass();
50
Response.Write(oMsgr.MyStatus.ToString());
51
}
52
}
53
}
using System;2
using System.Collections;3
using System.ComponentModel;4
using System.Data;5
using System.Drawing;6
using System.Web;7
using System.Web.SessionState;8
using System.Web.UI;9
using System.Web.UI.WebControls;10
using System.Web.UI.HtmlControls;11
using MessengerAPI;12

13
namespace WebMessenger14
{15
/// <summary>16
/// WebForm1 的摘要说明。17
/// </summary>18
public class WebForm1 : System.Web.UI.Page19
{20
private void Page_Load(object sender, System.EventArgs e)21
{22
// 在此处放置用户代码以初始化页面23
getMsgrObj();24
}25

26
Web 窗体设计器生成的代码46

47
private void getMsgrObj()48
{49
MessengerAPI.MessengerClass oMsgr = new MessengerAPI.MessengerClass();50
Response.Write(oMsgr.MyStatus.ToString());51
}52
}53
}我百思不得其解,同样的方法难道只能在本地使用?那这段代码不就没有意义了吗?恳请各位大虾指点迷津。m(_ _)m 拜..
附Windows Messenger下载地址:
http://nj.onlinedown.net/soft/3366.htm

浙公网安备 33010602011771号