分类: Uncategorized

  • 厚积薄发,丰富的公用类库积累,助你高效进行系统开发(8)—-非对称加密、BASE64加密、MD5等常用加密处理

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(8)—-非对称加密、BASE64加密、MD5等常用加密处理 (转)

    俗话说,一个好汉十个帮,众人拾柴火焰高等都说明一个道理,有更多的资源,更丰富的积累,都是助你走向成功,走向顶峰的推动力。

    本篇继续继续整理优化已有的共用类库,并继续发表随笔介绍公用类库的接口方法以及详细使用操作,力求给自己继续优化,积攒更丰富的公用类库资源,加深了解的同时,也给大家展现公用类库好的方面。

    本篇的公用类库的介绍主题是加密解密的部分,加解密算法包括DES加解密、Base64加解密、

    AES RijndaelManaged加解密、MD5加密、以及RSA非对称加密等操作。如果你对前面的类库介绍文章有兴趣,可以参考下面的连接了解。

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(7)

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(6)

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(5)

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(4)

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(3)

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(2)

    厚积薄发,丰富的公用类库积累,助你高效进行系统开发(1)

    1、非对称加密、解密、验证辅助类 RSASecurityHelper

    本人开发过很多共享软件,在共享软件注册方面积累了一些自己的经验,其中采用非对称加密方式实现注册码验证的操作,就是其中一个比较重要的步骤,由于其逻辑不可逆的特点,采用非对称加密方式,较一般的对称加密方式,能够隐藏授权的逻辑,因此具有更好的效果。 这个非对称的解密解密、验证操作,是我所有共享软件里面用到的授权操作,很早很多朋友就这个问题问过我很多次,现在奉献给大家注册码实现的思路及操作接口,希望大家能够在享受代码带来的便利外,也可以提高自己对知识产权的保护。

    一般来说,非对称加密方式,结合代码混淆和强名称验证,是比较好的实现注册授权机制的功能。

    实现效果

    1)本辅助类主要是用来方便实现非对称加密、解密、验证等相关操作。

    2)非对称加密有RSA、椭圆曲线等,最流行的是RSA。所谓的非对称,是因为它有两个密钥,一个称为公钥,一个称为私钥。公钥是可以对外发布的,而私钥是自己保存的。用公钥加密,必须用私钥解密,反之,用私钥加密必须用公钥解密。所以,我们可以在软件中保存公钥的内容,这个是可以公开的;私钥我们可以自己留着。别人拿不到私钥,根本计算不出注册码来。

    3)使用辅助类RSASecurityHelper实现注册机制如下:

    a. 注册码产生过程:

    注册信息(包括用户名等信息)—> RSA私钥加密 —> 注册码。

    b. 软件验证注册码过程:

    注册码 —> RSA公钥验证 —> 验证成功或失败。

    实现代码

    1)辅助类提供的方法接口如下所示:

    复制代码

    /// <summary> /// 非对称加密生成的私钥和公钥 /// </summary> /// <param name="privateKey">私钥</param> /// <param name="publicKey">公钥</param> public static void GenerateRSAKey(out string privateKey, out string publicKey) #region 非对称数据加密(公钥加密) /// <summary> /// 非对称加密字符串数据,返回加密后的数据 /// </summary> /// <param name="publicKey">公钥</param> /// <param name="originalString">待加密的字符串</param> /// <returns>加密后的数据</returns> public static string RSAEncrypt(string publicKey, string originalString) /// <summary> /// 非对称加密字节数组,返回加密后的数据 /// </summary> /// <param name="publicKey">公钥</param> /// <param name="originalBytes">待加密的字节数组</param> /// <returns>返回加密后的数据</returns> public static string RSAEncrypt(string publicKey, byte[] originalBytes) #endregion #region 非对称解密(私钥解密) /// <summary> /// 非对称解密字符串,返回解密后的数据 /// </summary> /// <param name="privateKey">私钥</param> /// <param name="encryptedString">待解密数据</param> /// <returns>返回解密后的数据</returns> public static string RSADecrypt(string privateKey, string encryptedString) /// <summary> /// 非对称解密字节数组,返回解密后的数据 /// </summary> /// <param name="privateKey">私钥</param> /// <param name="encryptedBytes">待解密数据</param> /// <returns></returns> public static string RSADecrypt(string privateKey, byte[] encryptedBytes) #endregion #region 非对称加密签名、验证 /// <summary> /// 使用非对称加密签名数据 /// </summary> /// <param name="privateKey">私钥</param> /// <param name="originalString">待加密的字符串</param> /// <returns>加密后的数据</returns> public static string RSAEncrypSignature(string privateKey, string originalString) /// <summary> /// 对私钥加密签名的字符串,使用公钥对其进行验证 /// </summary> /// <param name="originalString">未加密的文本,如机器码</param> /// <param name="encrytedString">加密后的文本,如注册序列号</param> /// <returns>如果验证成功返回True,否则为False</returns> public static bool Validate(string originalString, string encrytedString) /// <summary> /// 对私钥加密的字符串,使用公钥对其进行验证 /// </summary> /// <param name="originalString">未加密的文本,如机器码</param> /// <param name="encrytedString">加密后的文本,如注册序列号</param> /// <param name="publicKey">非对称加密的公钥</param> /// <returns>如果验证成功返回True,否则为False</returns> public static bool Validate(string originalString, string encrytedString, string publicKey)

    复制代码

    #endregion

    2) 辅助类RSASecurityHelper的使用例子代码如下所示

    复制代码

    //生成加解密私钥、公钥 string publicKey = ""; string privateKey = ""; RSASecurityHelper.GenerateRSAKey(out privateKey, out publicKey); string originalString = "testdata"; string encryptedString = RSASecurityHelper.RSAEncrypt(publicKey, originalString); string originalString2 = RSASecurityHelper.RSADecrypt(privateKey, encryptedString); if (originalString == originalString2) { MessageUtil.ShowTips("解密完全正确"); } else { MessageUtil.ShowWarning("解密失败"); } string regcode = RSASecurityHelper.RSAEncrypSignature(privateKey, originalString); bool validated = RSASecurityHelper.Validate(originalString, regcode, publicKey);

    MessageUtil.ShowTips( validated ? "验证成功" : "验证失败");

    复制代码

    3)实际项目使用的注册验证代码如下所示。

    复制代码

    /// <summary> /// 每次程序运行时候,检查用户是否注册 /// </summary> /// <returns>如果用户已经注册, 那么返回True, 否则为False</returns> public bool CheckRegister() { // 先获取用户的注册码进行比较 string serialNumber = string.Empty; //注册码 RegistryKey reg = Registry.CurrentUser.OpenSubKey(UIConstants.SoftwareRegistryKey, true); if (null != reg) { serialNumber = (string)reg.GetValue("SerialNumber"); Portal.gc.bRegisted = Portal.gc.Register(serialNumber); } return Portal.gc.bRegisted; } /// <summary> /// 调用非对称加密方式对序列号进行验证 /// </summary> /// <param name="serialNumber">正确的序列号</param> /// <returns>如果成功返回True,否则为False</returns> public bool Register(String serialNumber) { string hardNumber = HardwareInfoHelper.GetCPUId(); return RSASecurityHelper.Validate(hardNumber, serialNumber); } public string GetHardNumber() { return HardwareInfoHelper.GetCPUId();

    }

    复制代码

    2、 DES对称加解密、AES RijndaelManaged加解密、Base64加密解密、MD5加密等操作辅助类 EncodeHelper

    实现效果

    1)本辅助类主要是用来方便实现DES对称加解密、AES RijndaelManaged加解密、Base64加密解密、MD5加密等操作。

    2)本辅助类实现多种加解密处理,可以实现字符串、文件、文件流等加密处理。该加密辅助类汇集各种加密处理逻辑,是一个非常常用、方便应对各种加密处理的辅助类。

    实现代码

    1)辅助类提供的方法接口如下所示:

    复制代码

    /// <summary> /// 使用默认加密 /// </summary> /// <param name="strText"></param> /// <returns></returns> public static string DesEncrypt(string strText) /// <summary> /// 使用默认解密 /// </summary> /// <param name="strText">解密字符串</param> /// <returns></returns> public static string DesDecrypt(string strText) /// <summary> /// 加密字符串,注意strEncrKey的长度为8位 /// </summary> /// <param name="strText">待加密字符串</param> /// <param name="strEncrKey">加密键</param> /// <returns></returns> public static string DesEncrypt(string strText, string strEncrKey) /// <summary> /// 解密字符串,注意strEncrKey的长度为8位 /// </summary> /// <param name="strText">待解密的字符串</param> /// <param name="sDecrKey">解密键</param> /// <returns>解密后的字符串</returns> public static string DesDecrypt(string strText, string sDecrKey) /// <summary> /// 加密数据文件,注意strEncrKey的长度为8位 /// </summary> /// <param name="m_InFilePath">待加密的文件路径</param> /// <param name="m_OutFilePath">输出文件路径</param> /// <param name="strEncrKey">加密键</param> public static void DesEncrypt(string m_InFilePath, string m_OutFilePath, string strEncrKey) /// <summary> /// 解密数据文件,注意strEncrKey的长度为8位 /// </summary> /// <param name="m_InFilePath">待解密的文件路径</param> /// <param name="m_OutFilePath">输出路径</param> /// <param name="sDecrKey">解密键</param> public static void DesDecrypt(string m_InFilePath, string m_OutFilePath, string sDecrKey) #endregion #region 对称加密算法AES RijndaelManaged加密解密 /// <summary> /// 对称加密算法AES RijndaelManaged加密(RijndaelManaged(AES)算法是块式加密算法) /// </summary> /// <param name="encryptString">待加密字符串</param> /// <returns>加密结果字符串</returns> public static string AES_Encrypt(string encryptString) /// <summary> /// 对称加密算法AES RijndaelManaged加密(RijndaelManaged(AES)算法是块式加密算法) /// </summary> /// <param name="encryptString">待加密字符串</param> /// <param name="encryptKey">加密密钥,须半角字符</param> /// <returns>加密结果字符串</returns> public static string AES_Encrypt(string encryptString, string encryptKey) /// <summary> /// 对称加密算法AES RijndaelManaged解密字符串 /// </summary> /// <param name="decryptString">待解密的字符串</param> /// <returns>解密成功返回解密后的字符串,失败返源串</returns> public static string AES_Decrypt(string decryptString) /// <summary> /// 对称加密算法AES RijndaelManaged解密字符串 /// </summary> /// <param name="decryptString">待解密的字符串</param> /// <param name="decryptKey">解密密钥,和加密密钥相同</param> /// <returns>解密成功返回解密后的字符串,失败返回空</returns> public static string AES_Decrypt(string decryptString, string decryptKey) /// <summary> /// 加密文件流 /// </summary> /// <param name="fs">文件流</param> /// <returns></returns> public static CryptoStream AES_EncryptStrream(FileStream fs, string decryptKey) /// <summary> /// 解密文件流 /// </summary> /// <param name="fs">文件流</param> /// <returns></returns> public static CryptoStream AES_DecryptStream(FileStream fs, string decryptKey) /// <summary> /// 对指定文件加密 /// </summary> /// <param name="InputFile">输入文件</param> /// <param name="OutputFile">输出文件</param> /// <returns></returns> public static bool AES_EncryptFile(string InputFile, string OutputFile) /// <summary> /// 对指定的文件解压缩 /// </summary> /// <param name="InputFile">输入文件</param> /// <param name="OutputFile">输出文件</param> /// <returns></returns> public static bool AES_DecryptFile(string InputFile, string OutputFile) #endregion #region Base64加密解密 /// <summary> /// Base64是一種使用64基的位置計數法。它使用2的最大次方來代表僅可列印的ASCII 字元。 /// 這使它可用來作為電子郵件的傳輸編碼。在Base64中的變數使用字元A-Z、a-z和0-9 , /// 這樣共有62個字元,用來作為開始的64個數字,最後兩個用來作為數字的符號在不同的 /// 系統中而不同。 /// Base64加密 /// </summary> /// <param name="str">Base64方式加密字符串</param> /// <returns></returns> public static string Base64Encrypt(string str) /// <summary> /// Base64解密字符串 /// </summary> /// <param name="str">待解密的字符串</param> /// <returns></returns> public static string Base64Decrypt(string str) #endregion #region MD5加密 /// <summary> /// 使用MD5加密字符串 /// </summary> /// <param name="strText">待加密的字符串</param> /// <returns>MD5加密后的字符串</returns> public static string MD5Encrypt(string strText) /// <summary> /// 使用MD5加密的Hash表 /// </summary> /// <param name="input">待加密字符串</param> /// <returns></returns> public static string MD5EncryptHash(String input) /// <summary> /// 使用Md5加密为16进制字符串 /// </summary> /// <param name="input">待加密字符串</param> /// <returns></returns> public static string MD5EncryptHashHex(String input) /// <summary> /// MD5 三次加密算法.计算过程: (QQ使用) /// 1. 验证码转为大写 /// 2. 将密码使用这个方法进行三次加密后,与验证码进行叠加 /// 3. 然后将叠加后的内容再次MD5一下,得到最终验证码的值 /// </summary> /// <param name="s"></param> /// <returns></returns> public static string EncyptMD5_3_16(string s) #endregion /// <summary> /// SHA256函数 /// </summary> /// <param name="str">原始字符串</param> /// <returns>SHA256结果(返回长度为44字节的字符串)</returns> public static string SHA256(string str) /// <summary> /// 加密字符串(使用MD5+Base64混合加密) /// </summary> /// <param name="input">待加密的字符串</param> /// <returns></returns> public static string EncryptString(string input) /// <summary> /// 解密加过密的字符串(使用MD5+Base64混合加密) /// </summary> /// <param name="input">待解密的字符串</param> /// <param name="throwException">解密失败是否抛异常</param> /// <returns></returns> public static string DecryptString(string input, bool throwException)

    复制代码

    2) 辅助类EncodeHelper的使用例子代码如下所示

    复制代码

    /// <summary> /// 对字符串加密 /// </summary> /// <returns></returns> private string EncodePassword(string passwordText) { return EncodeHelper.MD5Encrypt(passwordText);

    }

    复制代码

    复制代码

    private void btnEncrypt_Click(object sender, EventArgs e) { string original = "测试加密字符串"; Console.WriteLine("original:" + original); string encrypt = EncodeHelper.SHA256(original); Console.WriteLine("EncodeHelper.SHA256" + encrypt); //DES加解密 encrypt = EncodeHelper.DesEncrypt(original); Console.WriteLine("EncodeHelper.DesEncrypt:" + encrypt); string decrypt = EncodeHelper.DesDecrypt(encrypt); Console.WriteLine("EncodeHelper.DesDecrypt:" + decrypt); //MD5加密 encrypt = EncodeHelper.MD5Encrypt(original); Console.WriteLine("EncodeHelper.MD5Encrypt:" + encrypt); encrypt = EncodeHelper.MD5EncryptHash(original); Console.WriteLine("EncodeHelper.MD5EncryptHash:" + encrypt); encrypt = EncodeHelper.MD5EncryptHashHex(original); Console.WriteLine("EncodeHelper.MD5EncryptHashHex" + encrypt); encrypt = EncodeHelper.EncyptMD5_3_16(original); Console.WriteLine("EncodeHelper.EncyptMD5_3_16:" + encrypt); //Base64加解密 encrypt = EncodeHelper.Base64Encrypt(original); Console.WriteLine("EncodeHelper.Base64Encrypt" + encrypt); decrypt = EncodeHelper.Base64Encrypt(encrypt); Console.WriteLine("EncodeHelper.Base64Encrypt" + decrypt); encrypt = EncodeHelper.AES_Encrypt(original); Console.WriteLine("EncodeHelper.AES_Encrypt" + encrypt); decrypt = EncodeHelper.AES_Decrypt(encrypt);

    Console.WriteLine("EncodeHelper.AES_Decrypt" + decrypt);

    复制代码

    3、 MD5各种长度加密字符、验证MD5等操作辅助类 MD5Util

    实现效果

    1)本辅助类主要是用来方便实现MD5各种长度加密字符、验证MD5等操作。

    2)MD5即Message-Digest Algorithm 5(信息-摘要算法 5),用于确保信息传输完整一致。是计算机广泛使用的散列算法之一(又译摘要算法、哈希算法)。

    3)MD5已经广泛使用在为文件传输提供一定的可靠性方面。例如,服务器预先提供一个MD5校验和,用户下载完文件以后,用MD5算法计算下载文件的MD5校验和,然后通过检查这两个校验和是否一致,就能判断下载的文件是否出错

    实现代码

    1)辅助类提供的方法接口如下所示:

    复制代码

    /// <summary> /// 获得32位的MD5加密 /// </summary> public static string GetMD5_32(string input) /// <summary> /// 获得16位的MD5加密 /// </summary> public static string GetMD5_16(string input) /// <summary> /// 获得8位的MD5加密 /// </summary> public static string GetMD5_8(string input) /// <summary> /// 获得4位的MD5加密 /// </summary> public static string GetMD5_4(string input) /// <summary> /// 添加MD5的前缀,便于检查有无篡改 /// </summary> public static string AddMD5Profix(string input) /// <summary> /// 移除MD5的前缀 /// </summary> public static string RemoveMD5Profix(string input) /// <summary> /// 验证MD5前缀处理的字符串有无被篡改 /// </summary> public static bool ValidateValue(string input) #region MD5签名验证 /// <summary> /// 对给定文件路径的文件加上标签 /// </summary> /// <param name="path">要加密的文件的路径</param> /// <returns>标签的值</returns> public static bool AddMD5(string path) /// <summary> /// 对给定路径的文件进行验证,如果一致返回True,否则返回False /// </summary> /// <param name="path"></param> /// <returns>是否加了标签或是否标签值与内容值一致</returns>

    public static bool CheckMD5(string path)

    复制代码

    2) 辅助类

    MD5Util 的使用例子代码如下所示

    复制代码

    //为文件增加MD5编码标签,然后验证是否被修改 string file = @"c:\test.xls"; bool flag2 = MD5Util.AddMD5(file); Console.WriteLine(flag2); //对给定路径的文件进行验证,如果一致返回True,否则返回False bool flag3 = MD5Util.CheckMD5(file);

    Console.WriteLine(flag3);

    复制代码

    4、基于Base64的加密编码辅助类 Base64Util

    实现效果

    1)本辅助类主要是用来方便实现基于Base64的加密编码。

    2)Base64被定义为:Base64内容传送编码被设计用来把任意序列的8位字节描述为一种不易被人直接识别的形式。Base64编码一般在电子邮件中可以查看到,打开一封Email,查看其原始信息(您可以通过收取、导出该邮件用文本编辑器查看)。加密是肯定的,但是加密的目的不是让用户发送非常安全的Email。这种加密方式主要就是“防君子不防小人”。即达到一眼望去完全看不出内容即可。

    3)采用Base64编码不仅比较简短,同时也具有不可读性,即所编码的数据不会被人用肉眼所直接看到。

    实现代码

    1)辅助类提供的方法接口如下所示:

    复制代码

    /// <summary> /// 使用默认的密码表加密字符串 /// </summary> /// <param name="input">待加密字符串</param> /// <returns></returns> public static string Encrypt(string input) /// <summary> /// 使用默认的密码表解密字符串 /// </summary> /// <param name="input">待解密字符串</param> /// <returns></returns> public static string Decrypt(string input) /// <summary> /// 获取具有标准的Base64密码表的加密类 /// </summary> /// <returns></returns>

    public static Base64Util GetStandardBase64()

    复制代码

    2) 辅助类Base64Util的使用例子代码如下所示

    复制代码

    private void btnBase64_Click(object sender, EventArgs e) { string original = "这是一个测试的Base64加密字符串"; string encrypt = Base64Util.Encrypt(original); Console.WriteLine(encrypt);//输出内容:6LZ5pi_5LiA5Liq5rWL6KV55qEQmFzZTY05Yqg5b*G5b2X56ym5Liy string decrypt = Base64Util.Decrypt(encrypt); Debug.Assert(original == decrypt);//验证相等

    }

    复制代码

    5、QQ密码加密操作辅助类 QQEncryptUtil

    实现效果

    1)本辅助类主要是用来方便实现QQ密码加密操作。 2)在QQ的很多模拟网页采集数据,需要输入用户账号、密码,其中密码是需要进行加密操作的,一般使用js脚本实现,这里把它转化为C#的代码操作,其实也就是把密码和验证码通过3次MD5加密实现的。

    实现代码

    1)辅助类提供的方法接口如下所示:

    /// <summary> /// QQ根据密码及验证码对数据进行加密 /// </summary> /// <param name="password">原始密码</param> /// <param name="verifyCode">验证码</param> /// <returns></returns>

    public static string EncodePasswordWithVerifyCode(string password, string verifyCode)

    2) 辅助类QQEncryptUtil的使用例子代码如下所示

    复制代码

    private bool CheckLogin() { HttpHelper httpHelper = new HttpHelper(); string refUrl = "http://ui.ptlogin2.qq.com/cgi-bin/login?appid=3000801&amp;s_url=http%3A%2F%2Fqun.qq.com%2Fgod%2Fsucc.htm&amp;f_url=loginerroralert&amp;lang=2052&amp;bgcolor=ffffff&amp;style=1&amp;low_login=1&amp;link_target=blank&amp;target=self&amp;hide_title_bar=1&amp;dummy=1"; string verifyCode = this.txtVerify.Text; string postData = string.Format("u={0}&p={1}&verifycode={2}&aid=3000801&u1=http%3A%2F%2Fqun.qq.com%2Fgod%2Fsucc.htm&h=1&ptredirect=0&ptlang=2052&from_ui=1&dumy=&fp=loginerroralert", this.txtUsername.Text, QQEncryptUtil.EncodePasswordWithVerifyCode(this.txtPassword.Text, verifyCode), verifyCode); string result = httpHelper.GetHtml("http://ptlogin2.qq.com/login?" + postData, Portal.gc.cookieQun, refUrl); string errorTxt = result; bool isLogin = result.Contains("登录成功!"); return isLogin;

    }

    复制代码

    CHM帮助文档持续更新中,统一下载地址是: http://www.iqidi.com/download/commonshelp.rar

    最新公用类库DLL+XML注释文件下载地址是:http://files.cnblogs.com/wuhuacong/WHC.OrderWater.Commons.rar

    主要研究技术:代码生成工具、Visio二次开发、客户关系管理软件、送水管理软件等共享软件开发 专注于Winform开发框架、Web开发框架、WCF开发框架的研究及应用。 转载请注明出处: 撰写人:伍华聪  http://www.iqidi.com

    标签: 公用类库使用帮助

  • JavaScript MVC 框架技术选型(转)

    你很喜欢Gmail和Trello之类的单页面应用,但是不太确定该从何开始。也许你的JavaScript代码是如此的杂乱无章,以致于你很想在下一个项目上尝试下JavaScript MVC库和框架,却苦于没有头绪?我正在撰写一本单页面应用的书,所以我阅读了大量网上的相关资料。在这里我尝试提供一些看法,希望可以帮助你下决定。

    简介

    JavaScript MVC frameworks

    这里讨论的是时下最热的框架,AngularJS、Backbone、Ember和Knockout。同时提到了Batman、CANjs、Meteor和Spine,但是没有详细展开。

    我们从多个不同的角度考察每个项目,包括社区、领导、成熟度、大小、依赖、互操作性、启发、理念和特性。

    社区

    社区是一个衡量任何开源项目健康程度的重要指数。以下表格显示了GitHub上每个项目的关注者数量。

    GitHub watchers

    你当然不该仅仅根据这些数据做决定,但是它们确实为你提供了关于这些框架的一些感性认识:

    最主流:

    • Backbone.js
    • AngularJS

    正在高速成长的:

    • AngularJS
    • Meteor
    • Ember
    • Knockout

    关注总量较低但是增长迅猛的:

    • CANjs
    增长性

    特别值得注意的是AngularJS 13个月以来的惊人增长(379%)。在你做决定的时候要考虑上这一点。下面的图表比较了13个月以来GitHub关注者的增长速度,可以看出某个项目的社区成长的速度。考虑到原先的社区大小,Meteor(130%)、Ember(104%)、Knockout(76%)和Backbone(64%)的增长速度也很惊人。

    Growth

    领导

    了解项目的核心开发者的背景,他们创建框架时尝试解决的问题,有助于你欣赏他们在设计上的决策和动机。例如,David Heinemeier Hansson,流行的Ruby on Rails框架的缔造者,是37signals的签约开发者,从事项目设计,每周只有10小时能花在开发框架上。Ruby on Rails事实上是从他和37signals的签约工作中提取出来的。这一背景有助于你理解为什么这个框架需要将开发效率提升到极限——这意味这使用大量的约定(已经做出的决定)和支架程序(生成的代码)。下面,我将介绍JavaScript MVC 框架的缔造者,也许也能激起你对他们的工作的欣赏。

    Backbone

    Jeremy Ashkenas和DocumentCloud

    Jeremy Ashkenas

    Jeremy Ashkenas是CoffeeScript编程语言、Backbone.js JavaScript框架和Underscore.js JavaScript工具库的创立者。根据维基百科,他现在在NYTimes/DocumentCloud从事互动新闻方面的开发。

    图片来自The Canadian University Software Engineering Conference。

    AngularJS

    iško Hevery和Adam Abrons

    AngularJS最初由Google的Miško Hevery和Adam Abrons于2009年开发,当时是一个在线JSON存储服务的一部分。Abrons后来离开了这个项目,但是在Google工作的Hevery继续开发,和Google的员工Igor Minár、Vojta Jína一起维护这个库。

    图片来自Devoxx 2012

    Knockout

    Steve Sanderson

    Steve Sanderson是Knockout的原作者。Steve Sanderson现在为微软工作,他所在的团队开发ASP.NET、IIS和其他web项目。他以前以外包开发者或顾问身份为Bristol周边的客户开发.NET下的软件,他还为Apress写了一些书,包括《Pro ASP.NET MVC框架》。

    图片来自Steve Sanderson的博客

    Ember

    Ember核心成员中最知名的公众人物是Yehuda Katz和Tom Dale。

    Yehuda Katz是Ember.js、Ruby on Rails和jQuery的核心开发者,他白天的时间花在他创办的创业公司,Tilde Inc.。Yehuda是畅销书《jQuery in Action》和《Rails 3 in Action》的作者之一。

    Tom Dale原先在SproutCore团队工作。他以前是苹果软件工程师,在开发MobileMe和iCloud应用时精通了前端JavaScript技能。

    Yehuda Tom Dale

    图片来自Ember Team

    Meteor

    Meteor的开发团队刚刚得到了1.12千万美金,所以他们可以全职开发。他们的团队有12名开发者,每个开发者的简历都让人印象深刻。这个团队拥有雄心勃勃的计划,超越了大多数专注于组织客户端代码和状态的JavaScript MVC框架。Meteor是一个全端框架,包括服务器架构和数据库。

    成熟度

    评估框架的成熟度可以帮助你理解在项目中使用新技术的风险。未经考验的新框架在文档、扩展性、稳定性(API改变)和支持(寻找了解该框架的开发者来维护代码)方面可能存在问题,这些问题可能导致出乎意料的结果,即使从其他方面看起来决策很明智。需要考虑的项目包括:多少生产环境下的应用使用这些框架?这些应用有多少用户?文档是否良好?例子和教程是否充足?例子是否过时?API是否稳定?其他开发者了解或正打算了解这门技术么?

    • Backbone(最成熟)
      • 大量3年以上的生产环境应用,包括GroupOn、 FourSquare、USAToday、DocumentCloud。
      • 良好的文档。
      • 良好的示例代码,但是很多都过时了。
      • API非常稳定。
      • GitHub上有大量关注者。
    • AngularJS(成熟)
      • Google将其用于生产环境,但是不像其他项目一样拥有长久的历史记录。
      • 良好且持续改进的文档。
      • 大量的示例代码。
      • GitHub上有大量关注者。
    • Knockout(成熟)
      • 用于生产环境至今已有2年。
      • 良好的文档,内含类似jsfiddle的代码样例。
      • API很稳定。
      • 大量的示例代码。
      • GitHub上有大量关注者。
    • Ember.js
      • 在两年的开发之后,第一个可用于生产的发布(1.0)在2013年8月30日放出。
      • 文档正在改善。
      • API在1.0之前都不稳定(这是有意的)。
      • 大量示例代码,由于1.0前的API变动,有些已经过时。
      • GitHub上有大量关注者。
    • Meteor
      • 处于开发的早期阶段,较多地用于示例应用
      • 文档不错,然而尚不完整
      • API仍处于变动之中。
      • 一些示例代码。
      • GitHub上有大量关注者。

    大小

    了解每个框架的大小,它会在你的应用中增加多少分量是很重要的。大小会影响性能,不过它同时也会暗示你这个框架的雄心有多大,你学习它可能需要花多少时间,以及它提供多少帮助你构建应用的方式(即特性和鲁棒性)。一个框架的野心越大,特性越多,通常也就意味更难在应用的页面上将它与其他部件组合。轻量的框架更像一个库,将他集成到你的项目中所耗费的精力也相对较小。

    size

    包括Backbone和Spine在内的一些项目为自己的轻量而自豪,这些项目更多地将自己视作库,而不是框架。通常这些小型的框架留下了空间,你可以使用你自己的库来实现特定功能,例如模板和路由。我在讨论这些框架的特性的时候将继续讨论这个话题。

    包括Ember和AngularJS在内的其他项目雄心勃勃,更适合叫做框架。它们通常拥有更多内建的特性,更少依赖外部库。

    下面的列表显示了我更倾向于将哪些项目归入库或框架:

    库 框架

    Backbone Ember

    Knockout AngularJS

    Spine Batman

    CanJS Meteor

    依赖性

    使用这些项目构建真实世界的应用的时候还需要哪些库?以下的图表展示了为了保证开发效率每个库所需的依赖,以及这些依赖的大小。

    通过从cdnjs下载库,我们收集了这些数据。在实践中,大多数的项目会使用jQuery配合这些框架处理DOM,因为需要动画和AJAX。在移动应用中,使用Zepto.js来代替jQuery处理DOM不是什么稀奇的事。Zepto.js是一个比jQuery轻量得多的库。虽然Zepto.js不支持Internet Explorer,但是移动应用通常不需要为此操心。AngularJS包含了一个jQuery 的缩减版jQLite。但是如果你在项目中使用了jQuery的话,它会被覆盖。AngularJS团队鼓励开发者,如非必要,不要添加完整的jQuery库。为了帮助你做出正确的选择,下面的表格同时显示了移动版(假定使用Zepto.js)和web版(假定使用jQuery)。

    size of javascript mvc frameworks w dependencies web app

    size of javascript mvc frameworks w dependencies mobile app

    互操作性

    这一部分讨论是否框架设计为控制整个页面或者它可以被用于现存页面的一个部分——你可能想渐渐将新技术引入现有的项目。前面的库和框架的讨论基本可以体现每个项目的互操作性,库更倾向于很容易地集成到现存的项目,而框架为你做更多的事,但是不容易和其他项目配合。

    AngularJS

    AngularJS可以和其他库很好地配合,但是它鼓励开发者们考虑是否可以不用jQuery和jQueryUI.事实上Angular内置了一个jQuery的子集jqLite。遵循这一实践的理由是让单元测试更容易,因为很多依赖库和插件设计的时候没有考虑单元测试,相应地更难和单元测试配合。在实践中,大多数的开发者最终还是因为某些特性使用了jQuery.

    Backbone

    由于Backbone的小尺寸和无预设的架构,将其包含在众多流行的客户端库和服务器端技术中很容易。

    Ember.js

    被设计为在运行时控制整个页面,所以不太适合用于页面的部分。

    Knockout.js

    可以在项目中作为小组件使用,不控制整个页面。

    启发

    记者采访音乐家时最爱问的问题是“你在成长的时候听哪些艺术家的音乐,或者说,谁启发了你?”这个问题常常使得读者能够预期音乐家的声乐。这些框架中大部分的观念都不是全新的,而是来自于创造者以前工作的项目中喜欢的部分。这一部分总结了我从框架创造者的访谈中收集到的关于启发的信息。

    AngularJS

    HTML类的声明性的语言,Adobe和Flex、微软的WPF\Silverligt等RIA技术给AngularJS的影响很深。这些声明性技术没有”主体“方法,仅仅表达需要发生什么,而不指定具体实现。视图和模型中的数据双向绑定是这一声明式编程风格在绝佳例子。此外,在Google的服务器端Java代码中大量使用的依赖注入和IOC容器(特别是Juice)也启发了AngularJS的创造者。他们重视单元测试,需要框架被设计允许依赖注入,这样测试就可以从其他应用层剥离出来,运行起来也会更快。

    Ember

    Tom Dale在Quora上谈了Ember受到的影响:

    Ember.js刚开始开发的时候,我们从Cocoa等本地应用程序框架引入一些概念,不过后来我们觉得这些概念弊大于利,或者说它们和Web应用程序格格不入。因此,我们开始从Ruby on Rails和Backbone.js 等开源项目中寻找灵感。因此,Ember.js结合了本地应用的强大和现代web的轻量。

    此外,Ember.js是SproutCore JavaScript库的进化版,SproutCore停止仿效Cocoa而更多地借鉴jQuery的时候,Ember诞生了,理解这一点很重要。

    Knockout

    hanselminutes的播客提供了Steve Sanderson受到哪些方面启发的背景信息。总结一下,MVVM设计模式和微软的WPF、Sliverlight等声明性技术是最大的启发者。你可能会发现Knockout的最佳特性——声明性的数据双向绑定——和Anjular相似,因为两者的启发者是相似的。

    理念

    报纸在报道新闻的时候努力保持中立。唯一的例外是编者案,鼓励表达观点,作者通常在问题上占据一个强烈的立场。但是大多数情况,这两者既不是严格的中立报道,也不是强烈的意见表达,而是位于两者之间的连续统。技术框架也有类似的划分,即是否强主张。例如,Ruby on Rails推崇约定优于配置,并且为开发者做了大量决定,包括文件结构和数据访问。相应地,它被认为是强主张的。其他Sinatra类的服务器端框架更轻量,并不预设文件结构和数据访问。相应的,被看成是无主张的。服务端框架有理念,客户端JavaScript MVC框架同样有,我们讨论的框架也可以被置于强主张和无主张的连续统中考察。让我们看看每个项目,然后讨论他们的理念。

    Backbone: 无主张

    Backbone是最开明的框架,极度无主张,允许开发者做出自己的决定,有时这会导致代码差异过大而难以维护。唯一的例外是Backbone假定服务器端有一个REST服务,我会在特性部分详细讨论这一点。这一假定可以通过覆盖模型的sync方法来绕过。

    AngularJS: 强主张

    AngularJS有较强的主张,特别是它强调可测试性和依赖注入。此外,HTML类的声明性编程很棒的理念也在框架中广泛体现。

    Ember: 极度强主张

    Ember力求开发者仅对应用的特有部分作决定,其余全部交给约定和支架。这个理念和Ruby on Rails和jQuery很接近。这一理念最好的表达出现在emberjs.com的网站上:

    不要浪费时间做那些无关紧要的选择。Ember.js吸纳了常见的惯用法,因此你可以专注于应用的特殊部分,而不是重新发明轮子。

    Ember标准化了文件和url结构,当然,有必要的时候也允许你覆盖这些设定。你可以预期的是大量的代码会为你生成,大量的类似文件结构的约定。相应地,你需要做出的常规选择更少,因为框架已经为你选定了合理的默认值,你可以着手构建你的应用的特殊部分。

    Knockout: 无主张

    路由和数据存储留给开发者决定。不预设文件或URL结构。甚至允许用基于字符串的模板替换声明性的基于DOM的模板。

    特性

    我们可以将这些JavaScript MVC框架看成是帮助开发者构建单页应用的常用特性集合。每个框架实现这些特性的方式,或者不实现这些特性的方式(通过其他库来补全框架的功能)是值得留心的。

    JavaScript MVC框架的主要特性是什么?
    • HTML和客户端JavaScript对象模型的双向绑定
    • 视图模板
    • 数据存储(本地存储或者通过服务器存储到数据库)
    • URL路由(确保后退按钮和搜索引擎正常工作)

    除此以外,一些框架提供常用的语言层面的服务,例如通用的pub/sub事件模型和面向对象的继承支持。

    数据绑定

    这是最受吹捧的特性。你通过HTML input修改了数据,绑定到input的JavaScript对象马上更新,其他绑定的用户接口元素也随之更新。在很多框架中,反之亦然。如果你修改了JavaScript对象,html会自动刷新。这是一个web上的双向的数据绑定,我们在Flex、Windows Forms、WPF等富客户端应用框架中见过这类绑定。以下的表格显示了哪些框架支持数据绑定。

    data binding

    有些人可能持有异议,因为Backbone和Spine部分支持数据绑定。但是我觉得大量工作需要留给开发者,保险起见,不如说这些库不支持这些特性。

    视图模板

    客户端的JavaScript数据模型需要穿插在HTML中,这些框架采用两种方式解决问题。

    基于字符串的模板(目前最流行的是handlebars.js),将字符串、文本模板中的动态部分替换为模型中的数据。字符串常被提到也饱受争议的特性之一是性能。其缺点是调试控制语句类的逻辑很困难。

    基于DOM的模板拥抱标记语言的声明式本性,这是开了挂的html,通过html中的附加属性来描述需要的绑定和事件。这些库需要的代码大大减少,为开发者做了很多事情。

    view templates

    模型(可观察的:跟踪改动)

    一些框架(Backbone、Spine)更专注于模型,要求开发者在base模型的基础上扩展JavaScript类,通过.get()和.set()访问属性,这样就能跟踪改动,模型的变动也会触发事件。KnockoutJS让开发者在原始的JavaScript对象上应用可察封装,然后通过object.propertyName()访问属性(小心,别丢了括号)。

    其他库(AngularJS)对页面上的所有绑定的DOM元素作脏检查,因为没有标准的get和set访问器。因此将这些库用于大页面时将导致性能问题。这些库不仅需要更少的刷新模板的代码,也不需要你使用特定的get和set访问器来修改模型中的数据,所以你可以使用原始的JavaScript对象。这大大提升了开发效率,这一点在框架的初学者身上体现得尤为明显。

    数据存储

    这些框架通过以下方式将数据存储到服务器

    • 与REST服务自动同步
    • 需要开发者自行实现ajax调用,调用针对返回json的web服务
    • 同时允许以上两种方式
    REST

    一些框架默认预设后端有非常整洁的REST JSON服务,并且,至少在默认的情况下,前端与后端频繁交互,在后台异步更新数据,而用户界面响应流畅。这些框架内部使用jQuery或Zepto发送合适的AJAX请求给服务器。用户界面的HTML DOM元素监听应用的JavaScript对象模型的改动,同步机制得到模型属性的更改提醒,将改动发送给REST服务,确保模型和服务器同步。

    在线和离线

    Backbone默认在客户端保存数据之前发送请求,这样服务器端和客户端同步就很容易。和Backbone非常类似的Spine框架,采用了不同的方式,在异步发送请求到服务器前,先在客户端存储记录,这提供了更好的用户界面响应,在移动应用中常发生的离线状态下也能工作。如果你的项目需要支持离线,需要了解清楚框架对该特性的支持

    DIY

    这些框架要求开发者使用$.ajax(jQuery)来调用服务,或者添加兼容的开源库处理数据存储需求。

    数据存储特性

    Meteor之类精心制作的框架拥有更完整的数据存储方案,但是要求服务器端有MongoDB数据库。这类方案试图提供一个扩展性优异的默认解决方案,提供从头到尾的JavaScript开发体验。

    以下的表格总结了每个框架是如何处理数据存储的。

    路由

    将URL路由映射到JavaScript函数,可以支持浏览器的后退按钮。单页应用最大的缺点之一是由于页面无刷新,浏览器历史不会添加条目,所以后退按钮通常无法将用户带回页面的前一状态,除非开发者在主要的状态改变时做一些额外的工作,通过在URL后附加井号,或者,使用现代浏览器的push和pop状态,实现状态跟踪机制。总之,大多数项目都提供基本、初步而有用的功能。Knockout的做法很简单,允许你使用其他的第三方开源库。

    routing

    苹果对苹果

    考察各个框架的特性之后,我发现我并不是在做一个“苹果对苹果”的比较。一个更为公平的比较也许是将AngularJS和EmberJS之类全面的框架与配合第三方库使用的Backbone和KnockoutJS之类的MV*框架进行比较。具体来说,下面的比较会更有意义:

    • AngularJS
    • EmberJS
    • Backbone 搭配 Marionette
    • KnockoutJS 搭配 DurandalJS、HistoryJS或SammayJS。

    以后的博客中我会继续深入。

    告诉我更多

    为项目选择JavaScript MVC框架时有大量需要考虑的事项,我希望本文是一个良好的开始。请在评论中分享你使用这些框架的体验,包括它们的优异之处,也包括它们使用上的陷阱。


    原文 Choosing a JavaScript MVC Framework 翻译 SegmentFault

    from:http://segmentfault.com/a/1190000000379723

  • ASP.NET impersonation

    采用问答式, 快餐式获取要点.

    string currentUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

  • SQL Server Reporting service ToolBarItemsDisplayMode

    定制Sharepoint 2013报表工具栏

    C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\template\layouts\ReportServer\RSViewerPage.aspx
    
    <RSWP:ReportViewerWebPart id="m_sqlRsWebPart" runat="server" SuppressWebPartChrome="true" Height="100%" Width="100%" 
    
    ToolBarItemsDisplayMode="Back,Export,Find,PageNavigation,Print,Refresh" />
    
    .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
  • IIS7.0 Appcmd (quote)

    一:准备工作 APPcmd.exe 位于 C:\Windows\System32\inetsrv 目录 使用 Cd c:\Windows\System32\inetsrv 切换到该目录 二:命令操作简介 IIS 命令行管理工具基本格式: APPCMD (命令) (对象类型) <标识符> </参数1:值1 …> 支持的对象类型: SITE 虚拟站点的管理 APP 管理应用程序 VDIR 管理虚拟目录 APPPOOL 管理应用程序池 CONFIG 管理常规配置节 WP 管理工作进程 REQUEST 管理 HTTP 请求 MODULE 管理服务器模块 BACKUP 管理服务器配置备份 TRACE 使用失败请求跟踪日志 ———–这个就不解释很详细了,懂的人都知道这个IIS的层次。 三:对Site的命令详解 1.命令介绍 虚拟站点的管理 APPCMD <命令> SITE [标识符] [-参数1:值1 …] 如: appcmd list site (列出当前存在的站点) 支持的命令: list 列出虚拟站点 set 配置虚拟站点 add 添加新虚拟站点 delete 删除虚拟站点 start 启动虚拟站点 stop 停止虚拟站点 2.详解 列出虚拟站点 APPCMD list SITE [标识符] [-参数1:值1 …] 列出计算机上的虚拟站点。此命令可用于使用特定站点的标识符或 url 查找该站点,或者 基于指定的站点属性匹配零个或多个站点。 示例: appcmd list sites 列出计算机上的所有站点。 appcmd list site "Default Web Site" 查找站点“Default Web Site”。 appcmd list site http://localhost/app1 查找与指定的 url 关联的站点。 appcmd list site /serverAutoStart:false 查找“serverAutoStart”配置属性设置为“false”的所有站点。 添加新虚拟站点 APPCMD add SITE [标识符] [-参数1:值1 …] 使用指定的设置创建新的虚拟站点。至少,必须提供站点名称和 ID。 支持的参数: /name (必需) 站点名称 /id 站点 ID /bindings “http://domain:port,…”好记格式或“protocol/bindingInformation,…”原始格式的绑定列表 /physicalPath 如果指定,将导致为该站点创建包含指向指定路径的根虚拟目录的根应用程序。如果忽 略,将创建一个没有根应用程序的站点,并且该站点在创建根应用程序之前将无法启动。 示例: appcmd add site /name:"My New Site" /id:2 /bindings:http://www.domain.com:80 使用指定的好记绑定创建一个新站点“我的新站点”,以便在端口 80 上侦听对 www.d omain.com 的 http 请求。 appcmd add site /name:"My New Site" /id:2 /bindings:http://*:81 使用指定的好记绑定创建一个新站点“我的新站点”,以便在端口 81 上侦听对任何域 名的 http 请求。 appcmd add site /name:"My New Site" /id:2 /bindings:http/:81: 使用指定的 ID 和绑定创建新站点“我的新站点”。创建后,新站点中不包含任何应用 程序。 appcmd add site /name:"My New Site" /id:2 /bindings:http/:81: /physicalPath:"c :\inetpub\mynewsite" 使用指定的 ID 和绑定创建新站点“我的新站点”。系统将自动创建根虚拟目录指向指 定物理路径的根应用程序。 appcmd add site /name:"My New Site" /bindings:http/*:81: 使用绑定创建新站点“我的新站点”,并自动生成站点 ID。创建后,该新站点不包含 任何应用程序。 配置虚拟站点 APPCMD set SITE [标识符] [-参数1:值1 …] 允许设置指定虚拟站点的属性。必须提供准确的站点标识符,并且必须将该标识符解析为现 有站点。 支持的参数: identifier (必需) 要修改的站点的站点名称或 url /site.name 要修改的站点的站点名称或 url (与标识符相同) /bindings “http://domain:port,…”好记格式或“protocol/bindingInformation,…”原始 格式的绑定列表 示例: appcmd set site "Default Web Site" /serverAutoStart:false /id:100 设置“Default Web Site”站点的“serverAutoStart”和“id”属性。 这里对 set 操作附加一些高级操作(重要) 当时用 appcmd set site "Default Web Site" 当时用后其他高级参数 解释后续补上………… -name 名称 -id ID标识 -serverAutoStart 是否自动启动 -bindings.[protocol=’string’,bindingInformation=’string’].p -bindings.[protocol=’string’,bindingInformation=’string’].b -limits.maxBandwidth -limits.maxConnections -limits.connectionTimeout -logFile.logExtFileFlags -logFile.customLogPluginClsid -logFile.logFormat -logFile.directory -logFile.period -logFile.truncateSize -logFile.localTimeRollover -logFile.enabled -traceFailedRequestsLogging.enabled -traceFailedRequestsLogging.directory -traceFailedRequestsLogging.maxLogFiles -traceFailedRequestsLogging.maxLogFileSizeKB -traceFailedRequestsLogging.customActionsEnabled -applicationDefaults.path -applicationDefaults.applicationPool -applicationDefaults.enabledProtocols -virtualDirectoryDefaults.path -virtualDirectoryDefaults.physicalPath 网站的物理路径 -virtualDirectoryDefaults.userName 物理路径凭据的账户 -virtualDirectoryDefaults.password 物理路径凭据的密码 -virtualDirectoryDefaults.logonMethod -virtualDirectoryDefaults.allowSubDirConfig -[path=’string’].path -[path=’string’].applicationPool -[path=’string’].enabledProtocols -[path=’string’].virtualDirectoryDefaults.path -[path=’string’].virtualDirectoryDefaults.physicalPath -[path=’string’].virtualDirectoryDefaults.userName -[path=’string’].virtualDirectoryDefaults.password -[path=’string’].virtualDirectoryDefaults.logonMethod -[path=’string’].virtualDirectoryDefaults.allowSubDirConfig -[path=’string’].[path=’string’].path -[path=’string’].[path=’string’].physicalPath -[path=’string’].[path=’string’].userName -[path=’string’].[path=’string’].password -[path=’string’].[path=’string’].logonMethod -[path=’string’].[path=’string’].allowSubDirConfig 删除虚拟站点 APPCMD delete SITE [标识符] [-参数1:值1 …] 描叙: 从计算机删除指定的虚拟站点。必须提供准确的站点标识符,并且必须将该标识符解析为现有站点。 支持的参数: identifier (必需)要删除的站点的站点名称或 url /site.name 要删除的站点的站点名称或 url (与标识符相同) 示例: appcmd delete site "Default Web Site" 删除站点“Default Web Site”。 启动虚拟站点 APPCMD start SITE [标识符] [-参数1:值1 …] 启动指定的虚拟站点并启用该站点,以开始侦听其所有绑定端点上的新请求。必须提供准确的站点标识符,并且必须将该标识符解析为现有站点。 支持的参数: identifier (必需)要启动的站点的站点名称或 url /site.name 要启动的站点的站点名称或 url (与标识符相同) 示例: appcmd start site "Default Web Site" 启动站点“Default Web Site”。 停止虚拟站点 APPCMD stop SITE [标识符] [-参数1:值1 …] 停止指定的虚拟站点,阻止在其绑定端点上接收新请求。必须提供准确的站点标识符,并且 必须将该标识符解析为现有站点。 支持的参数: identifier (必需)要停止的站点的站点名称或 url /site.name 要停止的站点的站点名称或 url (与标识符相同) 示例: appcmd stop site "Default Web Site" 停止站点“Default Web Site”。 转自:http://blog.chinaunix.net/uid-20787846-id-3126923.html