本文仅在ITECN上发表,谢绝转载! 欢迎大家批评指正...
最近做了一个算是比较tough的case,感觉还是蛮有价值的,贴在ITECN中,期与跟大家一起分享。
客户报告说,在IE中打开页面发生了失败,并附加了截图:
请注意地址栏,开始是outlook:\\,这里代表一种outlook的协议,各位可以在开始-->运行菜单中输入outlook:\\,如果你是outlook 2003,这时会自动调用outlook.exe这个application.
但是如果你是outlook 2007,就没有那么幸运了,会弹出如下的对话框:
这是为什么呢?KB中给出了很好的解释。
929590 Known issues when you develop custom solutions for Office Outlook 2007
http://support.microsoft.com/default.aspx?scid=kb;EN-US;929590
原因很简单,The Outlook protocol no longer works outside Outlook,
This protocol will only work when you use it in Outlook.You can use this protocol on a folder home page, on the Web toolbar, or in the body of an Outlook item.
简言之,在安装过程中,outlook不会试图去注册这个outlook的协议。
为什么Office Team要取消这个协议的注册呢?还是安全问题,我这里引用了微软官方的一段文字来解释:
There are various attacks which are aided by the outlook:// protocol. This protocol allows attacks to occur by someone browsing to a web site which contains a link (A HREF, IMG SRC, document. location redirect, etc) to the outlook:// protocol. The protocol acts as a big stepping stone to allow for easily exploiting other bugs.
问题到这里似乎是解决了,但是客户还是需要使用这个协议,经过我们的分析,确定了可以增加注册表中HKEY_CLASSES_ROOT的一些items来解决这个问题,当我们跟客户discuss这个action plan的时候,客户首先对我们的research表示感谢,但是还是有一些concern,那就是客户端也许很多,且安装的路径可能有所不同,因此依靠手工导入注册表的方式似乎有一点困难,经我们与CPR商讨,决定使用开机脚本来解决客户的concern:
GTSC的工作氛围就是这样,一切为客户着想,一切以客户满意为准绳,任何一个action plan都要严谨,保证可行性,在测试环境中将出问题的概率降至最低,经过商讨,我们认为有以下一些事情需要注意:
- 开机脚本针对计算机生效,也就是startup的script,而客户端是Windows Vista,并且启用了UAC,那么在登陆之前,也就是停留在安全桌面时,UAC的特性会不会block掉这个动作?
- 脚本需要加入判断语句,如果客户端运行过一次,这个脚本就不再运行了,直接退出。
- 由于客户端安装office的路径可能不同,因此还要让脚本去get HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\12.0\Outlook\InstallRoot下install的位置,然后将这个变量传递给下面的脚本,进行修改注册表的动作。
这三个问题我也是请教了很多人,包括国内著名的系统专家,资深desktop方面的专家,彭爱华,盆盆,盆盆认为:注册表内的权限有所区分,并不是说所有修改的动作都需要admin 的权限,如果是修改HKCU的键值,不需要admin,可以通过查询键值的ACL来确定这一点,例如:HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts,这下面有很多键值,就是禁止Current User访问的,可以在试验环境中测试一把;此外,在登陆之前,系统的startup的script是以system的credential来运行的,理论上是可以work的。
经过反复的测试,和研究,脚本终于写成了,贴在这里,供大家参考,也希望大家能多多提出宝贵意见:
免责声明:该代码仅用于技术交流和分享,请勿部署在生产环境中,由于该脚本给您带来的损失,笔者不承担任何责任。任何由于使用或无法使用脚本而带来的损失(包括但不局限于商业利润、业务中断、业务信息或其他财产上的损失),本站及其笔者或涉及内容创建的任何其他人等对任何上述的损失概不负责。
=======================================================
'这里做const的动作,表明是在HKEY_LOCAL_MACHINE下进操作,注意其后的&H80000002在不同位置是有所不同的,变化规律如下:
'const HKCR = &H80000000 ' HKEY_CLASSES_ROOT
'const HKCU = &H80000001 ' HKEY_CURRENT_USER
'const HKLM = &H80000002 ' HKEY_LOCAL_MACHINE
'const HKU = &H80000003 ' HKEY_USERS
'const HKCC = &H80000005 ' HKEY_CURRENT_CONFIG
Const HKEY_LOCAL_MACHINE = &H80000002
'这段代码用于取出office outlook的安装路径,设为strValue1,并传递至下面的脚本
strComputer = "."
Set objRegistry = GetObject("winmgmts:\\" & _
strComputer & "\root\default:StdRegProv")
strKeyPath = "SOFTWARE\Microsoft\Office\12.0\Outlook\InstallRoot"
strValueName = "Path"
dim strValue1
strValue1 = "C:\Program Files\Microsoft Office\Office12\"
objRegistry.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue1
const HKEY_CLASSES_ROOT = &H80000000
strComputer = "."
Set objRegistry = GetObject("winmgmts:\\" & _
strComputer & "\root\default:StdRegProv")
strKeyPath = "outlook"
strValueName = "URL Protocol"
objRegistry.GetStringValue HKEY_CLASSES_ROOT,strKeyPath,strValueName,strValue
'这里开始进行判断,也就是说没有运行过就运行,运行过之后退出
If IsNull(strValue) Then
strComputer = "."
'开始修改HKEY_CLASSES_ROOT中的值
Set StdOut = WScript.StdOut
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" &_
strComputer & "\root\default:StdRegProv")
strKeyPath = "outlook"
strvalueName = "URL Protocol"
strvalue = ""
oReg.CreateKey &H80000000,strKeyPath
oreg.setstringvalue &H80000000, strKeyPath, strValuename, strValue
strKeyPath = "outlook"
strvalueName = ""
strvalue = "URL:Outlook Folders"
oreg.setstringvalue &H80000000, strKeyPath, strValuename, strValue
strKeyPath = "outlook\DefaultIcon"
oReg.CreateKey &H80000000,strKeyPath
strvalueName = ""
dim strValue2
strValue2 = strValue1 & ",-9403"
oreg.setstringvalue &H80000000, strKeyPath, strValuename, strValue2
'Create "[HKEY_CLASSES_ROOT\outlook\shell] and @="open""
strKeyPath = "outlook\shell"
oReg.CreateKey &H80000000,strKeyPath
strvaluename = ""
strvalue = "open"
oreg.setstringvalue &H80000000, strKeyPath, strValuename, strValue
'Create [HKEY_CLASSES_ROOT\outlook\shell\open] and @=""
strKeyPath = "outlook\shell\open"
oReg.CreateKey &H80000000,strKeyPath
strvaluename = ""
strvalue = ""
oreg.setstringvalue &H80000000, strKeyPath, strValuename, strValue
'Create [HKEY_CLASSES_ROOT\outlook\shell\open\command] and @="\"c:\\Program Files\\Microsoft Office\\Office12\\OUTLOOK.EXE\" /select \"%1\""
strKeyPath = "outlook\shell\open\command"
oReg.CreateKey &H80000000,strKeyPath
strvaluename = ""
dim strValue3
'这里需要注意几个地方,第一,value data需要带引号,但是我们不能在vbs中直接添加引号,因为这样会被vbs认为是一个常量,我们可以使用转换函数chr将ASCI编码中的引号0x34转换,让vbs识别,从而添加至valuedata中;还有,从installroot中取出的只有:X:\Program Files\Microsoft Office\Office12\这一部分,没有outlook.exe,这一部分,这里需要使用&符号,将变量与常量结合起来,填充至valuedata中
strValue3 = strValue1 & "outlook.exe" & chr(34) & " /select " & "%1"
strvalues = chr(34)& strValue3 & chr(34)
oreg.setstringvalue &H80000000, strKeyPath, strValuename, strValues
wscript.echo "Finished!"
Else
Wscript.Echo "The registry key exists."
End If
=========================================================
我在测试环境中的vista测试通过,已经交给team中的其他members,让大家黑箱白箱测试,如果没有什么问题的话,可以solution deliverd了,hope everything goes well. ^_^
感兴趣的朋友可以发邮件至lkj5210@hotmail.com索取源码进行调试,也希望诸位高手多提宝贵意见,谢谢大家!