SharePoint Server 2007 的一个问题

在用 Deep Zoom Composer 生成内容后,传到 SharePoint Server 2007 中后,发现不能浏览,仔细检查发现 Deep Zoom Composer 生成的很多以 _files 的目录,传到 SharePoint Server 2007 中后,目录被改了名字,自动在最后加了下划线 “_”,导致不能正常访问。

此处详细介绍了此问题。

 

老问题:注册表误修改如何修复?

虽然几乎所有文档都在提醒操作人员在修改注册表的时候,都要进行备份,但实际上,这并不是大多数人的必备步骤。

如果你不慎修改或删除了 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet 中的很多东西,而且也不知道这些东西是做什么用的,那么在重新安装整个操作系统和应用软件之前,可以尝试如下方法看能否恢复:

1. 先把 HKEY_LOCAL_MACHINE\SYSTEM 的各个子键备份一下

2. 不要马上重启机器,不当修改这个子键,最常见的结果就是系统不能启动,或者反复重启

3. 如果你能接触到机器的控制台,那么重启,按 F8,选择“已知最近正确模式”(LastKnownGood)进入 Windows,这样能避免上次的不当修改。

4. 如果不能接触机器的控制台(适用于访问机房中的虚拟机、托管在IDC的托管机等),按不了 F8 ,那该怎么办呢? 两个办法:

1) 在 Boot.ini 中加入 /lastknowngood 参数,然后重启(此功能和F8类似),正常重启并登录后,再把 boot.ini 中的此参数去掉

2) 在HKEY_LOCAL_MACHINE\SYSTEM\Select 子键下,将 Current 的值修改为和 LastKnownGood 的值一样,此法和按 F8 的作用也是类似的

以上经验来自于一次重要的服务器恢复过程。

 

System Center Operation Manager 2007 是个好东西

最近在实施项目时,发现 System Center Operation Manager 2007 (OpsMgr)真是个好东西。监控的最主要功能包括:

  • 网络设备
  • Operating System(磁盘、重要性能计数器、网卡)
  • SQL Server
  • DNS
  • AD
  • Terminal Service
  • NLB
  • Cluster Service
  • BizTalk Server
  • SMS
  • DHCP
  • Web Application
  • 自定义分布式应用程序
  • ……

最后这个得多说一下,大家开发过比较复杂系统都知道,如果用户反映系统出现故障,一步一步去确定系统的各个环节是否有问题是非常麻烦,检查交换机和路由器、Ping 操作系统、检查数据库服务器、检查数据库是否正常(如日志已满)、检查 IIS 及 App Pool 是否异常、检查自定义的 Socket 程序是否正常等…

通过自定义分布式应用程序,可以把以上所有内容整合在一起,系统会自动监控每个环节,如果有问题,会以图形化的方式及时显示系统状况,这个视频中有介绍,真的很 Cool ,不骗你。

 

超流量拒绝?!

平时白天使用中国建设银行个人网上银行系统并不多,今天由于要做一笔转帐,在下午登录个人网银系统并输入正确的身份信息后,竟然显示这样一条比较有意思的错误信息:

"超流量拒绝"还真是个新词,不知道是建设银行发明的,还是网银系统的平台厂商 IBM 发明的,难道是 QoS ?

此外也觉得"拒绝"二字有点生硬,即使不是谦语,也难道不能有更人性一点的提示吗?

好消息:湖北告破熊猫烧香电脑病毒案,抓获8名疑犯

在过去一两个月内,我身边感染“熊猫烧香”病毒的人非常多,远在新疆伊犁家中的一台电脑也未能幸免。病毒的破坏性已经让人非常头疼,病毒作者不思悔改,反倒不停地推出新版本,并在程序中的一些故意预留一些信息,何其猖狂。

今天看到新闻,总算有所安慰,希望这次事件能够让现在这些无法无天的病毒、流氓软件的作者/公司警醒,网络空间不能为所欲为,危害中国数量庞大的计算机用户的结果一定是法律的严惩。

Vista 中的截图工具

今天偶然发现 Vista 中自带一个截图工具,可以方便地截取任意格式、矩形、窗口或全屏幕,截取之后可以直接存储为 JPG、PNG等格式,而且能够进行一些批注,同时也能够直接发送电子邮件。不过遗憾的是,在直接存储成 JPG 时,截图工具和画笔一样,都会使图形失真,还是先保存成其他格式,然后再转换成 JPG 。

如此 Keywords

号称“国内最火热的IT 产业资讯站点太平洋产业资讯”(地址:http://www.pconline.com.cn/news

看看其页面源码:

<title>|&gt;&lt;| 国内最火热的IT产业资讯站点–太平洋产业资讯</title>
<META NAME=”description” CONTENT=”国内最火热的IT新闻频道,最多IT业界内幕的新闻频道,扎根市场深入渠道的IT新闻报道,全方位透视IT业界,联系消费者与业界人士的IT新闻频道。”>
<META NAME=”keywords” CONTENT=”googleCEO网络,名人,财报,思科,SUN,微软,网络,三星,甲骨文,oracle,microsoftoffice,riaa盗版,色情,裸体歌星,影星排行,联想,苹果,宽带,资费,adsl,电影,音乐,破产,收购,liunx,开源,共享,网络,垃圾邮件,网站,itunes,cnnic,3721,百度,IBM,windows,p2p黑客,破解,病毒,、为,小灵通,UT斯达康,3G“>

为了搜索结果,道德和脸面都不要了。

在 GridView 中增加记录的方法

在 ASP.NET 2.0 中,GridView 支持修改/删除记录,但却不支持新增记录的功能(个人感觉是 GridVew 的一大缺憾,估计在下一版本中会加入此功能),大多数人建议用 FormView 来完成增加记录的功能,但是 FormView 和 GridView 不是同一个表格,所以无法在同一个页面的同一个表格中显示。如果故意将 FormView 或自己的一堆于用新增功能的控件使用普通的表格组装起来,那么会碰到一个很麻烦的问题,即两个表格的列宽如何协调一致,大多数情况下,大家在做表格的时候,表格中各列的宽度都是自动调整的,所以强行指定宽度在很多情况下并不适用。

通过实践,想出了一种办法,主要步骤如下所示:

1) 在 GridView 的 EmptyDataView 中,放置一个普通的Html Table,以便在GridView绑定的数据源中无数据时依旧显示表头(如果数据源为返回的数据行数为0,GridView默认是不显示表头的),假设 ID 为 tbHeader,它的作用是下面用于新增功能的 tbForm 的各列控件提供说明(充当表头);

2)在 GridView 下面,放置一个普通的 HTML 表格,其列数和 GridView 中定义的列数保持一致,但行数只有一行,然后在此表格的各列中放入用于新增功能的各个控件(如 TextBox等),假设此表格的 ID 为 tbForm

3)在页面中加入一段客户端脚本,以便使页面展示到客户端时,利用 Javascript 将两个表格强行合并到一起,这样就可以将只有一行的 tbForm 合并到 GridView中,因此 GridView 的最下面多出一行,其中有 tbForm 表格中定义的输入控件和“添加”链接(按钮),主要代码(JavaScript)如下:

function MergeTable(source,dest)
{
    var row;
    var cell;
    var sourceTb = document.all(source);
    var destTb = document.all(dest);
    for (var i=0; i<sourceTb.rows.length; i++)
   {
         row = document.createElement(“TR”);
         for (var j=0; j<sourcetb.ROWS(I).CELLS.LENGTH; j++)
<sourceTb.rows(i).cells.length; j++)
        {
             cell = document.createElement(“TD”);
             row.appendChild(cell);
             //复制对象
             for(k=0;k<sourceTb.rows(i).cells(j).all.length;k++)
                 cell.appendChild(sourceTb.rows(i).cells(j).all.item(k));
        }
        destTb.tBodies(0).appendChild(row);
    }
    for (var i=sourceTb.rows.length-1; i>=0; i–)
    {
        sourceTb.deleteRow(i)
    }
}

function ChangeTableLayout()
{
     if(document.all(‘tbHeader’) == null)
        MergeTable(‘tbForm’,”);
    else
        MergeTable(‘tbForm’,’tbHeader’);
}

ChangeTableLayout();

如果 GridView 绑定时没有数据,将不显示其中定义的各列,而只显示 EmptyDataView 中的 tbHeader,这时要合并 tbHeader 和 tbForm。如果 GridView 绑定时包含数据,则不会显示 EmptyDataView(当然也不会显示其中的 tbHeader),但这时会显示 GridView 中定义的各个列,因此只需将 GridView 本身和 tbForm 合并即可。 GridView 的客户端ID可以用GridView.ClientID来获取。

在服务器端很容易知道 GridView 绑定后是否包含数据,但对于客户端来说,不容易检查,一个简单的作法就是检查页面中有没有 tbHeader 对象(如果有,则说明表格没有数据,如果无此对象,表示 GridView 中包含数据… 好啰嗦)

4)如果是 AJAX 环境,上述脚本有可能不被执行,可以调用 Sys.Application.load.add ( JavaScriptFunction) 来强制执行脚本,来合并表格,主要代码如下(C#):

ScriptManager myScriptManager = ScriptManager.GetCurrent(Page);
if (myScriptManager.IsInPartialRenderingMode)
{
    Page.ClientScript.RegisterStartupScript(this.GetType(), “ShowFullTable1”, “ChangeTableLayout();\n”, true);
}
else
{
    Page.ClientScript.RegisterStartupScript(this.GetType(), “ShowFullTable2”, “Sys.Application.load.add (ChangeTableLayout);\n”, true);
}

注:上述代码中的 ChangeTableLayout 为客户端脚本函数的名称,其中调用第3步骤中的代码,上述代码在 Atlas 中通过,在 ASP.NET AJAX Beta 上尚末测试。

另:为了更能说明上文代码的效果,我抓了一个截图,图中包括表头在内的前三行就是 GridView,最下面一行其实来自于另一个表格,在客户端强制合并后,显示效果就是这样,看起来象是一个表格。

感谢大家的意见,我对原文中的表述不明确的地方进行了更改。

授权管理器(AzMan)中授权策略信息的存储方式的选择

授权管理器(AzMan)是 Windows Server (2000、2003、Longhorn Server…)中自带的、能够和AD紧密集成的、供应用程序使用的授权检查引擎,它实现了完整的基于角色的授权管理框架,利用它,可以在应用程序中大大简化与授权有关的代码编写与实现。

在目前版本中,授权策略信息有两种存储方式:

  • XML
  • 目录(如活动目录-AD或ADAM)

上述两类三种存储方式的适用场景分别如下:

  • 简单的小型应用可以直接使用XML,在这种方式中,不用设置/扩展 AD/ADAM 的 Schema,非常方便
  • 如果基础域环境不好(如应用程序不便访问DC、存在多个Domain)等情况时,可以使用 ADAM
  • 如果基础域环境较好,且应用程序的身份完全与AD集成,最好使用AD

在 Vista 中,AzMan 又增加了一种存储方式:SQL Server,这样对于应用程序来说,又多了一种更实用的选择,而且即然能存在 SQL Server中,估计通过一些手段,这些信息也能存储到其他类型的数据库中,如Access、Oracle等,现在 ASP.NET 2.0中的一些 Provider 不也是公开源代码了,并且实现了其他数据库类型的 Provider 了嘛。

不过,AD/ADAM 具有复制功能,可以方便地实现多个实例之间的目录同步,而SQL Server 不具有此功能,另外 AD/ADAM 在查询方面具有性能优势(AzMan的绝大多数请求是查询),所以到底要使用哪一种存储方式,还是要综合评估。

关于 AzMan 的更多信息,可以参考 AzMan MSDN Blog

ASP.NET 中处理页面“回退”的方法

我们在编写基于 ASP.NET 的应用程序时,如果代码执行出错或检测到异常,一般会提示用户“返回”或“回退”,或者在多步操作、列表/详细的查看界面中,也会给用户提供回退到上一页面的链接,对于这种情况,大家很快就会想到的简单做法就是利用 Javascript 来实现,即 history.go(-1) ,但是由于 ASP.NET 页面的 PostBack 机制,所以 history.go(-1) 可能还是当前页面,而不能真正回退到上一页面。

在 Classifieds Site Starter Kit 中,学习到一种不错的关于回退的处理方法,可以分别在客户端和服务器控件中实现页面的回退,代码如下:

1)首先在页面中增加两个属性

//记录上一个页面的信息
private string UrlReferrer ...{ get ...{ return ViewState["UrlReferrer"] as string; } set ...{ ViewState["UrlReferrer"] = value; } } //记录 PostBack 的次数 public int NumPostBacks ...{ get ...{ if (ViewState["NumPostBacks"] != null) return (int)ViewState["NumPostBacks"]; else ...{ ViewState["NumPostBacks"] = 0; return 0; } } set ...{ ViewState["NumPostBacks"] = value; } }
 

2)在 Page_Load 事件记录上一页面地址、更新 Postback 次数、设置回退链接的地址

// 记录上一页面的信息或更新 PostBack 的次数 protected void Page_Load(object sender, EventArgs e) ...{ if (!Page.IsPostBack) ...{ if (Request.UrlReferrer != null) this.UrlReferrer = Request.UrlReferrer.ToString(); } else NumPostBacks++; int goBackSteps = NumPostBacks + 1; BackLink.NavigateUrl = String.Format("javascript:history.go(-{0});", goBackSteps); }

 

3)直接在代码中处理回退操作(如 Back_Click),可以直接调用如下方法

//在代码中回退 protected void ReturnToPreviousPage() ...{ string referrer = UrlReferrer; if (referrer != null) Response.Redirect(referrer); else Response.Redirect("~/default.aspx", true); }