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. 管理后台-第二部分:Custom sections in Umbraco 7 – Part 2 the views(翻译文档)

    在上一篇文章中我们讨论了怎样在我们Umbraco7.0版本中去添加一个新的自定义的应用程序(或部分)和如何去定义一个树.现在我将给你展示你改何如添加视图,来使你的内容可以做一些更有意义的事情. The ...

  2. 【递归】数字三角形 简单dp

    [递归]数字三角形 题目描述 对于大多数人来说,“我们是这么的正常,因此也就这么的平庸.”而天才总是与众不同的,所以当邪狼问修罗王:“老大,你蹲在那儿一动不动看了有半个小时了,蚂蚁有那么好看吗?” 修 ...

  3. 获得自动增长的MySQL主键

    下面的脚本教您如何获得自动增长的MySQL主键,如果您对MySQL主键方面感兴趣的话,不妨一看,相信对您学习MySQL主键方面会有所启迪. import java.sql.Connection; im ...

  4. js实现全屏

    详细内容请点击 1.window.open方式 第一种: 在已经打开的一个普通网页上,点击“全屏显示”,然后进入该网页对应的全屏模式.方法为:在网页的<body>与</body> ...

  5. 常见的Activity Action Intent常量

    Intent的中文意思是“意图,目的”的意思,可以理解为不同组件之间通信的“媒介”或者“信使”. 目标组件一般要通过Intent来声明自己的条件,一般通过组件中的<intent-filter&g ...

  6. android View 绘制完成监听

    <span style="font-size:18px">//view重绘时回调 view.getViewTreeObserver().addOnDrawListene ...

  7. Jquery判断$("#id")获取的对象是否存在的方法

    如果是下面的 jquery 代码判断一个对象是否存在,是不能用的 if($("#id")){ }else{} 因为 $(“#id”) 不管对象是否存在都会返回 object . 正 ...

  8. android ListView的怪异现象

    我们已经知道,当条目没显示一次,那个类重写的最后一个函数就执行一次,但是现在,发生了怪异现象!当窗体的属性设置为包裹的时候,会重复显示多次,所以,高度,宽度都要设置为充满类型才可以

  9. flume+kafka (分区实现 默认单分区)

    这篇文章主要是log4j+flume+kafka的内容 首先从从下面的地址下载flume+kafka的插件包 https://github.com/beyondj2ee/flumeng-kafka-p ...

  10. 解析json数据总结

    json格式的数据一般就是两种类型的,一种是数组类型的,一种是对象类型的. 数组类型:[{"id":"a001","name":" ...