# Monday, July 07, 2008

    近期在对一些客户做技术培训的时候,发现了一个问题。一些我们平常天天在用的软件工具,比如:Windows、Office、SQL Server、Visual Studio等等,很多都没有得到用户较充分的使用。很多已经被软件厂商早已攻克的问题,却在用户那里在被重复研究解决方案,原因为什么?因为用户根本不知道原来这个每天都在用的软件工具还有这样或那样的功能,可以解决我们目前所碰到的问题。比如说:

  • Excel就已经可以轻松解决家庭的收支结算问题,有人却偏偏要安装什么管家婆或者形形色色的所谓家庭财务管理软件,甚至还要求你安装个sql server呢。难道你只把excel当作一个普通表格使用吗?
  • 不少人抱怨Word排版很差,对文章分层次时,要手工敲入那些“第一、第二”或者“1)、2)”等,为什么不用编号功能呢?
  • sql server 2005 有个“数据库引擎优化顾问”,可以在一定程度上帮助优化数据库,而对应于sql 2000中也存在“索引优化向导”,而他们都依赖于sql profile,另外数据库有执行计划等一系列分析优化的工具,为什么连这些都没用过就问人索要什么优化工具呢?
  • Windows自身就带有磁盘清理等系统优化工具,为啥你只为了清理一下系统盘的空间,却要安装“超级**”或是“**优化大师”呢?

    上述都只是一些简单的例子,但在相当多用户中存在类似的问题,而在软件开发人员中问题依然不少见。问题出在哪里,用户自身是问题之一,而作为软件提供商来说,是否应该考虑一下自身的问题,是否应该下一下功夫对用户进行培训教育呢?UI是否可以设计的再合理一些,让用户更直接的了解到软件的已有功能呢?

     正如某些分析师说的:“微软的Windows、Word和Excel等产品中功能丰富,但消费者却并不完全了解.其结果就是,消费者耗费大量的时间来解决一些微软产品已经攻克的问题.因此,鲍尔默应该在该领域投入一笔资金,以帮助用户了解微软产品的功能”。个人认为这样这个问题不光是微软应该考虑的问题,IBM、Oracle以及我们国内的金山等软件企业是否也应该思考呢?共享软件作者亦应如此。

posted on Monday, July 07, 2008 5:22:05 PM (China Standard Time, UTC+08:00)  #    Comments [0]
# Thursday, January 31, 2008

在C#中有个较为重要,而常被一些人忽视的符号——问号(?)。在这里整理一下它在C#的几种情况:

  1. 可空类型修饰符“T?”:可空类型的基础类型可以是任何非可空值类型或任何具有struct约束的类型参数,但不能是可空类型或引用类型。例如:int?代表是可空的整形,而int??则是无效类型。即可空类型可以表示其基础类型的所有值和一个额外的空值。语法T?是System.Nullable<T>的缩写形式。可空类型具有一个HasValue的bool类型只读属性,当可空类型实例的该属性为true时,则表示该实例是非空实例,包含一个已知值Value;HasValue为false时,访问Value属性将导致System.InvalidOperationException。可空类型T?具有一个类型为T的单个参数的公共构造函数,如new int?(123)将获得一个值为123的int?类型实例。从T?到由T实现的任何接口都存在装箱转换,并且从由T实现的任何接口都存在到T?的拆箱转换。但是任何情况下可空类型都不满足接口约束,即使基础类型实现了该特定接口
  2. 条件运算符“x ? y : z” : “x ? y : z”的意思大部分程序员应该都熟悉,稍微啰嗦一下:) 如果表达式x为true,则计算y;如果x为false,则计算z。省却if{}else{}的简单形式了。
  3. 空合并运算符“??”:该运算符是在泛型出现后,C#词法语法中新增加的标记,同时出现的还有一个“::”(命名空间别名限定符)。形式为“a??b”的空合并表达式要求a为可空类型或引用类型。如果a为非空则表达式“a??b”返回的结果为a;否则返回b。空合并运算符为结合运算符,即操作时从右向左进行组合的。如,“a??b??c”的形式按“a??(bb??cc)”计算。

曾有人说过“细节决定胜负”,我们程序员应该更好的把握编程语言的细节才能更好的保证软件质量。

特此整理存档:D

posted on Thursday, January 31, 2008 4:31:34 PM (China Standard Time, UTC+08:00)  #    Comments [0]
# Tuesday, November 27, 2007

在一些网站或者软件系统中,由于安全或者程序异常等问题,可能会在SQL Server 2000中造成一个异常问题:在企业管理器中打开数据库发现有一些“坏表”,即无法使用,也无法正常删除。其原因往往是因为在尝试建表的过程中,只向数据库服务器的系统表sysobjects中写入了类型为“U”的记录,却并未真正在数据库中成功创建该表的实体。ok,解决问题有思路了:

假设“坏表”的表名为cmd,那么我们在查询分析器中对当前的数据库写一个sql语句:

delete from sysobjects where [name]='cmd' and xtype='U'

按F5执行,可能会碰到一个错误提示:“未启用对系统目录的特殊更新。系统管理员必须重新配置 SQL Server 以允许这种操作。” 解决这个小小的问题的方法是:打开mssql server 属性---》服务器选项----》启用对系统目录的特殊更新(允许对系统目录进行直接修改)  即可。之后重新在查询分析器中执行刚才的sql语句。

执行成功后。在企业管理器中会发现那个坏表已经不存在了。

[ 注:SQL2005中,由于微软做了重大调整,正常情况下不允许对系统表进行即席更新操作。所以本文提到的问题目前仅适用于SQL2000数据库,敬请注意 ]

posted on Tuesday, November 27, 2007 11:35:54 PM (China Standard Time, UTC+08:00)  #    Comments [0]
# Friday, October 19, 2007

youku0.3     近日党的十七大召开,而我没有电视看,就喜欢到优酷网上看看别人上传的相关视频,部分视频希望能在机器上有所保留,但优酷自己并不提供文件的下载功能。找了个维棠FLV视频下载软件,却发现它无法完整下载较长的优酷视频,我稍作了原因分析后,发现是优酷的一些较长的视频是采用多文件连播的方式,也就是一个视频由多个文件共同组成,于是乎自己花了一大袋烟的工夫用c#写了这个小工具,直接将视频所在的网页地址复制到该软件的指定位置,然后点击“Go!”按钮就开始下载了,哈哈……
    鉴于支持和促进和谐社会发展,俺也把这个自写小工具共享出来给朋友们使用。由于时间仓促,有一些不完善的地方敬请原谅,抽空俺也会继续更新这个小工具的:D

声明:本软件仅因个人爱好而开发,跟优酷网无任何关系:)

名     称:优荡
当前版本:0.5
环     境:Windows ,Microsoft .NET Framework 2.0
作     者:衣明志(网名:qihangnet)
最近更新:
             2007年10月19日(0.5.0.0版):
                          代码进行进一步优化
                          加快了视频分析速度
                          显示视频文件总大小
                          显示当前已下载文件文件大小
                          显示下载总进度的进度条
                          添加了单视频的多文件自动合并功能(一些视频优酷使用多文件存储的,本软件下载后将同一视频的多文件进行的无缝合并,并随后删除原始文件)
                          修复了多项小Bug
             2007年10月17日(0.3.0.1版):
                          修复了2个界面上的小bug
下载地址:http://www.qihangnet.com/content/binary/YouDown.exe

posted on Friday, October 19, 2007 1:52:30 AM (China Standard Time, UTC+08:00)  #    Comments [3]
# Tuesday, October 09, 2007

Micorosoft Visual Web Developer 2005 Express Edition:立即构建网站    时代在进步,社会在发展,IT技术则以更快的速度成长着。IT人需要不断的学习才能使得自己处于不败之地,而想踏入这个行业的学生和IT技术爱好者们更希望以最快的速度踏上这趟“动车”,占据有利位置。而在SaaS(Software-as-a-service 软件即服务)甚至S+S(Software + service 软件加服务)概念被不断被赋予新意的今天,Web技术变成了超热门。从微软的.Net诞生那天开始,asp.net技术就以它超群的表现冲击着web领域,尤其是asp.net 2.0。那么对一个asp.net2.0的新手而言,一个可以带领自己快速入门的工具是必要的,而Visual Web Developer 2005 Express Edition就是这工具!
    记得在2005年的微软Tech.Ed大会上,我在王洪超主持的“微软技术聊斋”会议中,提出了加大对高校学生及编程爱好者市场的力度方面的建议后获得“最佳建议奖”时,心里暗暗替学生们和编程爱好者们高兴。学生本来就是个高消费群体,那里买得起价格昂贵的商业版VS套件,更何况很多学生的电脑配置并不是很高的,运行那些高级版本的开发环境,未必会有真正好的体验,即使运行良好,作为新手看着庞大的界面和超大量的功能会有找不到北的感觉,失去学习的积极性。再者,若我们平常做的都是一些小型的开发,用庞大的商业版VS套件,总有一种炮打蚊子的感觉。微软推出2005版的Express Edition系列工具后,这些问题全都解决了:免费、小巧、功能完整——这正是我们需要的!Visual Web Developer 2005 Express Edition是微软Visual Studio 2005套件的一个功能完整的子集开发软件。它是为初学者、编程爱好者和学生量身定制的新型开发环境,内置完备的开发套件,可以帮助您快速上手Web应用开发;通过所见即所得的拖拽界面就可以创建出美观、易用的网站;内置60余种控件、上百段代码片断,可以帮助您大幅度降低创建互动式Web应用的时间;支持页面模板,从而使您可以统一的管理网页的排版与布局;通过IntelliSense,可以更快的访问资源库和方法;只需一下点击,就可以通过Common Tasks 和 Smart Tags 调用最常用的Web开发功能。它可伴跟随用户共同成长,随着用户对开发需求的不断增加,只需要在Visual Studio产品线中升级到更高一级产品即可。
    《Microsoft Visual Web Developer 2005 Express Edition:立即构建网站》是微软送给asp.net技术爱好者的又一惊喜,它几乎告诉了你Microsoft Visual Web Developer 2005 Express Edition的全部功能和asp.net 2.0技术的全部特性,让你在鼠标拖拽和键盘敲击中享受web开发的乐趣。这本书是由美国的Jim Buyens编著,微软出版社出版,在中国又由上海世界图书出版公司重印发行的不错的工具类图书。该书继承了微软出版社图书的优良传统,思路清晰,言语简洁到位,配图准确清晰,并非常详细了罗列了一些重要功能的优缺点、注意事项和提示信息,是我个人非常喜欢的风格。
    全书分为16章,每章基本都有2-5个主要的小节组成。从工具的简介、安装、用户界面的熟悉到创建网站站点,从拖拽现成控件、编写代码到创建用户控件、网页模板、皮肤,从界面表现到数据处理,都在关键点上有清晰的陈述。读者可以从第一章开始一步步走进asp.net技术的殿堂,也可以直接阅读自己喜欢的章节,学习某方面的web技术技能,不断提高自己的web技术能力。推荐初学者、编程爱好者和学生阅读该书学习。
    正所谓“师傅领进门,修行在个人”,书籍是良师益友,但起决定作用的往往在于自己。阅读什么书都应该保持良好的心态,多实践多思考。Web技术博大精深,但基础表现的也由为重要,所以建议新手们在想进一步发展自己之前,学好html、css、js等基础技术,而借助于Microsoft Visual Web Developer 2005 Express Edition会增快您学习web基础内容的进度。正如书名上写的“Build a Web Site”立即构建网站吧!

posted on Tuesday, October 09, 2007 8:18:45 AM (China Standard Time, UTC+08:00)  #    Comments [0]
# Wednesday, June 13, 2007

asp.net 2.0中引入的Membership机制给我们做web开发带来很多便利,使得我们在做很多项目开发时处理用户和角色及权限问题时减少了相当的工作量。不过我们开发中可能会碰到一个小小的问题如下:

我们知道MembershipUser中有如下重载的方法

  • MembershipUser.ResetPassword () :将用户密码重置为一个自动生成的新密码。
  • MembershipUser.ResetPassword (String passwordAnswer) :将用户密码重置为一个自动生成的新密码。

msdn中有如下描述:

ResetPassword 调用 ProviderName 属性所引用的成员资格提供程序的 MembershipProvider.ResetPassword 方法,以将成员资格用户的密码重置为自动生成的新密码。然后将该新密码返回到调用方。

如果 EnablePasswordReset 为 false,则成员资格提供程序将返回一个异常。

如果 RequiresQuestionAndAnswer 为 true,则必须使用以密码提示问题答案作为参数的 ResetPassword 重载方法,并提供成员资格用户的密码。如果需要密码答案并提供了不正确的密码答案,成员资格提供程序将引发 MembershipPasswordException。

而另外一个方法MembershipUser.ChangePassword(String oldPassword, String newPassword) 又必须提供原始密码,那么这里就产生了一个矛盾:我们希望用户能够通过安全问题和答案来作为找回密码,又希望管理员可以重置某用户的密码怎么办?上述方法均无法直接使用,要么使用MembershipUser.ResetPassword ()而无安全问题和答案验证,要么必须知道问题答案或者原始密码,我们知道这些安全相关的东西我们都是加密的,而且往往采用单向编码的方式,也是说我们不可能轻易的通过读取数据库数据知道用户的答案和旧密码!那么好,如何解决这个问题呢?下面我来提供一个小的解决方案:

Membership的数据库中包含有一个设置用户密码的存储过程:

CREATE PROCEDURE aspnet_Membership_SetPassword
(

 @ApplicationName nvarchar(256),

 @UserName nvarchar(256),

 @NewPassword nvarchar(128),

 @PasswordSalt nvarchar(128),

 @CurrentTimeUtc datetime,

 @PasswordFormat int = 0
)

返回值:成功返回 0;
用户不存在,返回 1;

那么ok,我们开始解决我们的需求吧!思路很简单我们先设置用户一个默认的密码,然后以该密码为旧密码使用MembershipUser.ChangePassword(String oldPassword, String newPassword) 修改用户的密码。下面的代码是在以DataAccess.RunProcedure方法是已经实现的执行存储过程的方法为前提编写的:

public class MembershipSafe
 {
     public static string ResetPassword(string username)
     {
         //将用户密码修改为8位且包含一个特殊符号的随机密码
         return ResetPassword(username, Membership.GeneratePassword(8,1));
    }
  
     public static string ResetPassword(string username, string newpassword)
     {
         //先将用户密码修改为123123
  
         SqlParameter[] _sp = {
                              new SqlParameter("@ApplicationName",Membership.ApplicationName)
                             ,new SqlParameter("@UserName",username)
                             ,new SqlParameter("@NewPassword","1M4h3eZLAKW1WbVTTwYJiJZa33w=")
                             ,new SqlParameter("@PasswordSalt","rcVy3pCccZ9tXW7NHp1Maw==")
                             ,new SqlParameter("@CurrentTimeUtc",DateTime.Now)
                             ,new SqlParameter("@PasswordFormat",1)
         };
         bool op = DataAccess.RunProcedure("aspnet_Membership_SetPassword", _sp) == 0;
         //以123123为原始密码,修改为新密码
         Membership.GetUser(username).ChangePassword("123123", newpassword);
         return newpassword;
     }
 }

注:以上代码仅做参考,不一定是符合您具体项目的需求,比如有人可能会继续问修改了密码怎么告诉用户啊,答案是发邮件或者电话通知啊,哈哈~~

推荐浏览:

posted on Wednesday, June 13, 2007 2:41:02 PM (China Standard Time, UTC+08:00)  #    Comments [0]
# Saturday, May 05, 2007

    最近不少Web技术圈内的朋友在讨论协议方面的事情,有的说web开发者应该熟悉web相关的协议,有的则说不用很了解。个人认为这要分层次来看待这个问题,对于一个新手或者刚入门的web开发人员而言,研究协议方面的东西可能会使得web开发失去趣味性、抹煞学习积极性,这类人应该更多的了解基本的Web技术使用。而对于在该行业工作多年的老鸟来说,协议相关的内容、标准相关内容应该尽量多些的了解,因为只有这样才能使得经手的web系统更加优秀(安全、漂亮、快速、兼容性好、体验好……)。本文我们来说一下MIME 协议的一个扩展Content-disposition。

    我们在开发web系统时有时会有以下需求:

  • 希望某类或者某已知MIME 类型的文件(比如:*.gif;*.txt;*.htm)能够在访问时弹出“文件下载”对话框
  • 希望以原始文件名(上传时的文件名,例如:山东省政府1024号文件.doc)提供下载,但服务器上保存的地址却是其他文件名(如:12519810948091234_asdf.doc)
  • 希望某文件直接在浏览器上显示而不是弹出文件下载对话框
  • ……………………

    要解决上述需求就可以使用Content-disposition来解决。第一个需求的解决办法是

Response.AddHeader "content-disposition","attachment; filename=fname.ext"
 
将上述需求进行归我给出如下例子代码:
public static void ToDownload(string serverfilpath,string filename)
{
    FileStream fileStream = new FileStream(serverfilpath, FileMode.Open);
    long fileSize = fileStream.Length;
    HttpContext.Current.Response.ContentType = "application/octet-stream";
    HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + UTF_FileName(filename) + "\";");
    ////attachment --- 作为附件下载
    ////inline --- 在线打开
    HttpContext.Current.Response.AddHeader("Content-Length", fileSize.ToString());
    byte[] fileBuffer = new byte[fileSize];
    fileStream.Read(fileBuffer, 0, (int)fileSize);
    HttpContext.Current.Response.BinaryWrite(fileBuffer);
    fileStream.Close();
    HttpContext.Current.Response.End();
}

public static void ToOpen(string serverfilpath, string filename)
{
    FileStream fileStream = new FileStream(serverfilpath, FileMode.Open);
    long fileSize = fileStream.Length;
    HttpContext.Current.Response.ContentType = "application/octet-stream";
    HttpContext.Current.Response.AddHeader("Content-Disposition", "inline; filename=\"" + UTF_FileName(filename) + "\";");
    HttpContext.Current.Response.AddHeader("Content-Length", fileSize.ToString());
    byte[] fileBuffer = new byte[fileSize];
    fileStream.Read(fileBuffer, 0, (int)fileSize);
    HttpContext.Current.Response.BinaryWrite(fileBuffer);
    fileStream.Close();
    HttpContext.Current.Response.End();
}

private static string UTF_FileName(string filename)
{
    return HttpUtility.UrlEncode(filename, System.Text.Encoding.UTF8);
}

 

简单的对上述代码做一下解析,ToDownload方法为将一个服务器上的文件(serverfilpath为服务器上的物理地址),以某文件名(filename)在浏览器上弹出“文件下载”对话框,而ToOpen是将服务器上的某文件以某文件名在浏览器中显示/打开的。注意其中我使用了UTF_FileName方法,该方法很简单,主要为了解决包含非英文/数字名称的问题,比如说文件名为“衣明志.doc”,使用该方法客户端就不会出现乱码了。

 需要注意以下几个问题:

  1. Content-disposition是MIME协议的扩展,由于多方面的安全性考虑没有被标准化,所以可能某些浏览器不支持,比如说IE4.01
  2. 我们可以使用程序来使用它,也可以在web服务器(比如IIS)上使用它,只需要在http header上做相应的设置即可

可参看以下几篇文档:

posted on Saturday, May 05, 2007 3:03:14 AM (China Standard Time, UTC+08:00)  #    Comments [0]
# Friday, April 06, 2007

数据库镜像是SQL Server 2005的一个新特性,它允许你将一个SQL Server中的数据库内容镜像到另一个SQL Server上。它还让你可以在发生错误的时候,通过镜像数据库来进行错误恢复。镜像的拷贝是一个备用的拷贝,不能直接访问,它只用在错误恢复的情况下。SQL2005的这一特性给数据库系统维护人员带来了不错的实惠,而给最终用户的体验也是不错的。至于如何配置数据库镜像系统,大家可以到TechNet 中文网络广播 中查找一下相关视频教程,尤其推荐大家去看看MVP牛可的相关讲座视频哦。再这里就不多说了。我们直奔主题吧!!

在使用数据库镜像功能时,如果我们使用的是工作组,那么我们需要注意一下数据库用户的问题:用普通方式创建的数据库用户,在主数据库中和镜像数据库中是有一些差异的,而这个差异最终会造成一个“奇怪”的结果,我们在主数据库和镜像数据库中对某数据库影射的“相同用户”,在发生故障转移后数据库验证会发生异常,称该用户无法登录我们的数据库,WHY? 原来是两个数据库中的同名用户在系统表syslogins中的sid不同造成的。解决方法就是在两个数据库上建立同名同sid的用户,具体方法如下:

假设有镜像的服务器是MIR-A和MI-B,要访问镜像数据库的登录账号是tom,使用下面这个方法就可以在MIR-A上创建登录名tom,然后在镜像数据库中创建数据库用户tom并映射到登录名tom
执行下列语句取回tom的sid

select [name], sid from syslogins where [name] = 'tom'
------  -----------------------------------------------
tom 0xD6AABCC8F83E3243A6C3C97F28A4CB55

然后在MIR-B上用下面的语句创建登录名tom

sp_addlogin @loginame = 'tom', @passwd = 'password', @sid = 0xD6AABCC8F83E3243A6C3C97F28A4CB55
Ok,这样就没有问题了。
posted on Friday, April 06, 2007 9:51:10 PM (China Standard Time, UTC+08:00)  #    Comments [1]