应朋友要求帮着做一个 ASP.NET( 基于 .NET 2.0) 的安装程序,因为之前做过许多 WinForm 项目的安装程序也算有些经验就欣然答应。
首先按照习惯发布 ASP.NET 程序到一个指定目录如图1 (ASP.NET 2.0 网站发布的详细步骤请参看 MSDN 或其它资料,总之与 ASP.NET 1.1 的发安装发布大有不同 ) ,然后手工配置到本地 IIS 服务器进行测试。
( 图1 )
下来新建一个 WEB 项目安装程序,把刚才发布测试好的 WEB 系统的所有文件放到所建的 WEB 项目安装程序的 “Web 应用程序文件夹 " 中,如下图
( 图 2)
然后在此处 (Web 应用程序文件夹 ) 删除不需要的文件,添加附加的必备文件或数据等。
因为我的 WEB 应用程序使用的数据库是 Access 的数据库,并且放在了应用程序的当前目录下的 App_Data 目录下 ( 实际项目中最好不要这要做,防止数据库文件被下载,对于使用的是单文件数据库的系统建议将数据库设置成 ODBC 型的连接形式,数据库文件单独安装在其它非网站的目录中 ) ,所以要设置相应的读写权限。
如何在安装后给指定的目录设置访问权限?我们可以试着想一下简单的可以通过在系统初次启动时用程序代码来设置。这个想法在 WINFORM 系统中基本没什么大问题,只要你的 WINFORM 程序以管理员权限运行基本上 ( 使用管理员权限有时候也不一定会成功的,因为 WINDOWSXP/2003 系统中可以将管理员对一个目录或文件的权限封掉 ) 就会成功。但是在 WEB 系统中它是宿住于 IIS 系统中的, WEB 应用程序的权限是非常低的,由于它本身权限低也就指望不上它再为别的目录设置更高的访问权限了。如果没有进行特别设置的话 WEB 应用程序对服务器的文件夹是没有写入权限的。所以要让我的 WEB 应用程序能后写正常读写数据库文件,我得给数据库文件加上 IIS 用户的读写权。即然 WEB 程序没有权限为目录或文件设置更高的访问权限,那么另外一种解决方案便是让安装程序去给这个目录设置权限。
但是在安装的时候我尚无法从安装程序中得到我的 WEB 应用程序被安装的物理路径,所以暂时制作单独的权限设置程序,如下图:
( 图 3)
我的这个设置权限的程序很简单,只有一个窗体。将来它必须放在 ( 图2 ) 中的 "Web 应用程序文件夹 " 目录下,在我这个实例中是必须放在这个位置的,因为只有放在这里将来它运行起来后得到的目录才是我想到的 ( 用反射调用无效,因为用反射调用时取得的目录是宿主程序的 ) 。其实还可以用别的方法,比如作成 DLL ,让安装程序调用也是可以的。但我想让这个程序在安装好后还能用就做成了单独的 EXE 程序了。做成单独的 EXE 程序还有个好处就是在使用 SQL SERVER 数据库的时候,可以把一些维护功能也放在这个里面,用安装程序给它建一个快捷方式放在开始菜单里这样就更好了。
这里我仅仅让它给目录设置个权限所以我的实现就比较简单,把所有实现代码放到窗体的加载事件中,如下:
private void Form1_Load( object sender, EventArgs e)
{
addLog( "正在设置数据库..." );
// Create a new DirectoryInfo object.
string tmpPath = string .Format( "{0}App_Data" , AppDomain .CurrentDomain.BaseDirectory);
AddDirectorySecurity(tmpPath, @"Everyone" , FileSystemRights .Modify, AccessControlType .Allow);
addLog( string .Format( "设置目录[{0}]的权限" , tmpPath));
addLog( "设置完成..." );
this .button1.Enabled = true ;
}
// Adds an ACL entry on the specified directory for the specified account.
public static void AddDirectorySecurity( string FileName, string Account, FileSystemRights Rights, AccessControlType ControlType)
{
// Create a new DirectoryInfo object.
DirectoryInfo dInfo = new DirectoryInfo (FileName);
// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = dInfo.GetAccessControl();
// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule( new FileSystemAccessRule (Account, Rights, InheritanceFlags .ObjectInherit, PropagationFlags .InheritOnly,ControlType));
// Set the new access settings.
dInfo.SetAccessControl(dSecurity);
}
void addLog( string msg)
{
this .richTextBox1.AppendText(msg + "\r\n" );
}
private void button1_Click( object sender, EventArgs e)
{
this .Close();
}
AddDirectorySecurity方法是我从MSDN里面抄来的,我只是在窗体加载事件里调用了它一下。另外我还改了一下使帐户对目录下的子目录有访问权,这个叫权限继承详细内容可以参看MSDN中关于ACL部分。
明眼人一看就知道我上面设置的权限太大了,呵呵没错,我是把这个目录的权限给了 Everyone用户,其实对于IIS来说只要设置IUSR_你的计算机名 这个用户就可以了。在Windows XP和Windows2003好像这个用户还不是一样的。
好了,我们来测试一下。下面是设置之前App_Data目录的权限表:
这个目录下的文件的权限列表:
开始执行设置权限的程序
下面是我执行之后的权限列表
但是有个问题我尚未搞明白就是我设置的是那个 App_Data 目录,但是这个目录加上了 Everyone 用户却没有为其设置权限,如下图
网上也有用户提出这个疑问不知道哪位清楚,可通过 tianjh83@gmail.com 联系我,希望不吝赐教。
好了,我们就把这个制作好的权限设置程序放到刚才说的那个目录下去,如下图 2 选中的那一项。
下面开如设置其它参数如,安装程序的名称,版权等信息,最后打包。
下面我们看一下安装效果:
看到没有,那个刚才制作好的程序在安装的最后一个画面时自动执行了。
有些人就奇怪了它怎么就知道执行那个程序而不是别的呢,如果我那的是多个 EXE 程序呢?好下面我就来讲如何让它来执行指定的程序。请看下图:
点击之后进入下面画面:
这下明白了吧为什么是在提交之前执的而不是在别的步骤下执行那个程序了吧。还要注意一下看右边属性框框中的那个 InstallerClass 属性了没有,默认是 True ,你一定要将它打成 False ,否则在安装中会报出一个未打到 xxx 类的异常。这个选项是为那个 DLL 形的配置模块用的。我用这里用的是 EXE 程序,这个选项就要这么设置。
看到这个图大家可以发挥一下,是不是可以在程序卸载的时候我把那个目录的权限收回呢?如何收回这还用我再细讲吗??
为了验证效果我手工把安装后那个系统的 App_Data 目录的 Everyone 用户删掉,让大家看一下没有设置权限之前的效果和执业行那个程序之后的效果,在这里大家应该明白为什么我要把它单独做成 EXE 型程序的用意了吧?
未设之前程序写数据时报出异常:
点击修改
下面我执行一下设置权限程序
然后再单击修改弹出如下画面
浙公网安备 33010602011771号