Cascade Skyline - with Microsoft Logo and Project Support header - author Brian Smith

August, 2010

  • Brian Smith's Microsoft Project Support Blog

    Project Server: Adding Custom Fields to Projects and Tasks using the PSI


    This is a long time coming, prompted by a question on the forums and a promise I made in my blog from 2007

    This was created targeting  Project Server 2007, but there should be no issues using the exact same approach with Project Server 2010.

    I have built this around the SDK LoginDemo sample, and just added to the btnCreateProject_Click method.  The sample just creates a project - see  I have added a task, and both Project and Task level custom fields.  Across the project and task levels I have used each type of custom field to show which values need setting.  This is just to create a project - obviously adding or changing them later is very similar.

    In this example I created 3 project level custom fields – cost, date and a text one based on a lookup table.  For the task I created 4 custom fields – flag, number, duration and text.  I made them all required just to validate my code – except the Flag which will always have a value and therefore does not have the option to set to required (see

    For simplicity (and laziness) I have hard coded many of the GUIDs I am using.  For the Custom Fields I copied these from the URLs when in the edit screen for custom fields.  I got the lookup table value GUID in the 'View Source' page when editing the lookup table.  Obviously you could also get these from the database.  In a real situation you would use the Custom Field and Lookup Table web services.  Obviously your GUIDs will be different from mine.

    private void btnCreateProject_Click(object sender, EventArgs e)
                string projectCreatedLabel = "Project created!";
                string wssUrl;
                string projectWorkspace = ResetWorkspaceUrl();
                bool created = false;
                // GUIDs for my CFs etc - in practice you would use the CF and LU PSI calls
                Guid projCostGuid = new Guid("e672bd64-c535-4486-bc64-8f4999547390");
                Guid projDateGuid = new Guid("3dafa5d4-9473-4781-9503-aafe207a71bb");
                Guid projTextGuid = new Guid("08758857-1a69-4efb-a657-27ed61d7d7c3");
                Guid taskTextGuid = new Guid("30665299-bc21-4c51-b954-220d407ba47e");
                Guid taskFlagGuid = new Guid("3658a81d-2e64-436f-afb9-970b778954b1");
                Guid taskNumberGuid = new Guid("d5c0318c-06cc-4d82-a891-7f3ea43503ab");
                Guid taskDurationGuid = new Guid("58519124-7e1d-44b8-b14c-7435408f02e7");
                Guid colourLUValueRed = new Guid("5b730bab-7212-4ffb-823d-60aef0df1fff");
                lblProjectCreated.Text = "";
                lblWorkspaceUrl.Text = projectWorkspace;
                this.Cursor = Cursors.WaitCursor;
                    WebSvcProject.ProjectDataSet dsProject = 
                        new WebSvcProject.ProjectDataSet();
                    WebSvcProject.ProjectDataSet.ProjectRow projectRow = 
                    Guid projectGuid = Guid.NewGuid();
                    projectRow.PROJ_UID = projectGuid;
                    projectRow.PROJ_NAME = this.txtProjectName.Text;
                    projectRow.PROJ_TYPE = 
                    //Adding a row for my first Project CF - ProjCost
                    WebSvcProject.ProjectDataSet.ProjectCustomFieldsRow cfRowCost = 
                    cfRowCost.PROJ_UID = projectGuid;
                    // The Custom_Field_UID is the unique identifier for each custom field row
                    cfRowCost.CUSTOM_FIELD_UID = Guid.NewGuid();
                    // The MD_PROP_UID identifies the specific custom field
                    cfRowCost.MD_PROP_UID = projCostGuid;
                    // Cost custom fields have their value set in NUM_VALUE
                    // The value entered is decimal and 100 times the actual cost - 5000 = $50 in my case
                    cfRowCost.NUM_VALUE = 5000;
                   //Adding a row for my second Project CF - ProjDate
                    WebSvcProject.ProjectDataSet.ProjectCustomFieldsRow cfRowDate =
                    cfRowDate.PROJ_UID = projectGuid;
                    cfRowDate.CUSTOM_FIELD_UID = Guid.NewGuid();
                    cfRowDate.MD_PROP_UID = projDateGuid;
                    // Date custom fields have their values set in DATE_VALUE as a DateTime data type
                    cfRowDate.DATE_VALUE = DateTime.Parse("Aug 25, 2010 10:45:00 PM");
                    //Adding a row for my third Project CF - ProjText, which is based on a Lookup Table
                    WebSvcProject.ProjectDataSet.ProjectCustomFieldsRow cfRowText =
                    cfRowText.PROJ_UID = projectGuid;
                    cfRowText.CUSTOM_FIELD_UID = Guid.NewGuid();
                    cfRowText.MD_PROP_UID = projTextGuid;
                    // Custom fields based on a lookup table have the GUID that identifies the row in
                    // the lookup table entered against CODE_VALUE.  See the LT_STRUCT_UID from the 
                    // LookupTable web service
                    cfRowText.CODE_VALUE = colourLUValueRed;
                    //Adding my CFRows to the dataset
                    //Now for the Task custom fields.  First I will add a Task
                    WebSvcProject.ProjectDataSet.TaskRow taskRow =
                    Guid taskGuid = Guid.NewGuid();
                    taskRow.PROJ_UID = projectGuid;
                    taskRow.TASK_UID = taskGuid;
                    taskRow.TASK_NAME = "My Task";
                    //  And add some custom fields to my task
                    // First a text field not based on a lookup table
                    WebSvcProject.ProjectDataSet.TaskCustomFieldsRow cfRowTaskText =
                    cfRowTaskText.PROJ_UID = projectGuid;
                    // For our Task CF rows we need the Task UID as well as the Project UID
                    cfRowTaskText.TASK_UID = taskGuid;
                    cfRowTaskText.CUSTOM_FIELD_UID = Guid.NewGuid();
                    cfRowTaskText.MD_PROP_UID = taskTextGuid;
                    // As we have no lookup table for this text field the value goes in TEXT_VALUE
                    cfRowTaskText.TEXT_VALUE = "My Text Value";
                    // Next a Flag field
                    WebSvcProject.ProjectDataSet.TaskCustomFieldsRow cfRowTaskFlag =
                    cfRowTaskFlag.PROJ_UID = projectGuid;
                    cfRowTaskFlag.TASK_UID = taskGuid;
                    cfRowTaskFlag.CUSTOM_FIELD_UID = Guid.NewGuid();
                    cfRowTaskFlag.MD_PROP_UID = taskFlagGuid;
                    // Flags are a bool, so expect true or false - they default to false
                    // Also Flags cannot be made required, as they will always have a value anyway
                    // They are entered against FLAG_VALUE
                    cfRowTaskFlag.FLAG_VALUE = true;
                    // Next a Number field
                    WebSvcProject.ProjectDataSet.TaskCustomFieldsRow cfRowTaskNumber =
                    cfRowTaskNumber.PROJ_UID = projectGuid;
                    cfRowTaskNumber.TASK_UID = taskGuid;
                    cfRowTaskNumber.CUSTOM_FIELD_UID = Guid.NewGuid();
                    cfRowTaskNumber.MD_PROP_UID = taskNumberGuid;
                    // Numbers are decimal - the M suffix is used as this value would normally default to double
                    // They are entered against NUM_VALUE
                    cfRowTaskNumber.NUM_VALUE = 25.6M;
                    // Finally a duration field
                    WebSvcProject.ProjectDataSet.TaskCustomFieldsRow cfRowTaskDuration =
                    cfRowTaskDuration.PROJ_UID = projectGuid;
                    cfRowTaskDuration.TASK_UID = taskGuid;
                    cfRowTaskDuration.CUSTOM_FIELD_UID = Guid.NewGuid();
                    cfRowTaskDuration.MD_PROP_UID = taskDurationGuid;
                    // Durations have a format for their display which is best enumerated as below
                    // They are entered against NUM_VALUE
                    cfRowTaskDuration.DUR_FMT = (int)PSLibrary.Task.DurationFormat.Day; 
                    // Duration is indicated in tenths of minutes. A value of 100 indicates 10 minutes
                    cfRowTaskDuration.DUR_VALUE = 24000;
                    // Add my custom field rows to the dataset
                    Guid jobGuid = Guid.NewGuid();
                    bool validateOnly = false;
                    // Create and save project to the Draft db
                    project.QueueCreateProject(jobGuid, dsProject, validateOnly);
                    // Wait 3 seconds (more or less) for Queue job to complete.
                    // Or, add a routine that checks the QueueSystem for job completion.
                    WebSvcProject.ProjectRelationsDataSet dsProjectRelations =
                        new WebSvcProject.ProjectRelationsDataSet();
                    jobGuid = Guid.NewGuid();
                    // Set wssUrl = "" to have default WSS project workspace, or null to have no workspace.
                    if (chkDefaultWorkspace.Checked)
                        wssUrl = "";
                    else if (projectWorkspace == "")
                        wssUrl = null;
                        wssUrl = projectWorkspace;
                    bool fullPublish = true;
                    // Publishes project to the Published db
                    dsProjectRelations = project.QueuePublish(jobGuid, projectGuid, fullPublish, wssUrl);
                    created = true;
                catch (SoapException ex)
                    string errMess = "";
                    // Pass the exception to the PSClientError constructor to get 
                    // all error information.
                    PSLibrary.PSClientError error = new PSLibrary.PSClientError(ex);
                    PSLibrary.PSErrorInfo[] errors = error.GetAllErrors();
                    for (int j = 0; j < errors.Length; j++)
                        errMess += errors[j].ErrId.ToString() + "\n";
                    errMess += "\n" + ex.Message.ToString();
                    MessageBox.Show(errMess, "Error", MessageBoxButtons.OK,
                catch (WebException ex)
                    string message = ex.Message.ToString() +
                        "\n\nLog on, or check the Project Server Queuing Service";
                    MessageBox.Show(message, "Project Creation Error", 
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.Cursor = Cursors.Default;
                if (created)
                    lblProjectCreated.ForeColor = Color.Green;
                    lblWorkspaceUrl.Visible = true;
                    lblWorkspaceLabel.Visible = true;
                    projectCreatedLabel = "Project not created";
                    lblProjectCreated.ForeColor = Color.Red;
                    lblWorkspaceUrl.Visible = false;
                    lblWorkspaceLabel.Visible = true;
                lblProjectCreated.Text = projectCreatedLabel;
                lblProjectCreated.Visible = true;

    I hope this was worth waiting for!

    Technorati Tags: ,,
  • Brian Smith's Microsoft Project Support Blog

    Project Server 2010: Copying custom Project site templates across instances


    Interesting question came in today via the blog on my previous customization topic at and thought it worth a broader response, as it wasn’t something I had really thought about…  If you follow the directions at that blog then you can use the custom template in that PWA instance – but what about in other instances – or web apps or indeed other farms?  I played around a little and it is somewhat similar to the process in 2007 where you save off the template and then import – but I’ll guide you through the UI and also deal with an issue I ran in to – which I have a workaround for, but not sure why it worked on one of my sites but not another…

    If you have already used my previous article then you will have your template in a solution gallery – so browse to that gallery (Site Actions, Site Settings, Solutions (in the Galleries section) and you should see something like this:


    I have two custom templates, called BaseSite and Rainbow.  If I want to use these in another PWA instance then I need to Right Click and use the “Save Target as…” option to save a WSP file (my desktop is my usual destination for such things – just so I can find them again).

    The next step is to go to the same location in your target instance, click the Solutions tab and click the Upload Solution option in the ribbon.


    You can then browse to your saved .wsp file and upload.  This will bring up another dialog where you should Activate the solution:


    Once activated then it should look like the first screenshot – and show Activated under the Status column.  It will then be available to be selected as the template to be used within your Enterprise Project Type definition.  Here is my selection when I updated the Basic Project Plan EPT to use my new Rainbow template.  One gotcha is that you do need to update the EPT definition – just changing the value in the Project Site Provisioning settings page will do nothing.


    For me these steps were enough in one of my sites and I could successfully create and publish a new Basic Project Plan and got a ‘Rainbow’ based site.  (Just as an aside – I called this Rainbow not because it was colorful, but I was testing another scenario and had changed the values in the Issues and Risks ‘Category’ field choices list from the usual (1) Category 1… to Red, Orange, Yellow, etc.  This worked fine and these selections can be used for categorizing issues and risks – it breaks nothing, and even gets in to the reporting database without even needing to re-publish the plan – and will even be in the cube at the next build.

    Back to the main story.  For all my other sites,  I got a couple of failures in the queue when trying to create from this new template.  It appeared that the site was created but the template was not applied – as I could browse to it and it asked what template I would like…  So here are the messages, just so the search engine can have something useful to read:

    CreateWssSiteContent: Creating project site failed! Project Uid=5fd8daf5-619f-46c5-b884-8efe39b5935a, site URL=http://myserver.f.q.d.n/PWA/Test1, site name=Test1. Microsoft.SharePoint.SPException: The site template requires that the Feature {b90f23c9-68d5-4570-a3ef-4e491ee6d35a} be activated in the site collection

    WSSCreateSiteFailure (16400). Details: id='16400' name='WSSCreateSiteFailure' uid='bb9a4b90-5c77-4dc4-9bc9-2854554f6288' projectUID='5fd8daf5-619f-46c5-b884-8efe39b5935a' workspaceUrl='http://myserver.f.q.d.n/PWA/Test1/Test1' projectWorkspaceName='Test1'.

    Followed by:

    WSSWebAlreadyExists (16402). Details: id='16402' name='WSSWebAlreadyExists' uid='5703a3a1-4092-4a12-a15c-37b523ca9861'.

    There were also the usual 26000 GeneralQueueJobFailed messages too.

    From the message it appeared a feature hadn’t been activated and peeking into the content database this appeared to be something to do with AssociationForm.xsn.  This is probably related to the Dynamic Workflow solution starter I have been playing with – but you may well run in to other similar issues when moving things around so may need to activate features too.  This can be carried out via a PowerShell command – so start the SharePoint 2010 Management Shell as administrator then execute a command similar to:

    Enable-SPFeature –identity ‘b90f23c9-68d5-4570-a3ef-4e491ee6d35a’ –URL http://myserver.f.q.d.n/PWA

    where the identity will be the GUID from the first error message and URL will be the PWA instance where you want this template to work.

    Thanks to bpettersen for the question that prompted me to look deeper in to this topic.

    Technorati Tags: ,
  • Brian Smith's Microsoft Project Support Blog

    SharePoint Server 2010: Accidentally stopped your Central Administration service? Start it again with PowerShell!


    OK, I had one of those days yesterday.  I was working on my various servers and Hyper-V images to get them all patched and also wanted to update my SQL Server, but rather than shut down my Project Server 2010 application server I thought I’d just stop all the service in Central Administration.  Including Central Administration itself…  If you haven’t tried that one then you will go from this:


    to this, when you click Stop.


    Excellent!  A chance to learn some more PowerShell, as I was sure there must be some way of recovering from this from the SharePoint 2010 Management Shell.  So using the wonderful TAB feature to auto complete commands I soon found, by opening the Management Shell as administrator, typing start and then TAB a few times the command I needed – Start-SPServiceInstance.  I guess get-command, or gcm start* would have been nearly as quick.  A quick look at get-help start-SPServiceInstance and I found I needed the GUID (Identity) that represented the Central Administration service.  Come on, you all know yours by heart?  Get-SPServiceInstance came to the rescue, but I knew there was a better way than cutting and pasting the GUID after first sifting through all the services… (Tip – Get-SPServiceInstance | fl > servicelist.txt makes it a bit easier to read).  I should be able to pipeline the filtered output from my Get command through to my Start command.  So a few minutes and syntax checks later I had it solved:

    Get-SPServiceInstance | Where-Object {$_.TypeName –eq ‘Central Administration’} | Start-SPServiceInstance

    and my Central Administration site was back and available!  If you try this and it just sticks at provisioning then perhaps your SharePoint Timer Service is not running (Check Administrative Tools, Services on the application server) .  You can check the status with:

    Get-SPServiceInstance | Where-Object {$_.TypeName –eq ‘Central Administration’}

    it should eventually say Online.  It will say Disabled before you start it, and then Provisioning and finally Online.

    It is certainly worth getting to know what PowerShell can do to automate SharePoint.

  • Brian Smith's Microsoft Project Support Blog

    Project Server: Resource Plans and the PSI


    I was doing some investigations this week on the Resource Plans Web Service and want to share this as it probably gives more information than we have in the SDK currently – or at least pulls it together.  The example I will be working towards is adding a resource to a resource plan, along with an assignment within that resource plan.  My work was specifically with 2007, but as far as the dataset manipulation is concerned this applies equally to Project Server 2010.

    But first a quick look round the resource plan dataset and explaining how this maps to the UI.  The SDK article for 2007 is here and for 2010 is here – but to be honest you will be hard pressed to find much difference.

    The dataset has four data tables, Utilization, Dates, PlanAssignmentCustomFields and PlanResources.

    Utilization – This table shows the utilization type and date – which relate to the UI in this screenshots – 2007 and 2010. The types are as listed 0, 1 and 2 – with the date only applicable for type 2 (plan until:

    image           image

    From the SDK: The ResourcePlan.UtilizationType type is used in the RESPLAN_UTILIZATION_TYPE column of the ResourcePlanDataSet Utilization table. Values and descriptions for the ResourcePlan.UtilizationType type are provided solely for interpreting the information in this table.

    This is not intended to be used directly from your code.

    Dates – This table shows the start and end dates of the intervals defined for the Resource Plan.  The overall range will be set by the start and end dates entered when reading the dataset, and it will be broken into intervals according to the TimeScale specified.  The TimeScaleClass enumeration can be used when reading the dataset.  3 = Days, 4 = weeks, 5 = months and 7 = years – or (short)PSLibrary.TimeScaleClass.TimeScale.Months. 

    PlanAssignmentCustomFields – You can have custom fields set for the resource’s assignments in a resource plan!  Who knew?  I’m guessing not many people have seen the following screen.  This is from 2007, but almost identical to the 2010 equivalent.  This is also the place you can change the resource from Committed to Proposed – or vice versa.


    I’ve not played around with these via the PSI – but this is the table you would work with, and as is usual with Custom Fields, you need to add a row then set the properties.

    PlanResource – This table is the one that I will be working with in my sample code where we will be adding a resource.  When you read a Resource Plan you will see it contains a ton of information on the resource, most of which you do not need to enter when adding one, along with a flag for Committed or Proposed (ASSN_BOOKING_TYPE) and a set of fields Interval0 to Interval’n’ which relates to the ‘n’ intervals you will see in the dates table.  When adding a resource you can also add an assignment by putting some value in one or more of these intervals.  The parameters for getting the resource plan dataset using ReadResourcePlan are:

    filter - XML filter to limit data returned. For more information, see How to: Use a Filter Parameter with PSI Methods. I am not using filters, and as you can specify the project GUID there probably aren’t many circumstances when you’d need to filter down – unless you have a really large number of resources assigned.
    projectUid - Project GUID.
    startDate - Start date. This is the start date of the data you want to pull down from the server and manipulate – so it is potentially just a window on the entire resource plan, and need not relate to the date settings within the UI
    endDate - End date.
    timeScale - Time scale specified by the TimeScaleClass.TimeScale enumeration. Explained above – controls the time intervals
    timephasedFTE - If true, return the full time equivalent resources.  This will govern if you enter FTEs, or, if false, then time (in 1/10th of a minutes) for the work values.
    autoCheckOut - If true, check out the resource plan for editing.  This will depend exactly what you are doing.  You might want to check out just before the update, and you would also want to check that it wasn’t already checked out too.

    A similar set of parameters also apply to the QueueUpdateResourcePlan method:

    projectUid - Project GUID.
    rpds - ResourcePlanDataSet that specifies changes in the specified resource plan.  Basically a manipulated version of the one you read in.  Don’t AcceptChanges!
    timephasedFTE - If true, update with timephased full time equivalent resources. Same meaning as above.
    autoCheckIn - If true, check in the resource plan after updating.
    jobUid - Queue job GUID.

    Also I am assuming there is already a Resource Plan for the project – if not my code would fail with a System.Web.Services.Protocols.SoapException: ProjectServerError(s) LastError=GeneralItemDoesNotExist and you would need to use the UI or QueueCreateResourcePlan method.  And finally you cannot publish the resource plan unless the project plan is published – or you will get another error - System.Web.Services.Protocols.SoapException: ProjectServerError(s) LastError=ResourcePlanProjectPublishIncomplete.  It would be unusual to get this condition as in most cases you create resource plans on published projects, but could happen with Activitity plans and proposals and server-side or other programmatically created projects.

    Rather than repeat things I have added comments in the code where I think some explanation is necessary.  This snippet assumes you have a reference to PSLibrary = Microsoft.Office.Project.Server.Library; and a web reference to the Resource Plan web service.  I’ve hardcoded quite a bit of stuff just to show what is going on.


    Guid projUid = new Guid("357afdea-0b68-46bc-8358-7557c8f90a8f");            
    Guid resUid = new Guid("f249df7c-eca9-41c7-bd52-48def0ab50bc");                        
    ResourcePlan resourcePlan = new ResourcePlan();           
    resourcePlan.Credentials = CredentialCache.DefaultCredentials;           
    resourcePlan.Url = "http://brismithupgrade/2k7/_vti_bin/PSI/resourceplan.asmx";
    ResourcePlanDataSet dsResourcePlan = new ResourcePlanDataSet();
    // Read in a resource plan dataset for our chosen project 
    dsResourcePlan = resourcePlan.ReadResourcePlan(null, projUid               
     ,DateTime.Parse("01/01/2010"), DateTime.Parse("12/31/2010")
     ,(short)PSLibrary.TimeScaleClass.TimeScale.Months , false, false); 
    // Create a new Plan Resource Row and set some properties
    ResourcePlanDataSet.PlanResourcesRow resourcePlanRow 
    = dsResourcePlan.PlanResources.NewPlanResourcesRow();            
    resourcePlanRow.PROJ_UID = projUid;            
    resourcePlanRow.RES_UID = resUid; 
    // Assignment UID does not need to be specified - it will be auto generated             
    // The value used against intervalx will depend on the setting for the timePhasedFTE value            
    // If set to true, then enter values like 1 for one Full Time Equivalent            
    // If set to false the Intervalx values are entered as 1/10th Minutes - 600 = 1h, 4800 = 1d            
    // This entry adds 4800 = 1d = 8h, to the 7th interval - August with the settings I am using
    resourcePlanRow["Interval7"] = 4800;
    // And this one adds 5 days to September
    resourcePlanRow["Interval8"] = 48000;
    // 0 = Committed and 1 = Proposed or use the enumeration
    resourcePlanRow.ASSN_BOOKING_TYPE = (byte)PSLibrary.Resource.BookingType.Committed ;
    // Add the row the the resource plan 
    // Use the same jobUid for the update and checkin.
    Guid jobUid = Guid.NewGuid();
    resourcePlan.CheckOutResourcePlans(new Guid[1] { projUid });            
    resourcePlan.QueueUpdateResourcePlan(projUid, dsResourcePlan, false, false, jobUid);  
    //  Need to be sure the project plan is published or this will fail
    resourcePlan.QueuePublishResourcePlan(projUid, Guid.NewGuid());            
    resourcePlan.QueueCheckInResourcePlans(new Guid[1] { projUid }, false, new Guid[1] { jobUid });

    I hope this help you understand how to work with Resource Plans in a programmatic way.

  • Brian Smith's Microsoft Project Support Blog

    Project Server 2010: Business Intelligence Center – Behind the Scenes


    In this posting I wanted to take a look at the structure behind the Business Intelligence Center in Project Server 2010 so that hopefully if you run in to any issues you can work out what might be wrong.  This adds to the TechNet article on configuring reporting at which includes some great videos, and also Treb’s blog posting on troubleshooting reporting problems

    When you provision a new PWA site you get a Data Connection library, with folders for each language version you have loaded, then within each folder is a set of Office Data Connection (ODC) files that contain the details of the source of the data, the SQL query that will return the data, and the ID of the Target Application profile used to get the data (ProjectServerApplication is the default).  You also get the Sample Reports Library and the Templates libraries during the provision process, which also contain folders for each installed language pack.  When you build a cube you will see added another folder for each cube within each language folder for the Templates library and the Data Connections library – which again contains ODC files for the OLAP report templates added in the templates language directories at the same time the cube is built.

    So when you click on a sample report, then assuming it is in a trusted file location it will go off to the referenced ODC in the report, and assuming that too is in a trusted data connection location then this will use the credentials in the Target Application and go off and get you data.  What could possibly go wrong?

    Things can get interesting if you change Alternate Access Mappings (AAM).  Now the Sample Reports and Templates will still be there, but referenced by a different URL, so you will need to update the trusted file locations for those.  Also your data connections will be on a different URL so the trusted data connections address will also need to be updated.  So where will the report look for the ODC file?  You guessed it – in the original location.  If by pure luck or good planning the original location also happens to have a path that is still in the Alternate Access Mappings list then you will still get your report.  If not then a message will appear; The following data connection file does not exist or you do not have permissions to it: and it will look like this::


    Now one answer would be to just add the AAM – but this may not be desirable or practical, particularly if the new AAM was added for Internet access and was a fully qualified domain name with SSL to replacing the original NETBIOS server name – or perhaps as in my testing you provisioned everything on one server, got it all working and then added a Web Front End.  You could of course just edit each report and update the ODC to look in the right place – but assuming you are just getting started and have not added a whole bunch of your own reports, templates and ODCs there is another way…  Delete the Business Intelligence Center!  Now obviously this is a big step, and as I said, you would only want to do this if you had added nothing of value that you didn’t mind re-creating, but by deleting the site, and then running the PWA provision ‘Edit’ option it will get re-created and the ODCs will point to wherever the default AAM is now pointing.

    To delete the BI Center (once you have re-read the paragraph above, and are really, really sure you want to do this), click on the option in the left navigation for Business Intelligence, then Site Actions, Site Settings, Delete this site (and it doesn’t go into the recycle bin!).  Once it is gone then check that your default AAM is pointing where you want it and go to the Project Service Application, select the Edit option from the drop down for the site you wish to re-create your Business Intelligence Center. then without making any changes in the page that comes up - click Edit.


    You will see it go through the usual steps of provisioning, but what it is really doing is similar to a repair on a client installation – and when it find the BI Center is not there is will re-create it, but this time with the links to the ODCs now pointing to the right place.  Once the site is provisioned then go back to Business Intelligence and all will be good.  All libraries and folders for all languages will be there – even the ones for any cubes you have already built.

    I think OLAP was the most read topic of my 2007 blogs after common installation issues – so I am sure there will be more topics to add, but hopefully this background will help you understand what can and might go wrong.

    Technorati Tags: ,
Page 1 of 3 (11 items) 123