WMI Functions from ASP.NET

 
Introduction

This article demonstrates how to use WMI in ASP.NET to create a website, add a virtual folder, and add host headers. I have tested it using Windows Server 2003 and IIS 6.

It took me three days to get it working, some hours to write the code, and the remaining time finding out why I got a Win32: Access denied error. I could, of course, figure out that neither the NETWORK SERVICE or the IUSR_<servername> account has too many rights. I didn't have a clue, however, how WMI and the IIS metabase security work. I still don't, much, really. I did, however, solve my problem.
Using the code

To get a website ID from Internet Information Services Manager, click the 'Web Sites' node and check the column 'Identifier' for the ID. The default website always has the ID 1.

The functions we'll use are in this namespace, so include it:

Collapse

using System.Management;

Hence the variable 'ServerName'. This is where you put your server's name, or a dot if it's the one you're running your code on.

To create a website, you'll want to use the following function. It returns the ID of the website that you can use in the functions mentioned further on.

Collapse

public static string CreateWebsite(string serverName, string appPoolName, string ip, 
string pathToRoot, string hostName, string domainName, int port)
{
ConnectionOptions options = new ConnectionOptions();
options.Authentication = AuthenticationLevel.Connect;
options.EnablePrivileges = true;
options.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope scope = new ManagementScope(string.Format(@\\{0}\root\MicrosoftIISv2, 
serverName), options);
scope.Connect();
ManagementObject oW3SVC = new ManagementObject(scope, 
new ManagementPath(@"IIsWebService='W3SVC'"), null);

ManagementBaseObject[] serverBindings = new ManagementBaseObject[1];
serverBindings[0] = CreateServerBinding(scope, 
string.Format("{0}.{1}", hostName, domainName), ip, port);
ManagementBaseObject inputParameters = oW3SVC.GetMethodParameters("CreateNewSite");
inputParameters["ServerComment"] = string.Format("{0}.{1}", hostName, domainName);
inputParameters["ServerBindings"] = serverBindings;
inputParameters["PathOfRootVirtualDir"] = pathToRoot;
ManagementBaseObject outParameter = 
oW3SVC.InvokeMethod("CreateNewSite", inputParameters, null);

string siteId = Convert.ToString(
outParameter.Properties["ReturnValue"].Value).Replace(
"IIsWebServer='W3SVC/", "").Replace("'", "");
ManagementObject oWebVirtDir = new ManagementObject(scope, 
new ManagementPath(string.Format(
@"IIsWebVirtualDirSetting.Name='W3SVC/{0}/root'", siteId)), null);
oWebVirtDir.Properties["AppFriendlyName"].Value = 
string.Format("{0}.{1}", hostName, domainName);
oWebVirtDir.Properties["AccessRead"].Value = true;
oWebVirtDir.Properties["AuthFlags"].Value = 5; // Integrated Windows Auth.
oWebVirtDir.Properties["AccessScript"].Value = true;
oWebVirtDir.Properties["AuthAnonymous"].Value = true;
oWebVirtDir.Properties["AppPoolId"].Value = appPoolName;
oWebVirtDir.Put();

ManagementObject site = new ManagementObject(scope, 
new ManagementPath(Convert.ToString(
outParameter.Properties["ReturnValue"].Value)), null);
site.InvokeMethod("Start", null);
return siteId;
}

To add a virtual folder:

Collapse

public static void AddVirtualFolder(string serverName, string websiteId, 
string name, string path)
{
ManagementScope scope = new ManagementScope(
string.Format(@"\\{0}\root\MicrosoftIISV2", serverName));
scope.Connect();

string siteName = string.Format("W3SVC/{0}/Root/{1}", websiteId, name);

ManagementClass mc = new ManagementClass(scope, 
new ManagementPath("IIsWebVirtualDirSetting"), null);
ManagementObject oWebVirtDir = mc.CreateInstance();

oWebVirtDir.Properties["Name"].Value = siteName;
oWebVirtDir.Properties["Path"].Value = path;
oWebVirtDir.Properties["AuthFlags"].Value = 5; // Integrated Windows Auth.
oWebVirtDir.Properties["EnableDefaultDoc"].Value = true;
// date, time, size, extension, longdate ;
oWebVirtDir.Properties["DirBrowseFlags"].Value = 0x4000003E;
oWebVirtDir.Properties["AccessFlags"].Value = 513; // read script 
oWebVirtDir.Put();

ManagementObject mo = new ManagementObject(scope, 
new System.Management.ManagementPath("IIsWebVirtualDir='" + 
siteName + "'"), null);
ManagementBaseObject inputParameters = mo.GetMethodParameters("AppCreate2");
inputParameters["AppMode"] = 2;
mo.InvokeMethod("AppCreate2", inputParameters, null);
mo = new ManagementObject(scope, new System.Management.ManagementPath(
"IIsWebVirtualDirSetting='" + siteName + "'"), null);
mo.Properties["AppFriendlyName"].Value = name;
mo.Put();
}

To add a host header to the website:

Collapse

public static void AddHostHeader(string serverName, string hostHeader, 
string ip, int port, string websiteID)

ManagementScope scope = new ManagementScope(string.Format(
@"\\{0}\root\MicrosoftIISV2", serverName));
scope.Connect();

string siteName = string.Format("'W3SVC/{0}'", websiteID);

ManagementObject mo = new ManagementObject(scope, 
new System.Management.ManagementPath("IIsWebServerSetting=" + siteName), null);
ManagementBaseObject[] websiteBindings = 
(ManagementBaseObject[])mo.Properties["ServerBindings"].Value;

ManagementObject mco = CreateServerBinding(scope, hostHeader, ip, port);

ManagementBaseObject[] newWebsiteBindings = 
new ManagementBaseObject[websiteBindings.Length+1];
websiteBindings.CopyTo(newWebsiteBindings, 0);
newWebsiteBindings[newWebsiteBindings.Length - 1] = mco;

mo.Properties["ServerBindings"].Value = newWebsiteBindings;

mo.Put();
}

Last but not least, add the following function. It creates an object for server binding:

Collapse

private static ManagementObject CreateServerBinding(ManagementScope scope, 
string hostName, string ip, int port)
{
ManagementClass mc = new ManagementClass(scope, 
new ManagementPath("ServerBinding"), null);
ManagementObject mco = mc.CreateInstance();

mco.Properties["Hostname"].Value = hostName;
mco.Properties["IP"].Value = ip;
mco.Properties["Port"].Value = port;
mco.Put();

return mco;
}
Points of interest

Security. This won't run just like this. Of the millions of things I've tried, there seem to be two things that need to be done. WMI and IIS metabase access.

Windows Server 2003 and IIS 6.0 run ASP.NET under NETWORK SERVICE, by default. But, we're going to use impersonation.

So you want to add this to your web.config:

Collapse

<identity impersonate="true" />

The account used to grant your permission accessing the IIS metaBase will be the IUSR_<servername> account. I will continue to refer to this account just as IUSR_. You know you have to append your server's name.
WMI permission

Go to Control Panel -> Administrative Tools -> Computer Management -> Services & Applications.

Right-click WMI Control, choose Properties.

Click Security.

Open the tree.

Click MicrosoftIISv2.

Click Security.

Click Advanced.

Double click IUSR_ (or add it if it isn't there).

Select 'Apply onto': This namespace and sub-namespaces.

Check all the checkboxes.

Apply and Close all dialogs.
IIS metabase permission

Download and install the IIS 6 Resource Kit.

Run the MetaBase Explorer (find it in the Resource Kit menu under Start).

Open the tree, and right click the first or second node and choose Permissions.

If it complains about the current key inheriting from /, click Yes.

Click IUSR_ or add it.

Check Full Control.

Apply and Close all dialogs.

You should be ready to run with enough permissions.

It would be great if someone with more experience could comment on this and point out how to properly configure IIS and WMI to run this code. As I mentioned earlier, I found this out by trying, so I don't know if this is the optimal solution to the problem.

If someone has any problems running this code, I would like to help more.

 

ASP.NET操作WMI

 
前言

本文介绍了ASP.NET如何通过WMI创建站点、添加虚拟目录和添加主机头。并且已在Windows Server 2003及IIS6的环境下测试通过。

这玩意儿花了老子3天时间才搞定,用了几个小时写代码,而且当中还花了不少时间解决Win32: Access denied error的问题。当然我要指出的是,无论NETWORK SERVER帐户还是IUSR_<servername>帐户都不要设置过大的权限。对于WMI和IIS metabase的安全机理,我还是一无所知的。我只不过解决问题而已。
看代码

首先要从Internet信息服务(IIS)管理器中获取网站标识符,点击“网站”根节点,右侧“标识符”显示的就是网站的ID。默认网站的标识符通常是1。

获取网站标识的功能,我们要用到一个namespace,代码如下:

using System.Management;

下文所有’ServerName’都表示你的服务器名称,或者如果你的代码是本地运行的,也可以用一个点来表示。

创建一个站点,你会用到如下函数。这个函数返回新网站的ID,这样你可以进一步对这个网站进行操作。

public static string CreateWebsite(string serverName, string appPoolName, string ip,string pathToRoot, string hostName, string domainName, int port)
{
ConnectionOptions options = new ConnectionOptions();
options.Authentication = AuthenticationLevel.Connect;
options.EnablePrivileges = true;
options.Impersonation = ImpersonationLevel.Impersonate;
ManagementScope scope = new ManagementScope(string.Format(@\\{0}\root\MicrosoftIISv2,
serverName), options);
scope.Connect();
ManagementObject oW3SVC = new ManagementObject(scope,
new ManagementPath(@"IIsWebService='W3SVC'"), null);

ManagementBaseObject[] serverBindings = new ManagementBaseObject[1];
serverBindings[0] = CreateServerBinding(scope,
string.Format("{0}.{1}", hostName, domainName), ip, port);
ManagementBaseObject inputParameters = oW3SVC.GetMethodParameters("CreateNewSite");
inputParameters["ServerComment"] = string.Format("{0}.{1}", hostName, domainName);
inputParameters["ServerBindings"] = serverBindings;
inputParameters["PathOfRootVirtualDir"] = pathToRoot;
ManagementBaseObject outParameter =
oW3SVC.InvokeMethod("CreateNewSite", inputParameters, null);

string siteId = Convert.ToString(
outParameter.Properties["ReturnValue"].Value).Replace(
"IIsWebServer='W3SVC/", "").Replace("'", "");
ManagementObject oWebVirtDir = new ManagementObject(scope,
new ManagementPath(string.Format(
@"IIsWebVirtualDirSetting.Name='W3SVC/{0}/root'", siteId)), null);
oWebVirtDir.Properties["AppFriendlyName"].Value =
string.Format("{0}.{1}", hostName, domainName);
oWebVirtDir.Properties["AccessRead"].Value = true;
oWebVirtDir.Properties["AuthFlags"].Value = 5; // Integrated Windows Auth.
oWebVirtDir.Properties["AccessScript"].Value = true;
oWebVirtDir.Properties["AuthAnonymous"].Value = true;
oWebVirtDir.Properties["AppPoolId"].Value = appPoolName;
oWebVirtDir.Put();

ManagementObject site = new ManagementObject(scope,
new ManagementPath(Convert.ToString(
outParameter.Properties["ReturnValue"].Value)), null);
site.InvokeMethod("Start", null);
return siteId;
}

创建一个虚拟目录:

public static void AddVirtualFolder(string serverName, string websiteId,string name, string path)
{
ManagementScope scope = new ManagementScope(string.Format(@"\\{0}\root\MicrosoftIISV2", serverName));
scope.Connect();

string siteName = string.Format("W3SVC/{0}/Root/{1}", websiteId, name);

ManagementClass mc = new ManagementClass(scope,new ManagementPath("IIsWebVirtualDirSetting"), null);
ManagementObject oWebVirtDir = mc.CreateInstance();

oWebVirtDir.Properties["Name"].Value = siteName;
oWebVirtDir.Properties["Path"].Value = path;
oWebVirtDir.Properties["AuthFlags"].Value = 5; // Integrated Windows Auth.
oWebVirtDir.Properties["EnableDefaultDoc"].Value = true;
// date, time, size, extension, longdate ;
oWebVirtDir.Properties["DirBrowseFlags"].Value = 0x4000003E;
oWebVirtDir.Properties["AccessFlags"].Value = 513; // read script
oWebVirtDir.Put();

ManagementObject mo = new ManagementObject(scope,
new System.Management.ManagementPath("IIsWebVirtualDir='" +
siteName + "'"), null);
ManagementBaseObject inputParameters = mo.GetMethodParameters("AppCreate2");
inputParameters["AppMode"] = 2;
mo.InvokeMethod("AppCreate2", inputParameters, null);
mo = new ManagementObject(scope, new System.Management.ManagementPath(
"IIsWebVirtualDirSetting='" + siteName + "'"), null);
mo.Properties["AppFriendlyName"].Value = name;
mo.Put();
}

给网站添加一个主机头:

public static void AddHostHeader(string serverName, string hostHeader, string ip, int port, string websiteID)
{
ManagementScope scope = new ManagementScope(string.Format(
@"\\{0}\root\MicrosoftIISV2", serverName));
scope.Connect();

string siteName = string.Format("'W3SVC/{0}'", websiteID);

ManagementObject mo = new ManagementObject(scope,
new System.Management.ManagementPath("IIsWebServerSetting=" + siteName), null);
ManagementBaseObject[] websiteBindings =
(ManagementBaseObject[])mo.Properties["ServerBindings"].Value;

ManagementObject mco = CreateServerBinding(scope, hostHeader, ip, port);

ManagementBaseObject[] newWebsiteBindings =
new ManagementBaseObject[websiteBindings.Length+1];
websiteBindings.CopyTo(newWebsiteBindings, 0);
newWebsiteBindings[newWebsiteBindings.Length - 1] = mco;

mo.Properties["ServerBindings"].Value = newWebsiteBindings;

mo.Put();
}

最后别忘了这个函数,它可以为网站绑定一个网络标识。

private static ManagementObject CreateServerBinding(ManagementScope scope,string hostName, string ip, int port)
{
ManagementClass mc = new ManagementClass(scope,
new ManagementPath("ServerBinding"), null);
ManagementObject mco = mc.CreateInstance();

mco.Properties["Hostname"].Value = hostName;
mco.Properties["IP"].Value = ip;
mco.Properties["Port"].Value = port;
mco.Put();

return mco;
}

注意的几点

安全。如果之用上面的那坨代码还不行。我千方百计想让其运行,但貌似忽视了2件事情。访问WMI和IIS metabase。

ASP.NET在Windows Server 2003和IIS6.0上运行默认使用的是NETWORK SERVICE帐户。但是,我们还是要使用客户端模拟。

所以在Web.config中添加下面一个配置:

<identity impersonate="true" />

使用了这个配置,IUSR_<servername>会使用客户端模拟的方式去访问IIS metabase。在后面的文章里,我就用IUSR_来表示这个帐户。不要忘记,在IUSR_后面加上你的服务器名称才是这个帐户的名字。

WMI权限设置

控制面板 –> 管理工具 –> 计算机管理 –> 服务和应用程序。

右键WMI控制,点击“属性”。

选择“安全”选项卡。

展开Root树

点击MicrosoftIISv2。

点击“安全设置”。

点击“高级”。

双击IUSR_(如果“组或用户名称”里面没有的话,就把它添加进去)

把IUSR_ “应用到”设置成“这个名称控件和子名称空间”

“允许”所有权限。

所有窗口都点击“确定”。

IIS metabase权限设置

下载并安装IIS6 Resource Kit。

运行MetaBase Explorer (在开始菜单的IIS Resource Kit中可以找到)。

展开树形目录,右键第一个或第二个节点并且选择“Permissions”。

如果提示你“The current key inherits its security permissions from the key /”,点击“是”。

选择“IIS_IUSRS”,如果没有的话,把它添加进去。

选择“Full Control”。

所有窗口都点击“确定”。

有了足够的权限就能运行了。

如果有高人能对这个方法谈谈自己的感想,并且能指出更好的配置IIS和WMI的方法,那就更赞了。记得之前,我都是自己捣鼓出来的,所以我不知道这个方法是不是最佳的方案。

如果你在运行代码的时候碰到任何问题,我愿意效劳。

 
 http://article.yeeyan.org/bilingual/49861

ASP.NET操作WMI的更多相关文章

  1. Asp.Net 操作XML文件的增删改查 利用GridView

    不废话,直接上如何利用Asp.NET操作XML文件,并对其属性进行修改,刚开始的时候,是打算使用JS来控制生成XML文件的,但是最后却是无法创建文件,读取文件则没有使用了 index.aspx 文件 ...

  2. ASP.NET操作ORACLE数据库之模糊查询

    ASP.NET操作ORACLE数据库之模糊查询 一.ASP.NET MVC利用OracleHelper辅助类操作ORACLE数据库 //连接Oracle数据库的连接字符串 string connect ...

  3. asp.net 操作Excel大全

    asp.net 操作Excel大全 转:http://www.cnblogs.com/zhangchenliang/archive/2011/07/21/2112430.html 我们在做excel资 ...

  4. ASP.NET 操作Cookie详解 增加,修改,删除

    ASP.NET 操作Cookie详解 增加,修改,删除 Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份而储存在用户本地终端上的数据(通常经过加密).定义于RFC2109.它 ...

  5. Asp.net操作Excel----NPOI!!!!1

    前言 Asp.net操作Excel已经是老生长谈的事情了,可下面我说的这个NPOI操作Excel,应该是最好的方案了,没有之一,使 用NPOI能够帮助开发者在没有安装微软Office的情况下读写Off ...

  6. Asp.net操作Excel(终极方法NPOI)(转)

    原文:Asp.net操作Excel(终极方法NPOI) 先去官网:http://npoi.codeplex.com/下载需要引入dll(可以选择.net2.0或者.net4.0的dll),然后在网站中 ...

  7. 使用ASP.NET操作IIS7中使用应用程序

    使用ASP.NET操作IIS7中使用应用程序   在最新发布的启明星Portal里,增加了安装程序,下面说一下.NET对IIS7操作.IIS7的操作和IIS5/6有很大的不同,在IIS7里增加了 Mi ...

  8. ASP FSO操作文件(复制文件、重命名文件、删除文件、替换字符串)

    ASP FSO操作文件(复制文件.重命名文件.删除文件.替换字符串)FSO的意思是FileSystemObject,即文件系统对象.FSO对象模型包含在Scripting 类型库 (Scrrun.Dl ...

  9. ASP.NET操作Word的IIS权限配置

    ASP.NET账号在默认情况下是没有权限操作Microsoft Office对象的,如果不进行权限的配置,代码会抛出类似以下的异常: 检索 COM 类工厂中 CLSID 为 {00024500-000 ...

随机推荐

  1. 百篇大计敬本年之系统篇《六》—— Ubuntu 16.04开启 root 超级用户

    Ubuntu 16.04系统在一开始安装完成时是无法切换到 root 用户的,普通用户需要使用 root 权限的时候通常需要在执行命令前加 "sudo",需要经常使用root权限的 ...

  2. oralce之存储过程

    一:--循环向表emp中插入数据 declare maxnumber ; v_count number; begin v_count :; ..maxnumber LOOP v_count :; in ...

  3. 跨域 HTTP 请求

    如果你需要从不同的服务器(不同域名)上获取数据就需要使用跨域 HTTP 请求. 跨域请求在网页上非常常见.很多网页从不同服务器上载入 CSS, 图片,Js脚本等. 在现代浏览器中,为了数据的安全,所有 ...

  4. FreeBSD 路由详解

    在同一个局域网上的计算机是直接连通的,但是不同的网络上的计算机并没有直接相连,只能通过一台特殊的专用计算机 -路由器来完成连通.路由器连接有多个网络界面,每一个网络界面连接到一个相应的网络上,具有一个 ...

  5. Linux 网络设备驱动程序设计(2)

    二.回环网卡的程序设计 /*************************** *******回环网卡的驱动程序*** ***********吕晓宁*********** *********2015 ...

  6. Sharepoint 2013 安装部署系列篇 第二篇 -- SQL集群安装

    第一部分 系统集群安装. 第三部分 安装和配置网络负载均衡在前端web服务器 第四部分 安装和配置sharepoint 场(三层拓扑部署) 以下图片均为sharepoint 2010..由于本人的笔记 ...

  7. 【转载】理解OAuth 2.0

    http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html 作者: 阮一峰 日期: 2014年5月12日 OAuth是一个关于授权(authorizat ...

  8. 使用OLEDB读取excel和csv文件

    这是我第一次在博客上写东西,简单的为大家分享一个oledb读取文件的功能吧,这两天在做一个文件导入数据库的小demo,就想着导入前先在页面上展示一下,之前调用Microsoft.Office.Inte ...

  9. Android使用JNI(从java调用本地函数)

    当编写一个混合有本地C代码和Java的应用程序时,需要使用Java本地接口(JNI)作为连接桥梁.JNI作为一个软件层和API,允许使用本地代码调用Java对象的方法,同时也允许在Java方法中调用本 ...

  10. Android里viewpager切换页面存在页面不相邻的页面被销毁的问题

    我之前一直因为viewpager+fragment时,所有页面的状态都会被自动保存 这次自己做了一个添加了5跟fragment的viewpager 测试时发现当从第一个切换到第四个页面时,再回到第一个 ...