.NET技术

收罗.NET相关的新闻,技巧,资料以及自己平时学习的笔记和经验总结等

C# HttpWebResponse下载限速

MitchellChu 2016-03-10 .NET技术

在使用HttpWebResponse请求网络内容的时候,一般如下面这种方法: // 非生产环境代码,请在实际使用时进行必要调整 // —— Mitchell Chu // Blog:blog.useasp.net HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); using(var response = (HttpWebResponse)request.GetResponse()) using(var stream = response.GetResponseStream()) { byte[] buffer = new byte[4096]; int read = 0; while((read = stream.Read(buffer, 0, buffer.Length)) >0){ // buffer... } }  使用这种方式,一旦我们开始下载数据,即是全速下载——即理论上是客户端和服务端的最小速度为当前下载速度。如果以这个速度持续下载,要不服务端被拖垮,要不就是客户端被服务端封禁。当然,一般情况下,后者居多。在持续的针对某站资源下载的时候,限速是非常必要的。 在HttpWebResponse里面限制下载速度比较简单,只需要控制读取的速度,即可达到限速的目的: // 非生产环境代码,请在实际使用时进行必要调整 // —— Mitchell Chu // Blog:blog.useasp.net HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); using(var response = (HttpWebResponse)request.GetResponse()) using(var stream = response.GetResponseStream()) { byte[] buffer = new byte[4096]; int read = 0; long total_read = 0; DateTime begin = DateTime.Now; TimeSpan ts...

BitConverter.IsLittleEndian在x86的机器上返回false

MitchellChu 2016-03-09 .NET技术 编程语言

在DEBUG写的.NET程序时,发现一个有趣的现象,就是本应该返回true的BitConverter.IsLittleEndian,返回的却是false!但在使用BitConverter之后,再次查看其值,却发现变成了正常的true状态。难道在X86的系统上存在两种状态? DEBUG的代码如下: ... // 前面没有使用BitConverter // DEBUG断点设置到这里的时候,可以看到是false的值 // BitConverter.IsLittleEndian // 如果使用BitConverter之后,得到的值却是true byte[] bdata = BitConverter.GetBytes(num); // 此时DEBUG中看到的是true. 但这明显不科学,首先BitConverter.IsLittleEndian在X86下应该是false,其次,不应该在一个系统内,同时出现true和false这两种状态。 抱着好奇的心态,翻开了源代码看了一下,看到如下代码: public static readonly bool IsLittleEndian = true; 赫然写着true啊!哪里来的false? 经过一番搜索,发现有这么一句: 通过调试器读取成员并不会触发执行成员的初始化代码。1 也就是说:通过调试器读取内存中的成员仅仅是读取到该对象的默认初始值而已。有这么一句话,解释起来就豁然开朗了。 为了验证这个说法的真实性,我们可以自己定义一个类来进行验证下: public static class DebuggerInitTester { public static bool BoolData = true; } 在DEBUG中我们可以看到,我们可以在没有调用前尝试获取到BoolData值,发现是true,并非是默认的false!这是什么情况,再仔细看了一遍代码,发现BitConverter里面有静态构造函数: static BitConverter() { // Note: this type is marked as 'beforefieldinit'. BitConverter.IsLittleEndian = true; } 在BitConverter中使用了静态的构造函数,而我们的并没有,看来问题在这里了,我们也改造下代码: static DebuggerInitTester() { DebuggerInitTester.BoolData = true; } 再次测试,确实,这个时候默认是false了。看起来问题就在这个静态构造函数了,原来不是一直听说static的是在加载前初始化了的么?看来并不是这个样子的,还是Too Young Too Simple! 看来是beforefieldinit引起的问题了(可参见Mitchell的另一篇关于BeforeFieldInit的文章) 如果没有BeforeFieldInit标记,则CLR会在第一次访问静态成员的时候调用静态构造函数对静态类中的字段进行初始化。比如,DebuggerInitTester这个类,我们定义了静态构造函数,因此将初始化BoolData的时机锁定了。 一切看起来是这样了,可再仔细看,又蒙了——压根就没有静态构造函数!BitConverter那个构造函数是自动生成的,是有BeforeFieldInit标记的。 .class public abstract auto ansi sealed beforefieldinit System.BitConverter extends System.Object { .custom instance void __DynamicallyInvokableAttribute::.ctor() = ( 01 00 00 00 ) } 根据BeforeFieldInit规则,也就是说BitConverter中IsLittleEndian的初始化会在访问前的任意时候完成,自然也可能会和有自定义静态构造函数那样在第一次访问的时候初始化,也许CLR对于BitConverter是这样处理。  如果能解释初始化时间点后,调试器读取成员不触发成员初始化代码倒是非常可以理解的,因为这样调试器的调试才安全可靠,不至于导致意外的发生(如:读取导致数据变化带来后继逻辑的)。   困惑 BitConverter由于使用了BeforeFieldInit标记,将初始化时机交给了CLR,也就是说这将导致IsLittleEndian初始化时间点不确定,很有可能就是在第一次访问的时候进行初始化的。 令人疑惑的是,为什么自定义的DebuggerInitTester类中的BoolData会那么快就完成了初始化呢?另外测试了好几次(其他类)均是非常早的完成初始化。 这里面到底是什么原因决定CLR来选择BeforeFieldInit标记过的类的初始化时机?    参考 Why does BitConverter.LittleEndian return false on my x86 machine? IsLittleEndian field...

C#的类型构造器和beforefieldinit标志

MitchellChu 2016-03-09 .NET技术 编程语言

首先让我们来看两个类型的定义: // 代码来自C# in Depth // 为了后继的讨论方便,对类名进行了更改(Test改为Test1和Test2) // —— Mitchell Chu class Test1 { static object o = new object(); } class Test2 { static object o; static Test2() { o = new object(); } } 这两个类,经常会被误认为是一样的,但实际情况是如何呢?让我们编译后,反编译后来看看他们产生的代码: // IL代码 // Test1和Test2在定义的时候出现了不同. // —— Mitchell Chu .class private auto ansi beforefieldinit ClassLibrary1.Test1 extends [mscorlib]System.Object { // Fields .field private static object o // Methods .method public hidebysig specialname rtspecialname instance...

VS清除打开项目时的TFS版本控制提示

MitchellChu 2015-12-15 .NET技术 其他技术

对于曾经做过TFS版本控制的项目,在版本控制服务不可用的时候,依然会在每次打开项目的时候都提示:当前项目是版本控制的项目,但是当前版本控制不可用,balabala的信息,如果是需要进行版本控制的项目在临时无法连接到版本控制服务器的时候出现这个提示,也属于正常的,但是如果是不再需要进行版本控制的项目,还这么次次打开都这么提示,就有些受不了——关键是,没有TFS,只能想办法删除了。 在项目中要永久清除TFS版本控制,需要操作三步(请确保操作之前没有在使用当前项目): 清除(删除)项目下的所有版本控制文件,这些文件有:*.vssscc,*.vspscc 删除这些版本控制文件比较简单,搜索这些后缀的文件,删除即可; 修改项目的解决方案文件:*.sln 先要确认解决方案文件(*.sln)是可修改的,如果是Read-Only的文件,则需要先调整为可修改。 切勿使用Visual Studio打开文件,使用文本编辑器打开*.sln文件,在文件中,我们将能看到类似下面的代码: GlobalSection(TeamFoundationVersionControl) = preSolution SccNumberOfProjects = 4 SccEnterpriseProvider = {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} SccTeamFoundationServer = here is your project's tfs SccLocalPath0 = . SccProjectUniqueName1 = project-unique-name1.csproj SccProjectName1 = your-project-name ...

log4net配置后不运行,没有日志输出

MitchellChu 2015-05-25 .NET技术

偷懒,新建项目中使用Nuget下载了log4net的配置文件(就那不带版本号的log4net.detail里面有说明是log4net xml),但设置好之后,log4net竟然奇葩的罢工了,没有任何报错。该配置方式是使用独立的log4net.xml文件来进行配置。 加载使用: var log4net_config = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location),"log4net.xml"); XmlConfigurator.Configure(new FileInfo(log4net_config));  检视过整个配置之后,发现这个Nuget来的配置文件有些地方出现纰漏: 其一是文件名称,log4net.xml并不是那么好用的,因为log4net自己也会生成一个同名的文件,如果顽固的使用xml文件,那么你需要配合第二点,并确保输出目录中的这个文件确实是配置文件,个人建议改成log4net.config更为妥当; 其二是项目中该文件属性,复制到输出目录需要设置成始终复制或较新复制,生成操作更应该不是无,请选择内容; 按照上面的修改配置文件之后,使用下面的代码加载后,log4net又活过来了。 var log4net_config = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location),"log4net.config"); // here is diff. XmlConfigurator.Configure(new FileInfo(log4net_config));  当然,为了简单,你也可以在AssemblyInfo.cs中使用: // 注意:是在AssemblyInfo.cs文件中添加 [assembly:log4net.Config.XmlConfigurator(ConfigFile="log4net.config",Watch=true)];  恩,就这样,log4net又能和我们一起愉快的玩耍了。  

获取本机系统内已经安装的浏览器列表

MitchellChu 2015-01-15 .NET技术 其他技术

最近突然碰到个比较棘手的问题,客户需要罗列出机器上所有可用的浏览器列表,至于作用么,就是让用户可以选择自己喜欢的浏览器来浏览指定信息。对于混杂的浏览器市场,这个需求确实够喝上一壶的了。 带着泪流满面的表情进入了无穷无尽的方案寻找中,不过到现在还是没有一个完满的答案。本文就记录下已经得到的一些信息吧。 对于一些标准的浏览器(有国内的么?自然是没有,谢谢),他们都会将自己的信息保存到StartMenuInternet这个注册表项下面,里面提供了丰富多彩的内容,基本上你想要的,他都能告诉你。需要注意的是,在64位系统中,会有两个位置可以找到。 HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Clients\StartMenuInternet HKEY_LOCAL_MACHINE\SOFTWARE\Clients\StartMenuInternet 上面这两个路径下,就包含了机器上所有的浏览器信息(再次排除国内浏览器)。如果是在32位系统中,只有后一个路径可以使用。 知道位置之后,在程序中要获取浏览器列表信息就比较简单了,参见以下C#(.NET)代码: public static void BrowsersData() { RegistryKey browsersKey; browsersKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\Clients\StartMenuInternet"); if (browsersKey == null) browsersKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Clients\StartMenuInternet"); using (browsersKey) ...

异常处理:必须使用适当的属性或方法修改此标头

MitchellChu 2013-09-03 .NET技术

在 .NET (v4.0)中,使用HttpWebRequest请求Web页面,当向HttpWebRequest的Headers的标头集合中添加Referer,Host这类HTTP标头(Header)时,会收到:System.ArgumentException: 必须使用适当的属性或方法修改此标头。这样的报错! 这个问题的引起在官方的说法是: 通常通过 WebRequest.Headers 或 WebResponse.Headers 访问 WebHeaderCollection 类。 某些公共标头被视为受限制的,它们或者直接由 API(如 Content-Type)公开,或者受到系统保护,不能被更改。 受限制的标头是: Accept Connection Content-Length Content-Type Date Expect Host If-Modified-Since Range Referer Transfer-Encoding User-Agent Proxy-Connection 要解决这个问题可以用以下这些方法: 方法一: 通过HttpWebRequest/HttpWebResponse对象的相应属性来设置这些表头 HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://blog.useasp.net/"); request.Host = "http://blog.useasp.net/"; request.Referer = "http://blog.useasp.net/tags/.net"; /* 你可以在这里设置其他限制的标头. 注意: Range HTTP标头是通过AddRange来添加 If-Modified-Since HTTP标头通过IfModifiedSince 属性设置 Accept由 Accept 属性设置。 Connection由 Connection 属性和 KeepAlive 属性设置。 Content-Length由 ContentLength 属性设置。 Content-Type由 ContentType 属性设置。 Expect由 Expect 属性设置。 Date由 Date属性设置,默认为系统的当前时间。 Host由系统设置为当前主机信息。 Referer由 Referer 属性设置。 Transfer-Encoding由 TransferEncoding 属性设置(SendChunked 属性必须为 true)。 User-Agent由 UserAgent 属性设置。 */ using((HttpWebResponse)response = (HttpWebResponse)request.GetResponse()) { // do something here too. by Mitchell Chu } 要将所有的这些受限HTTP标头在写程序的时候记住,还是有点难度的,我们更希望能够自动判定那些HTTP标头是可以直接添加的,哪些是需要特殊处理的。在WebHeaderCollection中有个方法IsRestricted正好是解决这个问题的。因此上面的代码可以改为将所有需要的标头添加到WebHeaderCollection,在为HttpWebRequest添加标头的时候,再使用IsRestricted来确定特殊处理与否。 foreach (string key in headers.AllKeys) { if...

流之间的拷贝方法

MitchellChu 2013-08-29 .NET技术

方法一:在 .NET 4.5以上,可以使用CopyToAsync方法来完成拷贝。该方法使用请参考:CopyToAsync方法 方法二:在.NET 4.0,可以直接使用Stream.CopyTo(stream)的方法。 // SourceStream 为要拷贝的流 // DestinationStream 为要拷贝流的目标 SourceStream.CopyTo(DestinationStream);  方法三:在.NET 3.5及以前的版本中,要在Stream和Stream之间拷贝,需要自己手动完成。 public static void CopyStream(Stream source, Stream destination) { byte[] buffer = new byte[4096]; //你也可以设置的更大一些 int read; while ((read = source.Read(buffer, 0, buffer.Length)) > 0) { destination.Write (buffer, 0, read); } }

HttpWebRequest请求中使用安全证书的方法

MitchellChu 2013-08-27 .NET技术

在 .NET 中,我们会使用HttpWebRequest或HttpWebResponse来发送一个客户端数字证书,具体的方法: 方法一:使用X509Certificate证书类读取数字证书文件 (*.cer),之后将证书附加到请求(SSL/TLS)当中去: public void GetResponseString(string uri) { try { X509Certificate Cert = X509Certificate.CreateFromCertFile("C:\\证书.cer"); //证书存放的绝对路径 ServicePointManager.CertificatePolicy = new CertPolicy(); //处理来自证书服务器的错误信息 HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(uri);//要访问的像https://要访问的地址/mitchellchu/test.aspx,要用SSL访问的地址 Request.ClientCertificates.Add(Cert); Request.UserAgent = "Mitchell Chu robot test"; // 使用的客户端,如果服务端没有要求可以随便填写 Request.Method = "GET"; // 请求的方式:POST/GET using(HttpWebResponse Response = (HttpWebResponse)Request.GetResponse()) //获取Response { using(StreamReader sr = new StreamReader(Response.GetResponseStream(), Encoding.Default)) { int count; char [] ReadBuf = new char[1024]; do { count = sr.Read(ReadBuf, 0, 1024); if (0 != count) { Console.WriteLine(new string(ReadBuf)); } }while(count > 0); } } } catch(Exception e) { Console.WriteLine(e.Message); } } class CertPolicy: ICertificatePolicy { public bool CheckValidationResult(ServicePoint srvPoint , X509Certificate certificate, WebRequest request, int certificateProblem) { // 你可以在这里加上证书检验的方法,错误值可以在WinError.h中获得 // 这里只是简单的返回true,任何证书都可以正常的使用。 return true; } }  优点:简单方便 缺点:需要证书文件,如果没有,需要先导出证书文件方可使用。   方法二: 使用 CryptoAPI 调用,之后获取证书集合,找到需要使用的证书,以X509Certificate对象形式返回,并附加在请求(HttpWebRequest 或HttpWebResponse)中发送证书。 /* 该案例来源于微软官方网站 @MitchellChu */ using System; using System.Net; using System.IO; using System.Text; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Runtime.InteropServices; namespace SelectClientCert { class MyCerts{ private static int CERT_STORE_PROV_SYSTEM = 10; private static int CERT_SYSTEM_STORE_CURRENT_USER = (1 << 16); ///private static int CERT_SYSTEM_STORE_LOCAL_MACHINE = (2...

.NET获取文件的MIME类型(Content Type)

MitchellChu 2013-08-23 .NET技术

获取文件的MIME类型有很多方法,闲话少絮,直接进入主题,下面是使用C#获取文件的MIME类型(Content Type)的各种方法。 第一种:这种获取MIME类型(Content Type)的方法需要在.NET 4.5之后才能够支持,但是非常简单。 MIME TYPE: // 需要先行引入System.Web // 之后可以直接使用MimeMapping类的静态方法获取文件的MIME类型 string file = @"mimetype.txt"; string contentType = MimeMapping.GetMimeMapping(file); Console.WriteLine("{0}'s MIME TYPE:{1}", file, contentType); // Console output: /* mimetype.txt's Mime Type: text/plain */ 优点:方便快捷 缺点:只能在.NET 4.5之后使用 如果没有的MIME TYPE将会返回: application/octet-stream   第二种:直接在系统中通过文件的后缀获取文件的Content Type   // 自定义一个方法 // 通过系统中的Content Type来获取MIME TYPE public static string GetMimeType(string fileName) { string mimeType = "application/unknown"; string ext = Path.GetExtension(fileName).ToLower(); RegistryKey regKey = Registry.ClassesRoot.OpenSubKey(ext); if (regKey != null && regKey.GetValue("Content Type") != null){ mimeType = regKey.GetValue("Content Type").ToString(); } return mimeType; }  优点: 1. 直接快速 2. 没有.NET的版本限制; 缺点: 1. 需要有访问注册表的权限; 2. 获取的Content Type范围受系统环境约束。 这个方法在没有找到对应的MIME Type时,返回的是application/unknow,当然,你也可以自己定义其他任何返回值。   第三种: 自己动手写代码,将MimeType写成Mapping类,需要的时候直接使用。 // 通过自己定义一个静态类 // 将所有的Content Type都扔进去吧 // 调用的时候直接调用静态方法即可。 public static class MimeMapping { ...

多种.NET下禁用或启用Windows网卡的方法讨论

MitchellChu 2013-06-17 .NET技术

  查资料查的好辛苦啊,还好,找好了。这不,又要来当回『孔乙己』了,孔老湿当年是非常喜欢研究『茴』字的多种写法的,我呢也比较喜欢研究程序中各个功能的多种实现方法的。咳咳……嗯…… 这个Windows下禁用/启用网卡是有很多种方法滴,你知道这个禁用/启用网卡有几种方法呢,在.NET怎么写么?话说,我就是这么把自己套进去了,不过话说回来,还真给找到有好几种方法可以实现这个禁用/启用网卡的功能,不过实现方法却并不是每种都能够在你的机器下运行起来的。让我们来看看吧。   首先,第一种方法,网站上流传还是比较广的,中文内容到处非常多贴着这个代码来讨论如何禁用/启用网卡的。这么悬乎,是什么方法?查查:C# 启用或禁用网卡,应该出镜率不是第一就是第二了吧,Here we go, 上代码: /* * blog.useasp.net * MitchellChu's Blog * 网卡的禁用/启用方法 * * 要在项目中使用此方法,你必须添加对Shell32的引用。 * enable: 是bool值,表示网卡的启用或禁用,false 禁用 * networkConnectionName:网卡显示的名称,一般是:本地连接,本地连接 2这样的。 */ public static bool ChangeNetworkConnectionStatus(bool enable, string networkConnectionName) { const string discVerb = "停用(&B)"; // "停用(&B)"; const string connVerb = "启用(&A)"; // "启用(&A)"; const string network = "网络连接"; //"网络连接"; string sVerb = enable ? connVerb : discVerb; Shell sh = new Shell(); //Shell32.Shell() Folder folder = sh.NameSpace(Shell32.ShellSpecialFolderConstants.ssfCONTROLS); try { //进入控制面板的所有选项 ...

WMI中的SQL,WQL简明教程系列5:工具,命名空间,路径

MitchellChu 2013-06-17 .NET技术 其他技术 编程语言

  WMI的WQL简明教程系列的前四篇文章[1,2,3,4]完全介绍WQL的各个基本知识,相信对于WMI的WQL的开发来说,这些知识已经足够我们步入WMI的世界,并能准确的驾驭WQL中的各个使用细节了。这些掌控的所有细节,自然只有在实战中进行发挥,才能体现我们学习WMI的WQL的作用。在实际中使用,我们还需要一些辅助的工具来进行开发。WMI的基本知识就像是武功修练中的内功心法,我们练得非常的醇厚,自然可以徒手独步武林,但在我们还没有练到随心所欲,化腐朽为神奇的境界,选择个武器共创天地也不失是个好主意,同样的道理,在全然彻底的了解WMI中的方方面面的时候,工具神码都是浮云,而在我们未能做到这个之前,选择一些工具来帮助我们就显得非常重要了。   由于MitchellChu也是初涉WMI不久,在WMI中的工具可能涉及不够全面,因此如果有不正确的地方,请各位不吝赐教。下面是用过的一些工具,以表格方式放出: 工具名称 描述 ...

WMI中的SQL,WQL简明教程系列4:语法

MitchellChu 2013-06-16 .NET技术 其他技术 编程语言

  WMI的WQL简明教程系列的前三篇文章[1,2,3]分别介绍WQL中的关键字,运算符和WMI中的类,由这三个东西,理论上已经能够完成WQL语句的编写了,不过也仅是理论上。就好比盖房子,理论上有水泥,钢筋和砖头是可以盖的,但实际上,并不是一定能盖出好房子的,甚至房子盖不成的也有,要盖好房子,还需要一个设计图纸,相对应的,咱们的WQL也同样,只有了一些基础的配件,有的时候并不一定能够装配出能正常运行的WQL语句。为了能够让我们能够组装出能够运行的WQL语句,就需要WQL的设计图纸——语法。   从WQL关键字篇我们能够看到,WQL并没有UPDATE,INSERT这类SQL中的语句,因此我们能够想象的到,WMI的WQL最主要的功能就是为了查询系统数据,因此我们学习WQL语法的时候,首先只要能够了解到查询数据的语法,基本上就能够应付大部分情况了,怎么样,还是相当的简单吧?那让我们开始吧,先看看下面的WQL: SELECT * FROM Device WHERE __CLASS = "Modem" OR __CLASS = "Keyboard"   从上面的语句中我们能够看到WQL的基本语法结构,其和SQL语法类似,但WQL中多处了ASSOCIATORS OF和 REFERENCES OF两个查询结构,具体的WQL查询分为Schema,Data和Event查询,他们的区别: 数据查询:用于获取类实例,它返回特定类的所有实例,包括各自的请求属性集 Schema查询:获取类定义,使用的基本语法的形式与其他类型的查询一样 事件查询:用于过滤出一个特定事件通知的属性。事件表征被管理环境的变更。 每个查询允许添加一些附加的操作符,如: WITHIN:指定轮询 GROUP:分组相同的事件 HAVING:过滤WITHIN和GROUP子句收集事件的通知。一般与NumberofEvents属性(收集事件数量)一起。这样可以侦测何时特定事件的数量超过了时间间隔中设置的极限。 下面是Schema和Data查询的语法结构: ; ----------------------------------- ; http://blog.useasp.net/ ; MitchellChu's Blog ; WQL tutorial ; WQL schema and data 查询的语法结构 ; ----------------------------------- DATA-WQL = ("SELECT" <PROPERTY-LIST> "FROM" <CLASS-NAME> <OPTIONAL-SEL-WHERE>)/ ("SELECT" ASTERISK "FROM" <CLASS-NAME> <OPTIONAL-SEL-WHERE>)/ ("SELECT" ASTERISK "FROM META_CLASS" <OPTIONAL-META-WHERE>)/ ("ASSOCIATORS OF {" <OBJECT-REL-PATH> "}" <OPTIONAL-ASSOC-WHERE>)/ ("REFERENCES OF {" <OBJECT-REL-PATH> "}" <OPTIONAL-REF-WHERE>) ;======================================== ; PROPERTY-LIST:属性列表 ; 属性列表有属性名组成,多个属性名使用逗号分隔 ; 如果奥全部选择,可以直接使用*(星号)代替 ;======================================== PROPERTY-LIST = <PROPERTY-NAME> <PROPERTY-LIST2> PROPERTY-LIST2 = [COMMA...

WMI中的SQL,WQL简明教程系列3:类

MitchellChu 2013-06-15 .NET技术 其他技术 编程语言

  系列1和系列2两篇文章比较简单的介绍了下WMI中WQL的关键字和运算符,有这两样东西我们就能够按照WQL的语法规则来写WQL语句了,等等,我们的WQL要操作的是什么?没错,我们会发现,在WQL语句中还缺少一个要操作的对象,这就是本文要说的,WMI中最重要的一个组成部分——类。用过SQL语句的都应该清楚,无论是在MS SQL 还是MySQL中,我们如果要从数据库中查询数据,必须需要在SQL语句中指定查询的对象——表。在WQL中类的作用就相当于表,我们需要的数据会在不同的类中,而要将数据取出来,就要去找到各种对应的类。   如果我们把WQL比作SQL的话,WMI你就可以粗略的看作是数据库了,而WMI中的类,就是数据库中的表了,而类中返回的各种实例对象,可看作是表中的数据了。这个类比不完全正确,当深入会发现,每当要查询数据的时候,我们需要连接到指定的命名空间下,连接成功后,才能进行类的操作。现在暂时不去细究,初步有个概念就好,等具体操作的时候我们就能够明白了。   那么,在WMI中,我们有多少类可以供WQL查询呢?这个Mitchell倒是没有具体去统计数字,但在普通的操作中,能够涉及到的却并不是十分的多,我们可以用表格的形式列出在Win32下面比较常用的一些类。表格如下: 类名 描述 Win32_Fan 系统风扇 ...

WMI中的SQL,WQL简明教程系列2:运算符

MitchellChu 2013-06-15 .NET技术 其他技术 编程语言

  系列1中我们已经介绍了WMI的查询语言WQL中的关键字,相信在看完关键字之后,对于WQL的语句肯定不会那么陌生了,然而,有了关键字,自然还是不够的,至少在使用WHEE子句的时候,我们需要用到一些条件不是,而这些条件自然而然的就需要使用到本文说到的东西——运算符。虽然可以看作是SQL的一个子集,但是关键字会有些不同(前面已经有说过),运算符也会有些诧异。那么让我们看看在WQL中有哪些运算符。   既然WQL是SQL的一个自己,可以预见的是WQL中的运算符和SQL中的运算符应该差别也不是很大,在前面将关键字的时候,我们给出的WQL语句中就有部分运算符在使用了,而在关键字列表中,我们也给出了部分的运算符。先给个例子: SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE   在上面例子中我们在WHERE子句中就使用了=运算符,TRUE运算符。进入主题,WQL的基本运算符有以下这些: WQL运算符 WQL运算符描述 使用类型 = 等于 ...

WMI中的SQL,WQL简明教程系列1:关键字

MitchellChu 2013-06-15 .NET技术 其他技术 编程语言

  WMI(Windows Management Instrumentation, Windows 管理规范)是一项核心的 Windows 管理技术;用户可以使用 WMI 管理本地和远程计算机。WMI 通过编程和脚本语言为日常管理提供了一条连续一致的途径。而要在编程或者脚本语言中使用WMI,那自然不可或缺的就是WMI的查询语言(WQL,WMI Query Language),WQL是在美国国家标准研究所结构查询语言(ANSI SQL)的一个子集,并在此基础上作出稍许语义变化。WQL非常类似与通常使用的SQL语句,却没有SQL语句那么的复杂多变,算起来也可以说只是SQL语句的一个小子集。   要了解和使用WQL,WQL中使用的关键字是不可或缺的一环,像下面这些语句,你了解多少呢? SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True SELECT * FROM Meta_Class WHERE __Class LIKE "%Win32%" ASSOCIATORS OF {Win32_LogicalDisk.DeviceID="C:"} WHERE RequiredQualifier = Locale 看不懂? 没关系,本文就是本着看懂WQL语句的目的而来的。下面这个表格就是WQL会用到的关键字列表,而且后面还有对关键字的解释,相信你在看完MitchellChu整理翻译的这张表之后,上面这些语句应该不在话下了——至少知道他们大概是干什么的了。 WQL 关键字 关键字解释 AND ...

程序侦测当前网络连通性的各种实现

MitchellChu 2013-06-14 .NET技术

  在实际的应用开发中,我们的应用程序经常需要在运行时侦测当前系统的网络连通性,特别是在应用程序需要访问网络的时候,可以通过运行时的侦测网络连通性,及时反馈给用户,以便用户做出正确的选择;也可以在得到侦测结果后,系统根据网络的连通性状态做出相应的处理,比如在需要网络访问才能正常使用的应用程序中,一旦检测到网络不能正常使用之后,做出相应的处理,可以更好的防止不必要错误异常发生。当前系统.NET进行网络的连通性侦测有很多种方法,本文将使用.NET(C#/VB)代码展示多种具有代表性且比较简易的方法来检测网络的连通性。 第一种方法:使用WebRequest/HttpWebRequest对象来访问指定的主机名。代码如下: //通过访问网页的方式确定当前系统的连通性 //需要注意,选择的主机名/域名必须确保异常的可能性尽可能小 public bool HttpRequestMonitor(string host) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host); request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36"; request.Method = "GET"; try { using (HttpWebResponse response = ((HttpWebResponse)request.GetResponse())) { return true; } } catch (Exception ex) { ...

.NET正则表达式提取HTML元素所有属性的方法

MitchellChu 2013-06-14 .NET技术 HTML&HTML5

  在各类文本处理中,往往要涉及到在文本中提取数据、替换数据的操作,这种情况下,我们一般使用正则表达式系统来简化我们的处理(一般没谁会自己写吧?写了效率也不一定高啊)。同样,在涉及到HTML的一些处理中,个人也非常喜欢使用正则表达式系统来进行HTML元素内容的替换、提取等操作,HTML也是文本嘛。   随着使用的频次增多,对正则表达式系统的了解自然也就不断深入,在后来的一次,突然发现,正则表达式原来可以提取HTML元素(标签)中的所有属性,甚至 可以直接将HTML解析成DOM树。面对突如其来的强大功能,一时间还真有些不知所措,要知道,在之前,解析HTML咱是靠第三方工具的。正则表达式最多也就是提取下特定的字串内容,替换下内容,像对于提取HTML元素中多个属性的方法想都没想能用正则表达式,而是毫不犹豫的将元素提取出来后老老实实的去做字串处理,要不就是使用第三方的插件来完成这无比艰巨的工作。现在发现正则表达式竟然可以如此简单的完成,太惊喜了!   为了展现正则表达式的强大功能,让我们赶紧找个例子来试试吧——用正则表达式提取HTML标签(元素)中所有的属性。   输入内容:任意HTML源码   要求:提取指定元素的所有属性   输出内容:指定HTML元素的所有属性   来看看正则表达式是怎么完成的,代码: // 注意:本例仅为测试用,投入到生产环境中需要根据需求进行调整 // 测试结果相当的不理想:解析64KB数据,10个匹配项,耗时99s public static IList<IDictionary<string,string>> ParseHtml(string html) { IList<IDictionary<string, string>> tags = new List<IDictionary<string, string>>(); //MitchellChu .NET Blog // 首先定义下正则表达式 Regex regexParser = new Regex("<img(?:\\s*([\\w\\-]+)(?:\\s*=\\s*(?<qouta>['\"]?)([^'\"]*)\\k<qouta>)?\\s*)*>", RegexOptions.IgnoreCase); // 这里注意 ...

VisualStudio使用IIS调试出错的处理方法

MitchellChu 2013-06-14 .NET技术 其他技术

  在Visual Studio 2008/2010中,当网站需要进行web调试的时候,我们一般都是直接使用VS自带的Server进行调试,也就是直接F5就解决了问题,但并不是所有的问题都能在这种问题下解决,因此我们有的时候需要使用IIS作为Web Server来进行调试。使用IIS作为宿主的时候,很有可能不会像使用VS自带的Web Server调试来的顺利,而我最近的一次调试中就出现下面这个报错: 英文报错:Unable to start debugging on the web server.An authentication error occured while communicating with the web server. 中文报错:无法在WEB服务器上启动调试。   当然,也可能出现其他的错误,经过摸索,问题解决了,在网上也看到有很多人在使用IIS6/7进行调试的时候出现不能调试的情况,为了让有同样的问题朋友们能够有一个更简单的处理方式,我将可能出现问题的地方做了个初步汇编,如果出现不能使用IIS来调试Web程序时,可以按照这个步骤来检查下开发机器上的配置是否正确。 No1. IIS配置检查   要使用IIS来调试网站,自然要在IIS中配置好网站,具体的配置请参见IIS新建网站的配置说明,这里不赘述。为了保证网站能够正常运行,你可能需要关注网站的权限问题。在网站能够正常运行的情况下,却无法使用Visual Studio进行Web Debugging的时候,请检查下面配置: 网站配置项中,网站标签下的连接是否启用了保持HTTP连接项,IIS6的操作路径: IIS6管理器中右键当前调试网站--属性--网站--连接--保持HTTP连接  检查是否启用Windows身份验证。IIS6路径: IIS6管理器中右键当前调试网站--属性--目录安全--身份验证和访问控制--编辑--用户访问需经过身份验证--集成Windows身份验证 如果是ASP这样的网站也许你要启用在服务端进行ASP调试的选项,路径为:  IIS6管理器中右键当前调试网站--属性--主目录--应用程序设置--配置...--调试--调试标志--启用ASP服务器端脚本调试 && 启用ASP客户端脚本调试 启用IIS中ASP.NET的调试项,这项也可以从web.config中设置,路径为: IIS6管理器中右键当前调试网站--属性--ASP.NET--Edit Configuration(编辑配置)--应用程序--公共编译、页和运行时设置--勾选:启用调试--确定 如果你是IIS7,可以尝试启用IIS7中的Class .NET AppPool,经典的.NET应用程序池,路径: 当前调试站点--高级设置--应用程序池--Class .NET AppPool(经典模式) 上述问题配置配置如果设置之后,还是无法正常使用IIS调试VS中的Web程序,那么你可能还需要检查。 No2. 注册表配置检查[1] 禁用环回检查,将DisableLoopbackCheck 注册表项值置为1,Mitchell自己在Windows2003的问题就是这个方法解决的,注册表路径: 开始--运行--输入:regedit--确定--路由到下面路径: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa --右键:Lsa--新建--DWORD值--键入:DisableLoopbackCheck--右键:DisableLoopbackCheck--修改--数值数据框输入:1--确定。 ##注意: 操作后如果无法直接生效,可能需要重启系统。 ...

IIS6 404自定义错误页面带来乱码的处理方法

MitchellChu 2013-06-01 .NET技术 其他技术

  ASP.NET MVC在IIS6上绝少出现因为文件编码问题而导致的乱码问题,即使出现,也可以通过web.config的配置或者修改文件编码来解决,然而今天碰到的这例乱码问题,却无法使用这些方法来解决,无论怎么修改,乱码依旧。让人懊恼不已!   问题是这样的:ASP.NET MVC2在IIS6上进行部署,由于系统还有一些暂时未能完全使用MVC架构的代码存在,就利用了IIS6中自定义错误页面的URL重定向机制,将404错误页面转发回系统页面进行处理,在系统中进行判定页面是否不存在或者重新配置页面地址重定向,让MVC Routing能够进行处理。想法是不错的,处理英文的时候也是非常顺畅的,但碰到中文的时候,系统就情不自禁的抽起疯来,根本就无法达到预期的效果。—— 一查,参数未解码的时候中文编码都是%ufffd,一解码全是乱码,能达到预期效果反而奇怪了!   开始以为是配置上问题,检查了下config文件,发现request和response的Encoding都是UTF8,进而检查文件编码,也是UTF8,这和配置中的编码一致。理论上这样乱码应该不存在的,但理论往往和实际相差甚远!只好进一步检查,在历尽千辛万苦,最后发现问题原来出现在IIS的URL重定向上。当访问一个不存在的页面(含中文参数),IIS6会触发404错误,并将产生错误的内容重定向到指定的URL上,目标页面获取参数信息,但在处理中文时,需要进行解码,但根据IIS6定向过来的内容解码就会出现乱码,这就导致组合后的新地址经过MVC 路由后,无法正确的加载指定功能 —— 参数不对。   以前我一直的说法是找到问题就是成功解决问题的关键,这话的确没错,接下来要解决它,只需要找到为什么IIS6传递过来的内容会出现解码错误即可。然而,随着进一步的检查发现,问题远没有想象的那么简单,IIS6.0在处理字串的时候默认使用的是Unicode编码(注:这里比较乱,有说GBK,也有说GB2312,还有说是ASCII,谁知道请告诉我,IIS6使用的默认编码是什么?这里用Unicode)。这个编码和我们有什么关系么?—— 我现在是没有想出具体的关系的,但是肯定是有关系的。以下为本人观点,猜测成分比较大,如果你有更详细的这方面资料请分享,将非常感激。   在我们站点都使用UTF8的时候—— 这里我们需要补充个基础知识,UTF8的字符集是明显大于Unicode编码的。当IIS6检测到错误的时候,需要将UTF8转为IIS6的编码,并进行封装再转交给我们站点内处理,由于IIS6使用的是Unicode编码,在将UTF8字串转为Unicode时,因为字符集不够,所以出现无法转换现象,在无法转换是,系统用%ufffd来表示未能转换的字符。因此使用Unicode处理数据,再转交给站点内模块,程序设置为UTF8编码,UTF8去解码Unicode编码字串,结果可想而知,解码出来的中文自然而然就是乱码。这个思路大概用下面的图来概括(注:图中用的是GBK表示) 这个图片描述的可能有误,但迄今为止尝试了很多各种编码的组合方式,都没有很好的将中文转成在程序中获取到的那种样子,所以也不能确定到底IIS6使用的是什么东西。   解决方法网上有提供一些,但他们能真正的解决问题吗?   1. 最多人的建议是使用UrlEncode方法将所有的中文进行编码之后传到服务端。   但这种方法对于自定义错误页面的方法根本就无法解决。IIS6同样会将URL中的中文变成乱码。   2. 另一种比较多的方法是在BeginRequest事件中处理,用Encoding去尝试转码来解决编码问题。   个人认为这个方法也没能真正解决问题,因为我们一旦获取到的是%ufffd这种的参数时,就意味着我们的参数已经出现问题了。再说,这个方法和前一种方法一样,真正错误的是在IIS6中的自定错误页面过来的参数,在这之前已经出现错误,后面怎么弥补都无济于事。   调试可以发现,在Request对象中,虽然QueryString,Url中的所有的都是乱码,但是RawUrl是正常的。如下图:   经过多次的测试发现,如果要比较好的解决这个问题,可以使用以下两种方法:   1. 如果真的要在BeginRequest中处理乱码——当然,你也可以在你需要获取参数的时候进行处理,使用RawUrl。因为只有这个参数能够完整的保留中文信息。   2. 对当前处理逻辑调整,直接处理掉可以处理的页面内容,而不要依赖IIS6的自定义错误页面来解决在程序中原本是非错误的页面,比如:数据库中页面,先要进行404跳转之后,再进入指定页面再来处理,这种处理方式比较闹心,但当下却还是有一些在用,我这篇文章就是这么来的。    当然了,上面的建议都是理想状态的,对于现存的项目来说,要实现不是一时半会,还需要仔细斟酌。针对我当前特定版本的解决方法,项目是MVC的,直接在Route中添加了对应规则,让这些都转入指定的模块中"销毁"吧,这和上述第二点原理一样,但却治不了根。    根据网上的一些信息综合起来看,这个问题应该是出自IIS6内部,不仅是中文,就连很多国际友人在做开发的时候也碰到过各种各样的Unicode Problem。有些反馈是说在IIS7下面没有这种现象,这个我没有测试,如果哪位有条件的可以测试下。     问题暂时解决了,可以先休息会,毕竟这个问题折腾了我好几天啊!   参考: CSDN 设置404页面所导致的乱码问题的帖子: http://bbs.csdn.net/topics/390358009 IIS.NET上面关于Unicode字符丢失的帖子:http://forums.iis.net/t/1085091.aspx/1  

关于博主

  一枚成分复杂的网络IT分子,属于互联网行业分类中的杂牌军。