Hello world!

Welcome to WordPress.com. This is your first post. Edit or delete it and start blogging!

发表在 未分类 | 一条评论

How to prevent duplicate insert or other action when user refresh browser

How to prevent Browser Refresh
This article is about the solution  of duplicate action about the Browser Refresh after postback.

Why the browser refresh will cause the old data to post again.

The page refresh or backwards is a sort of browser internal operation without any notification.

The browser caches the latest request it had served, including viewstate, when you refresh the browser,

it will reissues the data.

Solution:

My Solution: since viewstate will be cached old but session not, we can indicate the browser action by this difference.

if the value of viewstate does not equal to the value of session, then it’s refresh action

Create a base page class, then all sub-class can inherit the functionality.

in base page class constructor:

 

#region Constructor

public BasePage()

{

this.Page.PreRender += new EventHandler(Page_PreRender);

}

#endregion

in Page_PreRender method:

#region Method: Page_PreRender
void Page_PreRender(object sender, EventArgs e)
{
     
if (IsPostBack == false)
     
{
         SetActionTick();
     }
     ViewState[
"ActionTick"] = Session["ActionTick"];
}
#endregion

In SetActionTick() to set the timestamp of this action.

Method: SetActionTick#region Method: SetActionTick
  
protected void SetActionTick()
  
{
      Session[
"ActionTick"] = Server.UrlEncode(DateTime.Now.ToString("yyyyMMddhhmmss"));
  }
  
#endregion

The property IsRefresh

Property: IsRefresh#region Property: IsRefresh
protected bool IsRefresh
{
    
get
    
{
        
//if (Session["RefreshTick"] == null)
        //{
        //    return false;
        //}
        if (ViewState["ActionTick"as string == Session["ActionTick"as string)
        
{
            SetActionTick();
            
return false;
        }
        
return true;
    }
}
#endregion

So the sub-page class can use this property.

if (IsRefresh == false)

// Insert

发表在 ASP.NET | 4条评论

项目管理十二大著名法则


项目管理中不得不遵守的法则,可以触类旁通。

一、马太效应

《新约.马太福音》中有这样一个故事,一个国王远行前,交给三个仆人每人一锭银子,吩咐他们:“你们去做生意,等我回来时,再来见我。”国王回来时,第一个仆人说:“主人,你交给我们的一锭银子,我已赚了1 0锭。”于是国王奖励他10座城邑。第二个仆人报告说:“主人,你给我的一锭银子,我已赚了5锭。”于是国王例奖励了他5座城邑。第三个仆人报告说:“主人,你给我的一锭银子,我一直包在手巾里存着,我怕丢失,一直没有拿出来。”于是国王命令将第三个仆人的一锭银子也赏给第一个仆人,并且说:“凡是少的,就连他所有的也要夺过来。凡是多的,还要给他,叫他多多益善。”这就是马太效应。

看看我们周围,就可以发现许多马太效应的例子。朋友多的人会借助频繁的交往得到更多的朋友;缺少朋友的人会一直孤独下去。金钱方面更是如此,即使投资回报率相同,一个比别人投资多1 0倍的人,收益也多10倍。 这是个赢家通吃的社会,善用马太效应,赢家就是你。

对企业经营发展而言,马太效应则告诉我们,要想在某一个领域保持优势,就必须在此领域迅速做大。当你成为某个领域的领头羊的时候,即使投资回报率相同,你也能更轻易的获得比弱小的同行更大的收益。而若没有实力迅速在某个领域做大,就要不停地寻找新的发展领域,才能保证获得较好的回报。

二、手表定理

手表定理是指一个人有一只表时,可以知道现在是几点钟,而当他同时拥有两只表时却无法确定。两只表并不能告诉一个人更准确的时间,反而会让看表的人失去对准确时间的信心。你要做的就是选择其中较信赖的一只,尽力校准它,并以此作为你的标准,听从它的指引行事。记住尼采的话:“兄弟,如果你是幸运的,你只需有一种道德而不要贪多,这样,你过桥更容易些。” 如果每个人都“选择你所爱,爱你所选择”,无论成败都可以心安理得。然而,困扰很多人的是:他们被“两只表”弄得无所,心身交瘁,不知自己该信仰哪一个,还有人在环境、他人的压力下,违心选择了自己并不喜欢的道路,为此而郁郁终生,即使取得了受人瞩目的成就,也体会不到成功的快乐。

手表定理在企业经营管理方面给我们一种非常直观的启发,就是对同一个人或同一个组织的管理不能同时采用两种不同的方法,不能同时设置两个不同的目标。甚至每一个人不能由两个人来同时指挥,否则将使这个企业或这个人无所适从。手表定理所指的另一层含义在于每个人都不能同时挑选两种不同的价值观,否则,你的行为将陷于混乱。

三、不值得定律

不值得定律最直观的表述是:不值得做的事情,就不值得做好,这个定律似乎再简单不过了,但它的重要性却时时被人们疏忘。不值得定律反映出人们的一种心理,一个人如果从事的是一份自认为不值得做的事情,往往会保持冷嘲热讽,敷衍了事的态度。不仅成功率小,而且即使成功,也不会觉得有多大的成就感。

哪些事值得做呢?一般而言,这取决于三个因素。

1、价值观。关于价值观我们已经谈了很多,只有符合我们价值观的事,我们才会满怀热情去做。

2、个性和气质。一个人如果做一份与他的个性气质完全背离的工作,他是很难做好的,如一个好交往的人成了档案员,或一个害羞者不得不每天和不同的人打交道。

3、现实的处境。同样一份工作,在不同的处境下去做,给我们的感受也是不同的。例如,在一家大公司,如果你最初做的是打杂跑腿的工作,你很可能认为是不值得的,可是,一旦你被提升为领班或部门经理,你就不会这样认为了。

总结一下,值得做的工作是:符合我们的价值观,适合我们的个性与气质,并能让我们看到期望。如果你的工作不具备这三个因素,你就要考虑换一个更合适的工作,并努力做好它。 因此,对个人来说,应在多种可供选择的奋斗目标及价值观中挑选一种,然后为之而奋斗。“选择你所爱的,爱你所选择的”,才可能激发我们的奋斗毅力,也才可以心安理得。而对一个企业或组织来说,则要很好地分析员工的性格特性,合理分配工作,如让成就欲较强的职工单独或牵头来完成具有一定风险和难度的工作,并在其完成时给予定时的肯定和赞扬;让依附欲较强的职工更多地参加到某个团体中共同工作;让权力欲较强的职工担任一个与之能力相适应的主管。同时要加强员工对企业目标的认同感,让员工感觉到自己所做的工作是值得的,这样才能激发职工的热情。

四、彼得原理

彼得原理是美国学者劳伦斯?彼得在对组织中人员晋升的相关现象研究后得出的一个结论;在各种组织中,由于习惯于对在某个等级上称职的人员进行晋升提拔,因而雇员总是趋向于晋升到其不称职的地位。彼得原理有时也被称为“向上爬”原理。这种现象在现实生活中无处不在:一名称职的教授被提升为大学校长后无法胜任;一个优秀的运动员被提升为主管体育的官员,而无所作为。

对一个组织而言,一旦组织中的相当部分人员被推到了其不称职的级别,就会造成组织的人浮于事,效率低下,导致平庸者出人头地,发展停滞。因此,这就要求改变单纯的“根据贡献决定晋升”的企业员工晋升机制,不能因某个人在某一个岗位级别上干得很出色,就推断此人一定能够胜任更高一级的职务。要建立科学、合理的人员选聘机制,客观评价每一位职工的能力和水平,将职工安排到其可以胜任的岗位。不要把岗位晋升当成对职工的主要奖励方式,应建立更有效的奖励机制,更多地以加薪、休假等方式作为奖励手段。有时将一名职工晋升到一个其无法很好发挥才能的岗位,不仅不是对职工的奖励,反而使职工无法很好发挥才能,也给企业带来损失。

对个人而言,虽然我们每个人都期待着不停地升职,但不要将往上爬作为自己的惟一动力。与其在一个无法完全胜任的岗位勉力支撑、无所适从,还不如找一个自己能游刃有余的岗位好好发挥自己的专长。

五、零和游戏原理

当你看到两位对弈者时,你就可以说他们正在玩“零和游戏”。因为在大多数情况下,总会有一个赢,一个输,如果我们把获胜计算为得1 分,而输棋为-1分,那么,这两人得分之和就是:1 (-1)=0。 这正是“零和游戏”的基本内容:游戏者有输有赢,一方所赢正是另一方所输,游戏的总成绩永远是零。

零和游戏原理之所以广受关注,主要是因为人们发现在社会的方方面面都能发现与“零和游戏”类似的局面,胜利者的光荣后面往往隐藏着失败者的辛酸和苦涩。从个人到国家,从政治到经济,似乎无不验证了世界正是一个巨大的“零和游戏”场。这种理论认为,世界是一个封闭的系统,财富、资源、机遇都是有限的,个别人、个别地区和个别国家财富的增加必然意味着对其他人、其他地区和国家的掠夺,这是一个“邪恶进化论”式的弱肉强食的世界。

但20世纪人类在经历了两次世界大战,经济的高速增长、科技进步、全球化以及日益严重的环境污染之后,“零和游戏”观念正逐渐被“双赢”观念所取代。人们开始认识到“利己”不一定要建立在“损人”的基础上。通过有效合作,皆大欢喜的结局是可能出现的。但从“零和游戏”走向“双赢”,要求各方要有真诚合作的精神和勇气,在合作中不要耍小聪明,不要总想占别人的小便宜,要遵守游戏规则,否则“双赢”的局面就不可能出现,最终吃亏的还是自己。

六、华盛顿合作规律

华盛顿合作规律说的是:一个人敷衍了事,两个人互相推诿,三个人则永无成事之日。多少有点类似于我们“三个和尚”的故事。人与人的合作不是人力的简单相加,而是要复杂和微妙得多。在人与人的合作中,假定每个人的能力都为1 ,那么10个人的合作结果就有时比10大得多,有时甚至比1还要小。因为人不是静止的动物,而更像方向各异的能量,相推动时自然事半功倍,相互抵触时则一事无成。我们传统的管理理论中,对合作研究得并不多,最直观的反映就是,目前的大多数管理制度和行业都是致力于减少人力的无谓消耗,而非利用组织提高人的效能。换言之,不妨说管理的主要目的不是让每个人做到最好,而是避免内耗过多。2 1世纪将是一个合作的时代,值得庆幸的是,越来越多的人已经认识到真诚合作的重要性,正在努力学习合作。

邦尼人力定律:一个人一分钟可以挖一个洞,六十个人一秒种却挖不了一个洞。

合作是一个问题,如何合作也是一个问题。

七、酒与污水定律

酒与污水定律是指,如果把一匙酒倒进一桶污水中,你得到的是一桶污水;如果把一匙污水倒进一桶酒中,你得到的还是一桶污水。几乎在任何组织里,都存在几个难弄的人物,他们存在的目的似乎就是为了把事情搞糟。他们到处搬弄是非,传播流言、破坏组织内部的和谐。最糟糕的是,他们像果箱里的烂苹果,如果你不及时处理,它会迅速传染,把果箱里其它苹果也弄烂,“烂苹果”的可怕之处在于它那惊人的破坏力。一个正直能干的人进入一个混乱的部门可能会被吞没,而一个人无德无才者能很快将一个高效的部门变成一盘散沙。组织系统往往是脆弱的,是建立在相互理解、妥协和容忍的基础上的,它很容易被侵害、被毒化。破坏者能力非凡的另一个重要原因在于,破坏总比建设容易。一个能工巧匠花费时日精心制作的陶瓷器,一头驴子一秒钟就能毁坏掉。如果拥有再多的能工巧匠,也不会有多少像样的工作成果。如果你的组织里有这样的一头驴子,你应该马上把它清除掉;如果你无力这样做,你就应该把它拴起来。

八、水桶定律

水桶定律是讲,一只水桶能装多少水,完全取决于它最短的那块木板。这就是说任何一个组织都可能面临的一个共同问题,即构成组织的各个部分往往决定了整个组织的水平。

构成组织的各个部分往往是优劣不齐的,而劣质部分往往又决定整个组织的水平。

“水桶定律”与“酒与污水定律”不同,后者讨论的是组织中的破坏力量,而“最短的木板”却是组织中有用的一个部分,只不过比其它部分差一些,你不能把它们当成烂苹果扔掉。强弱只是相对而言的,无法消除。问题在于你容忍这种弱点到什么程度。如果它严重到成为阻碍工作的瓶颈,就不得不有所动作。

如果你在一个组织中,你应该: 1、确保你不是最薄弱的部分; 2、避免或减少这一薄弱环节对你成功的影响; 3、如果不幸,你正处在这一环节中,你还可以采取有效的方法改进,或者转职去谋另一份工作。

九、蘑菇管理

蘑菇管理是许多组织对待初出茅庐者的一种管理方法,初学者被置于阴暗的角落(不受重视的部门,或打杂跑腿的工作),浇上一头大粪(无端的批评、指责、代人受过),任其自生自灭(得不到必要的指导和提携)。相信很多人都有这样一段“蘑菇”的经历,但这不一定是什么坏事,尤其是当一切都刚刚开始的时候,当上几天“蘑菇”,能够消除我们很多不切实际的幻想,让我们更加接近现实,看问题也更加实际,而对一个组织而言,一般地新进的人员都是一视同仁,从起薪到工作都不会有大的差别。无论你是多么优秀的人才,在刚开始的时候都只能从最简单的事情做起,“蘑菇”的经历对于成长中的年轻人来说,就像蚕茧,是羽化前必须经历的一步。所以,如何高效率地走过生命中的这一段,从中尽可能吸取经验,成熟起来,并树立良好的值得信赖的个人形象,是每个刚入社会的年轻人必须面对的课题。

十、奥卡姆剃刀定律

如果你认为只有焦头烂额、忙忙碌碌地工作才可能取得成功,那么,你错了。 事情总是朝着复杂的方向发展,复杂会造成浪费,而效能则来自于单纯。在你做过的事情中可能绝大部分是毫无意义的,真正有效的活动只是其中的一小部分,而它们通常隐含于繁杂的事物中。找到关键的部分,去掉多余的活动,成功并不那么复杂。

奥卡姆剃刀:如无发要,勿增实体。

12世纪,英国奥卡姆的威廉对无休无止的关于“共相”、“本质”之类的争吵感到厌倦,主张唯名论,只承认确实存在的东西,认为那些空洞无物的普遍性要领都是无用的累赘,应当被无情地“剃除”。他主张,“如无必要,勿增实体。”这就是常说的“奥卡姆剃刀”。这把剃刀曾使很多人感到威胁,被认为是异端邪说,威廉本人也受到伤害。然而,这并未损害这把刀的锋利,相反,经过数百年越来越快,并早已超越了原来狭窄的领域而具有广泛的、丰富的、深刻的意义。

奥卡姆剃刀定律在企业管理中可进一步深化为简单与复杂定律:把事情变复杂很简单,把事情变简单很复杂。这个定律要求,我们在处理事情时,要把握事情的主要实质,把握主流,解决最根本的问题。尤其要顺应自然,不要把事情人为地复杂化,这样才能把事情处理好。

十一、二八法则

你所完成的工作里80%的成果,来自于你20%的付出;而80%的付出,只换来20%的成果 。

十二、钱的问题

当某人告诉你:“不是钱,而是原则问题”时,十有八九就是钱的问题。

照一般的说法,金钱是价值的尺度,交换的媒介,财富的贮藏。但是这种说法忽略了它的另一面,它令人陶醉、令人疯狂、令人激动的一面,也撇开了爱钱的心理不谈。马克思说,金钱是“人情的离心力”,就是指这一方面而言。

关于金钱的本质、作用和功过,从古到今,人们已经留下了无数精辟深刻的格言和妙语。我们常会看到,人们为钱而兴奋,努力赚钱,用财富的画面挑逗自己。金钱对世界的秩序以及我们的生活产生的影响是巨大的、广泛的,这种影响有时是潜在的,我们往往意识不到它的作用如此巨大,然而奇妙的是:它完全是人类自己创造的。致富的驱动力并不是起源于生物学上的需要,动物生活中也找不到任何相同的现象。它不能顺应基本的目标,不能满足根本的需求- 的确,“致富”的定义就是获得超过自己需要的东西。然而这个看起来漫无目标的驱动力却是人类最强大的力量,人类为金钱而互相伤害,远超过其他原因。

发表在 项目管理 | 留下评论

项目计划模版分享

项目计划模版
(项目名称)
项目综合计划
(项目经理姓名和/或关键小组成员)
修改号:
修改日期:
编写人:
日期:
审批人:
日期:
审批人:
日期:
修改号:
修改日期:
编写人:
日期:
审批人:
日期:
审批人:
日期:

项目计划大纲
1.0
引言
作为项目起源的问题/机会陈述。
2.0
项目概述和章程
此处包括项目的总体描述。即关键目标、长度,以及主要的风险和收益。还包括一个项目章程。项目章程规定了项目的目的、影响说明书和与外部组织的接口。
3.0
目标和目的
项目目标和目的应该包括项目成功应该满足的可衡量标准(成本、进度和质量)。
初步的项目成本/收益分析(ROINPV、回收期等等)的结果,当存在时,应该被包含在此章中。本章所描述的目标和目的将用来:
指导项目执行,记录项目计划编制的假定,以及有关项目方案的选择决策。
促进干系人之间的沟通,协助关键的管理审查。
提供项目进展衡量和项目控制的基线。
4.0
工作分解结构
工作分解结构(WBS)是以可交付成果为导向的项目元素的分组,它组织和定义了项目的总体范围。它用来建立或确认对范围的共同的理解,层次越低,对项目元素的描述越详细。WBS的每一细目都被分配了独特的编码,并且在WBS字典可以描述每个控制帐户;即分配给单个组织/个人的,用来管理范围、进度和成本的可管理的工作块。它的编码方式还可以包括成本帐户结构。
5.0
工作说明和范围要求
范围说明,(有时被称为工作说明(SOW)),是对已知的整体工作范围的叙述性描述,它因该反映成功完成项目所必需的所有工作。
范围说明应该使用与工作分解结构相同的结构,由段落和子段落组成。范围说明通常是写在WBS的高层和/或中层;如控制帐户及其以上的层次。
特征和功能要求应该加以明确规定,因为他们定义了项目应该包括和不应该包括的内容。
范围说明或工作说明的编写使干系人对于项目范围有了共同的理解。它应该包括:
A.
项目产品-产品描述摘要
B.
项目可交付成果-将项目范围的主要部分分为更小的更好管理的部分。可能时应该规定排除在可交付成果之外的情况。
6.0
进度
这一章描述了保证项目及时完成的进度过程。以下时对项目进度计划编制主要过程的概述。
活动/任务/子任务定义-识别出得到项目各种可交付成果所需的具体活动。还识别出与项目进展和结果相关的主要里程碑。
活动/任务/子任务排序-识别活动间的依赖关系、关键可交付成果和约束条件。
活动/任务/子任务历时-估算完成每个活动所需的历时。
进度计划编制-分析所收集的数据,将数据输入进度计划,分析活动顺序、历时和资源要求。
7.0
项目人员安排
利用范围说明或工作说明(SOW)以及项目工作分解结构识别必需的技能,应该选择和通过谈判获得人员组成一个项目小组,从而能够完成项目范围中的具体任务和子任务。项目小组的结构应该与项目WBS的结构匹配,采取职责矩阵的形式。项目职责矩阵应该记录小组的职责和任务。
8.0
预算/资源要求
预算/资源要求包括了四个主要过程,以保证项目在批准的预算内完成。这些过程共同建立和维持了一个综合的项目范围、进度和成本基线(也成为成本基线)。这一基线应该包括在本章节当中。
成本预算考虑了各种成本核算选择方案之后做出的对完成工作所需的资源成本的估算。
成本预算以工作范围为基础,将成本总估算分配给个别的工作细目,从而建立项目成本基线。而此项目成本基线将用来衡量和监测成本绩效。
资源计划编制确定完成工作所需的资源,包括编制规定团体成员的职责的职责分配矩阵,目的是,并且建立项目的必要沟通网络。
成本控制=这包括控制改变项目成本基线(综合的范围、进度、成本基线)的因素的行为。此部分应该包括对项目所运用的挣值管理技术的描述。
9.0
假定
在所有领域,特别是不存在明确定义的领域,必须设定和使用假定。一个假定的成败对其在项目中目前的未来的运用是至关重要的,假定应该在整个初期计划阶段被规定,并记录在本部分当中,用于所有的范围/质量、成本和进度计划。
对假定的详细记录包括识别与项目计划所有组成相对应的假定。项目控制账户的关键假定可以记录在wbs字典中。其他假定应该随着所有其他范围
质量、进度和成本计划的编制加以记录。
10.0
风险
风险管理包括在项目全过程中管理风险所使用的程序。本部分将对下列主要过程进行概述。
风险管理计划编制重点是编制风险管理计划。
风险识别可能影响项目的风险。
风险评估评价风险和风险的相互作用,从而评估可能的后果。必要时同时使用定性和定量的分析方法。
风险应对计划编制定义把握计划的步骤和应对威胁的方法,包括具体的应对选择方案和行动界限。
风险监测/控制跟踪风险和风险的影响,跟踪缓解计划的编制和执行产生的影响,寻找新的风险。参见以下的11.0
风险分析工作表的作用是纪录风险识别、定性分析、应对措施和控制/报告。

11.0项目报告和控制
报告再项目整个生命周期中,应该定期对项目成本、进度和技术绩效进行报告。这应该包括有报告内容的规定,如分发列表、管理审查和纠正措施。经常性的项目审查会议也应加以计划,并包括在本章当中。
控制对项目状况的管理审查、缓解项目绩效问题的纠正措施计划编制和实施。控制的重点应该是如下四个领域:
工作范围和技术应用评价正在完成的工作是否符合经批准的项目范围,并且评价相关技术是否满足项目目标。本部分应该记录挣值管理技术的方法和应用。
成本控制按照项目基线监测项目进度绩效,以保证以最低成本完成经批准的项目范围。
进度控制按照项目基线监测项目进度绩效,以保证及时完成。
风险应对控制评价个别的绩效问题如何影响项目的所有目标:范围、进度和成本。必要时进行综合的风险缓解跟踪。参见以上的10.0
12.0
变更控制
全面的变更控制包括(a)影响导致变更的因素:(b)确定变更是否发生;(c)变更发生时管理变更。这要求:
维持健全的绩效测量基线。
保证产品范围的变更被包含并且反映在项目范围定义中。变更指令日志是纪录所有变更申请处理情况的文档。
协调跨知识领域的变更。(进度变更常常影响成本、风险、质量和人员安排)
保证对项目基线变更进行明确的变更识别,管理审批,和正式实施。
13.0
约束条件
约束条件对项目可能产生正面或者负面的影响。在尽可能的情况下,每个项目都要识别约束条件(内部或者外部),约束条件的类型可能包括(还有其他泪向):
项目里程碑
资源可得性
交付日期
监管机构或法律问题
14.0
沟通计划编制
项目沟通计划编制包括保证项目信息及时并且适当地生成、收集、散布、储存和最终处理所必需的过程。它是项目成功所必需的人员、想法和信息之间的关键连接。此处应该适当的记录并且由项目经理及其小组遵循的主要过程如下。
沟通计划编制--确定干系人的信息和沟通需求:睡需要什么信息;他们何时需要;如何将信息传达给他们。应该包括所有重复进行的项目会议计划编制。
信息分发--使项目干系人及时获得所需信息。
绩效报告--收集和散布绩效信息。这包括状态报告、进展衡量和预测。适当参考本项目计划的11.017.0和其他有关章节。
管理收尾--生成、收集和散布信息,从而正是结束项目阶段或项目。
15.0
质量计划编制
项目质量计划编制包括保证项目满足其预定需求所必需的过程。这包括确定质量政策、目标和责任的所有活动。
此处应该适当记录并且由项目经理及其小组所遵循的主要过程如下。
质量计划编制--识别与项目相关的质量标准并且确定如何满足这些标准。
质量保证--定期评价项目总体绩效,从而保证项目将满足相关的质量标准。
质量控制--检测具体项目结果,从而确定它们是否符合相关质量标准,并且设法消除造成不满意绩效的原因。
16.0
合同和采购计划编制
项目合同和采购计划编制包括从执行组织外部获取货物和服务所必需的过程。这些货物和服务,或“产品”,是通过六个过程获取的。
此处应该适当记录并且由项目经理及其小组所遵循的主要过程如下。
合同采购/计划编制-确定采购什么,何时采购,包括需提前很长时间定购的货品。
询价计划编制-记录产品要求和识别潜在供方。
询价-获取适当的报价、出价、发盘或建议书。
供方选择-从潜在卖方中选择。
合同/采购管理-管理与卖方的关系。
合同/采购收尾-合同/采购的完成和解决,包括任何未决事项的解决。
可能的话,主要的分包商、咨询顾问和供应商应该在此或在本计划的第7.0章确定。
17.0
项目完成
在项目生命周期的早期阶段做好项目完成计划将保证所有必要的项目完成可交付成果被捕捉。这些可交付成果可以作为未来项目的参考和/或用于审计目的。
项目完成可交付成果可以包括,但不局限于,如下内容:
可交付成果 初期 末期 所有
项目计划 x x
工作范围
x x
估算
e x x
成本文件
s x x
变更指令申请
x
进度
x x
月度状态报告
x
工程设计图纸
x
规格
x
可交付成果摘要
x
项目文档索引和关键项目函件,以及外部文档
x
经验教训
x
其它项目细节

变更指令日志
x x
又见有关项目沟通计划编制的第14.0章的管理收尾,作为相互参照。

18.0
附属的与项目相关的计划
范围计划
进度计划
成本计划
质量计划
人员获取计划
沟通计划
风险管理计划
风险应对计划
采购计划
其它计划可能也属于项目计划编制,这取决与项目的需求以及客户和项目母公司的政策。

发表在 项目管理 | 留下评论

工程WBS分解示例

今天在项目管理论坛上看到 “工程项目管理的WBS分解结构”,发现软件项目和传统项目在WBS分解上是非常相似,收藏!

A 签订项目管理委托合同
B 项目管理部进场
C 工程图设计
C/01 方案设计
C/02 初步设计
C/03 初步设计报批
C/04 施工图设计
C/04.01 施工图设计
C/04.02 施工图审核
C/04.03 交付图纸
D 办理项目规划手续
D/01 申请规划设计方案审查通知书
D/02 专项审批(人防、消防、交通、园林)
D/03 年度开工计划转正式计划
D/04 申领建设工程规划许可证
E 办理工程开工证
E/01 领取开工审批表
E/02 市政配套签署意见
E/03 招标办领取申请表
E/04 招标办办理审批手续
E/05 施工总承包合同运作
E/05.01 资格预审文件、招标文件的编制与送审
E/05.02 投标预备会
E/05.03 发招标文件
E/05.04 勘查现场
E/05.05 招标文件编制与提交
E/05.06 开标
E/05.07 组织投标单位答辩,编制评标报告
E/05.08 定标、发中标通知书
E/05.09 商定总承包合同并签署
E/05.10 总承包合同备案
E/06 监理合同运作
E/06.01 投标资格审查
E/06.02 发招标文件
E/06.03 勘查现场
E/06.04 招标文件编制与提交
E/06.05 发标
E/06.06 组织投标单位答辩、编制评标报告
E/06.07 定标、发中标通知书
E/06.08 监理合同签署
E/06.09 监理合同备案
E/07 执行监理合同
E/07.01 项目监理大纲审查
E/07.02 项目实施过程的监理业绩评价
E/07.02.01 工程进度控制
E/07.02.02 工程质量控制
E/07.02.03 工程成本控制
E/07.02.04 工程变更、费用索赔与价格调整管理
E/07.02.05 工程施工风险防范与管理
E/07.02.06 工程计量与支付的管理
E/08 办理委托质量监督手续
E/08.01 办理市监督总站登记
E/08.02 政府质量监督部门批准手续
E/08.03 交纳监督费
E/09 施工单位和其上级主管部门的有关签章
E/10 粘土砖限制使用费交付
E/11 交纳北京市散装水泥专项基金
E/12 市统计局办理手续
E/13 向市建委申领开工许可证
F 施工准备
F/01 拆除
F/01.01 市场调研、编制招标文件
F/01.02 商务谈判
F/01.03 确定拆迁单位、签订合同
F/01.04 申办拆除许可证
F/01.05 拆除施工
F/01.06 探察封堵地下管道
F/02 筹组施工项目部
F/03 砌筑现场围墙、场地平整
F/04 施工用电和给排水敷设
F/05 临设搭建
F/06 规划钉桩
F/07 完成施工准备
G 建安工程
G/01 降水、土方、护坡工程
G/01.01 分包工程合同运作
G/01.01.01 文件编制
G/01.01.02 工程招标、评标、决标
G/01.01.03 签订合同
G/01.02 执行合同
G/01.02.01 审定土方工程施工方案
G/01.02.02 放线、验线
G/01.02.03 土方施工
G/01.02.04 土方工程验收
G/02 地下结构
G/02.01 验槽
G/02.02 垫层、防水、底板施工
G/02.03 -2层施工
G/02.04 -1层施工
G/03 主体结构
G/03.01 首层结构施工
G/03.02 2层结构施工
G/03.03 3层结构施工
G/03.04 4层结构施工
G/03.05 5层结构施工
G/03.06 6层结构施工
G/03.07 7层结构施工
G/03.08 结构工程验收
G/04 屋面工程及屋面设备安装
G/04.01 女儿墙、出屋面管口、设备基础
G/04.02 防水及面层施工
G/04.03 屋面机房、设备安装
G/04.04 屋面工程验收
G/05 电梯工程
G/05.01 电梯工程合同运作
G/05.01.01 施工单位资格预审
G/05.01.02 电梯工程招标文件编制
G/05.01.03 报业主审批
G/05.01.04 确定投标单位
G/05.01.05 工程发标
G/05.01.06 回标
G/05.01.07 评标
G/05.01.08 编制评标报告
G/05.01.09 业主确定中标单位
G/05.01.10 签订施工及供货合同
G/05.02 执行电梯工程合同
G/05.02.01 设备加工
G/05.02.02 设备到货验收
G/05.02.03 电梯井道设备安装
G/05.02.04 机房设备安装
G/05.02.05 其他成组设备安装
G/05.02.06 运行调试
G/05.02.07 电梯预验收
G/06 高压变配电工程
G/06.01 高压变配电工程合同运作
G/06.01.01 施工单位资格预审
G/06.01.02 变配电招标文件编制
G/06.01.03 报业主审批
G/06.01.04 修改、定稿
G/06.01.05 确定投标单位
G/06.01.06 工程发标
G/06.01.07 回标
G/06.01.08 评标
G/06.01.09 编制评标报告
G/06.01.10 业主确定中标单位
G/06.01.11 签订施工及供货合同
G/06.02 执行高压变配电工程合同
G/06.02.01 设备加工
G/06.02.02 设备到货与验收
G/06.02.03 设备安装
G/06.02.04 试运行
G/06.02.05 变配电设备验收
G/07 空调工程
G/07.01 空调工程合同运作
G/07.01.01 施工单位资格预审
G/07.01.02 空调招标文件编制
G/07.01.03 报业主审批
G/07.01.04 修改、定稿
G/07.01.05 确定投标单位
G/07.01.06 工程发标
G/07.01.07 回标
G/07.01.08 评标
G/07.01.09 编制评标报告
G/07.01.10 业主确定中标单位
G/07.01.11 签订施工及供货合同
G/07.02 执行空调工程合同
G/07.02.01 设备加工
G/07.02.02 设备到货与核查
G/07.02.03 风机盘管安装
G/07.02.04 自燃冷热源机组安装
G/07.02.05 系统试运行
G/07.02.06 空调系统验收
G/08 通风排烟工程
G/08.01 通风排烟工程合同运作
G/08.01.01 施工单位资格预审
G/08.01.02 空调招标文件编制
G/08.01.03 报业主审批
G/08.01.04 修改、定稿
G/08.01.05 确定投标单位
G/08.01.06 工程发标
G/08.01.07 回标
G/08.01.08 评标
G/08.01.09 编制评标报告
G/08.01.10 业主确定中标单位
G/08.01.11 签订施工及供货合同
G/08.02 执行通风排烟工程合同
G/08.02.01 设备加工
G/08.02.02 设备到货
G/08.02.03 设备安装
G/08.02.04 试运行
G/08.02.05 通风排烟系统验收
G/09 变配电防雷接地
G/09.01 设备安装
G/09.02 防雷接地验收
G/10 热水自引水工程
G/10.01 热水自引水工程合同运作
G/10.01.01 施工单位资格预审
G/10.01.02 空调招标文件编制
G/10.01.03 报业主审批
G/10.01.04 修改、定稿
G/10.01.05 确定投标单位
G/10.01.06 工程发标
G/10.01.07 回标
G/10.01.08 评标
G/10.01.09 编制评标报告
G/10.01.10 业主确定中标单位
G/10.01.11 签订施工及供货合同
G/10.02 执行热水自引水工程合同
G/10.02.01 设备加工
G/10.02.02 设备到货
G/10.02.03 设备安装
G/10.02.04 试运行
G/10.02.05 热水自引水系统验收
G/11 初装修
G/11.01 隔墙、维护墙砌筑
G/11.02 墙地面抹灰、修补
G/11.03 初装修验收
G/12 精装修
G/12.01 委托精装修设计
G/12.01.01 设计单位资格预审、评价
G/12.01.02 签订精装修合同
G/12.01.03 精装修设计方案
G/12.01.04 业主审定方案
G/12.01.05 施工图设计
G/12.02 精装修施工合同运作
G/12.02.01 编制施工招标文件
G/12.02.02 招标文件讨论
G/12.02.03 招标文件报业主审批
G/12.02.04 精装修发标
G/12.02.05 精装修回标
G/12.02.06 精装修评标
G/12.02.07 编制评标报告
G/12.02.08 确定中标单位
G/12.02.09 签订施工合同
G/12.03 执行精装修施工合同
G/12.03.01 二次设计
G/12.03.02 二次设计确认
G/12.03.03 样板间施工
G/12.03.04 执行精装修施工计划
G/12.03.05 精装修成果验收
G/13 外装修
G/13.01 外装修施工合同运作
G/13.01.01 编制外装修招标文件
G/13.01.02 招标文件讨论
G/13.01.03 招标文件报业主审批
G/13.01.04 外装修发标
G/13.01.05 外装修回标
G/13.01.06 施工队伍考察
G/13.01.07 外装修评标
G/13.01.08 编制评标报告
G/13.01.09 确定中标单位
G/13.01.10 签订外装修施工合同
G/13.02 执行外装修施工合同
G/13.02.01 二次设计
G/13.02.02 二次设计确认
G/13.02.03 预留预埋施工图
G/13.02.04 材料订货、加工
G/13.02.05 外窗安装
G/13.02.06 玻璃幕墙施工
G/13.02.07 干挂石材施工
G/13.02.08 外装修验收
G/14 消防工程
G/14.01 消防工程合同运作
G/14.01.01 编制招标文件
G/14.01.02 招标文件讨论
G/14.01.03 招标文件报业主审批
G/14.01.04 发标
G/14.01.05 回标
G/14.01.06 评标
G/14.01.07 编制评标报告
G/14.01.08 确定中标单位
G/14.01.09 签订施工合同
G/14.02 执行消防工程合同
G/14.02.01 二次设计
G/14.02.02 二次设计确认
G/14.02.03 设备订货、加工
G/14.02.04 消防系统安装
G/14.02.05 安装结束
G/15 弱电工程
G/15.01 弱电工程合同运作
G/15.01.01 系统功能确定
G/15.01.01.01 楼宇自控系统
G/15.01.01.02 有线及卫星电视系统
G/15.01.01.03 综合布线系统
G/15.01.01.04 保安监控及广播系统
G/15.01.01.05 红机电话手机直放系统
G/15.01.01.06 车库管理系统
G/15.01.01.07 业主确定系统功能
G/15.01.02 编制招标文件
G/15.01.03 招标文件讨论
G/15.01.04 招标文件报业主审批
G/15.01.05 确定投标单位
G/15.01.06 发标
G/15.01.07 回标
G/15.01.08 评标
G/15.01.09 编制评标报告
G/15.01.10 确定中标单位
G/15.01.11 签订施工合同
G/15.02 执行弱电工程合同
G/15.02.01 二次设计
G/15.02.02 二次设计确认
G/15.02.03 设备订货、加工
G/15.02.04 弱电系统集成
G/15.02.04.01 楼宇自控系统安装调试
G/15.02.04.02 有线及卫星电视系统安装调试
G/15.02.04.03 综合布线系统安装调试
G/15.02.04.04 保安监控及广播系统安装调试
G/15.02.04.05 红机电话手机直放系统安装调试
G/15.02.04.06 车库管理系统安装调试
G/15.02.05 弱电系统验收
H 市政工程
H/01 图纸及报装
H/01.01 施工总平面图
H/01.02 完善其它报装
H/01.03 确定各管口位置
H/01.04 竖向平面图
H/01.05 市政管线综合图
H/01.06 各专业设计单位问题协调
H/01.07 完成市政工程设计
H/02 市政施工
H/02.01 供电工程
H/02.01.01 报装
H/02.01.02 施工图设计
H/02.01.03 施工
H/02.01.04 竣工验收
H/02.02 排水系统
H/02.02.01 报装
H/02.02.02 施工图设计
H/02.02.03 施工
H/02.02.04 竣工验收
H/02.03 电信工程
H/02.03.01 报装
H/02.03.02 施工图设计
H/02.03.03 施工
H/02.03.04 竣工验收
H/02.04 有线电视工程
H/02.04.01 报装
H/02.04.02 施工图设计
H/02.04.03 施工
H/02.04.04 竣工验收
H/02.05 供水开通
H/02.06 热水开通
H/02.07 燃气工程
H/02.07.01 报装
H/02.07.02 工程设计
H/02.07.03 燃气内管线施工
H/02.07.04 燃气外管线施工
H/02.07.05 燃气内外管线连接
H/02.07.06 燃气内外管线验收
H/02.08 园林绿化工程
H/02.08.01 报装
H/02.08.02 施工图设计
H/02.08.03 施工
H/02.08.04 竣工验收
H/02.09 室外照明工程
H/02.09.01 报装
H/02.09.02 施工图设计
H/02.09.03 施工
H/02.09.04 竣工验收
H/02.10 雨污水及道路工程
H/02.10.01 报装
H/02.10.02 施工图设计
H/02.10.03 施工
H/02.10.04 竣工验收
H/02.11 其它市政工程
I 验收、移交
I/01 电梯验收
I/02 人防工程验收
I/03 消防工程验收
I/04 项目竣工验收
I/05 项目竣工备案
I/06 办理结算手续

发表在 项目管理 | 留下评论

公司VS小公司—-大公司学做人,小公司学做事


大学毕业求职,安安被一家著名的跨国公司录用,佳雯只能屈就一间小公司。安安喜不自禁,佳雯略感委屈。

安安每天挤地铁,穿套装,就像标准的公司白领。在这家大公司里,安安觉得自己就是流水线上的一个零件,随着非常有规律的流程运转,周而复始,天天如此。

而佳雯是一间小公司的出纳、秘书兼行政助理,穿休闲装还是套装没人规定,基本上她得视当天的工作状况而定。因为,她每天的日程不定,从公司注册到开银行户头,同文具商、家具商、展商或者广告商讨价还价,与物业管理处、税务局、工商局打交道,到处寻找打折机票,给客户订合他们心意的酒店,甚至给老板买晚报,帮老板娘到“杏花楼”门口排队领月饼等等等等。整天跑来跑去,佳雯觉得自己像一个打杂的。偶尔做些会议记录、回复信函、资料翻译的时候,她才有一点白领的感觉。

两年之后,安安的公司裁员,安安非常倒霉,名列其中。安安忽然发现,离开了大公司的流水线,自己似乎一无所长。她的确非常“专业”,但安安从事的这份专业在当年的职业市场上并不走俏。安安换了一家小公司,原以为自己出身“大家”,应付这样的小地方绰绰有余,没想到自己如同刚刚入行的新生,没有了流水线,她还真的不知道从何做起。
而佳雯重新去招聘中心的时候,发现自己跟两年前真的不可同日而语,同什么人都能聊出道道来,非常胸有成竹,对她感兴趣的单位不少。想起当年自己进小公司时,有经验的长者曾经安慰她道:“大公司学做人,小公司学做事。”不知从什么时候开始,自己已经成了职场“万金油”,佳雯想起来就欣喜不已。

发表在 项目管理 | 留下评论

VS2005 快捷键(shortcut)

vs2005常用快捷键

调试快捷键
F6: 生成解决方案
Ctrl+F6: 生成当前项目
F7: 查看代码
Shift+F7: 查看窗体设计器
F5: 启动调试
Ctrl+F5: 开始执行(不调试)
Shift+F5: 停止调试
Ctrl+Shift+F5: 重启调试
F9: 切换断点
Ctrl+F9: 启用/停止断点
Ctrl+Shift+F9: 删除全部断点
F10: 逐过程
Ctrl+F10: 运行到光标处
F11: 逐语句
编辑快捷键
Shift+Alt+Enter: 切换全屏编辑
Ctrl+B,T / Ctrl+K,K: 切换书签开关
Ctrl+B,N / Ctrl+K,N: 移动到下一书签
Ctrl+B,P: 移动到上一书签
Ctrl+B,C: 清除全部标签
Ctrl+I: 渐进式搜索
Ctrl+Shift+I: 反向渐进式搜索
Ctrl+F: 查找
Ctrl+Shift+F: 在文件中查找
F3: 查找下一个
Shift+F3: 查找上一个
Ctrl+H: 替换
Ctrl+Shift+H: 在文件中替换
Alt+F12: 查找符号(列出所有查找结果)
Ctrl+Shift+V: 剪贴板循环
Ctrl+左右箭头键: 一次可以移动一个单词
Ctrl+上下箭头键: 滚动代码屏幕,但不移动光标位置。
Ctrl+Shift+L: 删除当前行
Ctrl+M,M: 隐藏或展开当前嵌套的折叠状态
Ctrl+M,L: 将所有过程设置为相同的隐藏或展开状态
Ctrl+M,P: 停止大纲显示
Ctrl+E,S: 查看空白
Ctrl+E,W: 自动换行
Ctrl+G: 转到指定行
Shift+Alt+箭头键: 选择矩形文本
Alt+鼠标左按钮: 选择矩形文本
Ctrl+Shift+U: 全部变为大写
Ctrl+U: 全部变为小写
代码快捷键
Ctrl+J / Ctrl+K,L: 列出成员
Ctrl+Shift+空格键 / Ctrl+K,P: 参数信息
Ctrl+K,I: 快速信息
Ctrl+E,C / Ctrl+K,C: 注释选定内容
Ctrl+E,U / Ctrl+K,U: 取消选定注释内容
Ctrl+K,M: 生成方法存根
Ctrl+K,X: 插入代码段
Ctrl+K,S: 插入外侧代码
F12: 转到所调用过程或变量的定义
窗口快捷键
Ctrl+W,W: 浏览器窗口
Ctrl+W,S: 解决方案管理器
Ctrl+W,C: 类视图
Ctrl+W,E: 错误列表
Ctrl+W,O: 输出视图
Ctrl+W,P: 属性窗口
Ctrl+W,T: 任务列表
Ctrl+W,X: 工具箱
Ctrl+W,B: 书签窗口
Ctrl+W,U: 文档大纲
Ctrl+D,B: 断点窗口
Ctrl+D,I: 即时窗口
Ctrl+Tab: 活动窗体切换
Ctrl+Shift+N: 新建项目
Ctrl+Shift+O: 打开项目
Ctrl+Shift+S: 全部保存
Shift+Alt+C: 新建类
Ctrl+Shift+A: 新建项

发表在 ASP.NET | 留下评论

C# 使用Outlook Interface

*HOWTO:
The examples in this file are adapted for use from the
Professional VSTO 2005 edition published by Wiley
Each method illustrates a code listing in the chapter.
The solution represents a chapter.

To execute the examples, simply uncomment the relevant example
and run the solution from the Visual Studio Environment. Since
binaries are not included, you must compile the solution.

In some cases, there may be multiple handlers for one event.
The additional handlers are commented out. You will need to
uncomment the relevant handler to cause the code to work correctly.

For file loads, the actual file data is added as a file to the
solution. You will need to provide the fully qualified file path
to cause the application to run without error. The file path must
point to the file on disk. By default, the file is found in
the working folder directory. A sample file, data.txt is part of the project.

Where necessary, the excel spreadsheet contains data to cause
some examples to execute correctly. Additionally, controls may
already be present on the design surface as well.

A more detailed explanation of the code is already presented in the
chapter.
*/

using System;
using System.Windows.Forms;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
using System.Runtime.InteropServices;
using System.Reflection;

namespace AllSamples
{
    public partial class ThisApplication
    {
        private void Listing_5_1()
        {
            if (this.Session.Folders.Count > 0)
            {
                Outlook.MAPIFolder folder = this.Session.Folders[1];
                {
                    MessageBox.Show("The " + folder.Name + " folder contains " + folder.Items.Count + " items.");
                }
            }
        }
        private void Listing_5_2()
        {
            Outlook.MAPIFolder folder = this.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
            Outlook.Explorer explorerWindow = this.Explorers.Add(folder, Outlook.OlFolderDisplayMode.olFolderDisplayNormal);
            explorerWindow.Activate();
        }
        private void Listing_5_3()
        {
            Outlook.Application ol = new Microsoft.Office.Interop.Outlook.Application();
            Outlook.MailItem NewMail = ol.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem) as Outlook.MailItem;
            Outlook.Inspector inspectorWindow = this.Inspectors.Add(NewMail);
            inspectorWindow.Activate();
        }
        //to run this example, add a valid email address in the to field
        private void Listing_5_4()
        {
            CreateAndSendEmail();
        }
        public void CreateAndSendEmail()
        {
            Outlook.Application ol = new Microsoft.Office.Interop.Outlook.Application();
            Outlook.MailItem NewMail = ol.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem) as Outlook.MailItem;
            NewMail.Subject = "This is my email subject";
            NewMail.To = "Add a valid email address here";
            NewMail.Importance = Microsoft.Office.Interop.Outlook.OlImportance.olImportanceNormal;
            NewMail.HTMLBody = "This <u>is</u> truly <b>amazing</b>";
            NewMail.BodyFormat = Microsoft.Office.Interop.Outlook.OlBodyFormat.olFormatHTML;
            NewMail.Send();
        }
        private void Listing_5_5()
        {
            BlockAttachments();
        }
        private void BlockAttachments()
        {
            Outlook.MAPIFolder inbox = Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);

            if (inbox.Items.Count > 0)
            {
                foreach (object item in inbox.Items)
                {
                    Outlook.MailItem virus = item as Outlook.MailItem;
                    if (virus != null)
                    {
                        if (virus.Attachments != null)
                        {
                            System.Collections.ArrayList forbidden = new System.Collections.ArrayList(virus.Attachments.Count);
                            foreach (Outlook.Attachment attachObject in virus.Attachments)
                            {
                                object obj = attachObject.MAPIOBJECT;
                                if (obj != null)
                                {
                                    attachObject.Delete();
                                    forbidden.Add(attachObject.DisplayName);
                                }
                            }
                            if (forbidden.Count > 0)
                            {
                                MessageBox.Show("Some emails were blocked because they contain attachments");
                            }
                        }
                    }
                }
            }
        }
        private void Listing_5_6()
        {
            //creat the outlook appointment
            Outlook.Application appItem = new Microsoft.Office.Interop.Outlook.Application();
            Outlook.AppointmentItem appointment = appItem.CreateItem(Outlook.OlItemType.olAppointmentItem) as Outlook.AppointmentItem;

            //set up some custom features
            appointment.Subject = "This is my new appointment subject";
            appointment.Body = "This is my new appointment body";
            appointment.AllDayEvent = true;
            appointment.BusyStatus = Outlook.OlBusyStatus.olBusy;
            appointment.Start = DateTime.Now;
            appointment.End = DateTime.Now.AddMinutes(30);
            appointment.ReminderSet = true;
            appointment.Importance = Microsoft.Office.Interop.Outlook.OlImportance.olImportanceHigh;

            //activate
            appointment.Save();
        }
        //to fire this code, we first need to subscribe tot he newinspector event
        //after the application is run, trigger a newinspector object by double-clicking
        //on an email item, or a contact item etc.
        private void Listing_5_7()
        {
            Inspectors.NewInspector += new Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);
        }
        void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
        {
            if (this.Inspectors.Count > 0)
            {
                object item = this.Inspectors[1].CurrentItem;
                Type type = item.GetType();
                string propertyMapper = type.InvokeMember("MessageClass",
                BindingFlags.Public | BindingFlags.GetField | BindingFlags.GetProperty, null, item, new object[] { }).ToString();
                if (propertyMapper == "IPM.Note")
                {
                    Outlook.MailItem note = item as Outlook.MailItem;
                    if (note != null)
                    {
                        if (!note.IsConflict)
                        {
                            Outlook.Conflicts conflicts = note.Conflicts;
                            if (conflicts.Count < 1)
                            {
                                string subject = note.To;
                                MessageBox.Show("The email is addressed to " + subject);
                            }
                            System.Runtime.InteropServices.Marshal.ReleaseComObject(note);
                        }
                    }
                }
            }
        }
        private void Listing_5_8()
        {
            DeleteAppointments("This is my new appointment subject");
        }
        public void DeleteAppointments(string item)
        {
            Outlook.MAPIFolder oCalendar = Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
            string retVal = string.Empty;

            foreach (Outlook.AppointmentItem oResult in oCalendar.Items)
            {
                if (oResult != null)
                {
                    retVal = (string)oResult.GetType().InvokeMember("Subject", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.GetProperty, null, oResult, null, null);
                    if (retVal == item)
                    {
                        oResult.Delete();
                    }
                }
            }
        }
        //the code below demonstrates adding appointments. You will need to replace the
        //i.ToString() with valid attendees
        private void Listing_5_9()
        {
            //creat the outlook appointment
            Outlook.Application appItem = new Microsoft.Office.Interop.Outlook.Application();
            Outlook.AppointmentItem appointment = appItem.CreateItem(Outlook.OlItemType.olAppointmentItem) as Outlook.AppointmentItem;

            Outlook.Recipients attendees = appointment.Recipients;
            //add meeting participants
            for (int i = 0; i < 10; i++)
            {
                Outlook.Recipient developer = attendees.Add(i.ToString());
                developer.Type = (int)Outlook.OlMeetingRecipientType.olRequired;
            }
            //activate
            appointment.Send();
        }
        private void Listing_5_10()
        {
            Outlook.Application ol = new Microsoft.Office.Interop.Outlook.Application();
            Outlook.NoteItem NewNote;
            //Create a new note
            NewNote = ol.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olNoteItem) as Outlook.NoteItem;
            NewNote.Body = "This is my new note body";
            NewNote.Categories = "Memo";
            NewNote.Display(false);
        }
        private void Listing_5_11()
        {
            Outlook.Application ol = new Microsoft.Office.Interop.Outlook.Application();
            Outlook.NoteItem NewNote;
            //Create a new note
            NewNote = ol.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olNoteItem) as Outlook.NoteItem;
            object modal = true;
            NewNote.Body = "Holiday 2morrow";
            NewNote.Categories = "Business";
            NewNote.Height %= 2;
            NewNote.Color = Outlook.OlNoteColor.olBlue;
            NewNote.Display(modal);
        }
        private void Listing_5_12()
        {
            Outlook.MAPIFolder itemsBox = Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderDeletedItems);
            if (itemsBox.Items.Count > 0)
            {
                foreach (object item in itemsBox.Items)
                {
                    Outlook.MailItem oItem = item as Outlook.MailItem;
                    if (oItem != null)
                    {
                        //code to process items
                    }
                }
            }
        }
        private void Listing_5_13()
        {
            GetInfoFromAddressBook("contact", "enter search name here");
        }
        private Outlook.AddressEntry GetInfoFromAddressBook(string contact, string name)
        {
            if (name == null || name.Trim().Length == 0)
                return null;
            if (contact == null || contact.Trim().Length == 0)
                contact = "Contacts";

            contact = contact.Trim();
            name = name.Trim();

            if (Session.AddressLists != null && Session.AddressLists.Count > 0)
            {
                Outlook.AddressLists addressLists = Session.AddressLists as Outlook.AddressLists;
                foreach (Outlook.AddressList address in addressLists)
                {
                    if (address.Name.Trim() == contact)
                    {
                        foreach (Outlook.AddressEntry entry in address.AddressEntries)
                        {
                            if (entry.Name.Trim() == name)
                            {
                                return entry;
                            }
                        }
                    }
                }
            }
            return null;
        }
        private void Listing_5_14()
        {
            this.MAPILogonComplete += new Microsoft.Office.Interop.Outlook.ApplicationEvents_11_MAPILogonCompleteEventHandler(ThisApplication_MAPILogonComplete);
        }
        void ThisApplication_MAPILogonComplete()
        {
            MessageBox.Show("Welcome " + this.GetNamespace("MAPI").CurrentUser.Name.ToString());
        }
        //this routine searches the inbox folder for emails matching the subject "virus"
        private void Listing_5_15()
        {
            SearchRoutine("virus");
        }
        public void SearchRoutine(string searchToken)
        {
            Outlook.MAPIFolder oInbox = Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
            int count = oInbox.Items.Count;
            string retVal = string.Empty;

            foreach (object oResult in oInbox.Items)
            {
                retVal = (string)oResult.GetType().InvokeMember("Subject", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.GetProperty, null, oResult, null, null);
                if (retVal == searchToken)
                {
                    MessageBox.Show("Found a suspicious item");
                }
            }
        }
        private void Listing_5_16()
        {
            //OutlookSearch.Properties.
            Outlook.MAPIFolder oInbox = Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
            object oResult = oInbox.Items.Find(@"[Subject] = ""virus""");

            if (oResult != null)
            {
                Outlook.MailItem data = (Outlook.MailItem)oResult;
                if (data != null)
                {
                }
            }
        }
        private void Listing_5_17()
        {
            Outlook.MAPIFolder oInbox = Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
            object oResult = oInbox.Items.Find(@"[Subject] = ""virus""");
            do
            {
                oResult = oInbox.Items.FindNext();
            } while (oResult != null);

            Outlook.MailItem data;
            if (oResult != null)
            {
                MessageBox.Show("Found");
                data = (Outlook.MailItem)oResult;
            }
        }
        private void Listing_5_18()
        {
            string scope = @"’Inbox’";
            string filter = @"""subject"" LIKE ‘%vir%’";
            string tag = "uniqueTag";
            object subFolders = false;

            this.AdvancedSearchComplete += new Microsoft.Office.Interop.Outlook.ApplicationEvents_11_AdvancedSearchCompleteEventHandler(ThisApplication_AdvancedSearchComplete);
            this.AdvancedSearch(scope, filter, subFolders, tag);
        }
        //event handler code. Notice that this code is different from the text in the book
        //the reason for this change is that the advancedsearchcomplete method executes on
        //a separate thread that isn’t allowed to manipulate GUI objects that are part of
        //Outlook. The access simply causes a run-time exception. The code has been simplified
        //to show an appropriate message.
        void ThisApplication_AdvancedSearchComplete(Microsoft.Office.Interop.Outlook.Search SearchObject)
        {
            if (SearchObject != null)
            {
                MessageBox.Show("A piece of mail with subject ‘virus’ was found");
            }
        }
        //to run this example, add a valid email address in the to field
        private void Listing_5_19()
        {
            Outlook.MailItem NewMail = this.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem) as Outlook.MailItem;
            NewMail.Subject = "This is my email subject";
            NewMail.To = "vapordan@hotmail.com";
            NewMail.Send();
        }
        Office.CommandBar NewCommandBar;
        Office.CommandBarButton NewCBarButton;
        Office.CommandBars newCommandBar;
        Outlook.Explorer explorer;
        private void Listing_5_20()
        {
            explorer = this.ActiveExplorer();
            newCommandBar = explorer.CommandBars;

            object val = false;
            NewCommandBar = newCommandBar.Add("myButton", Office.MsoBarPosition.msoBarTop, false, false);
            NewCBarButton = (Office.CommandBarButton)NewCommandBar.Controls.Add(Office.MsoControlType.msoControlButton, missing, missing, missing, false);
            NewCBarButton.Caption = "button1";
            NewCBarButton.FaceId = 563;
            NewCommandBar.Visible = true;
            NewCBarButton.Visible = true;
            NewCBarButton.TooltipText = "My new button1";
            NewCBarButton.Click += new Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(NewCBarButton_Click);
        }

        void NewCBarButton_Click(Microsoft.Office.Core.CommandBarButton Ctrl, ref bool CancelDefault)
        {
            MessageBox.Show("Hello, world!");
        }
        private void Listing_5_21()
        {
            Outlook.Explorer explorer = this.ActiveExplorer();
            Office.CommandBars newCommandBar = explorer.CommandBars;

            //do not replicate command bar objects
            foreach (Office.CommandBar cmdBar in newCommandBar)
            {
                if (cmdBar.Name.Equals("ShortcutBar"))
                {
                    cmdBar.Delete();
                    break;
                }
            }
        }
        Office.CommandBar menubar;
        Office.CommandBarPopup cmdBarControl;
        Office.CommandBarButton menuCommand;
        private void Listing_5_22()
        {
            // Add the menu.
            menubar = this.ActiveExplorer().CommandBars.ActiveMenuBar;
            cmdBarControl = (Office.CommandBarPopup)menubar.Controls.Add(
            Office.MsoControlType.msoControlPopup, missing, missing, menubar.Controls.Count, true);
            if (cmdBarControl != null)
            {
                cmdBarControl.Caption = "&Add-in Tools";
                // Add the menu command.
                menuCommand = (Office.CommandBarButton)cmdBarControl.Controls.Add(
                Office.MsoControlType.msoControlButton, missing, missing, missing, true);
                menuCommand.Caption = "&Word Count…";
                menuCommand.Tag = DateTime.Now.ToString();
                menuCommand.Click += new Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(menuCommand_Click);
            }
        }
        void menuCommand_Click(Microsoft.Office.Core.CommandBarButton Ctrl, ref bool CancelDefault)
        {
            MessageBox.Show("Hello, World!");
        }
        //to run this example, pass in the string identifier of the bar to be removed
        private void Listing_5_23()
        {
            RemoveMenubar("statusbar");
        }
        private void RemoveMenubar(string menuTitle)
        {
            //remove the menu
            try
            {
                Office.CommandBarPopup foundMenu = (Office.CommandBarPopup)
                    this.ActiveExplorer().CommandBars.ActiveMenuBar.
                    FindControl(Office.MsoControlType.msoControlPopup,
                    missing, menuTitle, true, true);
                if (foundMenu != null)
                {
                    foundMenu.Delete(true);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        //the following start up event handler is designed to call the code for each
        //example in chapter 5. To run these examples, uncomment the appropriate function
        private void ThisApplication_Startup(object sender, System.EventArgs e)
        {
            //Listing_5_1();
            //Listing_5_2();
            //Listing_5_3();
            //Listing_5_4();
            //Listing_5_5();
            //Listing_5_6();
            //Listing_5_7();
            //Listing_5_8();
            //Listing_5_9();
            //Listing_5_10();
            //Listing_5_11();
            //Listing_5_12();
            //Listing_5_13();
            //Listing_5_14();
            //Listing_5_15();
            //Listing_5_16();
            //Listing_5_17();
            //Listing_5_18();
            //Listing_5_19();
            //Listing_5_20();
            //Listing_5_21();
            //Listing_5_22();
            //Listing_5_23();
        }

        private void ThisApplication_Shutdown(object sender, System.EventArgs e)
        {
        }

        #region VSTO generated code

        /// <summary>
        /// Required method for Designer support – do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisApplication_Startup);
            this.Shutdown += new System.EventHandler(ThisApplication_Shutdown);
        }

        #endregion
    }

发表在 ASP.NET | 留下评论

.Net Remoting 接口通信

在程序间通信

过去几年来,我们一直处于 Microsoft 为 Web 服务所发起的营销宣传的包围之中,但是它已经使人对不同的程序间的通信技术产生了错误的印象。Web 服务对于某些场合确实很好,但其他一些技术也是值得考虑的。

其中最重要的一种技术是 .NET 远程处理,当您在连接的两端都使用 .NET 时,该技术将很有用。您可以以透明方式使用任何类型,而不会被限制为 SOAP 类型。

简单的远程处理示例

作为示例,我将为媒体播放机程序生成一个远程控件。我将在一台计算机上运行该播放机程序,而从另一台计算机上远程控制该程序。

第一步是定义一个接口,以描述可以做的事情。服务器端对象将实现该接口,而客户端将基于该接口执行调用。严格说来,我不需要做这项工作。如果我在客户端使用服务器端类型,.NET 远程处理仍然可以很好地工作,但如果我那样做的话,客户端将需要访问服务器端对象,而这样并不好。所以,我将定义一个接口,然后将其放在类库对象中:

namespace RemotingLibrary
{
   public interface IPlayer
   {
      void Play();
      void Pause();
      string GetCurrentSong();
   }
}

下一步,我将在服务器上工作。我知道我需要一个对象来实现该接口,因此我从编写该对象开始。

using System;
using System.Runtime.Remoting;
using RemotingLibrary;

namespace RemotingServer
{
   public class MyRemote: MarshalByRefObject, IPlayer
   {
      public MyRemote()
      {
      }

      public void Pause()
      {
         // TODO:  Add MyRemote.Pause implementation
      }

      public void Play()
      {
         // TODO:  Add MyRemote.Play implementation
      }

      public string GetCurrentSong()
      {
         return "Devo - Girl U Want";
      }
   }
}

我已经为 GetCurrentSong() 植入了一些测试代码,从而可以检查我所得到的结果。注意,MyRemote 类型是从 MarshalByRefObject 派生的。要想从远程处理机制中使用对象,这是其中一项要求。这一点比较遗憾,因为这意味着我不能对该对象使用我自己的基类。

接下来,需要编写服务器代码。我将稍经修改的 MSDN 示例作为服务器代码的基础。

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
namespace RemotingServer
{
   class Server
   {
      public static void Main()
      {
         TcpChannel m_TcpChan = new TcpChannel(9999);
         ChannelServices.RegisterChannel(m_TcpChan);
         RemotingConfiguration.RegisterWellKnownServiceType(
               typeof(MyRemote),
               "MyRemote", WellKnownObjectMode.SingleCall);
         System.Console.WriteLine("Press ENTER to quit");
         System.Console.ReadLine();
      }
   }
}

这些代码似乎要比想象中的简单。在端口 9999 上打开了一个 TCP 信道,注册该信道,然后将我的类型注册为可以远程使用的类型。完成这一工作后,运行库将为我处理所有事情,所以我只须静静地等待。

要编写的最后一部分代码是客户端代码。

using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using RemotingLibrary;
namespace RemotingClient
{
   class RemoteClient
   {
      public static void Main()
      {
         TcpChannel tcpChan = new TcpChannel();
         ChannelServices.RegisterChannel(tcpChan);
         IPlayer player = (IPlayer)
            Activator.GetObject(typeof(IPlayer),
            "tcp://localhost:9999/MyRemote");
         Console.WriteLine(player.GetCurrentSong());
      }
   }
}

该类引用了我在前面创建的接口库。它创建了一个 TcpChannel 并将其注册,但不是在特定端口上创建。然后,它使用 Activator 类连接到远程对象,调用 GetCurrentSong(),并写出返回值。完整示例位于 RemotingToAType 子目录中。

如果我愿意,我可以通过更改到 http 信道,将我的示例转换成 Web 服务的样子。该示例位于 RemoteToATypeSoap 子目录中。您可以通过向字符串末尾添加“?wsdl”,将该服务器添加为 Web 引用,那样它就能像任何其他 Web 服务一样工作。不过,在 MSDN 中有一条重要的注意事项,声明虽然这对 WSDL 有效,但无法创建 XSD,因而可能无法对将来的工具起作用。

这是一个很不错的示例,尽管实际上它并没有让我向目标前行多少,因为所创建的对象与正在运行的应用程序没有任何联系。我希望远程控制服务器上正在运行的实例,而不是刚刚创建的实例。换一种说法,就是我不希望这是一个无状态模型。

远程控制实例

在我编写第一个版本后,我开始研究以便搞清楚如何对一个实例做同样的事情。我试图查找名为 RegisterInstance 的例程,或者与此类似的东西,但我的搜索失败了。

在使用 Google 进行了一番千辛万苦的搜索之后,我发现了一个这样的例程,但它的名称为“Marshal”。这个名称在我的文章中不是太好,因为它与我要完成的工作没有任何关系,但既然我知道了这个例程,我就可以修改我的代码。为此,我需要对 Server 类进行一些小的改动:

      public static void Main()
      {
         MyRemote myRemote = new MyRemote("The Scorpions - Always Somewhere");
         TcpChannel m_TcpChan = new TcpChannel(9999);
         ChannelServices.RegisterChannel(m_TcpChan);
         RemotingServices.Marshal(myRemote, "MyRemote");
         System.Console.WriteLine("Press ENTER to quit");
         System.Console.ReadLine();
      }

在这些代码中,我创建了 MyRemote 类的一个实例,然后使用 Marshal 注册了该实例。我还修改了 MyRemote 类,使它采用歌曲名称作为参数,这只是为了表明我确实在与该实例进行通信。

这些代码非常不错,简单并且有效,它们位于 RemotingToAnInstance 目录中。该示例仅仅涉及到远程处理技术的一些粗浅内容,实际上,在使用什么样的信道、使用什么样的安全性以及何时执行身份验证等方面都具有相当大的灵活性。如果使用 ASP.NET 作为宿主,其中大多数事情都更加容易做到。

发表在 ASP.NET | 2条评论

用VS.NET2003制作WEB应用程序的安装包

用vs.net2003来制作一个安装程序是非常的方便的,既使是制作一个web应用程序的安装程序也是如此。仅仅简单的几个步骤就可以完成。

首先,创建一个安装和部署项目。步骤如下:
1.在"解决方案资源管理器"中的解决方案中添加一个新项目。
用鼠标右键单击解决方案,在弹出的菜单中选择"添加"->"新建项目"。在打开的对话框中选择"安装和部署项目",并选择"Web安装项目"模板。在输入项目名称后,点击"确定"按钮,将新项目添加到解决方案中。
2.将项目的输出添加到安装和部署项目中。
 添加完安装和部署项目后,vs.net2003 IDE会自动打开一个名为"文件系统"的管理器。用鼠标右键单击此管理器右边树型结构中的"Web应用程序文件夹",在弹出的菜单中选择"添加"->"项目输出"。在弹出的对话框中,选择"项目"(这时只有一个,就是你的web应用程序项目),然后在下面的列表中选择"主输出"和"内容文件"两项(可以复选),接着在"配置"中选择"Release .NET",点击"确定"按钮。

经过上面两个步骤,一个基本的安装和部署程序就制作完成了,将此项目编译后就得到了一个Web安装程序包。

然而,在很多的情况下,我们做的Web应用程序都要使用到数据库,能不能在安装程序的同时也将数据库一起安装呢?答案是肯定的。那该怎么做呢?这个问题李洪根先生已经解决了,具体内容可以参看下面的文章
http://blog.csdn.net/lihonggen0/archive/2004/05/17/13654.aspx
在李洪根先生的这篇文章中详尽的介绍了安装程序的制作和如何同时安装数据库。在此大致叙述如下:
1.新建一个类库项目,删除自动生成的Class.cs,重新添加一个新项。鼠标右键此项目,在弹出的菜单中选择"添加"->"添加新项",在弹出的对话框中选择"安装程序类"。
2.创建一个自定义的安装对话框。鼠标右键点击"解决方案资源管理器"中的安装和部署项目,在弹出的菜单中选择"视图"->"用户界面"。在打开的"用户界面"管理器中,鼠标右键点击"启动",在弹出的菜单中选择"添加对话框"。在打开的对话框中选择"文本框(A)"。选择"文本框(A)",在属性中,依次设置含Property属性为CUSTOMTEXT1,CUSTOMTEXT2,CUSTOMTEXT3,CUSTOMTEXT4。
3.创建自定义操作。鼠标右键点击"解决方案资源管理器"中的安装和部署项目,在弹出的菜单中选择"视图"->"自定义操作"。在打开的"自定义操作"管理器中,鼠标右键点击"安装",在弹出的菜单中选择"添加自定义操作"。在打开的对话框中,在"查找范围"中选择"Web应用程序文件夹",选择下面列表中的"主输出来自Install1(活动)"(Install1是"安装程序类"所在的项目名。如果列表中没有,可以用上面提到的"将项目的输出添加到安装和部署项目中"的方法添加)。然后在"自定义操作"管理器中选择刚添加的内容,在属性窗口中设置CustomActionData属性/dbname=[CUSTOMTEXT1] /server=[CUSTOMTEXT2] /user=[CUSTOMTEXT3] /pwd==[CUSTOMTEXT4] /targetdir="[TARGETDIR]\"
注意:每个设置内容以/分隔,且以空格分开。
4.在此类中重写Install方法,并添加下面的代码
string strConn=String.Format("data source={0};user id={1};password={2};",this.Context.Parameters["server"],this.Context.Parameters["user"],this.Context.Parameters["pwd"]);
this.ExecuteSQL(strConn,"master","CREATE DATABASE "+this.Context.Parameters["dbname"]);

System.Diagnostics.Process pSQL=new System.Diagnostics.Process();
pSQL.StartInfo.FileName="osql.exe";
pSQL.StartInfo.Arguments=String.Format(" -U {0} -P {1} -d{2} -i {3}db.sql",this.Context.Parameters["user"],this.Context.Parameters["pwd"], this.Context.Parameters["dbname"],this.Context.Parameters["targetdir"]);
pSQL.StartInfo.WindowStyle=System.Diagnostics.ProcessWindowStyle.Hidden;
pSQL.Start();
pSQL.WaitForExit();
pSQL.Close();
这样,编译后的安装程序就可以连数据库一起安装了。

安装数据库的问题解决了,还有一个问题,那就是要使ASP.NET程序运行,一个重要的条件就是目标计算机上必须有.NET框架,那能不能在安装程序时也一同将.NET框架一块安装了呢?答案还是肯定的。具体可以参看
http://www.microsoft.com/china/MSDN/library/netFramework/netframework/Nfdnnetdepvsredistdeploy1_1.mspx
在这篇文章中提到了几种不同的方法重新分发.NET框架,其中最简单的一种应该算是使用VS.NET2003了。大致的步骤如下:
1.安装VS.NET框架引导程序插件。这个插件可以从微软的网站上下载,下载地址如下:
http://www.microsoft.com/downloads/details.aspx?familyid=627921a0-d9e7-43d6-a293-72f9c370bd19&displaylang=en
2.在"解决方案资源管理器"中,用鼠标右键单击安装和部署项目,在弹出的菜单中选择"视图"->"启动条件",打开"启动条件"管理器。
3.在"启动条件"管理器中,右键点击"目标计算机上的要求",在弹出的的菜单中选择"添加注册表启动条件"。你会发现在"搜索目标计算机"中多了一项"搜索 RegistryEntry1",在"启动条件"中多了一项"Condition1"。
4.选择"搜索 RegistryEntry1",在"属性"对话框中填写如下内容:
Property:MDACSEARCH
RegKey:Software\Microsoft\DataAccess
Root:vsdrrHKLM
Value:FullInstallVer
选择"Condition1" ,在"属性"对话框中填写如下内容:
Condition:MDACSEARCH>="2.6"
进行这一步是因为在安装.NET框架的时候需要MDAC。

OK,现在编译安装和部署项目,就得到了一个可以同时安装.NET框架的安装程序了

发表在 ASP.NET | 留下评论