Winfrom Installer Publish Web Application To IIS

  IIS部署: 对于非技术人员来说是头疼的一件事,当到现场实施碰到客户情况也各不相同, 急需一个类似系统备份的"一键工具"快速实现应用程序部署和数据库进行关联. 网上关于这方面资源也比较混乱,其中对于IIS的编程影响因素很多,操作技巧上加以细化小结.

A:获取IIS版本

IIS版本不同对应编程上基本上完全不同方式来进行的.先了解一下Iss版本在操作系统个具体要求.

ISS6.0时代主要以using System.DirectoryServices空间下的DirectoryEntry 对象作为编程访问一个主要载体.但随着ISS7.0发布.NET的Web程序由ISS6.0开始逐渐过渡到 7.0版本.而且在编程控制ISS上新添加的Microsoft.Web.Administration名称空间, 提出多个用于管理 操作 和访问ISS的对象, 使操作ISS的编程更加简洁 高效.

B:我们要做什么

实际用户操作环境中主要以Windows XP/2000/2003操作系统为主, 这就导致了ISS版本主要在5.0/5.1/6.0之间,所以本次演示的代码编程实例都是ISS7.0版本以下(不包含Iss7.0).

为了达到演示目的,我们现在需求是这样的: 把硬盘上Silverlight应用程序成功部署到本地机器ISS上. 并支持通过局域网访问. 需求很简单吧就是一句话, 其实当进入实际编程时因为客户的局域网环境是不可预知的, 这也就导致影响部署Silverlight程序到ISS上诸多未知因素. 所以要在编程中使Silverlight应用程序部署成功,我们必须利用编程除了控制ISS外还要控制其他主要影响ISS因素.

C:进入编程

既然提出需求我们大概确定一下解决思路 (下面我们以Silverlight Web 项目作为例子):

在默认站点下创建一个虚拟目录承载Silverlight 应用程序, 新建的虚拟目录运行在独立应用程序池中, 支持本地局域网匿名访问其实就是对访问权限控制, 为了直接使更改的应用生效需要多次重新启动ISS的服务, 这就需要对ISS服务进行编程控制.

<1>ISS版本的获取

在进入客户环境前我们先检测下是否存在安装了ISS,以及ISS版本获取提示,目前获取ISS版本的方式主要有两种,第一种方法是通过遍历DirectoryEntry实体目录 第二种方式是通过获取注册表的ISS修改版本值[经测试这种方式获取版本不稳定].

 1 public static void GetIssVersionByDri(string domainname)
 2 {
 3        try
 4        {
 5            if (string.IsNullOrEmpty(domainname))
 6            {
 7              //如果为空 则默认为本地机器
 8                domainname = "LOCALHOST";
 9            }
10            DirectoryEntry getEntity=new DirectoryEntry("IIS://" + domainname + "/W3SVC/INFO");
11            string Version=getEntity.Properties["MajorIISVersionNumber"].Value.ToString();
12            MessageBox.Show(Version);
13        }
14        catch (Exception se)
15        {
16            //说明一点:IIS5.0中没有(int)entry.Properties["MajorIISVersionNumber"].Value;属性,将抛出异常 证明版本为 5.0
17            MessageBox.Show("获取ISS的版本是发生异常信息:"+se.Message);
18        }
19  }  

通过系统注册表获取ISS版本的值:[测试发现不稳定]

public static string GetIssVersion()
{
  //RegistryKey表示 Windows 注册表中的项级节点.此类是注册表封装
  string issversion = string.Empty;
  RegistryKey getkey = Registry.LocalMachine.OpenSubKey("software\\microsoft\\inetstp");
  if (getkey != null)
   {
     issversion= Convert.ToInt32(getkey.GetValue("majorversion", -1)).ToString();
     MessageBox.Show(issversion.ToString());
   }
  return issversion;
}                                                                                       
<2>创建虚拟目录

每个Internet服务可以从多个目录中发布,通过以通用命名约定 (UNC) 名、用户名及用于访问权限的密码指定目录,可将每个目录定位在本地驱动器或网络上,虚拟目录可以一个宿主程序,这可发布的操作目录即为虚拟目录.再来看看在ISS6.0中创建的虚拟目录的步骤和控制的属性.

新建虚拟目录:

/// <summary>
/// 添加一个虚拟目录
/// </summary>
public void CreateVirtualDir(string virtualdirname, string logicDir)
{
    //如果存在重复 就直接删除虚拟目录
    if (IsExitesVirtualDir(virtualdirname))
        DeleteVirtualDir(virtualdirname);                                                                                                             

    DirectoryEntry rootEntry;
    rootEntry = new DirectoryEntry("IIS://localhost/W3SVC/1/root");                                                                                   

    DirectoryEntry newVirDir;
    newVirDir = rootEntry.Children.Add(virtualdirname, "IIsWebVirtualDir");
    newVirDir.Invoke("AppCreate", true);                                                                                                              

    newVirDir.CommitChanges();
    rootEntry.CommitChanges();                                                                                                                        

    newVirDir.Properties["AnonymousPasswordSync"][0] = true;
    newVirDir.Properties["Path"][0] = logicDir;//+ @"virtualdirentry\virtualname\";                                                                   

    //设置的端口绑定数据
    //_newVirDir.Properties["ServerBindings"].Value =AppEntitys.WebAppInfor.HostIp+AppEntitys.WebAppInfor.HostProt+AppEntitys.WebAppInfor.AppDesc;    

    //设置起始默认页:
    newVirDir.Properties["EnableDefaultDoc"][0] = true;
    newVirDir.Properties["DefaultDoc"][0] = "Default.aspx";                                                                                           

    //_newVirDir
    newVirDir.CommitChanges();
}   
这个方法在创建时主要有两个参数 一个是新建虚拟目录名称 另外一个要部署Silverlight应用程序物理路径.在获取根节目录时需要制定ISS的路径. ISS的路径格式如:IIS://ComputerName/Service/Website/Directory

 

找到根目录后添加新建虚拟目录. 制定参数为Schema-指每个结点的类型:IIsVirtualDir:

——虚拟目录 IIsWebDir :

——普通目录,

添加完成后调用ADSI中的"AppCreate"方法将目录真正创建.创建完成后通过根目录和新目录提交保存.

<3>目录属性设置

在DirectoryEntity虚拟目录属性可以说是非常多的,当时在编程时我为了区分属性间区别做了一个方法去遍历整个属性集合PropertyCollection. 然后把常用重要的属性跳出来进入赋值设置. 因为关于虚拟目录的属性在MSDN上的API中并没有直接提到, 特别是对虚拟目录访问权限控制非常重要属性等 .先说明局部的常用的属性:

de.Properties["AnonymousUserName"][0] = AnonymousUserName;//匿名用户
            de.Properties["AncnymousUserPass"][0] = AnunymousUserPzss;//匿名密码
            de.Properties["AccessRead"][0] = bugle;//读取权限
            de.Properties["AccessExecute"][0] = Boolean;//执行
            de.Properties["AccessWrite"][0] = Boolean;//写入
            de.Properties["AuthBasic"][0] = Boolean
            de.Properties["AuthNTLM"][0] = Boolean
            de.Properties["ContentIndexed"][0] = Boolean;
            de.Properties["EnableDefau1tDoc"][0] = Boolean;//能否编辑默认文档
            de.Properties["Enab1eDirBrowsing"][0] = Boolean;//可浏览目录
            de.Properties["AccessSSL"][0] = Boolean;//SSL 设置
            de.Properties["AccessScript"][0] = Boolean;//执行脚本
            de.Properties["Defau1tDoc"][0] = Defau1tDoc;//设置默认访问页面
            de.Properties["Path"][0] = path;//硬盘上的物理路劲

例如修改程序起始页:

//设置起始默认页:
newVirDir.Properties["EnableDefaultDoc"][0] = true;
newVirDir.Properties["DefaultDoc"][0] = "Default.aspx,Index.Html,index.asp";
newVirDir.CommitChanges(); 

DefaultDoc选项可以支持多个但注意选择性排序.一般修改目录属性后都选通过CommitChanges()方法提交保存, 但有时你会发现我明明修改属性 却没有保存生效. 这是因为ISS中部分属性设置需要重新启动ISS服务才能生效.这个时候我们需要对ISS服务进行控制.

<4>ISS服务控制

关于ISS服务控制微软提供一个命名空间System.ServiceProcess 提供能够快速操作本地系统服务API.对于ISS服务控制我们最常用的是重新启动使当前设置生效. 在设置服务时我先找到服务名称,打开计算机管理 在服务和应用程序目录下打开服务.

我们能看到ISS服务命名是:ISSAdmin 我们通过编码来控制:启动ISS.

 //获取IIS Serivcer控制声明 . 参数为Server在系统标识该服务的简称,.
ServiceController getservicecon = new ServiceController("IISADMIN");
getservicecon.Start();
//重启/暂停/停止ISS服务:                                                                                       

 if (getservicecon.Status == ServiceControllerStatus.Running)
     {
          //停止服务
          getservicecon.Stop();
          //暂停服务
          getservicecon.Pause();
          //重启服务
          //Process提供对本地和远程进程的访问并使您能够启动和停止本地系统进程
          //利用Start方法调用:启动(或重用)此 Process 组件的 StartInfo 属性指定的进程资源,并将其与该组件关联
          //如果启动了进程资源,则为 true;如果没有启动新的进程资源(例如,如果重用了现有进程),则为 false
          //通过指定文档或应用程序文件的名称来启动进程资源,并将资源与新的 Process 组件关联
          Process.Start("iisreset");
     }  

如上就是简单利用编程有效控制ISS服务运行状态.

<5>应用程序池创建与控制

ISS应用程序池是将一个或多个应用程序链接到一个或多个工作进程集合的配置。因为应用程序池中的应用程序与其他应用程序被工作进程边界分隔,所以某个应用程序池中的应用程序不会受到其他应用程序池中应用程序所产生的问题的影响, 当我们新建一个应用程序时 有时客户端环境我们无法清除预知, 为了尽量减少影响ISS设置外在因素, 我们把新建虚拟目录放到一个独立应用程序池中.

当创建一个虚拟目录后,也同时创建一个程序池 把虚拟目录放到其中:

/// <summary>
/// 建立程序池后关联相应应用程序及虚拟目录
/// </summary>
public static void SetAppToPool(string appname)
{
    //获取目录
    DirectoryEntry getdir = new DirectoryEntry("IIS://localhost/W3SVC");
    foreach (DirectoryEntry getentity in getdir.Children)
    {
        if (getentity.SchemaClassName.Equals("IIsWebServer"))
        {
             //设置应用程序程序池 先获得应用程序 在设定应用程序程序池
             //第一次测试根目录
            foreach (DirectoryEntry getchild in getentity.Children)
            {
                if (getchild.SchemaClassName.Equals("IIsWebVirtualDir"))
                {
                    //找到指定的虚拟目录.
                    foreach (DirectoryEntry getsite in getchild.Children)
                    {
                        if (getsite.Name.Equals(appname))
                        {
                            //【测试成功通过】
                            getsite.Properties["AppPoolId"].Value = appname;
                            getsite.CommitChanges();
                        }
                    }
                }
            }
        }
    }
}    

思路如下: 首先获得ISS的根目录即ISS://localhost/W3SVC. 获取成功后通过SchemaClassName获取节点类型.ISSWebServer普通目录 ISSWebVirturalDir虚拟目录. 通过虚拟目录的Name唯一名称获取指定虚拟目录, 在通过属性参数AppPoolId设置附属的应用程序池的名称. 然后提交保存.

其实通过应用我们可以清晰看到ISS中各个目录之间的关联关系.上面是修改一个已经存储在应用程序池,如何创建:

public static bool CreateAppPool(string metabasePath, string appPoolName, string Username, string Password)
{
    bool issucess = false;
    try
    {
        if (metabasePath.EndsWith("/W3SVC/AppPools"))
        {
            if (MyIISHelper.AppPoolExist(appPoolName))
            {
                //已经存在 先删除这个AppPool 在创建
                //MessageBox.Show("当前以站点名称命名的程序池已经存在!");
                DeleteRepPool(appPoolName);
            }                                                                                                  

                //创建一个新程序池
                DirectoryEntry newpool;
                DirectoryEntry apppools = new DirectoryEntry(metabasePath);
                newpool = apppools.Children.Add(appPoolName, "IIsApplicationPool");                            

                //设置属性 访问用户名和密码 一般采取默认方式
                newpool.Properties["WAMUserName"][0] = Username;
                newpool.Properties["WAMUserPass"][0] = Password;
                newpool.Properties["AppPoolIdentityType"][0] = "3";
                newpool.CommitChanges();
        }
        return issucess;
    }
    catch// (Exception ex)
    {
        return false;
    }
}  

基本上和创建一个DirectoryEntity雷同但注意指定的Schome类型是IIsApplicationPool用来标识创建的是一个应用程序池.当然创建可以删除 删除方式如下:

DirectoryEntry appPool = new DirectoryEntry("IIS://localhost/W3SVC/AppPools");
 foreach (DirectoryEntry getdir in appPool.Children)
   {
       if (getdir.Name.Equals(appname))
          {
            getdir.DeleteTree();//删除
          }
   }  

关于应用程序池如果不做任何设置则在ISS中会被DefaultPool中添加, 但有时默认程序池设置环境不一定能够满足当前程序需求,例如最常见的关于.NET版本的控制. 其中对3.0和3.5版本应用设置需要重新注册3.5 .NET FrameWork.部分组件这就涉及到一个.NET版本问题.

<6>.NET版本问题

在进行ISS控制中当然也是遇到各种各样的问题, 一方面因为测试XP 2003系统环境不同, 需要控制因素过多,当然其中值得一提就是关于整个应用程序池的.NET版本问题.我们先来看看多版本下ISS中设置:

如果我们的应用程序使用3.0或3.5版本 则在应用程序池的没有对应的.NET版本.这时应用程序运行会提示一个Http错误404.17 notFound:

其实ISS在处理应用程序池于.NET版本进行映射时,Net3.0\3.5没带处理程序aspnet_isapi.dll,所以IIS中指定网站适用框架时,这也是为什么我们在ISS映射时看不到.Net3.0\3.5版本. 最直接的方法重新注册.NET 3.5 由.NET 2.0版本托管: 这时我们需要执行一个Cmd命令:

从新把应用程序池.net版本切换成.net 2.0.同样实现.net 3.0/3.5托管.

<7>使用环境以及测试条件

如上应用程序和代码均在Windows 7./XP2/Windows Server 2003上通过. 对应的ISS版本范围从ISS5.0/5.1到Iss 6.0/7.0. 包含ISS7.0. 篇幅有限,实际中关于ISS的操作还有很多细节问题不能面面俱到,我只是挑了其中我认为基础或几位重要几个问题着重来写, 实际中关于ISS还有其他诸多因素, 所以对于这方面控制编程 只能折中的有目的性选择自己想做的效果. 切不可贪大求全. 因为这本身控制过程就是复杂的过程. 客户环境也不能诸如统一. 碰到特殊问题可以上百度,google 查找。

Tony.Chen

2012-05-17

时间: 2024-10-13 19:09:18

Winfrom Installer Publish Web Application To IIS的相关文章

Visual Studio Create Setup project to deploy web application in IIS

Introduction: In this article I will explain how to create setup file in visual studio 2008/2010 to deploy web application file directly in IIS or in client machine or how to place web application folder in c:\\inetpub\wwwroot folder by running setup

理解SharePoint Web Application和IIS Web Sites 和 HTTP请求

当你创建一个web application的时候,你实际上在IIS里面创建了一个站点.一个IIS站点有bindings,包含单独的IP地址,一个Host Header 和port.IIS通过Bindings来决定HTTP 请求是请求的哪个站点. 当一个用户请求一个网页的时候,比如http://intranet.contoso.com/SitePages/Home.aspx, 客户端发起了一个HTTP请求.客户端通过查询DNS来获取到Host(比如intranet.contoso.com)的IP地

Web Application Project is configured to use IIS. Unable to access the IIS metabase.(配置为使用IIS Web应用程序xxxx项目。无法访问IIS元数据库。)

这几天重装系统,装了win10,居然用vs2013打开项目出现下面这个提示错误,搞了很久才知道原因: Even though I am an administrator on the machine, Visual Studio is not running as administrator so it does not have permission to the IIS metabase files.  One solution is to run Visual Studio as admi

笔记:Advanced Installer 打包Web应用

原文:笔记:Advanced Installer 打包Web应用 公司要做一款增值税小产品,区别于ACME,本产品核心只有销项部分,面对的客户群是小企业,单税盒单开票机..... 我要做的主要有以下几点: 1.数据库改为SqlCE 2.统一安装配置VICA客户端,服务端(尽管VICA组同事不知道我要改这块^_^) 3.一键安装(支持32位,64位系统,暂时考虑NET4.5,Window7以上系统) 打包工具选择是Advanced Installer 12.7.2 制作安装包过程中遇到的问题: 1

ASP.NET Web Application中使用链接文件

最近重构一个内部的平台系统,作为一个平台,其下有几个子系统,每个子系统有自己的网站系统.而每个网站使用的是统一的风格,统一的验证机制,反馈系统,等等.所以,为了避免几个子系统中重复出现相同的资源或文件,我打算将以前的ASP.NET Web Site全部转换为ASP.NET Web Application,然后通过链接外部公共文件的方式解决这个问题.同时: 1. Web Application是Web Site的升级产品.2. Web Application允许添加链接方式,把其他目录的文件作为链

通过TeamCity实现ASP.NET Core Web Application的自动编译及发布

下载 TeamCity,当前版本:2017.1 TeamCity插件:.NET Core Support .NET Core SDK,当前版本:1.0.1 安装 安装TeamCity.需要注意的地方: 安装路径 端口,这里是9080 安装Server和Agent Windows 服务的账号(这里建议使用系统账号而不是用户账号) 安装完成后会自动打开TeamCity的页面,开始初始化配置.数据目录,数据库和管理用用户. 安装TeamCity插件:.NET Core Support. 安装插件有两种

The web application you are attempting to access on this web server is currently unavailable.......

今天去服务器安装了个.net 4.0 framework(原本有1.0和2.0的),配置好站点后,选择版本为4.0,访问出错,错误代码如下 Server Application Unavailable The web application you are attempting to access on this web server is currently unavailable.  Please hit the "Refresh" button in your web brows

利用Advanced Installer将asp.netMVC连同IIS服务和mysql数据库一块打包成exe安装包

原文:利用Advanced Installer将asp.netMVC连同IIS服务和mysql数据库一块打包成exe安装包 因为业务需要,项目中需要把asp.netmvc项目打包成exe安装程序给客户,让客户直接可以点下一步下一步安装部署web程序,并且同时要将IIS服务和mysql一同安装到服务器上,因为客户的电脑可能是64位也可能是32位,所以在打包的时候就需要打包成两份安装包.研究了几天终于有所收获,下边就是打包的步骤. 打包步骤: 一.前期准备 1.将asp.netmvc发布到本地目录中

ModSecurity web application firewall (WAF) Research

catalog 0. 引言 1. OWASP ModSecurity Core Rule Set (CRS) Project 2. Installation mod_security for Apache 3. Installation mod_security for nginx 4. Installation mod_security for IIS 5. mod_security Configuration Directives 6. Processing Phases 7. Variab