Project Server Help Videos

How many people actually read the help files that come with software? I know I tend not to until I get totally stuck. However, today whilst installing Project Server 2010 I decided to go and have a look around the Office 2010 help site at http://office2010.microsoft.com.

image

The site provides a wealth of helpful information around Project and Project Server, but what really stood out was the video content giving overviews of the a number of key features in Project Server, including the new web app, Portfolio management and workflows, each of which are linked to below:

Project 2010 New File Format

imageWith the Project 2010 client nearing launch, I thought it would be timely to remind everyone who is going to use this fantastic new release that the file format has changed. As such, schedules you create in Project 2010 need to be saved in a previous file version to share with people using Project 2007 and 2003. Luckily Project 2010 makes it really easy to save your schedules in a previous file format.

To save a file in a previous file format

Choose File > Save As. In the Save as Dialog, select the file version to save the file as from the ‘Save as type’ combo box.

Default files to save in a previous file format

You can also configure Project 2010 to default all new schedules created to save to a previous file format via the Project Options > Save option, and choosing from either Project 2007 or Project 2000 – 2003 in the ‘Save files in this format:’ combo box.

Opening an existing file

If you open a schedule in one of the previous file formats and try to save it, Project 2010 detects that it is an older format and prompts you to save in the newer format.

Upgrade the file

Unfortunately the dialog displayed doesn’t seem to respect your default Save Options configured above, instead if you’re not reading the dialog properly you can accidently upgrade your schedule to the newer 2010 format.

Compatibility between versions

As you would expect, the new file format is designed to support some of the new features, including inactive and manually scheduled tasks. So it makes sense if you save your schedule in a previous file format that some of these features will be not be saved in the file. If you try to save a Project 2010 created schedule in a Project 2007 file format, Project will warn you if a feature of that schedule is unsupported via a tool called the Compatibility checker.

Compatability checker

The compatibility checker will advise if a feature is unsupported, how many occurrences of that feature are in the schedule and what changes will be made. From scouring the Project 2010 help, the following features are unsupported when saving a Project 2010 schedule in the Project 2007 file format:

  • Manually scheduled tasks Manually scheduled tasks are set to automatic scheduling.
  • Inactive tasks Inactive tasks are deleted.
  • Strikethrough font Strikethrough font are removed. The task is not deleted.
  • Colour effects 32-bit colour is set to the closest of the 16 types of colour for bar styles, indicators, and other graphical effects.
  • Summary tasks Summary tasks that are manually scheduled are set to milestone tasks in Project 2007.Of course, none of this will be required if your colleagues all upgrade to Project 2010, but in the meantime I hope this is of use :)
  • Extending the backstage… Integrating data and the UI

    In the previous two posts, we covered off how to extract the workflow data from the Project Server Reporting database, and the basics of how to extend the Backstage view. In this post I will cover off how to merge the two together, and to discuss some of the limitations and problems I ran into.

    For the proof of concept I wanted the backstage view to render dynamic information about the project workflow in the backstage, checking out MSDN and Technet I found some fantastic resources to assist, including Customizing the Office 2010 Backstage View for Developers and it’s associated code . I have always found the best way to learn something was to look at some form of reference and then experiment.

    In dissecting the example above, I found numerous references to things called callbacks, these are methods that are called when the backstage is rendered. They are particularly useful if you want to incorporate dynamic information such as the workflow status. Now after a significant amount of experiment I had absolutely no luck in getting any of these callbacks to work in the beta, so decided to try something a little bit different (I intend to revisit these callbacks once Project has RTM’d and hopefully there is a little more reference material available).

    As the XML that renders the backstage is built programmatically in Project, I figured it would be possible to inject the data retrieved containing the workflow status directly into the XML. This does have the limitation that the data displayed in the backstage will only be as fresh as when the XML is built. If you intend on using this approach you need to take this limitation into account and ensure its relevant for the data you are displaying.

    Getting the data programmatically

    In the previous post I discussed the code required in order to retrieve the workflow status information from the reporting database. In order to make that data available we need to read the data into a record set using ADODB and point the code at the correct database to run against. To do this we first need to get the GUID of the current project, which can be done using the following code:

        Dim projectGUID As String
    
        projectGUID = ActiveProject.GetServerProjectGuid
    

    To use ADODB, you need to include a reference to ADODB in the project, or use something called late binding to bind in the ADODB libraries at runtime. For the purposes of this proof of concept, I explicitly added the the ADODB library in the project references.

    ADODB Reference

    Finally I added some error handling to check whether any data was returned. If no data is, the code assumes the project is not under a workflow and stops our custom workflow tab from being displayed.

    Sub qrySQLDatabase()
    
        ' First do a lookup to get the current project GUID
        Dim projectGUID As String
    
        projectGUID = ActiveProject.GetServerProjectGuid
    
        'Assume the project is in Project Server unless we get an error.
        blnWorkflowRecords = True
        Dim wfRS As ADODB.Recordset
        Set wfRS = New ADODB.Recordset
    
        ConnectionString = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=PWA_moss.contoso.com80_Reporting;Data Source=demo2010a;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=DEMO2010A;Use Encryption for Data=False;Tag with column collation when possible=False"
    
        ' Now we have the Project GUID, we need to query the reporting database to get the workflow status for that guid
    
        sqlQry = "select  epmp.ProjectName, " & _
                "epmwfs.StageName," & _
                "epmwfs.StageDescription, " & _
                "epmwsi.StageInformation, " & _
                "epmwfst.StageStateDescription " & _
                "from MSP_EpmWorkflowStatusInformation epmwsi " & _
                "inner join MSP_EpmWorkflowStage epmwfs on epmwsi.StageUID = epmwfs.StageUID " & _
                "inner join MSP_EpmWorkflowStatusType epmwfst on epmwsi.StageStatus = epmwfst.StageStatusID " & _
                "inner join MSP_EpmProject epmp on epmwsi.ProjectUID = epmp.ProjectUID " & _
                "where epmwsi.ProjectUID = '" + projectGUID + "' " & _
                "and (StageEntryDate is not null and StageCompletionDate is null) " & _
                "order by StageOrder"
    
        wfRS.Open sqlQry, ConnectionString, adOpenForwardOnly, adLockReadOnly, adCmdText
    
        If (wfRS.BOF Or wfRS.EOF) Then
    
            'No records are returned, so assume that the schedule is not in Project Server
            blnWorkflowRecords = False
    
        Else
            ' HACK
            ' move the values into the strings and append a space on the end.
            ' If there is an empty string the backstage won't render.
    
            txtProjectName = wfRS(0).Value + " "
            txtWorkflowStatus = wfRS(4).Value + " "
            txtWorkflowTitle = wfRS(1).Value + " "
            txtWorkflowDesc = wfRS(2).Value + " "
            txtWorkflowErr = wfRS(3).Value + " "
    
        End If
    
        wfRS.Close
    
        If Not wfRS Is Nothing Then Set wfRS = Nothing
    
    End Sub
    

    You’ll notice above that once the data has been retrieved it is extracted into a number of txt variables such as txtProjectName, txtWorkflowStatus etc which will be used to inject the data into the XML for the backstage. Unfortunately the backstage doesn’t handle empty strings very well, so I have appended a space to each variable to make sure no null strings are injected.

    Injecting into the backstage

    The process of injecting the variables into the backstage is incredibly easy, all that needs to be done is to break up the XML building and insert the various variables as per below:

    Private Sub AddWorkflowBackstageTab()
    
        Dim backstageXML As String
    
        backstageXML = "<customUI xmlns=""http://schemas.microsoft.com/office/2009/07/customui"">"
        backstageXML = backstageXML + " <backstage>"
        backstageXML = backstageXML + "  <tab id=""TabWorkflow"" label=""Workflow"" insertAfterMso=""TabInfo"" >"
        backstageXML = backstageXML + "    <firstColumn>"
        backstageXML = backstageXML + "      <group id=""grpWorkflow"" label=""Current project workflow status"" style=""" + txtGroupStyle + """>"
        backstageXML = backstageXML + "        <primaryItem>"
        backstageXML = backstageXML + "          <button id=""btnFeature"" label=""View workflow in PWA"" onAction=""workflowStatus"" imageMso=""ProjectWebAccessProjectDetails""/>"
        backstageXML = backstageXML + "        </primaryItem>"
        backstageXML = backstageXML + "         <topItems>"
        backstageXML = backstageXML + "             <labelControl id=""workflowStatus"" label=""Current status: " + txtWorkflowStatus + """/>"
        backstageXML = backstageXML + "             <labelControl id=""filler""  label="" "" />"
        backstageXML = backstageXML + "             <labelControl id=""currentError"" label=""" + txtWorkflowErr + " "" />"
        backstageXML = backstageXML + "             <labelControl id=""filler2""  label="" "" />"
        backstageXML = backstageXML + "             <labelControl id=""currentTitle""  label=""" + txtWorkflowTitle + """ />"
        backstageXML = backstageXML + "             <labelControl id=""currentDesc""  label=""" + txtWorkflowDesc + """ />"
        backstageXML = backstageXML + "         </topItems>"
        backstageXML = backstageXML + "       </group>"
        backstageXML = backstageXML + "    </firstColumn>"
        backstageXML = backstageXML + "  </tab>"
        backstageXML = backstageXML + " </backstage>"
        backstageXML = backstageXML + "</customUI>"
    
        ActiveProject.SetCustomUI (backstageXML)
    
    End Sub
    

    Pulling it all together

    Finally before the workflow tab can be used, a few pieces of logic need to be added to make sure it displays only when there is data, or when the client is connected to the Project Server instance we are querying the reporting database of.  As you can see in the backstage XML, I also included a button that takes the user off to the Project Web Access Workflow status page, so it was necessary to create a subroutine to perform this.  Finally I added some logic to set the backstage group to show the yellow warning style  if the workflow status had the word ‘Waiting’ within it. The full final code looks like this:

    Public txtWorkflowStatus As String
    Public txtWorkflowTitle As String
    Public txtWorkflowDesc As String
    Public txtWorkflowErr As String
    Public txtProjectName As String
    Public txtGroupStyle As String
    Public blnWorkflowRecords As Boolean
    
    Private Sub AddWorkflowBackstageTab()
    
        Dim backstageXML As String
    
        backstageXML = "<customUI xmlns=""http://schemas.microsoft.com/office/2009/07/customui"">"
        backstageXML = backstageXML + " <backstage>"
        backstageXML = backstageXML + "  <tab id=""TabWorkflow"" label=""Workflow"" insertAfterMso=""TabInfo"" >"
        backstageXML = backstageXML + "    <firstColumn>"
        backstageXML = backstageXML + "      <group id=""grpWorkflow"" label=""Current project workflow status"" style=""" + txtGroupStyle + """>"
        backstageXML = backstageXML + "        <primaryItem>"
        backstageXML = backstageXML + "          <button id=""btnFeature"" label=""View workflow in PWA"" onAction=""workflowStatus"" imageMso=""ProjectWebAccessProjectDetails""/>"
        backstageXML = backstageXML + "        </primaryItem>"
        backstageXML = backstageXML + "         <topItems>"
        backstageXML = backstageXML + "             <labelControl id=""workflowStatus"" label=""Current status: " + txtWorkflowStatus + """/>"
        backstageXML = backstageXML + "             <labelControl id=""filler""  label="" "" />"
        backstageXML = backstageXML + "             <labelControl id=""currentError"" label=""" + txtWorkflowErr + " "" />"
        backstageXML = backstageXML + "             <labelControl id=""filler2""  label="" "" />"
        backstageXML = backstageXML + "             <labelControl id=""currentTitle""  label=""" + txtWorkflowTitle + """ />"
        backstageXML = backstageXML + "             <labelControl id=""currentDesc""  label=""" + txtWorkflowDesc + """ />"
        backstageXML = backstageXML + "         </topItems>"
        backstageXML = backstageXML + "       </group>"
        backstageXML = backstageXML + "    </firstColumn>"
        backstageXML = backstageXML + "  </tab>"
        backstageXML = backstageXML + " </backstage>"
        backstageXML = backstageXML + "</customUI>"
    
        ActiveProject.SetCustomUI (backstageXML)
    
    End Sub
    
    Private Sub Project_Open(ByVal pj As Project)
    
        ' Initialise the boolean that indicates if there are workflow records returned
        ' in the SQL query of qrySQLDatabae
        blnWorkflowRecords = True
        qrySQLDatabase
    
        ' Check to see if there are any workflow data returned, or as our connection settings are hardcoded
        ' make sure we are connecting to the correct Project Server instance.
        '
        ' If any of the above are not correct, then don't show the workflow tab.
    
        If (blnWorkflowRecords and Application.Profiles.ActiveProfile = "Contoso") Then
    
    	' If the workflow status is waiting, set the group style to warning
             If (InStr(txtWorkflowStatus, "Waiting") = 0) Then
           	    txtGroupStyle = "normal"
    	 Else
    	    txtGroupStyle = "warning"
    	 End If
    
    	AddWorkflowBackstageTab
        End If
    
    End Sub
    
    Sub workflowStatus()
    ' Opens the project details page which will default to the workflow status
        Application.OpenServerPage (pjServerPageProjectDetails)
    End Sub
    
    Sub qrySQLDatabase()
    
        ' First do a lookup to get the current project GUID
        Dim projectGUID As String
    
        projectGUID = ActiveProject.GetServerProjectGuid
    
        'Assume the project is in Project Server unless we get an error.
        blnWorkflowRecords = True
        Dim wfRS As ADODB.Recordset
        Set wfRS = New ADODB.Recordset
    
        ConnectionString = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=PWA_moss.contoso.com80_Reporting;Data Source=demo2010a;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=DEMO2010A;Use Encryption for Data=False;Tag with column collation when possible=False"
    
        ' Now we have the Project GUID, we need to query the reporting database to get the workflow status for that guid
    
        sqlQry = "select  epmp.ProjectName, " & _
                "epmwfs.StageName," & _
                "epmwfs.StageDescription, " & _
                "epmwsi.StageInformation, " & _
                "epmwfst.StageStateDescription " & _
                "from MSP_EpmWorkflowStatusInformation epmwsi " & _
                "inner join MSP_EpmWorkflowStage epmwfs on epmwsi.StageUID = epmwfs.StageUID " & _
                "inner join MSP_EpmWorkflowStatusType epmwfst on epmwsi.StageStatus = epmwfst.StageStatusID " & _
                "inner join MSP_EpmProject epmp on epmwsi.ProjectUID = epmp.ProjectUID " & _
                "where epmwsi.ProjectUID = '" + projectGUID + "' " & _
                "and (StageEntryDate is not null and StageCompletionDate is null) " & _
                "order by StageOrder"
    
        wfRS.Open sqlQry, ConnectionString, adOpenForwardOnly, adLockReadOnly, adCmdText
    
        If (wfRS.BOF Or wfRS.EOF) Then
    
            'No records are returned, so assume that the schedule is not in Project Server
            blnWorkflowRecords = False
    
        Else
            ' HACK
            ' move the values into the strings and append a space on the end.
            ' If there is an empty string the backstage won't render.
    
            txtProjectName = wfRS(0).Value + " "
            txtWorkflowStatus = wfRS(4).Value + " "
            txtWorkflowTitle = wfRS(1).Value + " "
            txtWorkflowDesc = wfRS(2).Value + " "
            txtWorkflowErr = wfRS(3).Value + " "
    
        End If
    
        wfRS.Close
    
        If Not wfRS Is Nothing Then Set wfRS = Nothing
    
    End Sub
    
    

    In Conclusion

    Once all of the above is done, the finished backstage looked like this..
    Current Project Workflow Status

    The workflow data has been successfully pulled from the server, rendered in the backstage and had business logic applied, all with a minimum of coding. Of course this is only a simple proof of concept, with a little more effort the backstage could be wired up to use the PSI, integrate with VSTO add-ins and hooked into other data sources and systems, making it an incredibly powerful addition to Project 2010.  As the solution is VBA based, it can be added to the Enterprise Global for your Project Server instance and distributed to all users via this mechanism, making it very easy to distribute and control. As for the code, well it was a proof of concept and  certainly there needs to be a few improvements around the ADODB to remove the need to add the library via the Project References, but this should be relatively minor to implement. Once Project RTM’s I will certainly be revisiting the callbacks to see if I can get them working and post an update.

    Extending the Project backstage… Extending the GUI

    Hello World In this second post covering my proof of concept to expose workflow status information in the Project backstage I will cover off some of the basics on how to extend the backstage.

    Like all of the Office 2010 clients, Project’s backstage can be customised by defining the various interface elements and their associated behaviours using an XML schema that has been published by Microsoft and is available for download here.

    Perhaps the easiest way to understand the XML is to view an example. The XML below defines a new tab in the backstage called “Hello World” which consists of a single group called “Hello World Example” and has a single button that when clicked will call some arbitrary code called, yes you’ve guessed it, “HelloWorld”

        <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
         <backstage>
          <tab id="TabHello" label=”Hello World”>
            <firstColumn>
              <group id="grpOne" label="Hello World Example" helperText="Click here for some Hello World Action">
                <primaryItem>
                  <button id="firstButton" label="Hello World" onAction="HelloWorld" />
                </primaryItem>
               </group>
            </firstColumn>
          </tab>
         </backstage>
        </customUI>
    

    image

    The backstage also allows out of the box tabs to be extended such as the ‘Info’ or ‘Save & Send’ tabs. It is also possible to insert and position customisations within the out of the box tabs. To do so, there are a couple of special XML elements you need to be across. In the example above, the line:

    <tab id=”TabHello” label=”Hello World”>
    

    could be replaced with

    <tab idMso=”TabInfo”>
    

    to add the Hello World group and button the out of the box Info tab.

    image

    The idMso element tells the backstage that a Microsoft Office Control Id should be used, in this case the Info tab. Similarly through the addition of the insertAfterMso element in the group section, it is possible to define where our new group is inserted in the tab in relation to the other groups on the tab. Like idMso, insertAfterMso uses a ControlId to ‘navigate’ it’s way around. Microsoft have published a list of these Control Id’s for all of the Office 2010 clients that you can download here.

    Thinking Binary…

    In most of the Office 2010 clients, the custom XML used to define the backstage enhancements can simply be added into the document assembly and would be automatically picked up when the document was loaded. Unfortunately, as Project is still using a binary file format, this is not possible and the XML backstage definition needs to be added via code using a method called setCustomUI.

    Using setCustomUI is relatively simple to implement, once the XML has been defined, all that needs to be done is to transfer the XML into a variable and to call setCustomUI to implement it.  There are a couple of things you need to be careful of when encoding the XML:

    • Make sure you change all single quotes to double quotes
    • The backstage will fail to render if any of the elements have the incorrect name, check them all.
    • Double check that there are no empty strings, e.g. label=”””” as this will cause the backstage to fail to render.
      Finally, all that is required to do is wrap all of the code up in a couple of methods so that it will added automatically when the project is opened and to wire up the button.
    Private Sub AddBackstageTab()
    
        Dim backstageXML As String
    
        backstageXML = "<customUI xmlns=""http://schemas.microsoft.com/office/2009/07/customui"">"
        backstageXML = backstageXML + " <backstage>"
        backstageXML = backstageXML + "  <tab idMso=""TabInfo"">"
        backstageXML = backstageXML + "    <firstColumn>"
        backstageXML = backstageXML + "      <group id=""grpOne"" label=""Hello World Example"" helperText=""Click here for some Hello World Action"">"
        backstageXML = backstageXML + "        <primaryItem>"
        backstageXML = backstageXML + "          <button id=""firstButton"" label=""Hello World"" onAction=""HelloWorld""/>"
        backstageXML = backstageXML + "        </primaryItem>"
        backstageXML = backstageXML + "       </group>"
        backstageXML = backstageXML + "    </firstColumn>"
        backstageXML = backstageXML + "  </tab>"
        backstageXML = backstageXML + " </backstage>"
        backstageXML = backstageXML + "</customUI>"
    
        ActiveProject.SetCustomUI (backstageXML)
    
    End Sub
    
    Private Sub Project_Open(ByVal pj As Project)
            AddBackstageTab
    End Sub
    
    Private Sub HelloWorld()
        ' Do something
    End Sub
    

    In the next post, I will cover off how to incorporate the workflow data into the backstage.

    Extending the Project Backstage… Getting the data

    SQL Server 2008

    In the first of three posts covering my proof of concept to show the workflow status in the Project backstage, I will be covering off how to access the workflow data itself from within the Project Server.

    Now as this was a proof of concept, I decided to go with the simple approach of getting the information directly from the Reporting database instead of calling the Project Server PSI.  There were a couple of reasons for this, firstly simplicity, accessing the data in the Reporting database via SQL and VBA is much simpler in my opinion than calling the PSI. The second reason was it appeared that calling the PSI from the client requires custom code to be developed,  and my 2010 development environment didn’t have VS installed :)

    Workflow information in the reporting database

    In the 2010 Reporting database four new tables have been added to assist in reporting against the workflows.

    SQL Tables

    MSP_EPMWorkflowPhase – a lookup table consisting of the workflow phases and their associated description

    MSP_EPMWorkflowStage – a lookup table consisting of the workflow stages and their associated description

    MSP_EpmWorkflowStatusType – a lookup table consisting the workflow status and it’s associated language

    MSP_EPMWorkflowStatusInformation – Contains information about each project and it’s associated workflow status over time.

    These tables provide the core information about where a project is in a workflow, including the project stage, status and date information of when it entered and left the stage. Unfortunately what they don’t provide is an indication of any associated approvals, which makes sense when you understand that the approvals are not part of Project Server per se, but rather the underlying SharePoint platform.

    To extract the current workflow status of the project from the reporting database, I used the following query:

    select  epmp.ProjectName,
    epmwfs.StageName,
    epmwfs.StageDescription,
    epmwsi.StageInformation,
    epmwfst.StageStateDescription
    from MSP_EpmWorkflowStatusInformation epmwsi
    inner join MSP_EpmWorkflowStage epmwfs on epmwsi.StageUID = epmwfs.StageUID
    inner join MSP_EpmWorkflowStatusType epmwfst on epmwsi.StageStatus = epmwfst.StageStatusID
    inner join MSP_EpmProject epmp on epmwsi.ProjectUID = epmp.ProjectUID
    where epmwsi.ProjectUID = {Project GUID}
    and (StageEntryDate is not null and StageCompletionDate is null)
    

    The query takes the Project GUID as a parameter, and returns the currently in progress workflow stage as determined by the StageEntryDate and StageCompletionDate fields.

    For the purposes of the backstage proof of concept, I was only interested in returning the core project workflow information, but the query could easily be extended to return other information such as the Enterprise Project Type and it’s associated description.

    Now we have the workflow status information as retrieved from the Project Server Reporting database, in the next post, I will discuss how we extend the Project backstage and wire up the data we retrieved.

    Extending the Project Backspace…

    Demanad Management

    One of the significant changes in the Office 2010 client was the introduction of the backstage view. The way it has brought common commands front and centre and combined relevant supporting information has quickly become one of those features I can’t live without and certainly something I notice immediately when I use any 2007 Office client.

    In Project 2010, this is particularly noticeable, with a number of the Enterprise features that were previously buried away in the jungle of menu’s prominent on the backstage, including items such as Project Publish, Organising the Enterprise Global and accepting Status updates from your team, which is a massive improvement in usability and functionality.

    Whilst looking at the backstage, I started to think it would be a great way to present information about where the project was in its lifecycle as determined by the demand management* capabilities of Project Server 2010. At a very simplistic level demand management provides a framework for the collection and display of information through a number of web pages called Project Detail Pages (PDP’s) and workflows. Each of which can be customised in order to meet the specific requirements of the organisation. Demand management is a massive topic which I will be covering in a number of posts later on.

    So I decided to set out and create a proof of concept to integrate demand management workflow data in to the Project backstage. During the process I learnt a fair bit about how to extend the backstage view in Project, VBA and how to get the relevant workflow data, which I am going to share in a series of posts.

    * The demand management feature of Project Server has to be one of my most favourite features of the 2010 Server product. In fact I am so taken with it, I even went on record to say so :)

    Enable backwards compatibility mode on a fresh Project Server 2010 install

    One of the great features of Project Server 2010 is Backwards Compatibility Mode (BCM). With BCM, users can connect to Project Server 2010 with both Project Professional 2007 and 2010 clients. This can be a great bonus for companies that have already standardised on the Project 2007 toolset but want the features of Project Server 2010 without a costly client upgrade and rollout.

    Typically BCM is turned on when you upgrade your existing Project Server 2007 environment to Project Server 2010. If you do a fresh install of Project Server 2010, the server is installed in Native 2010 mode, only allowing Project 2010 clients to attach. However, it is possible to do a fresh 2010 install and enable backwards compatibility mode, and here’s how…

    1. Create a set of Project Server 2007 databases by provisioning a new Project Server PWA instance.

    Fresh Provision

    2. Save the four ‘clean’ databases created in your Project Server 2007 environment and back them up via SQL Server Management Studio. Restore the four ‘clean’ databases into your Project Server 2010 environment database and make sure they have the correct permissions for your environment (more info on restoring databases and setting the permissions can be found here)

    Restore DB

    3. In the 2010 environment, provision a new Project Web Application instance via Central Admin > Manage Service Applications > Project Server Service Application. In the configuration screen, change the four default database names to reflect the ‘clean’ Project Server 2007 databases restored above.

    Central Admin - new SA 1

    Central Admin - new SA 2

    4. Confirm that backwards compatibility mode has been turned on for the PWA instance in Server Settings > Additional Settings

    Additional Server Settings - BCM

    There you have it, the server now supports both Project Professional 2010 and Project Professional 2007.

    Update: Microsoft have released a set of clean Project Server 2007 databases that can be used to create a fresh 2010 instance. More details here.