前言:
用程序配置 IIS 所用到的“技术”无非是 ADSI 或者 WMI 提供的组件服务程序。可以通过 Windows Host Script 来执行 JScript 或者 VBScript 脚本,也可以在 VB/Delphi 这类快速开发工具开发程序来调用,甚至可以通过浏览器中运行的 JavaScript/JScript/VBScript 以及 IIS 运行的 ASP 来调用。因为支持 IDispatch 接口,所以可以后期绑定地通过 CreateObject 或者 GetObject 方式来获取 ADSI/WMI 的特定接口。
详细的有关 ADSI/WMI 的内容,可以查阅 MSDN,不仅仅可以用来配置 IIS,只要有足够的权限可以用来管理你的 Windows 的一切(Windows2000以后版本)。因为,WMI 本来就是:
Windows Management Instrumentation (WMI) 是可伸缩的系统管理结构,它采用一个统一的、 基于标准的、可扩展的面向对象接口。WMI 为您提供与系统管理信息和基础 WMI API 交互的标准方法。 WMI 主要由系统管理应用程序开发人员和管理员用来访问和操作系统管理信息。 WMI 可用于生成组织和管 理系统信息的工具,使管理员或系统管理人员能够更密切地监视系统活动。例如,可以使用 WMI 开发一个 应用程序,用于在 Web 服务器崩溃时呼叫管理员。
InstallShield X 版本不是已经可以配置 IIS 了么?
来自 InstallShield X 的文档中的这段话已经说明:如果要创建的站点已经存在,那么它的虚拟目录或许被创建到已有的站点下,而已有的站点的属性并不会改变,也不会创建新的站点。
本来,与数据库安装一样,我的观点是:单独做一个配置工具来完成对数据库和 IIS 的设置。那么,可以在安装过程中、安装结束后,以及用户使用的过程中的任何时候运行这个配置工具来进行初始化以及修改配置参数。
因此,多年来我从来没在 IS 中进行过类似的操作。但曾经多次也给朋友写过 VBS 脚本和 IS 脚本来达到同样的目的。今天又一次,有位朋友十万火急的找到我的 MSN Messenger,呵呵
好吧,那就把手边的代码整理了一下,形成下面的 InstallScript 脚本。明后天更新一下,把整理好的有关虚拟目录那一部分也加入进来。还有,就是数据库的基本操作。
这里不妨一次性说明一下:从 Windows2000 Server、Windows 2003 Server 的 IIS 虚拟目录的管理工具里可以找到一些微软提供的 VBS 脚本,用于管理 IIS 等,功能非常强大,代码也很健壮。也可以把它打包到你的安装程序里,然后用 LanuchAndWait 的方式来执行,同样能满足要求。
而对于 SQL Server 的脚本,要不可以用 IS 调用打包好的 exe、VBS,通过它们借助 ODBC(MDAC带了 OLEDB 驱动,Windows2000以上版本中默认就有MDAC2.5,而SQLServer SP3a 中带 MDAC2.7a),通过 ADO 数据库访问模型来操作 SQLServer 达到你的目的;或者,直接使用 OSQL.exe 这个 SQLServer 提供的命令行工具来执行脚本文件。
而上面说的这一切,其实都与 InstallShield 无关。ADSI 和 WMI 是 Windows 平台的东西,而 OSQL.exe 是 SQLServer 提供的东西。有了MSDN,有了这些知识,无非是用 InstallScript 来实现罢了。不必大惊小怪,我也不是什么高手,只不过比较善于把知识点关联起来而已。其实不用依靠别人,甚至不用去互联网搜索,你自己也很容易解决的。
有了下面的 IIS Config 脚本,结合 xzSQLDeploy Tools,用在你的 InstallScript MSI Project 中,很容易就能制作一个 Web 应用的安装程序。
呵呵,明天要去医院检查身体,很可能就没有空了。所以,如果你的动手能力还有点生疏,那就等我一两天,放一个 Project 的例子上来吧。
使用方法:
Step1
在 InstallScript 中 Behavior and Logic -> InstallScript 节点:
方法 A:InstallScript -> Files 右键单击并选择“New Script File”菜单项(或直接按“Insert”键)创建新的脚本,并命名:xzIISConfig.Rul
方法 B:保存下面的代码为 xzIISConfig.Rul 文件,并在选择“Insert Script Files...”菜单项,在文件浏览器中选中刚才保存的文件。
Step2
在需要调用的脚本文件,例如默认的 Setup.Rul 文件开头部分添加对刚才加入的文件的引用,如:
#include "xzIISConfig.rul"
///////////////////////////////////////////////////////////////////////
// InstallScript 设置 IIS 脚本
// 主要功能:通过 ADSI 查找、创建、更改、删除站点,查找、创建、更改、删除虚拟目录
// Description: XiaoZhu.com InstallScript File for IIS Configuration
// FileName: xzIISConfig.Rul
// Author: piggybank
// Contact: play@xiaozhu.com
//
// Version: 1.01.15
// Created: 2002.03.14. VBS 的初始版本
// Modified: 2004.10.19. 1.01.13
// Modified: 2004.10.21 1.01.14 调整了.
// Modified: 2004.10.22. 1.01.15 增加了两个函数用于设置站点和获取站点设置
// 授权说明: 你可以不受任何限制地使用本脚本。
// 你可以对它进行转载、修改、再发布,但必须保留注释说明完整性和来源。
//
// 欢迎访问 http://www.XiaoZhu.com 获取最新版本。
///////////////////////////////////////////////////////////////////////
//**************************
//** 常量定义
//**************************
#define xzIISConfig_WebSiteCount_MaxValue 30
#define xzIISConfig_LocalComputerName "LocalHost"
#define xzIISConfig_DefaultPort 80
/*
The ServerSize property specifies the general size of the server,
in terms of the number of client requests processed per day. A value
of 0 (zero) indicates a small Web site that expects to receive fewer
than 10,000 requests per day; a value of 1 indicates a medium site
handling between 10,000 and 100,000 requests per day; and a value of
2 designates a large site, processing more than 100,000 requests a day.
The value of this property is used in calculating the value for the
ServerListenBacklog property.
*/
#define xzIISConfig_ServerSize 1
#define xzIISConfig_DefaultDoc "index.asp,index.htm"
#define xzIISConfig_AppFriendlyName "默认站点"
#define xzIISConfig_AccessRead TRUE
#define xzIISConfig_AccessScript TRUE
#define xzIISConfig_AccessWrite FALSE
#define xzIISConfig_AspEnableParentPaths TRUE
#define xzIISConfig_EnableDefaultDoc TRUE
#define xzIISConfig_EnableDirBrowsing FALSE
#define xzIISConfig_AspScriptTimeout 90
#define xzIISConfig_AspSessionTimeout 20
/*
InProcFlag
Binary value that specifies whether the application being created
is to run in-process (0), out-of-process (1), or in a pooled
process (2). If the application already exists and is running,
changing the value of this flag will cause the application
definition to be deleted and a new application created to run in
the specified process space.
*/
#define xzIISConfig_WebSite_INPROC 0
#define xzIISConfig_WebSite_OUTPROC 1
#define xzIISConfig_WebSite_POOLED 2
#define xzIISConfig_WebSite_InProcFlag xzIISConfig_WebSite_POOLED
//**************************
//** 需要用到的 IIS 常量定义
//**************************
////ServerState
#define MD_SERVER_STATE_STARTING = 1;
#define MD_SERVER_STATE_STARTED = 2;
#define MD_SERVER_STATE_STOPPING = 3;
#define MD_SERVER_STATE_STOPPED = 4;
#define MD_SERVER_STATE_PAUSING = 5;
#define MD_SERVER_STATE_PAUSED = 6;
#define MD_SERVER_STATE_CONTINUING = 7;
prototype xzFindWebSite(STRING, STRING, NUMBER);
prototype xzCreateWebSite(STRING, STRING, STRING, NUMBER, STRING, BOOL);
prototype xzDeleteWebSite(NUMBER);
prototype xzChangeWebSite(NUMBER, STRING, STRING, STRING, NUMBER, STRING, BOOL);
prototype xzGetWebSiteState(NUMBER);
prototype xzSetWebSiteState(NUMBER, NUMBER);
//*********************************************************
//** xzCreateWebSite 更改指定序号的站点的属性
//** @param szSitePath 要修改的站点的根目录路径
//** @param szSiteComment 要修改的站点的描述及显示名称
//** @param szIPBind 要修改的站点的 IP 地址
//** @param nzPort 要修改的站点的端口
//** @param szHost 要修改的站点的主机头
//** @param bStart 修改完毕后是否启动该站点
//** @return > 0 找到了指定的站点;
//** -1 没能找到指定站点;
//** -2 获取指定站点根目录失败;
//** -3 获取 W3SVC 失败;
//** -4 尝试访问本机 W3SVC 失败
//*********************************************************
function xzCreateWebSite(szSitePath, szSiteComment, szIPBind, nzPort, szHost, bStart)
OBJECT objW3SVC, objNewSite, objRootDir;
NUMBER nvSiteIndex;
STRING szPort, szInfo;
VARIANT oServerBindings;
begin
szInfo = "正在创建 " + IFX_PRODUCT_NAME + " 站点,请稍等 ...";
SdShowMsg(szInfo, TRUE);
try
set objW3SVC = CoGetObject("IIS://" + xzIISConfig_LocalComputerName + "/W3SVC", "");
if (IsObject(objW3SVC)) then
nvSiteIndex = 1;
try
while(IsObject(objW3SVC.GetObject("IIsWebServer",nvSiteIndex)))
//while(IsObject(objW3SVC.GetObject("IIsWebDirectory",nvSiteIndex)))
nvSiteIndex = nvSiteIndex + 1;
endwhile;
catch
endcatch;
set objNewSite = objW3SVC.Create("IIsWebServer", nvSiteIndex);
if (IsObject(objNewSite)) then
NumToStr(szPort,nzPort);
oServerBindings = szIPBind + ":" + szPort + ":" + szHost;
objNewSite.DefaultDoc = xzIISConfig_DefaultDoc;
objNewSite.EnableDefaultDoc = xzIISConfig_EnableDefaultDoc;
objNewSite.ServerBindings = oServerBindings;
objNewSite.ServerComment = szSiteComment;
objNewSite.ServerSize = xzIISConfig_ServerSize;
objNewSite.SetInfo();
set objRootDir = objNewSite.Create("IIsWebVirtualDir", "ROOT");
if (IsObject(objRootDir)) then
objRootDir.Path = szSitePath;
objRootDir.AccessRead = xzIISConfig_AccessRead;
objRootDir.AccessScript = xzIISConfig_AccessScript;
objRootDir.AccessWrite = xzIISConfig_AccessWrite;
objRootDir.EnableDirBrowsing = xzIISConfig_EnableDirBrowsing;
objRootDir.EnableDefaultDoc = xzIISConfig_EnableDefaultDoc;
objRootDir.AppFriendlyName = szSiteComment;
objRootDir.AppCreate2(xzIISConfig_WebSite_InProcFlag);
objRootDir.SetInfo();
set objRootDir = NOTHING;
if ( bStart ) then
try
objNewSite.Start();
catch
szInfo = "启动新创建的站点失败。";
MessageBox(szInfo, INFORMATION);
endcatch;
endif;
else
nvSiteIndex = -2;
szInfo = IFX_PRODUCT_NAME + " 安装程序无法为新建的 IIS 站点创建根目录,请检查设置。";
endif;
set objNewSite = NOTHING;
else
nvSiteIndex = -1;
szInfo = IFX_PRODUCT_NAME + " 安装程序无法创建新的 IIS 站点,请检查设置。";
endif;
set objW3SVC = NOTHING;
else
nvSiteIndex = -3;
szInfo = IFX_PRODUCT_NAME + " 安装程序无法获得 IIS 设置。";
endif;
catch
szInfo = IFX_PRODUCT_NAME + " 安装程序创建 IIS 站点时出现错误。";
nvSiteIndex = -4;
endcatch;
if (nvSiteIndex < 0) then
SdShowMsg(szInfo,TRUE);
//MessageBox(szInfo, SEVERE);
endif;
SdShowMsg("", FALSE);
return nvSiteIndex;
end;
//*********************************************************
//** xzDeleteWebSite 删除指定序号的站点
//** @param nvSiteIndex 要删除的站点在 IIS 服务中的序号
//** @return 1 删除了指定的站点;
//** -1 没有删除指定的站点;
//*********************************************************
function xzDeleteWebSite(nvSiteIndex)
OBJECT objW3SVC, objDeleteSite;
NUMBER nvReturn;
STRING szPort, szInfo, szMsg;
begin
nvReturn = -1;
szMsg = IFX_PRODUCT_NAME + " 安装程序正在删除站点,请稍等...";
SdShowMsg(szMsg,TRUE);
try
set objW3SVC = CoGetObject("IIS://" + xzIISConfig_LocalComputerName + "/W3SVC", "");
if (IsObject(objW3SVC)) then
set objDeleteSite = objW3SVC.GetObject("IIsWebServer",nvSiteIndex);
if (IsObject(objDeleteSite)) then
try
// Delete Root of Web Site
objDeleteSite.Delete("IIsWebVirtualDir","ROOT");
catch
endcatch;
try
// Stop Web Site
objDeleteSite.Stop();
catch
endcatch;
set objDeleteSite = NOTHING;
nvReturn = 1;
endif;
objW3SVC.Delete("IIsWebServer",nvSiteIndex);
endif;
catch
nvReturn = -1;
endcatch;
if ( nvReturn > 0 ) then
szMsg = IFX_PRODUCT_NAME + " 安装程序已经删除站点。";
else
szMsg = IFX_PRODUCT_NAME + " 安装程序删除站点失败。";
endif;
SdShowMsg(szMsg, TRUE);
SdShowMsg(szMsg, FALSE);
return nvReturn;
end;
//*********************************************************
//** xzChangeWebSite 更改指定序号的站点的属性
//** @param nvSiteIndex 要修改的站点的序号
//** @param szSitePath 要修改的站点的根目录路径
//** @param szSiteComment 要修改的站点的描述及显示名称
//** @param szIPBind 要修改的站点的 IP 地址
//** @param nzPort 要修改的站点的端口
//** @param szHost 要修改的站点的主机头
//** @param bStart 修改完毕后是否启动该站点
//** @return > 0 找到了指定的站点;
//** -1 没能找到指定站点;
//** -2 获取指定站点根目录失败;
//** -3 获取 W3SVC 失败;
//** -4 尝试访问本机 W3SVC 失败
//*********************************************************
function xzChangeWebSite(nvSiteIndex, szSitePath, szSiteComment, szIPBind, nzPort, szHost, bStart)
OBJECT objW3SVC, objWebSite, objWebSiteRoot;
STRING szPort, szInfo;
variant vServerBindings;
begin
szInfo = IFX_PRODUCT_NAME + " 安装程序正在更改 IIS 站点设置,请稍等 ...";
SdShowMsg(szInfo, TRUE);
try
set objW3SVC = CoGetObject("IIS://" + xzIISConfig_LocalComputerName + "/W3SVC", "");
if (IsObject(objW3SVC)) then
try
if (IsObject(objW3SVC.GetObject("IIsWebServer",nvSiteIndex))) then
set objWebSite = objW3SVC.GetObject("IIsWebServer",nvSiteIndex);
NumToStr(szPort,nzPort);
vServerBindings = szIPBind + ":" + szPort + ":" + szHost;
objWebSite.DefaultDoc = xzIISConfig_DefaultDoc;
objWebSite.EnableDefaultDoc = xzIISConfig_EnableDefaultDoc;
objWebSite.ServerBindings = vServerBindings;
objWebSite.ServerComment = szSiteComment;
objWebSite.ServerSize = xzIISConfig_ServerSize;
objWebSite.SetInfo();
set objWebSiteRoot = objWebSite.GetObject("IIsWebVirtualDir", "ROOT");
if (IsObject(objWebSiteRoot)) then
objWebSiteRoot.Path = szSitePath;
objWebSiteRoot.AccessRead = xzIISConfig_AccessRead;
objWebSiteRoot.AccessScript = xzIISConfig_AccessScript;
objWebSiteRoot.AccessWrite = xzIISConfig_AccessWrite;
objWebSiteRoot.EnableDirBrowsing = xzIISConfig_EnableDirBrowsing;
objWebSiteRoot.EnableDefaultDoc = xzIISConfig_EnableDefaultDoc;
objWebSiteRoot.AppFriendlyName = szSiteComment;
objWebSiteRoot.AppCreate2(xzIISConfig_WebSite_InProcFlag);
objWebSiteRoot.SetInfo();
set objWebSiteRoot = NOTHING;
if ( bStart ) then
try
objWebSiteRoot.Start();
catch
endcatch;
endif;
else
nvSiteIndex = -2;
szInfo = IFX_PRODUCT_NAME + " 安装程序无法获取指定 IIS 站点的根目录,请检查设置。";
endif;
set objWebSite = NOTHING;
else
nvSiteIndex = -1;
szInfo = IFX_PRODUCT_NAME + " 安装程序无法获取指定 IIS 站点,请检查设置。";
endif;
catch
endcatch;
set objW3SVC = NOTHING;
else
nvSiteIndex = -3;
szInfo = IFX_PRODUCT_NAME + " 安装程序无法获得 IIS 设置。";
endif;
catch
szInfo = IFX_PRODUCT_NAME + " 安装程序更改 IIS 站点设置时出现错误。";
nvSiteIndex = -4;
endcatch;
if (nvSiteIndex < 0) then
SdShowMsg(szInfo,TRUE);
//MessageBox(szInfo, SEVERE);
endif;
SdShowMsg("", FALSE);
return nvSiteIndex;
end;
//*********************************************************
//** xzFindWebSite 指定三个条件至少一个,查询符合条件的站点,并返回序号
//** @param szIPBind 要查询站点的 IP 地址,可以不指定
//** @param szHost 要查询站点的主机头,可以不指定
//** @param nzPort 要查询站点的端口,可以不指定,但至少必须指定一项
//** @return > 0 找到了指定的站点;
//** -1 没能找到站点;
//** -2 获取 W3SVC 失败;
//** -3 尝试访问本机 W3SVC 失败
//*********************************************************
function xzFindWebSite(szIPBind, szHost, nzPort)
OBJECT objW3SVC, objWebSite;
NUMBER nvSiteIndex;
STRING szPort, szInfo;
STRING szServerBindings;
STRING oServerBindings();
begin
szInfo = IFX_PRODUCT_NAME + " 安装程序正在查询 IIS 站点,请稍等 ...";
SdShowMsg(szInfo, TRUE);
try
NumToStr(szPort,nzPort);
szServerBindings = szIPBind + ":" + szPort + ":" + szHost;
set objW3SVC = CoGetObject("IIS://" + xzIISConfig_LocalComputerName + "/W3SVC", "");
if (IsObject(objW3SVC)) then
for nvSiteIndex = 1 to xzIISConfig_WebSiteCount_MaxValue
try
set objWebSite = objW3SVC.GetObject("IIsWebServer", nvSiteIndex);
if (IsObject(objWebSite)) then
oServerBindings = objWebSite.ServerBindings;
if ( StrCompare(oServerBindings(0), szServerBindings) = 0 ) then
set objWebSite = NOTHING;
szInfo = IFX_PRODUCT_NAME + " 安装程序已经找到符合条件( " + szServerBindings + ")的 IIS 站点。";
SdShowMsg("", FALSE);
return nvSiteIndex;
endif;
endif;
nvSiteIndex = nvSiteIndex + 1;
catch
endcatch;
endfor;
set objW3SVC = NOTHING;
szInfo = IFX_PRODUCT_NAME + " 安装程序没有找到符合条件( " + szServerBindings + ")的 IIS 站点。";
nvSiteIndex = -1;
else
nvSiteIndex = -2;
szInfo = IFX_PRODUCT_NAME + " 安装程序无法获得 IIS 设置。";
endif;
catch
szInfo = IFX_PRODUCT_NAME + " 安装程序查询 IIS 站点时出现错误。";
nvSiteIndex = -3;
endcatch;
if (nvSiteIndex < 0) then
SdShowMsg(szInfo, TRUE);
//MessageBox(szInfo, SEVERE);
endif;
SdShowMsg("", FALSE);
return nvSiteIndex;
end;
//*********************************************************
//** xzGetWebSiteState 获取指定站点的状态
//** @param nvSiteIndex 制定站点的序号
//** @return > 0 指定的站点状态值;
//** -1 没有找到指定的站点;
//** -2 没有找到指定的站点(异常);
//** -3 获取 W3SVC 失败;
//** -4 获取 W3SVC 失败(异常);
//** -5 获取指定站点状态失败(异常);
//*********************************************************
function xzGetWebSiteState(nvSiteIndex)
OBJECT objW3SVC, objWebSite;
NUMBER nvResult;
STRING szInfo;
begin
szInfo = IFX_PRODUCT_NAME + " 安装程序正在尝试获取指定 IIS 站点状态,请稍等 ...";
SdShowMsg(szInfo, TRUE);
try
set objW3SVC = CoGetObject("IIS://" + xzIISConfig_LocalComputerName + "/W3SVC", "");
if (IsObject(objW3SVC)) then
try
set objWebSite = objW3SVC.GetObject("IIsWebServer", nvSiteIndex);
if (IsObject(objWebSite)) then
try
nvResult = objWebSite.ServerState;
szInfo = IFX_PRODUCT_NAME + " 安装程序获取 IIS 站点状态成功。";
SdShowMsg(szInfo, TRUE);
catch
//获取指定站点状态失败(异常)
nvResult = -5;
szInfo = IFX_PRODUCT_NAME + " 安装程序获取 IIS 站点状态失败:异常";
SdShowMsg(szInfo, TRUE);
endcatch;
else
//没有找到指定的站点
nvResult = -1;
szInfo = IFX_PRODUCT_NAME + " 安装程序获取 IIS 站点状态失败:没有找到指定的站点";
SdShowMsg(szInfo, TRUE);
endif;
catch
//没有找到指定的站点(异常)
nvResult = -2;
szInfo = IFX_PRODUCT_NAME + " 安装程序获取 IIS 站点状态失败:没有找到指定的站点(异常)";
SdShowMsg(szInfo, TRUE);
endcatch;
else
//获取 W3SVC 失败
nvResult = -3;
szInfo = IFX_PRODUCT_NAME + " 安装程序获取 IIS 站点状态失败:获取 W3SVC 失败";
SdShowMsg(szInfo, TRUE);
endif;
catch
//获取 W3SVC 失败(异常)
nvResult = -4;
szInfo = IFX_PRODUCT_NAME + " 安装程序获取 IIS 站点状态失败:获取 W3SVC 失败(异