Project Programmability

This blog focuses on customizations and programming for Project Web App, Project Server, Project Professional and Project Standard. Includes User Interface (UI) customizations, Project Server Interface (PSI) and Visual Basic for Applications (VBA) Programming. It also covers Business Intelligence.

  • Project Programmability and Business Intelligence

    ANNOUNCING: Project 2010 Solution Starters and related resources available!


    We are proud to announce that we have developed number of Solution Starters and Code Samples to help you achieve result quickly with implementing Project 2010. All mentioned Solution Starters are available for free download on the MSDN Code Gallery -

    - including documentation, ready to deploy packages and full source code. We have also conducted number of free webcasts that introduce the functionality of these Solution Starters – including how to benefit from their functionality, how to deploy them and even deep technical dive into the source code if you want to start building on top of them.

    List of the Project 2010 Solution Starters currently* available

    · Demand Management Export & Import Tool - Example of how a partner can export and package EPTs and all other associated entities (Stages, Phases, PDPs, CFs, …) so that customers can import as a single SharePoint feature.

    · Bulk Edit Tool - Tool to edit project custom fields simultaneously.

    · Bulk Import Tool (a.k.a. SharePoint To Project Importer) – Tool to import projects from a SharePoint List.

    · Dynamic Workflow - Dynamically create a linear workflow based on stages.

    · EPT Association Tool - A tool that creates an intuitive unified hierarchical view that allows a user to easily create and maintain EPTs, by seeing all of the individual stages, PDPS, and custom fields all in the same place.

    · InfoPath Form Viewer Web Part - View and Edit an InfoPath Form in a PDP. This is most commonly used to allow users to fill out a survey.

    · Project Workspace List Viewer Excel Project Cost Capture - A web part that allows users to view and edit list from the Project Workspace.

    · Workflow Visualization Web Part - A web part that visually represents the workflow and allows users to track where they are in the workflow.

    · Report Builder Tool - Tool to create an excel report with the SQL connection already configured.

    · Workspace Project Custom Field Web Part - Web part to display Project Custom Fields on the Workspace.

    · Excel Project Cost Capture - Example of using Excel to create/capture financials

    * As of 6/28/2010. We are working on others and we will continuously update and add new ones and announce them on the Project Programmability & BI Blog.

    Webcast series on Project 2010 Solution Starters





    Webcast URL

    MSDN Webcast: Project 2010 Solution Starters (Part 1 of 2): Achieve Results Quickly


    This Web Casts will go over the user experience of these tools.

    Sam Chung, Program Manager, Microsoft Corporation

    MSDN Webcast: Project 2010 Solution Starters (Part 2 of 2): Achieve Results Quickly


    This Web Casts will go over the user experience of these tools.

    Sam Chung, Program Manager, Microsoft Corporation

    MSDN Webcast: Project 2010 Solution Starters Drilldown & Code Walkthrough (Part 1 of 4)


    This webcast drills down and provide detailed code-level walkthrough for Bulk Edit and Bulk Import Solution Starters.

    Mike Shughrue, Principal Consultant, Microsoft Corporation

    MSDN Webcast: Project 2010 Solution Starters Drilldown & Code Walkthrough (Part 2 of 4)


    This webcast drills down and provide detailed code-level walkthrough for Demand Management Import, Export and Association Tool Solution Starters.

    Mike Shughrue, Principal Consultant, Microsoft Corporation

    MSDN Webcast: Project 2010 Solution Starters Drilldown & Code Walkthrough (Part 3 of 4)


    This webcast drills down and provide detailed code-level walkthrough for Sequential Workflow Builder, Workflow Visualization Solution Starters.

    Mike Shughrue, Principal Consultant, Microsoft Corporation

    MSDN Webcast: Project 2010 Solution Starters Drilldown & Code Walkthrough (Part 4 of 4)


    This webcast drills down and provide detailed code-level walkthrough for Project Detail Pages extensions using Excel Services and Forms Services - Cost and Benefit, InfoPath/Forms Services Form Viewer Web part Solution Starters.

    Mike Shughrue, Principal Consultant, Microsoft Corporation


    Q: Where do I learn more about these solution starters?

    A: We suggest that the best resources are the webcasts, the included documentation and solution starters themselves.

    Q: What if I have a question or want to report an issue?

    A: Please check the related discussion for answers or post your question or feedback there.

    Other Project 2010 Resources

    Product information and trial download

    o Main product site

    o Project Team Blog

    End-User Product Help

    o Project 2010 Help

    o Project Server 2010 Help

    Interactive content – Videos/Sessions/Webcasts

    o Quick Start Training -

    o Project Video Channel -

    o Project Webcasts -

     IT Professional related – TechNet

    o TechCenter

    o Admin Blog

    Developer related - MSDN

    o Developer center

    o Programmability blog

    Project & Project Server 2010 Demo Image

    o Download

    o Hosted Virtual Lab

    Got questions? Search or ask in the official Microsoft Forums


    SharePoint 2010 Resources



  • Project Programmability and Business Intelligence

    Statusing Transactions (Partial Documentation)



    Unlike the project Web Access “My Tasks” web part, the Statusing web service API restricts team member task assignment updates that combine with the create/reassign action to one per approval cycle. This means that once a create/reassign plus updated status is submitted it cannot be further updated until accepted or rejected by the Project Manager.

    This limitation is caused by the absence of “Node Consistency” functionality in the API. This component ensures that the task is kept schedule consistent during team member updates. The project Server 2007 architecture placed this component on the Project Web Access web front end server, rather than in the Project Server Interface business object layer, so as to deliver a responsive user experience in the UI.

    Unfortunately the application developer who is tasked with synchronizing status with an external system (such as an ERP or CRM system) has no means to detect this “blocked” status. We plan to add such a method in an upcoming release of Project Server. In the interim this documentation can be used to extend the Project Server Interface to add a web service/method to deliver the status update status.

    Note: This document contains interim documentation for tables in the Published database of a RTM-edition Project Server 2007 installation. Entities in this schema are subject to change without notice. This documentation is made available on a “best efforts” basis, Microsoft Product Support Services have not been trained in its usage and will not offer technical support for issues related to custom queries against this schema. This schema should not be updated by custom code, any updates to the data may break Project client cache code.

    Extending the Project Server Interface

    This is documented in the following Project Server 2007 Software Development Kit article.

    Note that any code will be required to connect to the Project Server 2007 Published database – in a single site farm this may safely be hard coded, however in a multi-site farm it is recommended that the developer implement a method for connecting to the correct published database, suggestions include:

    • Using the SharePoint site-id to index into an INI file with the correct connection string stored as an external string
    • Passing the database (and SQL Server name) as method arguments.

    Understanding the MSP_ASSIGNMENT_TRANSACTIONS Table

    All status updates are stored in the MSP_ASSIGNMENT_TRANSACTIONS table together with flags indicating the current state of the update. The flags necessary to locate a blocked task assignment are documented below.


    There are four ENUM fields that govern state, these are:

    Attribute Value Enumeration
    Not Submitted
    Submitted Pending Approval
    Approved or Rejected
    Task Assignment Update
    Declined Task Assignment
    Create Task Request
    Delegate Task Assignment Request
    Create Task Assignment Request
    Team Delegation Request
    Delete Task Request
    Delete Task Assignment Request
    InvalidUpdate; InvalidDelegation

    So a blocked task assignment and will have ASSN_TRANS_STATE_ENUM = 1 (pending approval) and ASSN_TRANS_TYPE_ENUM = 2,3,4 (indicating a pending task assignment add/change)

    SQL Server query to test the status of a particular task assignment:
    WHERE ASSN_UID = '617633E6-8B2A-4620-BCAD-F82A95AD398D' -- Assignment UID 

    If the task assignment status update is not blocked then no data will be returned; if it is blocked then a scalar value of integer 1 will be returned.

    See comments in the performance section before changing this query.

    Security Considerations

    PSI Extensions are responsible for implementing their own security. In this case there are mitigations which mean that additional permissions checks may be unnecessary:

    • All callers must be authenticated users making anonymous DoS attacks impossible
    • The proposed solution returns a single numeric result that indicates if the assignment is blocked (1) or not (null)
    • The argument is a UUID – these are very hard to predict/guess so it isn’t possible to cycle through a sequence hunting for hits
    • If an attacker discovers that a particular assignment UID is blocked then there is little they can do with that information
    • The call is extremely performant

    Note that it would be simple to make the call as the “interface user” and test for that in the PSI extension should further restrictions be required.

    Performance Notes

    The above query has been optimized for performance – strictly speaking the query is stronger than required as only the second task assignment status update is blocked by the pending approval. However checking for this first pending update would require the addition of a self-join to the query which would reduce performance considerably. This would test for the above condition AND a pending task assignment status update (ASSN_TRANS_TYPE_ENUM = 0). Provided the work is added in the same ChangeXML payload that changes the task assignment, it is superfluous.

    It is recommended that a query covering index be created on the MSP_ASSIGNMENT_TRANSACTIONS table to avoid both clustered index scans, secondary index scans or bookmark lookups as the table is indexed on a non-sequential UUID (so data access will be very random).

    The following index definition is suggested:

      [ASSN_UID] ASC, 
    ) ON [PRIMARY]

    The sample query (above) uses a TOP 1 clause to further reduce the SQL Server results processing (either no rows or a scalar result set will be returned).

    If you alter the query to return more data, or to use different search arguments then this index definition might need to change.

    Note that creating a stored procedure and using output parameters would further improve performance.


    Patrick Conlan

  • Project Programmability and Business Intelligence

    Building Web Parts using VS.NET extensions for SharePoint


    Mike McDonogh sent us this recommendation:


    If any of you are planning on building web parts for Project Server 2007 I’d HIGHLY recommending using the VS.NET extensions for SharePoint.



    The trick to get it working in VS.NET 2005 so that it will run in Project Server Sites is as follows:


    1.    Create a new Web Part project

    2.    Open the class and change the code System.Web.UI.WebControls.WebParts.WebPart to Microsoft.SharePoint.WebPartPages.WebPart

    3.    Create a DWP file, Project Web Access site required a DWP file to be imported

    <?xml version="1.0"?>

    <WebPart xmlns="">

       <Assembly>DynamicProjectRegistratonModule, Version=, Culture=Neutral, PublicKeyToken=99646028e7d67527</Assembly>

       <TypeName> DynamicProjectRegistratonModule.RegisterProjectWP</TypeName>

       <Title>Web part for registering new projects in Project Server</Title>

       <Description>You can put a description here.</Description>


    4.    Click deploy in Visual Studio.NET


    Why would you want to use the extensions [huge time saver]:


    ·         Build the Web Part assembly.

    ·         Package the Web Part solution as a Windows SharePoint Services Feature.

    ·         If this Web Part solution was deployed previously, the extensions retract the previous version of the Web Part solution Feature.

    ·         Updates the web.config safe controls settings automatically.

    ·         Install your Web Part assembly to the global assembly cache.

    ·         Deploy and activate your Web Part solution Feature in Windows SharePoint Services.

    ·         Add your Web Part to the SafeControls list.

    ·         Restart Microsoft Internet Information Services (IIS) by invoking the iisreset command.

    ·         Attach to the w3wp processes to enable debugging.

    ·         Packaging for deployment to QA/DEV/Production in VS.NET is easy.

  • Project Programmability and Business Intelligence

    Agile Custom Project Guide


    In 2003, we released an Agile custom Project Guide, based on MSF for Agile Software Development methodology (which is scenarios driven , context based, Agile software development process).  We have been able to get it working for Project 2007 as well.  The Agile Project Guide allows the project manager to easily implement the Agile methodology for their projects, by outlining the Agile process and offering templates for process documentation.

    The Agile Project Guide integrates with Microsoft Office Project 2007 in order to manipulate tasks within the project plan itself and provides context sensitive task/resource information in the project guide panel.


    Here is what you need to do to get the Agile custom Project Guide working:

    1.      Download the attached zip file that contains the Agile Custom Project Guide files to your local machine

    2.      Launch Project 2007 client,

    3.      Enable the Project Guide from the View menu or just go to Tools | Options | Interface and select the “Display Project Guide” checkbox

    From the Tools | Options menu | Interface tab

    4.      Select the “Use a custom page” radio button (from the “Project Guide Functionality and Layout Page:” section)

    a.      Click the Browse button and point to the mainpage.htm file, in the Agile Project Guide folder you’ve copied locally in step 1

    5.      Select the “Use custom content” radio button (from the “Project Guide Content:” section)

    a.      Click the Browse button and point to the AgileGuide.xml file, in the Agile Project Guide folder you’ve copied locally in step 1

    6.      Click Ok on the main dialog

    7.      You should now see the Agile Custom Project Guide






    Due to the size of the Zip file, I need to split the file into two. This post has the first file. I will do a second post that will have the second file attached.


  • Project Programmability and Business Intelligence

    Working with Deliverables


    The other day I had a request from an internal customer that wanted to create deliverables for a large number of tasks that already existed in their project plan. They wanted to be able to simply flag each task as a deliverable and have it published. They did not want to do all the steps involved with creating a deliverable. 

    They also wanted to tightly couple the task name and dates with the deliverable name and dates. Currently, if a deliverable is linked to a task, when the task’s dates change, the dates for the deliverable do not. This is by design to allow the project manager to intentionally make the change to the deliverable dates since these dates are commonly published to a large audience. In this case, the user wanted the deliverable dates to change with the task dates with minimum user intervention.

    To get started, I created a flag enterprise custom field. The custom field that I created was "Pub Deliverable" and it is a task custom field. I added the field to the Gantt Chart view in Project Professional:

    Next, I wrote the following VBA macro:

    Sub Create_Flagged_Tasks_As_Deliverables()
        Dim t As Task
        Dim fPub As String

        For Each t In ActiveProject.Tasks

            ' This gets the flag value from the Enterpise Custom Field
            fPub = t.GetField(FieldNameToFieldConstant("Pub Deliverable"))
            If fPub = "Yes" Then
                ' If the task has this deliverable GUID, then there is no deliverable
                If t.DeliverableGuid = "00000000-0000-0000-0000-000000000000" Then
                    DeliverableCreate t.Name, t.Start, t.Finish, t.Guid
                    DeliverableUpdate t.DeliverableGuid, t.Name, t.Start, t.Finish
                End If
                If t.DeliverableGuid <> "00000000-0000-0000-0000-000000000000" Then
                    DeliverableDelete (t.DeliverableGuid)
                End If
            End If
        Next t
    End Sub

    This macro loops through all the tasks. If the flag field "Pub Deliverable" is set to yes, then it either creates or updated the deliverable. If it is set to no and there is a deliverable associated with the task, the deliverable is deleted.

    Before you can run this code, you will need to publish and create a workspace for your project. To run it, follow these steps:

    1. Open your Project Plan

    2. Press Alt+F11 – This will open the VBA Editor

    3. Double click on ThisProject Object:

    4. Copy the VBA code into the Object

    5. Run it by clicking on the Play button:

    With this solution, the user can simply flag each task that they want published as a deliverable and run the macro. If you want to have this code executed regularly without user intervention, you might want to consider placing this code in an event handler (VBA Event Handler Example).

    Chris Boyd

  • Project Programmability and Business Intelligence

    Getting at the Task Time Phased Data


    I have been asked many times how to get the task time phased data from the PSI. Unfortunately there is no way to get this through the PSI. I suggest that you either go to the RDB for this information or the cubes. Here is a quick example.

    I created a project with one task and broke the work down over a week:


    I saved and published the project so that it would make its way into the reporting database. Here is the query I wrote to retrieve this data:

        INNER JOIN MSP_EpmTask_UserView 
    ON MSP_EpmAssignmentByDay_UserView.TaskUID = MSP_EpmTask_UserView.TaskUID WHERE (MSP_EpmTask_UserView.TaskName = 'Task 1')

    Here is the result of the query:

    Chris Boyd

  • Project Programmability and Business Intelligence

    Checking Errors

    Here is a great recommendation from Jim Corbin:

    There are two main places to check for configuration and runtime errors when you are developing solutions for Project Server. The Unified Logging Service (ULS) trace logs can be more detailed than the application event log.

    · Application events   In the Start menu on the Project Server computer, click Run, and then type eventvwr. In the left pane of the Event Viewer window, click Application to see the events logged by Project Server, Windows SharePoint Services, ASP.NET, SQL Server, custom event handlers, and other applications. The Project Server event sources include ProjectQueueService and pjevtsvc.

    · ULS You can configure the ULS trace log to record specific or all categories and levels of activities in Project Server and SharePoint. To view the trace logs, you can use Windows Notepad, Microsoft Excel, or the Log Viewer add-in feature for SharePoint. Log Viewer is a useful download that is available from CodePlex.

    To configure the ULS trace log for a specific Project category:

    1. Open the SharePoint 3.0 Central Administration application, click Operations, and then click Diagnostic logging in the Logging and Reporting section.

    2. In the Event Throttling section, select a specific category such as Project Server - Server-Side Events. If you select Project Server - General, all Project categories will be logged.

    3. Select the Verbose level for the least critical event to report in the trace log.

    Caution   Run verbose logging only when you need it. Especially on a production server, select only a specific category. The size of logs can grow to be large. To turn off all logging, select the empty category and None for the trace log least critical event. To record relatively few events, select High or Monitorable.

    4. Use the default path for the trace logs, for example, C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\LOGS\. If you use the Log Viewer add-in for SharePoint, it looks for trace logs in the default path.

    5. The default maximum number of log files to maintain is 96.

    6. The default number of minutes to use a log file is 30. That is, ULS tracing creates a new log file after 30 minutes. Log files include the date and time in the filename, for example, SERVERNAME -20070424-1612.log.

    To use the Log Viewer add-in for SharePoint:

    1. Download and install the Log Viewer feature from CodePlex SharePoint 2007 Features. See the Releases tab for the list of downloads. The release notes include installation instructions.

    2. The Log Viewer is a global feature. After it is installed, click Operations on the Central Administration page, and then click View Unified Logging Service in the Utilities section.

    3. On the Unified Logging Service (ULS) Logs page, select a file to view, and then select the Project Server category. That shows all of the specific categories such as Project Server Queue, Project Server Server-Side Events, Project Server Reporting, and so forth.

    4. To see all events in the ULS log, leave the trace severity drop-down list blank. If you select Verbose, that shows only the verbose level events.

    5. Click Go.

    Log Viewer add-in for SharePoint showing a ULS log for Project


  • Project Programmability and Business Intelligence

    ANNOUNCING: Microsoft Project 2010 Demonstration and Evaluation Installation Pack for RTM is HERE!


    This is a great news! We have just released the Microsoft Project 2010 Demonstration and Evaluation Installation Pack that builds on top of 2010 Information Worker Demonstration and Evaluation Virtual Machine  that SharePoint team has released recently. And yes the Virtual Image that has to be downloaded, imported and running prior to installing “our” Microsoft Project 2010 Demonstration and Evaluation Installation Pack.

    We also advice to watch the following webcast: Project 2010 Virtual Image, Getting Started Quickly (Level 100) 


    - End to end project lifecycle


    - New Business Intelligence story!


    - Built on top of common 2010 Information Worker Demonstration and Evaluation Virtual Machine  using NEW Project 2010 Demo Installation Platform


    Demo storyline

    It follows the life of a project from inception through to completion! Demo storyline offers a comprehensive overview of the new and existing capabilities in:

    · Microsoft Project Professional 2010

    · Microsoft Project Server 2010

    · Microsoft SharePoint 2010 products and technologies

    · Microsoft Office 2010 Products

    More information about the Project 2010 Demo Solution in this comprehensive XPS document (also available on the download page

    Project 2010 Demo Installation Platform

    We have published the entire source code of the Project 2010 Demo Installation Platform so us and partners could extend on it and built future demo packs for Project 2010!


    Q: Do I need to download, import and run the 2010 Information Worker Demonstration and Evaluation Virtual Machine ( before installing the Microsoft Project 2010 Demonstration and Evaluation Installation Pack?

    A: Absolutely yes. Refer to this comprehensive XPS document for more details.

    Q: Could I install this Microsoft Project 2010 Demonstration and Evaluation Installation Pack on any other VM, including Project 2010 Beta?

    A: No.

    Q: Is there anything around evaluation period and expiration I need to pay attention to?

    A: Please follow information included with 2010 Information Worker Demonstration and Evaluation Virtual Machine to properly understand procedure like re-arming and activation so you can prevent lot of unpleasant surprises!!!

    Q: Any recommended hardware for good performance?

    A: Yes -  we specify the additional HW requirements in this comprehensive XPS document. We recommend Solid State Drive for great performance. More about HW we use for demoing here.

    Q: How long does it take to install the Microsoft Project 2010 Demonstration and Evaluation Installation Pack on top of 2010 Information Worker Demonstration and Evaluation Virtual Machine?

    A: If the above VM is already running and working properly it takes up to 30 minutes. If you are using Solid State Drive it’s usually around 10 minutes.

    Q: What is in the Microsoft Project 2010 Demonstration and Evaluation Installation Pack?

    A: We have packaged the following content: 4 core Project databases, 1 SharePoint Content database, 1 OLAP Database, number of WSP customizations (check the Solution Starter webcast series here if you want to learn more), additional demo files and PowerShell script for configuring and deploying the whole solution. So that’s it in a nutshell. Check this link for more details

    Q: Could I only extract the Microsoft Project 2010 Demonstration and Evaluation Installation Pack?

    A: Yes, we have included that option as well based on the demand, but it’s intended for expert use only.

    Q: What if I have additional questions about this Project 2010 Demo Solution?

    A: You have several options – please check this webcast and search or post your questions in this forum.

  • Project Programmability and Business Intelligence

    Writing a PSI Extension for Project Server 2010


    The blog articles How to make PSI Extensions in Project Server 2010 - Part I and  Part II show how to create and use a simple PSI extension that reads a list of timesheets for the current user, by calling both the GetCurrentUserUid method and the ReadTimesheetList method in the extension. The code in the articles requires using the undocumented Microsoft.Office.Project.Server.Interfaces.dll and Microsoft.Office.Project.Server.Schema.dll assemblies, creates WCF channels for the Resource and Timesheet services, and then returns an XML string of the results.

    The blog articles show more information about using WCF development in Project Server than the Project 2010 SDK includes. For background information about why PSI extensions in Project Server 2010 are different than extensions in Project Server 2007, read those articles.

    The PSI Extensions in Project Server 2010.docx article in the attachment ( shows how to create and use a PSI extension that makes the same calls as in the previous blog, but with the following differences:

    • Use the Resource and Timesheet proxy service files, instead of the undocumented assemblies.
    • Configure the services programmatically, similar to the same way shown in Walkthrough: Developing PSI Applications Using WCF, instead of creating a WCF ChannelFactory.
    • Return a TimesheetListDataSet, instead of a string.
    • Use an app.config file for the client, as with any other PSI service, instead of creating a ChannelFactory.

    The attachment includes the draft article, complete code of the extension and a test application, and examples of the PSIExtensions.svc and web.config files for the PSI.


  • Project Programmability and Business Intelligence

    Reading Assignment Enterprise Custom Field Values with VBA



    There has been a number of people asking how to read assignment enterprise custom field values with VBA. In fact, we ran into this issue internally with our dogfood efforts and fixed it in SP1. So, if you need to get/set assignment custom field values, the first step is to download SP1:

    Once you have SP1 installed, it is fairly easy to read assignment enterprise custom fields. When you read and set task and resource enterprise custom fields, you use the GetField and SetField methods in VBA. To read and set the assignment values you don't use the GetField and SetField, but instead use the name of the enterprise custom field as a property of the assignment.  There are a couple of caveats, however:

    • The field name can't contain spaces in the name
    • When you're writing your code, you won't get auto complete to show you the field name. This is because the property isn't a part of the type library and therefore isn't early bound.  As long as you pass in a valid field name, however, then the code will late bind to it. 

    Here is a short example. Suppose your custom Field name is "ecfName", here is how you would read it:

    For Each T in ActiveProject.Tasks

      If Not (T is Nothing) Then

        For Each A in T.Assignments

          assignCFVal = A.ecfName

        Next A

      End If

    Next T

    Chris Boyd

  • Project Programmability and Business Intelligence

    Publishing Projects based off a Project Custom Field Value



    As part of the development process for the next version of Project, we are heavily relying on Project to manage all the work that is happening across team. As part of the process, we require up to date status reports. All the work is spread across 40 project plans, so we cannot rely on PMs publishing projects daily. To ensure the status reports are up to date, we publish all the projects nightly by running a custom application as a scheduled Windows task:



    Since we only want to publish our team's projects and cannot publish other teams projects on the server, we tag all of our team projects with text custom fields that have associated lookup table to ensure that everyone on the team is using the same tags:


    To setup the custom field and lookup tables:

    1. Log onto Project Server as an Administrator
    2. Click on "Server Settings" then click on "Enterprise Custom Field Definition"
    3. Scroll to the bottom of the page and click "New Lookup Table". We created a lookup table called "Office Division", which has all the divisions within Office:

    4. Next, create a custom field, which we called "Office Division", and associate it to the lookup table:


    The application to publish the projects nightly is attached to this post. It is a fairly simple application. At the top of the program class, we have set a few constants. If you wanted to try out this application, you should just have to change these constants and compile the application. These constraints are self explanatory:

    const string ls_projURL = "http://Office/PWA/";     // Server URL
    const string ls_CustomField = "Office Division";    // Custom Field 
    const string ls_LookupTableValue = "Project";       // Value in the lookup table

    Once we had the application built, we simple set up a scheduled task in Windows to run the application nightly:


    Chris Boyd

  • Project Programmability and Business Intelligence

    Update of Project 2010 SDK–Online and Download


    The Project 2010 SDK download and the MSDN online release are both updated. The updates have the same URLs as previous releases:

    New conceptual / how-to topic:

    ·Topic updates for MSDN online, since the last update on March 7, 2011:
    20 conceptual and how-to topics have updates. Most changes are relatively minor; the Change History table at the bottom of each topic shows significant changes.

    • Assn Element
    • ChangeList Elements
    • ChangeList Schema Reference
    • Developing Project Server Workflows
    • How to: Create a Project Server Event Handler and Log an Event
    • How to: Create a Proxy Assembly for WCF Services (SP1 note)
    • How to: Modify the Ribbon in PWA
    • Introduction to the ChangeList Schema and Statusing ChangeXML
    • Introduction to the SetAssignmentWorkData Schema
    • Prerequisites for ASMX-Based Code Samples (SP1 note)
    • Prerequisites for WCF-Based Code Samples (SP1 note)
    • Project 2010 SDK Documentation (overview of the Project 2010 SDK)
    • Project Server 2010 Programming Tasks
    • Project Server Error Codes
    • SetAssignmentWorkData Elements
    • SetAssignmentWorkData Schema Reference
    • Supported Project Fields and Field Information for Statusing ChangeXML (updated the valid change types for the Actual Overtime Work and Remaining Overtime Work fields)
    • Tables of VBA Object Model Changes
    • Walkthrough: Developing PSI Applications Using WCF
    • What's New for Developers in Project 2010 (programmability changes for SP1)

    600 managed code types (classes that include new descriptions for one or more properties, methods, and events) are updated. There are new code samples for the following PSI methods:

    • QueueDeleteProjects
    • ReadResource
    • UpdateStatus
    • ReadProjectStatus
    • SubmitStatusForResource
    • ReadStatusForResource
    • ReadEventHandlerAssociationsForEvent
    • UpdateEventHandlerAssociations
    • CreateEventHandlerAssociations

    New / updated items in the Project 2010 SDK download, which was last updated March 7:

    • Project2010SDK.chm is an HTML Help file that includes the same updated content that is online. In the managed code reference section, 99.8% of the types and members now have descriptions (26,530 out of a total 26,576 topics). That is up from 77.7% at RTM.
    • WINPROJ.DEV.hxs remains unchanged from the March update of VBA Help. There are instructions for replacing the local VBA Help file that was shipped with the Project RTM release.
    • IntelliSense files are updated for the PSI proxy assembly and the Project Server assemblies, to show descriptions of classes and members while programming in Visual Studio. The type and member descriptions have the same updates as in the HTML Help file (and in MSDN online).
    • The Microsoft.Office.Project.Server.Library.dll assembly is updated for distribution with third-party solutions for SP1.
    • Event handler solution: TestProjectEventHandlers.
    • Test application for the Queue System: UsingQueueSystem shows an example of when to wait for the queue, and when you don’t need to wait.
    • ProjTool has a minor update, so the functionality of the Project Details dialog matches the description in Using the ProjTool Test Application.
    • New PSI code samples include complete WCF-based solutions for the following events: ProjectEventReceiver: OnCreating, OnCreated, OnSaved. Other new solutions show the use of the following PSI methods: QueueDeleteProjects, CreateEventHandlerAssociations, UpdateEventHandlerAssociations, ReadEventHandlerAssociationsForEvent, using the ReadResources and ReadResource methods to get the RBS custom field, creating a changeXml parameter for a different resource with the UpdateStatus method, and using SubmitStatusForResource and ReadStatusForResource.
  • Project Programmability and Business Intelligence

    How to use the “Skip to Stage” Feature in Project Server 2010 Workflows



    The skip to stage feature is designed to allow administrators the ability to restart a workflow and have it attempt to skip along the workflow until it reaches a particular stage. A common scenario for this functionality is when a project has progressed to a specific point in a workflow, but needs to be pushed back to a previous stage due to any number of reasons, such as, a new stage was inserted that needs to be addressed, certain fields need to be changed that are exposed only in previous stages, etc.

    Project Server workflows, like SharePoint workflows, must always be executed linearly. They cannot begin execution at random locations within a workflow. Neither can they “jump” from one point to another point, unless coded to do so within the workflow. The skip to stage functionality cannot circumvent this limitation. As such, the issue with restarting a workflow and attempting to push it to a particular point is that any activities which “stopped” the workflow before will continue to do so again. For Example, activities such as SetProjectStage, OnProjectSubmit, OnProjectCommit, the officeTask, ect, will still cause the workflow to dehydrate and give control back to the user. Although for the SetProjectStage activity we have done some extra work and put logic inside it so that it can be skipped, so long as there are no required fields left in the stage

    Therefore, to fully work with the skip to stage functionality you will need to wrap activities within “if statements”. When an administrator restarts a workflow and chooses to skip to a certain stage, we pass into the workflow two properties. The first property indicates that a skip stage command has been sent, and the second property contains the stage Guid that the workflow should stop at. Our SetProjectStage activity reads these two variables and skips if the first variable is set to true, and if the current stage is not the stage that is set in the second property. However, it won’t skip if there are required fields in the stage. So you will need to mimic this behavior around your other activities. You should wrap all of the activities between the SetProjectStage activities (not including the SetProjectStage activity) with an ifElseActivity statement that checks the first Property.

    Customizing Workflows in Visual Studio to work with skip to stage

    To make any workflow work correctly with the skip to stage functionality an “if statement” should be placed around all of the activities between each of the SetProjectStages. The key example of when this would be necessary is for the office task activities.

    Screen shot of example workflow:


    In the above example the “ifElseActivity1” is used to bypass the leadApproval sequence activity, which contains all of our approval activities.

    As you can see from the above screen shot, it is the “if statement” that we need to figure out how to code. In order to do so, we need to be aware of the two properties that are passed into the workflow during a skip to stage event:

    WorkflowContext.SkipToStage : Boolean : If true, a skip to stage functionality has been requested

    WorkflowContext.StageUid : Guid : Guid of the stage the workflow should skip to

    Steps for creating the workflow:

    1. Insert and set the properties of a SetProjectStage activity

    · You will need to set the “AlwaysWait” property to True in order for the Skip to Stage scenario to properly work.

    · If you do not set the Always wait property to true the workflow may not be able to skip to and stop at previous stages.


    2. Insert an IfElseActivity

    3. Have the activity check the “projectSequence1.WorkflowContext.SkipToStage” variable.

    · If variable is set to false, execute all activities

    · Else, bypass



    The WorkflowContext.StageUid is not needed for the “If Statement” but is there in case you wish to check what stage the user is trying to skip to.

    *The complete above example is found in the attached Visual Studio solution.*

    Administration: Initiating the Skip to Stage feature

    To attempt to force a project to skip to a particular stage, do the following within Project Server.

    1. Log into Project Server as an Administrator

    2. Go to Server Setting


    3. Click on “Change or Restart Workflows”


    4. In the top drop down, select the EPT that the project(s) that you would like to restart and skip to a stage belong to.

    5. Select the project(s) which you would like restart and skip to stage from the left panel and add them to the right panel.


    6. Check the “Restart current workflow for the selected projects” option


    a. Alternatively you can also select the “Associate projects with a new Enterprise Project Type:” option. If you select an Enterprise Project Type that has a workflow associated with it, you can then select which stage in that workflow the project(s) should attempt to skip to.

    7. Next select which stage the project(s) should attempt to skip to

    a. Skip until the current workflow stage

    i. Selecting this option will tell the projects to attempt to skip until they reach the stage that the project(s) are in currently

    b. Skip to a particular workflow stage & then selecting a particular stage

    i. Selecting this option will tell the projects to attempt to skip until they reach the stage that has been selected

    ii. If the selected stage does not exist, the workflow will stop at the very first opportunity.

    8. Press OK

    9. The project restart jobs will be sent to the queue, and the projects will attempt to restart and skip.

    Skip to Stage Example

    Expected behavior of the skip to stage can be summed up by the following example.

    · A workflow has 3 stages

    · All stages are marked as “AlwaysWait”

    · Project is on Stage 2

    · Stage 1’s required custom fields are filled out

    · Stage 2’s required custom fields are not filled out

    · Stage 3’s required custom fields are not filled out

    Administrator will go and:

    o Restart Skip to current stage

    § This will make the workflow restart and stop at stage 2

    o Restart Skip to stage 1 (trying to make the workflow stop on a stage where all of the require custom fields are filled out)

    § This will make the workflow stop at stage 1 and wait for submit

    o Restart Skip to stage 3 (trying to make it jump over stage 2 even though its required custom fields are not yet filled out)

    § Workflow will stop at stage 2

    § Workflow will not be able to skip stage2 if it has required fields.

    § If you really want to skip it, you need wrap the SetProjectStage as well in an if/else skip condition, which checks the SkipToStage variable and the StageUid variable.

    o Restart Skip to stage 5 (trying to make the workflow stop on a stage that does not exist)

    § Workflow will stop at stage 1. This is because of the combination of “Destination stage” doesn’t exist & current stage=”Always wait”.


    This feature has been designed and created to address the majority of our customer needs when it comes to being able to skip between stages. In this blog we reviewed there are two steps to use this feature. The first is to correctly develop your workflows to be able to skip over the activities that are between the SetProjectStage activities. This is done by wrapping the activities within an ifElse activity. And the second stage is to restart the workflows and select the stage the project should attempt to skip to. This is done with Project Server --> Server Settings --> Change or Restart Workflows.

    If you have any additional questions please feel free to post comments, and I will follow up accordingly.

  • Project Programmability and Business Intelligence

    Technical Resources on Workflow/Demand Management in Project Server 2010



    This blog entry is designed to try and capture all of the different pieces of information that exists right now regarding workflows in Project Server 2010.  Based on the feedback we are in process of creating a dedicated “Demand Management” resource center on Microsoft TechNet that will became the “one-stop” shop for all your technical and developer resources for Demand Management, including Workflows in Project 2010.


    Demand Management in Project Server 2010


    Developing Project Server Workflows:

    Out of the Box Sample Workflow Source Code:

    Download the SDK: and find the source code in the “Samples\Workflow\SampleProposal2” directory

    Sharepoint Office Task Class:

    Using InfoPath Forms in a Workflow:


    Introduction to Demand Management:

    End User level Walkthrough of the Out of the Box Sample Workflow:

    How to use the Skip to Stage Feature:

    Debugging a Project Server Workflow in Visual Studio 2010

    Solution Starters (Open Source Solution Starters)

     Microsoft Project 2010 Solution Starters

    Recorded Videos:

    Demand Management Overview:

    Workflow Deep Dive:


    Demand Management Overview:

    Part 1:

    Part 2:

    Part 3:

    Part 4:

    Workflow Deep Dive:

    Part 1:

    Part 2:

    Tailored Tools for Workflow Creation:

    Project Forum:,projectprofessional2010/

    Project Server 2010 Demonstration Virtual Machine Image Download:

    Hitchhiker’s Guide to Demand Management (white paper)

  • Project Programmability and Business Intelligence

    Creating Deliverable Reports


    I have had many questions with regards to the Deliverables feature and reporting. If your not familiar with Deliverables, I suggest you take a look at my blog post on the Project blog:

    Just like all other project data, when a project plan is published, the data makes it way to the reporting database. This allows you to create some very useful reports on deliverables and dependencies. To get started with reporting, you may want to read through this post:

    In this post, I am only going to provide some background information on Deliverables and a couple of queries to get you started with creating your own reports. To begin with, these are the views and tables that are most commonly used for Deliverable reports:


    This view shows all the projects. Commonly you will join the Project UID in this view with the Project UID or the Relationship UID from the other views. By doing this you can get information about the project the deliverable or dependency is associated with, such as the name of the project.

    This view lists all the published deliverables, not the dependencies. In this view you can get information such the UID for the project a deliverable is associated with and the start and finish date of a deliverable.

    This is the same at the MSP_WssDeliverableToProjectLinks_UserView except that is has additional fields for deliverables that are linked to tasks. This allows you to report on task details for the associated deliverable. For example, you could use the task information to write a report that shows all deliverables where the deliverable finish date is before the task finish date.

    This view shows all the different associates with risks, issues and deliverables. Here you are going to want to look at the relationship type ID. The relationship type ID tells you if it is a deliverable or a dependency and if it is linked to a task or not. It is also where you can find if a dependency exists.

    This table lists the different types. These types refer to risks, issues and deliverables. For deliverables and dependencies, the following types are important:

    Relationship Type ID


    11 This is a deliverable that is linked to a task.

    This is a dependency on a deliverable that is linked to a task. 


    This is a deliverable for a project. It is not linked to any task within the project.


    This is a dependency on a deliverable for a project. It is not linked to any task within the project.

    There are a set of common queries that user tend to want when creating a report for deliverables. This first query is a simple list of all the deliverables and what project they are associated with:

    	ProjectName As 'Project Name', 
    	Title As 'Deliverable', 
    	StartDate As 'Start Date', 
    	FinishDate As ' Finish Date'
    	Inner Join MSP_EpmProject_UserView 
          	On 	MSP_WssDeliverableToProjectLinks_UserView.ProjectUID =

    The following query lists all the projects that have taken dependencies on a deliverable for given project. For the query to work, you need to set ProjectSelect.

    	DeliverableProj.ProjectName AS SelectedProject,
    DependancyProj.ProjectName AS DependentProject,
    DeliverableLinks.Title, DeliverableLinks.StartDate, DeliverableLinks.FinishDate FROM MSP_EpmProject_UserView AS DeliverableProj INNER JOIN MSP_WssListItemAssociation ON DeliverableProj.ProjectUID =
    MSP_WssListItemAssociation.ProjectUID INNER JOIN MSP_EpmProject_UserView AS DependancyProj ON MSP_WssListItemAssociation.RelatedProjectUID =
    DependancyProj.ProjectUID INNER JOIN MSP_WssDeliverable AS DeliverableLinks ON MSP_WssListItemAssociation.ListItemUID = DeliverableLinks.DeliverableUniqueID WHERE (MSP_WssListItemAssociation.ProjectUID
    <> MSP_WssListItemAssociation.RelatedProjectUID) AND (DeliverableProj.ProjectName = @ProjectSelect)

    This last query lists all the projects that a given project is dependent on. Again, you need to set ProjectSelect for the query to work.

    	DependancyProj.ProjectName AS SelectedProject,
    DeliverableProj.ProjectName, DeliverableLinks.Title, DeliverableLinks.StartDate, DeliverableLinks.FinishDate FROM MSP_WssListItemAssociation INNER JOIN MSP_EpmProject_UserView AS DependancyProj ON MSP_WssListItemAssociation.RelatedProjectUID = DependancyProj.ProjectUID INNER JOIN MSP_EpmProject_UserView AS DeliverableProj ON MSP_WssListItemAssociation.ProjectUID = DeliverableProj.ProjectUID INNER JOIN MSP_WssDeliverable AS DeliverableLinks ON MSP_WssListItemAssociation.ListItemUID = DeliverableLinks.DeliverableUniqueID WHERE (MSP_WssListItemAssociation.RelatedProjectUID <> MSP_WssListItemAssociation.ProjectUID) AND (DependancyProj.ProjectName = @ProjectSelect)

    To take a look at the last two queries in real reports, check out the Project Give and Get Reports in the Report Pack:

    This should be a good start with creating Deliverable reports. If you come up with some interesting queries for creating Deliverable reports, please share them by posting them as comments!

    Chris Boyd



  • Project Programmability and Business Intelligence

    Improve the Performance of Building the Project Server Data Analysis Cube


    Jack Li has passed along a great tip on how to improve the performance of building the Project Server Data Analysis Cube: 


    Recently we have worked with a big enterprise customer using Project Server. They ran into an issue where Project Server reporting component which uses Analysis Server ran very slow during cube population. Eventually, the issue was tracked down to a single query.  The query would take 17 hours to finish for 1 year of data. nHowever, if one applied force order to the query, it would finish within minutes.


    Customer had tight deadline and need a solution fast. It would be easy if one could just modify the query to add force order option.  Unfortunately, the query was generated by Analysis Service based on the cube definition. In other words, it couldn’t  be changed.


    Enter into plan guide for the  rescue. SQL Server 2005 gives you various means to influence the query plan for a query without adding hints to the query itself directly. You don’t need to change the query which may not be possible without changing the application.


    The simplest one is the use use sp_create_plan_guide stored procedure to add a query hint like force order etc.


    Here is exactly what we did for our customer:


    1)    We  used profiler trace to trace the exact query

    2)    We copied the exact query text and use sp_create_plan_guide to create the plan guide:


    EXEC sp_create_plan_guide N'guide_forceorder',

        N'<exact query>',




    N'OPTION (force order)'



    Steps are fairly easy yet it is tricky to implement. If you are not doing it correctly, SQL Server may not use the plan guide you just created.  Here are a few things you need to watch for:


    1)    ensure you have the exact text.  Even if you miss a space character, the plan won’t match.   To ensure you get exact text, you should launch  profiler trace while running the application to get the query.   See for more details.


    2)    There are two ways you can verify if SQL actually uses your plan guide. The first one obviously is that your query finishes faster.  Another way is that you will see PlanGuideDB word in the xml plan. So if you do set showplan_xml on and then run the query, you will get xml showplan. If you search the text, you will find PlanguideDB.  


    There are more advanced ways to use plan guide including parameterization or use plan. Please refer SQL Server 2005 books online for these advanced topics.



  • Project Programmability and Business Intelligence

    Creating a Task Hierarchy


    The following questions has been asked:

    "[...] is there a way to set up the task hierarchy within a single project?"

    and the answer is YES! To create a hierarchy within a single project, you have to set the outline level for the sub tasks. The below example creates two task, Summary Task and Sub Task. For the Summary Task, we do not set the outline level, we just create it as normal task. The Sub Task is where you set the outline level. In this example we set the outline level to 2:

    Connection conn = new Connection("http://chboyd01/pwa");

    WSProject.Project projWS = (WSProject.Project)conn.GetWebService(Connection.Project);

    Guid sessGuid = Guid.NewGuid();
    Guid jobGuid = Guid.NewGuid();
    Guid taskGuid = Guid.NewGuid();

    Guid projGuid = GetProjectUidFromProjectName("Excel");

    projWS.CheckOutProject(projGuid, sessGuid, "");

    WSProject.ProjectDataSet dsP;


    // Create a task with a constraint


    dsP = new WSProject.ProjectDataSet();

    WSProject.ProjectDataSet.TaskRow taskRow = dsP.Task.NewTaskRow();


    // Set the required fields

    taskRow.PROJ_UID = projGuid;
    taskRow.TASK_UID = taskGuid;
    taskRow.TASK_NAME =
    "Summary Task";

    taskRow.AddPosition = (int)PSLibrary.Task.AddPositionType.Last;


    projWS.QueueAddToProject(jobGuid, sessGuid, dsP, false);

    // Create a second task

    dsP = new WSProject.ProjectDataSet();


    taskRow = dsP.Task.NewTaskRow();

    Guid task2Guid = Guid.NewGuid();

    jobGuid = Guid.NewGuid();

    // Set the required fields

    taskRow.PROJ_UID = projGuid;
    taskRow.TASK_UID = task2Guid;
    taskRow.TASK_NAME =
    "Sub Task";

    // Set the start and finish dates

    taskRow.TASK_START_DATE = new DateTime(2007, 01, 31);
    taskRow.TASK_FINISH_DATE =
    new DateTime(2007, 02, 03);

    taskRow.TASK_OUTLINE_LEVEL = 2;

    taskRow.AddPosition = (int)PSLibrary.Task.AddPositionType.Last;


    projWS.QueueAddToProject(jobGuid, sessGuid, dsP, false);


    The below screen shot is the result of running the above sample code:

    Chris Boyd


    Technorati tags: , , ,
  • Project Programmability and Business Intelligence

    Security in Project Server 2010–What about Custom Permissions?


    SharePoint Server 2010 handles user authentication through claims processing, which is a new feature for SharePoint and Project Server. SharePoint handles both Windows authentication and Forms authentication for Project Server users. For authorization, you can use the ReadResourceAuthorization and SetResourceAuthorization methods in the Resource service of the PSI. Because you probably don’t often change security authorization settings for users, you would normally go to the Manage Users page in Project Web App to select a user and set the global and category permissions.

    The Security business object in Project Server (with programmatic access through the PSI Security service) manages security groups, categories, templates, and the global Project Web App permissions. The Security service can add existing permissions or remove permissions from the sets available for Project Server users. However, the Security service does not have a method for creating a custom permission. For example, if you created a Project Server extension that updates a Siebel CRM system, you might want a custom permission that enabled users to use that extension.

    In Office Project Server 2007, you can create custom global and category permissions by modifying security tables in the Published database. Custom permissions show in the PWA lists of permissions, where Project Server administrators can secure the 3rd-party extension the same way they secure other Project Server features. The Walkthrough: Creating and Using Custom Project Server Permissions article is the only SDK example where an exception is made for changing the Published database. 

    NOTE:  The Project team would like some feedback on the importance of custom permissions. If you need to create custom permissions in Project Server, please respond to this post.

     In Project Server 2010, that process for creating custom permissions still works as it did in Project Server 2007. In future versions of Project Server, no modifications to tables in the Published, Draft, or Archive databases will be supported. Custom permissions and secure links that rely on table modifications still work in Project Server 2010, but that process will be deprecated. As an alternative, you may have to create your own user interface to manage custom permissions, or use claims augmentation in a custom application. For more information, see Claims Provider.


    For more information about Project Server security, including a discussion of global and category permissions, see the Project Server Security Primer in the Project Server 2007 SDK and Security and protection for Project Server 2010 in TechNet.

  • Project Programmability and Business Intelligence

    Debugging a Project Server Workflow in Visual Studio 2010


    The How to: Install and Test a Project Server Workflow article in the Project 2010 SDK needs information about how to debug a workflow. Because Visual Studio 2010 can install a workflow solution on the local Project Server computer during development and testing, you can use Visual Studio to attach to a process that the workflow uses.

    After you deploy the workflow project in Visual Studio, on the Debug menu, click Attach to Process. In the Attach to Process dialog box, check Show processes from all users and Show processes in all sessions.

    Following are considerations to choose the correct process:

    • If the workflow creates a project or does another operation that uses one of the Queue methods in the PSI (for example QueueCreateProject), the process uses the Project Server Queue Service. In the Attach to Process dialog box, click the Microsoft.Office.Project.Server.Queuing.exe processes.

      Note:   There is a queue process for the application server and for each Project Web App instance. You can attach to all the queue processes, or check the ULS log for the ID of the queue process, and then convert that into a decimal value. For example, if the Microsoft.Office.Project.Server ID is 0x0FFC in the ULS log, the Microsoft.Office.Project.Server.Queuing.exe process ID is 4092.
    • When you submit or restart the workflow, the workflow runs in a w3wp process. Click one or more of the w3wp.exe processes . You can sometimes determine which w3wp process is involved, and find the process ID as in the previous note. Otherwise, attach to all of the w3wp processes.
    • If the workflow uses an approval process that includes many approvers, it might run under the SharePoint timer process. Click the OWSTIMER.EXE process . This is not common.

    When you attach to the correct process, a breakpoint remains as a solid red dot in the left of the code pane. If you do not attach to the correct process, the breakpoint turns into a hollow red circle with yellow caution indicator, and the tooltip for the breakpoint states, “The breakpoint will not currently be hit. No symbols have been loaded for this document.”

    When you click Attach, Visual Studio is ready to catch a breakpoint that you set in the workflow code.

  • Project Programmability and Business Intelligence

    Project Server 2007 Timesheet Data Population Tool

    Technorati tags: , ,


    The Project Server 2007 timesheet data population tool has been released on CodePlex:

    The Project Server 2007 Timesheet Data Population Tool enables you to simulate timesheet entries in your farm. This tool can help you perform scalability studies of your PS architecture and validate the sizing of an existing architecture (by measuring timesheet queue throughput for instance). This tool can also be used to test timesheet customization, for instance the Timesheet Tied-mode code sample on Codeplex. This powerful tool should not be run a production environment!

    The Timesheet Data Population tool is a console application written in C#.  It uses standard PSI (Project Server Interface) web service methods to populate timesheets.

    Please refer to the latest version of the Project Server Software Development Kit (SDK) for more information on the PSI methods and how to use them.

    This solution starter was written initially to perform Project Server 2003 vs. Project Server 2007 benchmarks, and has been used since to perform scalability studies and to test timesheet customizations.

    A special thank you to Isabel Bernardos and Steven Haden for helping me write and test the tool during PS 2007 scalability studies for large European customers. 

    If you are aware of any useful tools/solutions for Project and Portfolio Server 2007 and you would like to share them with the community via CodePlex please send me an email.

    About CodePlex

    CodePlex is Microsoft's open source project hosting web site. You can use CodePlex to create new projects to share with the world, join others who have already started their own projects, or use the applications on this site and provide feedback. A word about Microsoft’s role: Microsoft does not control, review, revise, endorse or distribute the third party projects on this site. Microsoft is hosting the CodePlex site solely as a web storage site as a service to the developer community.


    Q: Is the tool supported?

    A: There is no support in terms of CSS/PSS. We expect the support being a CodePlex community effort. Please note that the customization code uses standard supported web service calls available out of the box in EPM2007.

    Q: Is the tool free?

    A: Yes.

    Q: Can I distribute the tool and the source code to customers and partners?

    A: Customers and Partners can use both. Please go to CodePlex to agree on the license terms

    Q: Can a partner distribute the tool and code as is?

    A: No, but partners can point their customer to the website to download it.

    Q: Can a customer install the customization and use it?

    A: Yes the customer can, but he/she is responsible for testing it and running it.

    Q: Can I suggest changes to it?

    A: Yes, join the CodePlex community or send us an email:

    Q: Will this tool be distributed in other ways (i.e. DVDs)?

    A: No.

    Q: What skills do I need to modify or change the tool?

    A: C#, Project Server Interface, and a good understanding of the EPM 2007 data schema.

    Q: I’m trying to modify the code and do have questions. Who do I ask?

    A: Go to the Discussions forums on CodePlex.

    Q: What are all the EPM projects released on CodePlex?

    A. Check this:


    Christophe Fiessinger

  • Project Programmability and Business Intelligence

    Adding a Project to a Category


    Brian Smith from PSS has passed along this sample that we thought might be helpful:

    The scenario here is that you have a lookup table that shows the categories you want users to select from when creating a project, and then the GUID for the "real" security category is held in the description for the lookup table value.  You make the CF that feeds from the Lookup Table a required Project Level text field.  The Project.Created event fires and the dataset is read - the custom field identified and the GUID of the security category is then used to add the project to the security category.

    No error checking or exception handling is shown - you can do this bit. You would also need to set the categories to the rule "only projects...".  I've hardcoded my lookup table and a reference required to the Microsoft.Office.Project.Server.Library and Events. A Web References to LookupTable, Project, Security and LoginWindows is also required.

    The code will run as the user running the services - so you will either need that account to have PWA permissions or to change to use impersonation.

    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Diagnostics;
    using System.Text;
    using Microsoft.Office.Project.Server.Events;
    using Microsoft.Office.Project.Server.Library;

    namespace TestEventHandler

        public class AutoCategory:ProjectEventReceiver

            public override void OnCreated(PSContextInfo contextInfo, ProjectPostEventArgs e)

                // cfGuid holds CF for Project Category
                Guid cfGuid = new Guid("9bbc698f-5c1d-4f8d-a3d0-163006416bf2");

                // ltGuid holds LT for Categories
                Guid ltGuid = new Guid("625bab60-4427-4f0b-941b-9860d1293338");

                // lt_Struct_Uid gets the id for the selected LT value
                Guid lt_Struct_Uid = new Guid("00000000-0000-0000-0000-000000000000");

                // securityCategoryGuid gets the Security Categorty Guid from the Descriptio field in the lookup table
                Guid securityCategoryGuid = new Guid("00000000-0000-0000-0000-000000000000");

                // 32 is used to just get the CF entities from the readProjectEntities
                const int PROJECT_ENTITY_TYPE_PROJECTCUSTOMFIELD = 32;

                Guid SECURITY_CATEGORY_OBJECT_TYPE_PROJECT = new Guid("1771B1C0-6E26-4FB3-A480-C798AB506E82");

                WebSvcLoginWindows.LoginWindows loginWindows = new TestEventHandler.WebSvcLoginWindows.LoginWindows();
                WebSvcProject.Project project = new TestEventHandler.WebSvcProject.Project();
                WebSvcSecurity.Security security = new TestEventHandler.WebSvcSecurity.Security();
                WebSvcLookupTable.LookupTable lookupTable = new TestEventHandler.WebSvcLookupTable.LookupTable();


                //login to Project Server - this assumes the event service has a login with permissions

                // Impersonation would be better
                loginWindows.Url = @"https://SERVER_NAME/ProjectServer/_vti_bin/PSI/LoginWindows.asmx";
                loginWindows.Credentials = CredentialCache.DefaultCredentials;

                // Get the dataset
                project.Url = @"https://SERVER_NAME/ProjectServer/_vti_bin/PSI/Project.asmx";
                project.Credentials = CredentialCache.DefaultCredentials;

                lookupTable.Url = @"https://SERVER_NAME/ProjectServer/_vti_bin/PSI/LookupTable.asmx";
                lookupTable.Credentials = CredentialCache.DefaultCredentials;

                security.Url = @"https://SERVER_NAME/ProjectServer/_vti_bin/PSI/security.asmx";
                security.Credentials = CredentialCache.DefaultCredentials;

                WebSvcProject.ProjectDataSet dsProjectDataSet = new TestEventHandler.WebSvcProject.ProjectDataSet();

                dsProjectDataSet = project.ReadProjectEntities(e.ProjectGuid, PROJECT_ENTITY_TYPE_PROJECTCUSTOMFIELD, TestEventHandler.WebSvcProject.DataStoreEnum.WorkingStore);

                for (int i = 0; i < dsProjectDataSet.ProjectCustomFields.Count; i++)
                    if (dsProjectDataSet.ProjectCustomFields[i].MD_PROP_UID == cfGuid)
                        lt_Struct_Uid = dsProjectDataSet.ProjectCustomFields[i].CODE_VALUE;

                Guid[] arrayLtUid = new Guid[1]{ltGuid};
                WebSvcLookupTable.LookupTableDataSet dsLookupTable = new TestEventHandler.WebSvcLookupTable.LookupTableDataSet();
                dsLookupTable = lookupTable.ReadLookupTablesByUids(arrayLtUid, false, 1033);

                for (int i = 0; i < dsLookupTable.LookupTableTrees.Count; i++)
                    if (dsLookupTable.LookupTableTrees[i].LT_STRUCT_UID == lt_Struct_Uid)
                        securityCategoryGuid = new Guid(dsLookupTable.LookupTableTrees[i].LT_VALUE_DESC.ToString());

    WebSvcSecurity.SecurityCategoriesDataSet dsSecurityCategories
       = new TestEventHandler.WebSvcSecurity.SecurityCategoriesDataSet();

    // Read the existing values for the security category into the dataset
    dsSecurityCategories = security.ReadCategory(securityCategoryGuid);

                // Get a new objects row to put the created project into

                WebSvcSecurity.SecurityCategoriesDataSet.SecurityCategoryObjectsRow dsSecurityCategoryObjectsRow
    = dsSecurityCategories.SecurityCategoryObjects.NewSecurityCategoryObjectsRow();

                //Set the values
                dsSecurityCategoryObjectsRow.WSEC_OBJ_TYPE_UID = SECURITY_CATEGORY_OBJECT_TYPE_PROJECT;
                dsSecurityCategoryObjectsRow.WSEC_CAT_UID = securityCategoryGuid;
                dsSecurityCategoryObjectsRow.WSEC_OBJ_UID = e.ProjectGuid;

                // Add the row to the dataset and then pass to SetCategories to update

                // Create an EventLog instance and assign its source.
                EventLog myLog = new EventLog();
                myLog.Source = "Project Event Handler";

                // Get information from the event arguments, and

                // write an entry to the Application event log.
                string userName = contextInfo.UserName.ToString();
                string projectName = e.ProjectName.ToString();
                string secCatUid = securityCategoryGuid.ToString();
                int eventId = 3652;
                string logEntry;


                logEntry = "User: " + userName +

                        "\nProject: " + projectName +

                        "\nSecurity Category Uid: " + secCatUid;

                    myLog.WriteEntry(logEntry, EventLogEntryType.Information, eventId);




  • Project Programmability and Business Intelligence

    Project Initiation Phase using InfoPath & Forms Services


    Christophe just passed along some information about a new solution starter on CodePlex:


    A new solution starter that demonstrates how to leverage InfoPath & Forms Services as well Windows Workflow Foundation (hosted by SharePoint) to create your own project initiation phase has been released on CodePlex.

    The project initiation phase is different for every customers and organizations. It typically requires a set of custom attribute to be filled in a web based custom form; and then it needs to go through a custom approval process workflow reviewed by all key decision makers. InfoPath Forms services combined with a SharePoint’s sequential workflow enables you to achieve this business need. This solution starter also demonstrates the added value of deploying Project Server 2007 in a SharePoint Server farm (using InfoPath Forms Services).

    The goal of this solution starter is thus to provide the following two code samples:

    • InfoPath Form with managed code that issues Project Server Interface calls to populate and submit form data
    • SharePoint sequential workflow that leverages the form created earlier to create a custom workflow

    This solution starter requires Project Server 2007, InfoPath and Forms Services 2007, and Visual Studio 2008.

    Step 1 – Fill out and submit Project Initiation Form

    Step 2 – Approve data submitted in Step 1 and create Project in PS 2007

    Resulting data in Project Server 2007

    clip_image001 clip_image002 clip_image003

    This solution starter was created for a presentation I delivered at the 2008 Office Developer Conference.

    If you are aware of any useful tools/solutions for Project and Portfolio Server 2007 and you would like to share them with the community via CodePlex please send me an email.

    About CodePlex

    CodePlex is Microsoft's open source project hosting web site. You can use CodePlex to create new projects to share with the world, join others who have already started their own projects, or use the applications on this site and provide feedback. A word about Microsoft’s role: Microsoft does not control, review, revise, endorse or distribute the third party projects on this site. Microsoft is hosting the CodePlex site solely as a web storage site as a service to the developer community.


    Q: Is the tool supported?

    A: There is no support in terms of CSS/PSS. We expect the support being a CodePlex community effort. Please note that the customization code uses standard supported web service calls available out of the box in EPM2007.

    Q: Is the tool free?

    A: Yes.

    Q: Can I distribute the tool and the source code to customers and partners?

    A: Customers and Partners can use both. Please point them to CodePlex as they have to agree on the license terms

    Q: Can a partner distribute the tool and code as is?

    A: No, but he can point his customer to the website to download it, so he makes sure that the customer agrees with the license terms.

    Q: Can a customer install the customization and use it?

    A: Yes the customer can, but he/she is responsible for testing it and running it.

    Q: Can I suggest changes to it?

    A: Yes, join the CodePlex community or send us an email:

    Q: Will this tool be distributed in other ways (i.e. DVDs)?

    A: No.

    Q: What skills do I need to modify or change the tool?

    A: C#, Project Server Interface, and a good understanding of the EPM 2007 data schema.

    Q: I’m trying to modify the code and do have questions. Who do I ask?

    A: Go to the Discussions forums on CodePlex.

    Q: What are all the EPM projects released on CodePlex?

    A. Check this:


    Christophe Fiessinger

  • Project Programmability and Business Intelligence

    Getting a Project GUID on the Cheap


    Many people have requested for a complementary method to GetProjectNameFromProjectUid where they can pass in a project name and it returns the project's GUID. Unfortunately it did not make it into the Project API. Since it has been requested many times, I figured that it would be useful to post a method, GetProjectUidFromProjectName, which did just that:

    public static Guid GetProjectUidFromProjectName(string projectName)
      Guid projectGUID;

      WSProject.ProjectDataSet readProjDs = projWS.ReadProjectStatus(

      if (readProjDs.Project.Rows.Count == 1)
        projectGUID = new Guid(readProjDs.Project[0].PROJ_UID.ToString());
        throw new Exception("No Project by the name: " + projectName + " Found");

      return projectGUID;


    First thing to note is that projWS is defined elsewhere and it is a connection to the Project Web Service. See my earlier post on Getting Started with the PSI on how to make the connection to the Project Web Service.

    To get the GUID we are going to use the ReadProjectStatus method, as it is the cheapest call to make to get the project's GUID. As you will see, this method takes 4 parameters. The first parameter is the project GUID. In this case, we pass in an empty GUID because that is what we are looking for. Passing in an empty GUID tells Project Server not to search for a project by the GUID.  

    The second parameter is the store to get the project GUID from. Here we have the option of getting the GUID from the working, published or archived store. In this example, I am getting it from the working store, since I want to get the GUID for projects that are actively being worked on and may or may not have been published. Note that this will also get projects that have been published, since they exist in both stores with the same GUID. You may want to change the store based on your requirements.

    The third parameter is the name of the project. This is passed into our GetProjectUidFromProjectName method.

    The last parameter is the type of project. There a number of different project types:

    In most cases 0, which represents standard projects, will be the correct project type.

    The ReadProjectStatus returns a project dataset. If the number of rows returned for the project table is equal to 1, than we have found a project with the given name and we can return the GUID for the project. If the number of rows is not equal to one, than no project by the name was found and we throw an exception.

    Hope this helps,

    Chris Boyd

  • Project Programmability and Business Intelligence



    When working with Project Server Events, you may need to reference Microsoft.Office.Project.Server.Schema. Unfortunately, you will not find it in \Program Files\Microsoft Office Servers\12.0\Bin where you can find other common DLLs for Project Server.  For this DLL, you will need to copy it from the GAC:

    1.      Open Visual Studio Command Prompt

    2.      cd %windir%\assembly\GAC_MSIL\Microsoft.Office.Project.Schema\*"

    3.      Copy Microsoft.Office.Project.Schema.dll to a directory outside of the GAC

    4.      Go back to Visual Studio and create a reference to Microsoft.Office.Project.Schema.dll from the directory you copied it to

    Just one thing to keep in mind; you may need to copy the DLL from the GAC again if a Project Server update is installed.

    Hope this helps,


  • Project Programmability and Business Intelligence

    Reading Enterprise RBS values: the Easy Way and the Not-So-Easy Way


    There are a couple of ways to programmatically get the Resource Breakdown Structure (RBS) value for a Project Server user. The simplest way is to query the Reporting database, for example:

    SELECT [ResourceUID] ,[ResourceName] ,[ResourceBookingType] ,[ResourceIsActive] ,[RBS] FROM [ProjectServer_Reporting].[dbo].[MSP_EpmResource_UserView] AS res WHERE res.ResourceName = N'Linda Jones'

    The result on my machine is:







    Linda Jones



    User Assistance.DevDocs.SDK Writers

    To get the RBS by using the PSI is a bit more work. Because the RBS is an enterprise resource custom field that uses the RBS lookup table, you can use the following steps:

    1. Call the ReadResources method and filter the primary Resources table for the user name and GUID. Alternately, you can use the ReadUserList method to get all of the active resource names and GUIDs, and iterate through the ResourceDataSet for the specific resource. The attached example uses the –userList command line argument to have the application use the ReadUserList method, and displays the elapsed time for the method used.
    2. Call ReadResource with the resource GUID to get the full ResourceDataSet.
    3. Iterate through the ResourceDataSet.ResourceCustomFields table to get the CODE_VALUE for the RBS custom field (if it exists).
    4. Use a filter with the ReadLookupTables method to get a LookupTableDataSet that contains only the LookupTableTrees table for the RBS lookup table.
    5. Iterate through the LookupTableTrees table to get the LT_VALUE_FULL string that corresponds to the CODE_VALUE in the RBS custom field.  The LookupTableTrees row where the LT_STRUCT_UID element matches the  custom field CODE_VALUE contains the correct RBS string.

    The attached example also writes the various datasets to XML files, for debugging purposes. Keep in mind that the app user must have the ManageUsersAndGroups global permission, and the other permissions specified in the SDK topics for the methods used, in order to read data of other resources.

    The attached file contains the complete Visual Studio solution for the example described in this post. To use the sample, change the server name and Project Server name for the endpoint addresses in the app.config file. The sample uses the WCF interface for Project Server 2010; however, it can be adapted to use the ASMX interface for Project Server 2007.

    For example, the following command gets the same RBS value shown by the Reporting database query:

    C:\Test>ReadRbs -name "Linda Jones"

    XML output from ReadResources:

    Using ReadResources method: 412.309 milliseconds

    XML output from ReadResource:

    XML output from ReadLookupTables:

    User name: Linda Jones
            GUID: 0D455775-01CB-42E1-A481-A6F0F1F8208A
            RBS value: User Assistance.DevDocs.SDK Writers

    Press any key to exit...

Page 2 of 11 (255 items) 12345»