前期说明:在Project2007中可以选择一个团队项目(TFS),然后在Project2007中排好进度,作为工作项发布到TFS服务器上。之后可以直接作为工作项在VS2005等工具中填写项目进度。本文的目的就是要显示出TFS中保存的实时项目进度情况等。
技术说明:在Project2007之前的版本可以通过oledb的方式直接读取project的mpp文件来显示进度,在project2007时不再提供oledb的方式了,可能的两种实现方法有:
1、使用Project2007提供的COM接口,读取mpp文件中的任务 + TFS中的实时进度
2、把所有的进度安排(包括父任务)发布到TFS中,直接读取TFS中的实时进度
一、COM接口的方式
Code
private void Bind()
{
//Interop Com方式
MSProject.ApplicationClass app = null;
ArrayList taskList = new ArrayList();
try
{
//try
//{
// app = (MSProject.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("MSProject.Application");
//}
//catch (Exception ex)
//{
// //
//}
// execute the Microsoft Project Application
app = new MSProject.ApplicationClass();
// Do not display Microsoft Project
app.Visible = false;
// open the project file.
app.FileOpen(mppFileName, true, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, MSProject.PjPoolOpen.pjPoolReadOnly, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
// go through all the open projects--there should only be one
foreach (MSProject.Project proj in app.Projects)
{
// go through all the tasks in the project
foreach (MSProject.Task task in proj.Tasks)
{
ProTask proTask = new ProTask();
int iTaskLevel = task.OutlineLevel;
for (int j = 0; j < iTaskLevel; j++)
{
proTask.TaskName += " ";
}
proTask.TaskName += task.Name;
proTask.StartDate = Convert.ToDateTime(task.Start);
proTask.FinishDate = Convert.ToDateTime(task.Finish);
//项目进度从TFS服务器中取得
//proTask.PCT = task.PercentComplete.ToString() + "%";
proTask.PCT = GetPCTFromTFS(task.Text10);
proTask.Resources = task.ResourceNames;
taskList.Add(proTask);
}
}
gvTask.DataSource = taskList;
gvTask.DataBind();
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (app != null)
{
app.Quit(MSProject.PjSaveType.pjDoNotSave);
}
}
}
private string GetPCTFromTFS(string id)
{
if (string.IsNullOrEmpty(id))
{
return "";
}
string strSql = "Select [Microsoft.VSTS.Scheduling.RemainingWork],[Microsoft.VSTS.Scheduling.CompletedWork],[Microsoft.VSTS.Scheduling.TaskHierarchy] from workitems where id=" + id;
WorkItemStore Store = new WorkItemStore(tfsServer);
WorkItemCollection wicollection = Store.Query(strSql);
if (wicollection.Count > 0)
{
float RemainingWork = Convert.ToSingle(wicollection[0]["Microsoft.VSTS.Scheduling.RemainingWork"]);
float CompletedWork = Convert.ToSingle(wicollection[0]["Microsoft.VSTS.Scheduling.CompletedWork"]);
if ((int)CompletedWork == 0)
{
return "0%";
}
else if ((int)RemainingWork == 0)
{
return "100%";
}
else
{
float Rate = CompletedWork / (CompletedWork + RemainingWork);
Rate = Rate * 100;
string strRate = Convert.ToString(Rate);
if (strRate.Length > 2)
{
strRate = strRate.Substring(0, 2);
}
return strRate + "%";
}
}
return "";
}
这种方式我就不具体说了,可以看代码中的注释。采用这种方式有几个问题:
速度比较慢;b/s结构时有点问题;
经常报错:异常详细信息: System.Runtime.InteropServices.COMException: 消息筛选器显示应用程序正在使用中。试了一些解决方案,好像都不行的。
二、直接读取TFS的方式
主意思路是:在TFS中定制一个新的工作项类型,其中包含一个新的工作项字段(项目分解结构);设置Project和TFS之间同步哪些字段,把新的字段包含进去;在Project中使用这个新的工作项类型;使用TFS SDK读出进度情况。
主要分成以下几个步骤进行:
(以下的command命令都是在VS2005命令提示窗口输入的)、
1、加入新的工作项类型
用以下命令导出原有的工作项类型:
然后编辑这个xml文件,以下文件中红色的部分是修改的地方: