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

June, 2008

  • Brian Smith's Microsoft Project Support Blog

    My SSP stopped working when I restored to another domain! Unable to Edit a Project Server or SharePoint Shared Services Provider.

    • 7 Comments

    I’m guessing this problem may be more of an issue for us Project Server 2007 support guys at Microsoft than for most customers – but I can certainly see scenario’s where this one would bite you too, so worth an explanation.  I’ll throw in all the text from the logs etc. at the end as it makes better reading for the search indexers than for normal people and just concentrate first on what breaks and how to work around the issue.

    When you are restoring a farm backup you get the option to update the accounts used for most things – then some of the other accounts you can set once you have things up and running.  However, if you have added any accounts into the “Process Account with Access to this SSP” section of the Edit Properties part of the SSP the accounts just get carried through to the new configuration database.  Unfortunately this can break some stuff – and even more unfortunate is that the first thing it breaks is the page where you would go to remove them!  Basically the page tries to validate the data it has and gives the following error:-

    An unhandled exception occurred in the user interface.Exception Information: The specified account name is invalid.
    Parameter name: account

    The same problem occurs if an account added in Process Accounts is removed from AD – and this may well be the most common customer scenario if restoring across domains is not involved.  Verbose logging for Office Server General will also show the actual DOMAIN\User that is causing the problem.

    You can also see the same error if you try to run stsadm –o enumssp.  And other SSP related jobs may post a very similar error in the Application Event Log as they fail to work.  Our workaround until now has been the usual; create a new SSP and change associations, and only today did I get to the bottom of this particular failure.  The only supportable workaround is to take a fresh backup after removing any accounts from the Process Accounts section.  The stsadm –o editssp also does not seem to give a way to remove an account that is not valid – giving an error:

    A failure occurred during the processing of this command. Check diagnostic logs
    for more information.

    and logs the same kind of thing in the ULS logs as detailed below. 

    So here is the less interesting stuff that Live and any other search engines I have forgotten can lap up…

    ULS Log

    =======

    Verbose

    Office Server

    Office Server General

    792o

    Verbose

    NTAccount 'DOMAIN\User could not be translated to a SID. Exception: System.Security.Principal.IdentityNotMappedException: Some or all identity references could not be translated. at System.Security.Principal.NTAccount.Translate(IdentityReferenceCollection sourceAccounts, Type targetType, Boolean forceSuccess) at System.Security.Principal.NTAccount.Translate(Type targetType) at Microsoft.Office.Server.Utilities.WindowsSecurity.ValidateAccount(NTAccount account, Boolean throwIfInvalid)

    Exception

    Office Server

    Office Server General

    837w

    Exception

    Unhandled page level exception. Path: /_admin/sspdetails.aspx, Error: The specified account name is invalid. Parameter name: account, Details: System.ArgumentException: The specified account name is invalid. Parameter name: account ---> System.Security.Principal.IdentityNotMappedException: Some or all identity references could not be translated. at System.Security.Principal.NTAccount.Translate(IdentityReferenceCollection sourceAccounts, Type targetType, Boolean forceSuccess) at System.Security.Principal.NTAccount.Translate(Type targetType) at Microsoft.Office.Server.Utilities.WindowsSecurity.ValidateAccount(NTAccount account, Boolean throwIfInvalid) --- End of inner exception stack trace --- at Microsoft.Office.Server.Utilities.WindowsSecurity.ValidateAccount(NTAccoun... Continues...

    Application Event Log

    ==================

    No specific error relating to the failed Edit Properties page - but due to the same root cause there would likely be errors like the one below, possibly every minute.

    Event Type: Warning

    Event Source: Office SharePoint Server

    Event Category: Office Server Shared Services

    Event ID: 5783

    Date: 6/12/2008

    Time: 10:01:52 AM

    User: N/A

    Computer: W2K3

    Description: Synchronization for Shared Services Provider 'SSP1' has failed. The operation will be retried.

    Reason: The specified account name is invalid.

    Parameter name: account

    Technical Support Details:

    System.ArgumentException: The specified account name is invalid.

    Parameter name: account ---> System.Security.Principal.IdentityNotMappedException: Some or all identity references could not be translated. at System.Security.Principal.NTAccount.Translate(IdentityReferenceCollection sourceAccounts, Type targetType, Boolean forceSuccess) at System.Security.Principal.NTAccount.Translate(Type targetType) at Microsoft.Office.Server.Utilities.WindowsSecurity.ValidateAccount(NTAccount account, Boolean throwIfInvalid)

    --- End of inner exception stack trace ---

    at Microsoft.Office.Server.Utilities.WindowsSecurity.ValidateAccount(NTAccount account, Boolean throwIfInvalid) at Microsoft.Office.Server.Administration.SharedAccessRule.Validate() at Microsoft.Office.Server.Administration.SharedComponentSecurity.SetAccessRule(SharedAccessRule accessRule) at Microsoft.Office.Server.Administration.SharedComponentSecurityFormatter.DeserializeFromXml(XmlReader xmlReader, SharedComponentSecurity& security) at Microsoft.Office.Server.Administration.SharedComponentSecurityFormatter.FromXmlString(String xml) at Microsoft.Office.Server.Administration.SharedResourceProvider.InternalGetAccessControl() at Microsoft.Office.Server.Administration.SharedResourceProvider.GetApplicationSecurity() at Microsoft.Office.Server.Administration.SharedResourceProvider.Microsoft.Office.Server.Administration.ISharedComponent.Synchronize() at Microsoft.Office.Server.Administration.SharedResourceProviderJob.Execute(Guid targetInstanceId)

  • Brian Smith's Microsoft Project Support Blog

    TechEd Preview – Part 3 – Project Server 2007 Provisioning Project Specific Workspaces automatically

    • 10 Comments

    First day of TechEd today and despite the 3hr time difference from Seattle I still woke up early.  This posting will be part of the subject of the chalk talk I am delivering with Boris Scholl tomorrow (6/4) morning.  If any of you remember the Solution Accelerator for Six Sigma this is part inspired by some custom code that was in that solution – and is designed to allow a Project Manager to select a workspace type from a list in a custom project field – and then when she publishes that type of site will be provisioned from a pre-built template.

    The first part of this is to create some templates for new workspaces.  This is covered in the SDK, but briefly you must base any new template on an unlinked site, then you save as a template, then from the template gallery save to a file (*.stp) and then you use stsadm –o addtemplate to bring the template back in so it can be used for provisioning (and a final IIS reset).  You will also need to use the command stsadm –o enumtemplates to get the internal name (something like _GLOBAL_#2) for each of your templates for later use.

    The next step is creating a lookup table to hold the template details – and it should look something like this:-

    image

     

    I am using the description field to hold the internal name of the template as that is the one used when requesting a site to be provisioned.  You could resolve this in code somewhere – it just seemed easier to me to put it here. You also need to create a Project Level custom field that references this lookup table – and in my example I use the “NotYet” value to mean don’t create a site for me.  The names of the field/table aren’t important – but you will need to know the Guid associated with them.  Also you will need to turn off automatic site creation – as we will be controlling this via an event handler.  I am using Red/Green/Blue for the visual recognition for the demo – obviously ISO 9001, Six Sigma, Administration m- would be more useful types of templates to use.

    Now the event handler.  I’ve thrown a few comments in and also it logs to the application event log the different actions it can take.  It could certainly do with more (read some) exception handling… but it does the job.  Based on the custom field requested it will get the template name from the lookup table description.  If a site already exists it will stop – and if the requested site is already in use it will stop.

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Text;
    using System.Net;
    using Microsoft.Office.Project.Server.Events;
    using PSLibrary = Microsoft.Office.Project.Server.Library;
    
    
    namespace TechEdEventHandler
    {
        public class MyPublishedEventHandler : ProjectEventReceiver
        {
            private const string URLPREFIX = "http://";
            private const string LOGINWINDOWSWEBSERVICE = "_vti_bin/PSI/LoginWindows.asmx";
            private const string PROJECTWEBSERVICE = "_vti_bin/PSI/Project.asmx";
            private const string WSSINTEROPWEBSERVICE = "_vti_bin/PSI/WSSInterop.asmx";
            private const string LOOKUPTABLEWEBSERVICE = "_vti_bin/PSI/LookupTable.asmx";
            private string baseUrl = "http://brismithwfe/cal/";
            private const int EVENTID = 9191;
            
            private string webTemplateName;
            private Guid projectGuid;
            private Guid codeValue;
            const int PROJECT_CUSTOM_FIELDS_ENTITY_TYPE = 32;
            // We need the Guids for the lookup table and custom field - better practice would be to use a settings file
            private Guid workspaceTemplateLUTGuid = new Guid("b0fc9d01-b716-43d3-aa74-335a3297214b");
            private Guid workspaceTemplateCFGuid = new Guid("98c9444e-1fa2-4f12-ab2b-4cb7e1818738");
    
            private static WebSvcLoginWindows.LoginWindows loginWindows =
                new WebSvcLoginWindows.LoginWindows();
            private static WebSvcProject.Project project =
                new WebSvcProject.Project();
            private static WebSvcWssInterop.WssInterop wssInterop =
                new WebSvcWssInterop.WssInterop();
            private static WebSvcLookupTable.LookupTable lookupTable =
                new WebSvcLookupTable.LookupTable();
    
            public override void OnPublished(Microsoft.Office.Project.Server.Library.PSContextInfo contextInfo, ProjectPostPublishEventArgs e)
            {
                string eventName = "Auto Workspace Creation - OnPublished";
                
                loginWindows.Url = baseUrl + LOGINWINDOWSWEBSERVICE;
                loginWindows.Credentials = CredentialCache.DefaultCredentials;
                project.Url = baseUrl + PROJECTWEBSERVICE;
                project.Credentials = CredentialCache.DefaultCredentials;
                lookupTable.Url = baseUrl + LOOKUPTABLEWEBSERVICE;
                lookupTable.Credentials = CredentialCache.DefaultCredentials;
                wssInterop.Url = baseUrl + WSSINTEROPWEBSERVICE;
                wssInterop.Credentials = CredentialCache.DefaultCredentials;
    
                projectGuid = e.ProjectGuid;
    
                WebSvcWssInterop.WssServersDataSet dsWssServersDataSet = 
                    new WebSvcWssInterop.WssServersDataSet();
    
                WebSvcWssInterop.WssSettingsDataSet dsWssSettingsDataSet =
                    new WebSvcWssInterop.WssSettingsDataSet();
    
                WebSvcWssInterop.ProjectWSSInfoDataSet dsProjectWSSInfoDataSet =
                    new WebSvcWssInterop.ProjectWSSInfoDataSet();
    
                // If rowcount is greater than zero then a site already exists for the project - so exit
                dsProjectWSSInfoDataSet = wssInterop.ReadWssData(projectGuid);
                int rowCount = dsProjectWSSInfoDataSet.ProjWssInfo.Rows.Count;
                if (rowCount == 0)
                {
    
                    WebSvcProject.ProjectDataSet dsProject =
                        new WebSvcProject.ProjectDataSet();
                    // We are getting the project dataset - but only for the entity type 32 - custom fields
                    dsProject = project.ReadProjectEntities(projectGuid, PROJECT_CUSTOM_FIELDS_ENTITY_TYPE, WebSvcProject.DataStoreEnum.WorkingStore);
                    // The we look for the workspace template field - and get the code value
                    foreach (WebSvcProject.ProjectDataSet.ProjectCustomFieldsRow rowProjectCF in dsProject.ProjectCustomFields)
                        if (rowProjectCF.MD_PROP_UID == workspaceTemplateCFGuid)
                        {
                            codeValue = rowProjectCF.CODE_VALUE;
                        }
                    // Using the Guid for the lookup table we search for the code value 
                    Guid[] ltUidList = new Guid[] { workspaceTemplateLUTGuid };
                    WebSvcLookupTable.LookupTableDataSet dsLookupTable =
                        new WebSvcLookupTable.LookupTableDataSet();
                    dsLookupTable = lookupTable.ReadLookupTablesByUids(ltUidList, false, 1033);
                    // the code value gets us to the description which we use as the webtemplatename
                    foreach (WebSvcLookupTable.LookupTableDataSet.LookupTableTreesRow rowLookupTable in dsLookupTable.LookupTableTrees)
                        if (rowLookupTable.LT_STRUCT_UID == codeValue)
                        {
                            webTemplateName = rowLookupTable.LT_VALUE_DESC;
                        }
                    dsWssServersDataSet = wssInterop.ReadWssServerInfo();
                    dsWssSettingsDataSet = wssInterop.ReadWssSettings();
    
                    Guid wssServerUid = dsWssSettingsDataSet.WssAdmin[0].WADMIN_CURRENT_STS_SERVER_UID;
                    string wssWebFullUrl = dsWssServersDataSet.WssServers.FindByWSTS_SERVER_UID(wssServerUid).WSS_SERVER_URL
                        + "/" + dsWssSettingsDataSet.WssAdmin[0].WADMIN_DEFAULT_SITE_COLLECTION
                        + "/" + e.ProjectName.ToString();
    
                    int webTemplateLcid = 1033;
                    // If site exists then we cannot create it for this project...
                    bool SiteExists = wssInterop.WSSWebExists(wssWebFullUrl);
                    if (!SiteExists)
                    {
                        //NotYet means we will create it later
                        if (webTemplateName != "NotYet")
                        {   
                            // This is where we create a site if we need one
                            wssInterop.CreateWssSite(projectGuid, wssServerUid, wssWebFullUrl, webTemplateLcid, webTemplateName);
                            
                            string msg = string.Format("{0}: Site {1} created for Project {2}", eventName, wssWebFullUrl, e.ProjectName);
                            WriteEvent(msg, EventLogEntryType.SuccessAudit , EVENTID);
                        }
    
                        else
                        {
                            string msg = string.Format("{0}: No site required at this time for project {1}", eventName, e.ProjectName);
                            WriteEvent(msg, EventLogEntryType.Information, EVENTID);
                        }
    
    
                    }
                    else
                    {
                        string msg = string.Format("{0}: Site {1) already exists", eventName, wssWebFullUrl);
                        WriteEvent(msg, EventLogEntryType.Error, EVENTID);
                    }
    
                }
                else
                {
                    string msg = string.Format("{0}: Workspace already created", eventName);
                    WriteEvent(msg, EventLogEntryType.Information, EVENTID);
                }
                
            }
            
        private void WriteEvent(string msg, EventLogEntryType logEntryType, int eventId)
            {
                EventLog myLog = new EventLog();
                myLog.Source = "Project Event Handler";
    
                string message = msg;
                myLog.WriteEntry(msg, logEntryType, eventId);
            }
        }
    }

    Enjoy!

  • Brian Smith's Microsoft Project Support Blog

    TechEd 2008 Preview – Part 4 – COM Add-in from Project Professional making PSI calls

    • 1 Comments

    This is the last TechEd sample and is a very simple example of a PSI call from Project Pro (or Standard for that matter).  It shows how a user of the client not connected to the server can still make PSI calls.  Obviously they need an account in the PWA they are communicating with.  The sample shows a PSI call to check that the local project name (or any text you want to enter manually) is in use on the Project Server.  The response is shown on the form for the add-in and also put into the text1 field of the project – just to show how local data can also be updated with VSTO applications. 

    The details for creating a VSTO add-in for project were very well covered in Jack Dahlgren's posting http://zo-d.com/blog/archives/programming/making-the-move-from-vba-to-vsto-in-microsoft-project.html posting recently – thanks Jack – so I will just give samples of my code and not repeat the “how to” section.  I also needed web references to the Project and LoginWindows web services.  My code is also in C# so some differences to Jack’s posting. 

    The ThisAddIn.cs file looks like this and is adding a toolbar button and setting the for to show when the button is clicked:-

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml.Linq;
    using MSProject = Microsoft.Office.Interop.MSProject;
    using Office = Microsoft.Office.Core;
    using System.Windows.Forms;
    
    namespace TechEdComAddIn
    {
        public partial class ThisAddIn
        {
            private Office.CommandBar commandBar;
            private Office.CommandBarButton importButton;
    
            private void ThisAddIn_Startup(object sender, System.EventArgs e)
            {
                
                if (commandBar == null)
                {
                    int barPosition = 1;
                    bool isMenuBar = false;
                    bool isTemporary = true;
                    commandBar = Application.CommandBars.Add("ValidateBar", barPosition,
                                                             isMenuBar, isTemporary);
                }
                
                try
                {
                    importButton = (Office.CommandBarButton)commandBar.Controls.Add(
                        Office.MsoControlType.msoControlButton, missing, missing, missing, missing);
                    importButton.Style = Office.MsoButtonStyle.msoButtonCaption;
                    importButton.Caption = "Validate Project Name";
                    importButton.Tag = "Validate Project Name";
                    importButton.TooltipText = "Validates a name for later use in Project Server.";
                    importButton.Click +=
                        new Office._CommandBarButtonEvents_ClickEventHandler(ImportButtonClick);
    
                    commandBar.Visible = true;
                }
                catch (ArgumentException ex)
                {
                    MessageBox.Show(ex.Message, "Error adding toolbar button",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                
            }
    
            private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
            {
            }
    
            private void ImportButtonClick(Office.CommandBarButton ctrl, ref bool cancel)
            {
                //ImportDialogBox importDialog = new ImportDialogBox();
                //importDialog.Show();
                
                ProjNameValidate myForm = new ProjNameValidate(); ;
                myForm.Show();
            }
            
           
            #region VSTO generated code
    
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InternalStartup()
            {
                this.Startup += new System.EventHandler(ThisAddIn_Startup);
                this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
            }
            
            #endregion
        }
    }
     
    The form looks like this:-
     
    image 
    And the code behind:-
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Net;
    using System.Text;
    using System.Windows.Forms;
    
    namespace TechEdComAddIn
    {
        public partial class ProjNameValidate : Form
        {
            private const string URLPREFIX = "http://";
            private const string LOGINWINDOWSWEBSERVICE = "_vti_bin/PSI/LoginWindows.asmx";
            private const string PROJECTWEBSERVICE = "_vti_bin/PSI/Project.asmx";
    
            private string baseUrl = "http://brismithwfe/cal/";
    
    
      
            private static WebSvcLoginWindows.LoginWindows loginWindows =
                new WebSvcLoginWindows.LoginWindows();
            private static WebSvcProject.Project project =
                new WebSvcProject.Project();
    
            public ProjNameValidate()
            {
                InitializeComponent();
                string projName = Globals.ThisAddIn.Application.ActiveProject.Name.ToString();
                int extLocation = projName.LastIndexOf(".mpp");
                textBoxProjectName.Text = projName.Substring(0, extLocation);
            }
    
            private void btnValidateName_Click(object sender, EventArgs e)
            {
                try
                {
                    loginWindows.Url = baseUrl + LOGINWINDOWSWEBSERVICE;
                    loginWindows.Credentials = CredentialCache.DefaultCredentials;
                    project.Url = baseUrl + PROJECTWEBSERVICE;
                    project.Credentials = CredentialCache.DefaultCredentials;
    
                   
                    WebSvcProject.ProjectDataSet dsProject =
                            new WebSvcProject.ProjectDataSet();
                    dsProject = project.ReadProjectList();
                    foreach (WebSvcProject.ProjectDataSet.ProjectRow rowProject in dsProject.Project)
                        if (rowProject.PROJ_NAME == textBoxProjectName.Text.ToString())
                        {
                            lblResponse.Text = "Project name already in use";
                            lblResponse.Visible = true;
                            break;
                        }
                        else
                        {
                            lblResponse.Text = "Project name is OK to use.";
                        }
                    Globals.ThisAddIn.Application.ActiveProject.Text1 = lblResponse.Text;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
    
            }
        }
    }
    
    I don’t think there is anything too complicated.  I trim the .mpp off the local filename and then see if it exists on the server.  Globals is the way to interact with the local application object.
    Once you have that available most of the VBA developers out there should be on home territory.  Take a look at the VSTO stuff – it is very simple to deploy too – as Jack’s article outlines.
    Technorati Tags: , ,
     
     
     
     
     
     
     
  • Brian Smith's Microsoft Project Support Blog

    Our Project Server writers have been hard at work – latest demo videos and TechNet content links…

    • 0 Comments

    The latest updates for this month can be found at the following links.  Great work guys!  If there are any other topics you think we are light on then please let me know, so either I can blog on them or we can get other content prepared. 

    Demo Videos

    Watch this: Use lag and lead time

    This demo shows how to use lag and lead time to create gaps and overlaps between tasks in a project.

    Watch this: Create a project

    This demo shows how to create a project, set project properties, and set file properties.

    Watch this: Set up a recurring task

    This demo shows how to create a task that repeats on a set schedule throughout a project.

    Watch this: Split a task

    This demo shows how to interrupt a task, creating a gap between two portions of the task. It also shows how to move the entire split task, adjust the length of the gap created by the split, and rejoin the split portions of the task to remove the gap.

    Watch this: Insert a task

    This demo shows how to insert a new task between two existing tasks in a project.

    Watch this: Group tasks or resources

    This demo shows how to group tasks, remove the grouping, and create a new resource group using multiple criteria.

    Watch this: Create a cross-project link

    This demo shows how to create task dependencies across separate Project 2007 files.

    Watch this: Link tasks in your project

    This demo shows how to create task dependencies within a single project, and how to adjust the link type for the dependency.

    TechNet Content

    Best practices for managing the Microsoft Office Project Server Queue Service

    This article describes best practices for managing and troubleshooting the Queue system in Office Project Server 2007.

    View the ULS logs for queue job entries

    This article describes how to view Microsoft Office Project Server 2007 queue job entries in the ULS logs. It can be used in conjunction with the Manage Queue page in Project Web Access Server settings to help troubleshoot queue job issues.

    Configure maximum job processor threads for the Project Server Queue service

    This article provides guidance about how to configure the maximum job processor threads for each queue type for the Project Server queue service.

    WhitePaper: A phased approach to deploying Enterprise Project Management

    This whitepaper by Chris Vandersluis provides business decision makers, network administrators, and Project Server administrators guidance about various challenges you can face when planning to deploy the Enterprise Project Management solution in your environment. It is the feature article of the From the Trenches – Deploying EPM in the Real World column available on the Project Server 2007 TechCenter.

    Back up and restore the Shared Services Provider

    This article gives you an overview of the task of backing up and restoring the Shared Services Provider for Project Server 2007, and includes task requirements and best practices.

    Back up the Shared Services Provider

    This article provides procedural steps for backing up the Shared Services Provider for Project Server 2007, and includes task requirements.

    Restore the Shared Services Provider

    This article provides procedural steps for restoring the Shared Services Provider for Project Server 2007, and includes task requirements.

  • Brian Smith's Microsoft Project Support Blog

    Project Server - If you modify some of our files – they won’t get updated by service packs…

    • 2 Comments

    During one of the sessions at TechEd Developer 2008 I raised this point, and as many in the audience were unaware of this behavior when updates are applied I (and the audience) though this worthy of some blog space.  The KB below relates to Project Server 2003 sp2a and later service packs – and as far as I am aware (but I am double checking…) this behavior is still the standard for Project Server 2007 too.  So if you have modified any files in your deployment you should return the original (that you saved before customizing – right?) to its rightful place before applying the update.  Once the update is applied then you will obviously need to re-apply whatever changes you needed to the new file (after making another secure copy of course).  Regardless of if we overwrite your customization or don’t update modified file the above is good practice so that you know you have the latest files in place and you have consciously reviewed and re-applied updates.  Who knows – we might even have fixed something so that you no longer need your mod!

    http://support.microsoft.com/kb/906357

Page 1 of 2 (8 items) 12