Archive for 'Technical Issues' Category
Creating or Viewing Views in Data Analysis can cause Analysis Services to become unresponsive
23 April 2008At a previous client, I encountered an issue where, when creating or viewing certain views in Data Analysis, the Analysis Services service would spike in processor/memory utilization and become unresponsive.
I have recently discovered tghat this is a known issue in environments that have an interaction between Office Web Components and SQL Server 2005 Analysis Services with Service Pack 2 (which means Project Server).
Although I’m not 100% sure, I believe the KB that covers this issue is KB936251. The symptoms seem to fit.
At any rate, I have been told that the resolution was included way back in SQL Server 2005 Cumulative Update 2. I recommend that you install the current CU, which is CU7, due to the number of fixes it contains.
Discuss this post on the EPMFAQ Forums
© Stephen Sanderlin for EPMFAQ, 2008. | Permalink
Add to del.icio.us | Want more on this topic? Browse the archive of posts filed under Administration, Configuration, Defects, From The Field, HotFixes and Service Packs, Implementation and Deployment, PWA, Project Server 2007, Quick Tips, Reporting, SQL Analysis Services and OLAP.
Related Posts
- Creating or Viewing Views in Data Analysis can cause Analysis Services to become unresponsive
- Cube Build Failure: Your permissions on the server computer do not allow you to administer this Analysis server
- Slow or Failing Cube Builds and Very Large TempDB
- Are you recieving a ReportingWssSyncListFailed error after modifying a Project Workspace or deploying a customized Project Workspace Template?
- Privacy Policy
Copyright ©2007-2008 Stephen Sanderlin and others as listed. Some rights reserved.
All other trademarks and copyrights are the property of their respective owners.
All content in this feed is covered by the Creative Commons Attribution-Share Alike 3.0 United States License.
(digitalfingerprint: 98f116c448a33659cf8172e78f33f0e6 (66.150.96.121) )
Popularity: 14% [?]
Microsoft Project Conference 2007 Presentations
23 April 2008
You can find the presentations from the Microsoft Office Project Conference 2007 (European version) at:
http://www.ineventmedia.com/msprojectfinalupload/
Now these are just the slides and a lot of Good Stuff was either spoken, asked/answered or part of a demo. Based on just the slides, I will highlight the following:
- BP301 Managing Security in the EPM Solution by Phil Smail
- SA209 Project Server Disaster Recovery by Steven Haden and Christophe Fiessinger
- SA200 Chalk Talk: Project 2007 Common Questions and Answers by Adrian Jenkins
- SA201 Administration of an EPM solution by Adrian Jenkins (Brian Smith delivered this in Seattle)
Popularity: 18% [?]
MS Project Server 2007 Best Practice :: Forms vs Windows Authentication
23 April 2008I guess so many people are happy with the windows authentication features that comes with MS Project Server and found it very easy to setup and to use. But did they know that there is another way of authenticating users, i am sure that they knew but they never think when and how to use it
First let me focus on facts about each and when each one is recommended to be used?
Windows Authentication
- It is authenticate users against the AD that the Project Server is joint to. So, it can use only one AD. So if all of your users are belongs to one domain then this will be your right choice.
- Roles and groups (or any AD classification) are not used in EPM, remember that the title is all about Authentication, not authorization. Authorization is run through the security model embedded with the Project server itself.
- Project Server users list and the AD users list is not an linked. You need to schedule synch job from within Project Server itself from time to time, this means if user has became inactive then this will not be reflected into the Project Server. (needless to say that if the user became inactive or blocked in AD then he/she will not get authenticated to AD but he can be still used as a resource in Project Server)
“>Forms Authentication
- Conceptually, it is very similar to the AD authentication, except that Membership Provider will be used instead of AD
- More flexible to contain users regardless of the AD they belongs and even if they don’t belong to any AD
- Difficult (or not straight forward to setup) to setup and maintain the users credentials.
- No synch tool is available out of the box except for the "PjFormsAuthUpgrade" tool that comes with Project server
ore articles about Forms authentication, be tuned
Best Regards
Bilal Okour

Popularity: 14% [?]
Project Server Load Balancing Using F5
23 April 2008Ryan Korock from F5 has shared the following suggestions when discussing load balancing for Project Server:
- Load Balancing Method - Because of the nature of HTTP, any of the load balancing methods will work fairly well (this is not always true for other protocols). I suggest using least connections or predictive, as they start to take into account system performance when determining where to send the next connection.
- Persistence – Although most Project Server deployments do not require persistence (aka stickyness), there is a small benefit of enabling it. A SharePoint server does build a small cache, and so getting sent to the same server as before may generate a small performance gain. I recommend using ‘cookie’ persistence, which will persist a user based upon http cookies. BIG-IP allows you to create a ‘backup’ method of source IP based persistence, which is also recommended.
- Health Monitoring – I always recommend monitoring the servers at an ‘application layer’. This means building an http based monitor for the Project Server, which can give us more insight into the server health, beyond just a ping or tcp port check.
g F5 hardware for load balancing the following are recommended by Ryan:
- Cookie persistence is a great way to make sure http users are resuming their sessions on the same front end they were originally sent to
- Least Connection load balancing is also great option for sending new users to the currently least utilized servers
Last but not least F5 and HP have also published a recent study that could be of interest depending on your deployment topology: Deploying F5 Networks BIG-IP Local Traffic Manager with WebAccelerator for Microsoft Office SharePoint Server 2007
Popularity: 8% [?]
Impersonation Within a Project Server 2007 Server-Side Event Handler
23 April 2008One topic that our customers and partners seem to be having a hard time with is impersonation. One reason is that the term we are using – impersonation – may already mean something to developers, and so the specific steps required to get impersonation working for Project Server 2007 and the PSI aren’t taken into consideration. The SDK covers this in a couple of topics, but to show a couple more examples I’ve prepared a couple of event handlers that show what happens when you use and don’t use impersonation.
What does impersonation achieve with event handlers? It allows a an event handler to take action as a particular user – and this is useful for a few different reasons.
1. Whatever transaction that is carried out will be running as a chosen user – so it will look as though this user made any changes – and this will be reflected in any user accounts associated with the transaction.
2. The account running the event service (the SSP administrator) does not need to be a user in PWA and/or have any specific permissions.
3. For certain web services, particularly statusing, the call returns data based on the user making the request – so you need to pretend to be the user in question – rather than the SSP Admin.
If you don’t impersonate and the SSP Admin is not a user in PWA you will get errors like The request failed with HTTP status 401: Unauthorized. If this exception is not handled it will also mean the event handler crashes and if it is a “pre” event it will be canceled. Depending on where the event comes from the user may or may not get any notification that the cancellation occurred – so you need to code for this . If they are a user, then they will need the right permissions for whichever web service they are calling – and if they call a statusing web service such as ReadStatus then the result will be the tasks for the SSP Admin – and not for the user who triggered the request.
If you do impersonate then you don’t need to be a user in PWA, and a request to ReadStatus gets the tasks for the user who triggered the request.
My code sample below shows the same code both with and without impersonation and catches the timesheet OnCreated event, and also the statusing OnStatusUpdate. The event handlers don’t do anything useful – just write to the event log both some data from the event payload and also make a request to a web service and write some details of the response – just to illustrate the differences seen when impersonating.
As usual, my samples don’t include the level of exception handling you should include – and also include some hard coded values that you may wish to either use in application settings or to resolve at run-time using reflection. Remember that with event handlers, and particularly the “pre” events, you want your code to be very light weight. Also remember that in “pre” events that although you have access to more of the payload than post events you cannot modify it.
For my sample responding the the timesheet OnCreated event that does not use impersonation then if the SSP Admin is not a user we get the expected 401 error – whoever creates a timesheet, because the call to the ReadTimesheet fails. If the SSP Admin is a user but is just a team member then the call to ReadTimesheet will work ONLY when the SSP Admin creates a timesheet – but will fail with a GeneralSecurityAccessDenied error from the event handler – as the SSP Admin cannot read anyone else’s timesheet. If they are an administrator (or explicitly have the View Resource Timesheet global permission) then they can successfully call the ReadTimesheet and the event handler will work. If the same is done using impersonation then it will work regardless of the SSP Admin permissions – and they do not even need to be a user in Project Server.
For the sample responding to the statusing OnStatusUpdate event that does not use impersonation we see slightly different behavior. We still see failure if the SSP is not a user (401), but if they are a user then the call to ReadStatus will work – but does not return the number of tasks for the user who triggered the event – but always the number of tasks for the SSP Admin (so only correct if the user triggering the event was SSP Admin) and we also see that the name of the SSP Admin is the one returned from this call.
Basically the steps needed for impersonation are that the code is running as the SSP Admin (which the event service always does – so no problem here) and that the call to web services goes to the SSP location of the web service and not the PWA location (see the code below for examples). This also needs context setting for the resource and site uid – both of which are available from the contextInfo of the event itself. The final point is that you need to create web services derived from the Project Server web services that has an override of the WebRequest to add a couple of items to the header. I used classes already included in the ProjTool sample (in the Utils directory) with very minor changes.
Here is the code - and the only other thing you need to know is that you will need to add web references to the LoginWindows, TimeSheet and Statusing web services - and references to the Microsoft.Office.Project.Schema, Microsoft.Office.Project.Server.Library and Microsoft.Office.Project.Server.Events.Receivers.
I’ve also attached a zip of the two .cs files as I noticed there is some trimming of the longer lines.
First without impersonation…
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Text; using Microsoft.Office.Project.Server.Events; using PSLibrary = Microsoft.Office.Project.Server.Library; namespace EventHandlerWithNoImpersonation { public class MyEventHandler:TimesheetEventReceiver { const string LOGINWINDOWS = “_vti_bin/PSI/LoginWindows.asmx”; const string TIMESHEET = “_vti_bin/PSI/TimeSheet.asmx”; private static WebSvcLoginWindows.LoginWindows loginWindows = new WebSvcLoginWindows.LoginWindows(); private static WebSvcTimeSheet.TimeSheet timeSheet = new EventHandlerWithNoImpersonation.WebSvcTimeSheet.TimeSheet(); private string baseUrl = “http://servername/cal/”; public override void OnCreated(PSLibrary.PSContextInfo contextInfo, TimesheetPostEventArgs e) { base.OnCreated(contextInfo, e); loginWindows.Url = baseUrl + LOGINWINDOWS; loginWindows.Credentials = CredentialCache.DefaultCredentials; timeSheet.Url = baseUrl + TIMESHEET; timeSheet.Credentials = CredentialCache.DefaultCredentials; WebSvcTimeSheet.TimesheetDataSet dsTimeSheet = new EventHandlerWithNoImpersonation.WebSvcTimeSheet.TimesheetDataSet(); // As this call is using a specific UID it doesn’t require dsTimeSheet = timeSheet.ReadTimesheet(e.TsUID); WebSvcTimeSheet.TimesheetDataSet.HeadersRow headersRow = (WebSvcTimeSheet.TimesheetDataSet.HeadersRow)dsTimeSheet.Headers.Rows[0]; string tsName = headersRow.TS_NAME; // Create an EventLog instance and assign its source. EventLog myLog = new EventLog(); myLog.Source = “Timesheet Event Handler”; // Get information from the event arguments, and // write an entry to the Application event log. string userName = contextInfo.UserName.ToString(); string timesheetGuid = e.TsUID.ToString(); int eventId = 3937; string logEntry; logEntry = “User: “ + userName + “nTimesheet UID: ” + timesheetGuid + “nThis timesheet is called: “ + tsName; myLog.WriteEntry(logEntry, EventLogEntryType.Information, eventId); } } public class MyEventHandler2 : StatusingEventReceiver { const string LOGINWINDOWS = “_vti_bin/PSI/LoginWindows.asmx”; const string STATUSING = “_vti_bin/PSI/Statusing.asmx”; private static WebSvcLoginWindows.LoginWindows loginWindows = new WebSvcLoginWindows.LoginWindows(); private static WebSvcStatusing.Statusing statusing = new EventHandlerWithNoImpersonation.WebSvcStatusing.Statusing(); private string baseUrl = “http://servername/PWA/”; public override void OnStatusUpdating(Microsoft.Office.Project.Server.Library.PSContextInfo contextInfo, StatusUpdatePreEventArgs e) { base.OnStatusUpdating(contextInfo, e); loginWindows.Url = baseUrl + LOGINWINDOWS; loginWindows.Credentials = CredentialCache.DefaultCredentials; statusing.Url = baseUrl + STATUSING; statusing.Credentials = CredentialCache.DefaultCredentials; WebSvcStatusing.StatusingDataSet dsStatusing = new EventHandlerWithNoImpersonation.WebSvcStatusing.StatusingDataSet(); dsStatusing = statusing.ReadStatus(Guid.Empty,DateTime.MinValue,DateTime.MaxValue); WebSvcStatusing.StatusingDataSet.ResourcesRow resourceRow = (WebSvcStatusing.StatusingDataSet.ResourcesRow)dsStatusing.Resources.Rows[0]; int taskCount = dsStatusing.Tasks.Count; string statusOwner = resourceRow.RES_NAME; // Create an EventLog instance and assign its source. EventLog myLog = new EventLog(); myLog.Source = “Statusing Event Handler”; // Get information from the event arguments, and // write an entry to the Application event log. string userName = contextInfo.UserName.ToString(); string statusingXml = e.ChangeXml; int eventId = 3938; string logEntry; logEntry = “User: “ + userName + “nChangeXML: ” + statusingXml + “nThis statusing dataset has “ + taskCount + ” tasks, and they belong to “ + statusOwner; myLog.WriteEntry(logEntry, EventLogEntryType.Information, eventId); } } }
and then with impersonation…
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Text; using Microsoft.Office.Project.Server.Events; using PSLibrary = Microsoft.Office.Project.Server.Library; namespace EventHandlerWithImpersonation { public class MyEventHandlerImp :TimesheetEventReceiver { const string LOGINWINDOWS = “LoginWindows.asmx”; const string TIMESHEET = “TimeSheet.asmx”; private string baseUrl = “http://servername:56737/SharedServices1/PSI/”; private static LoginWindowsDerived loginWindows = new LoginWindowsDerived(); private static TimesheetDerived timeSheet = new TimesheetDerived(); public override void OnCreated(PSLibrary.PSContextInfo contextInfo, TimesheetPostEventArgs e) { base.OnCreated(contextInfo, e); bool isWindowsAccount = contextInfo.IsWindowsUser; Guid trackingGuid = Guid.NewGuid(); string lcid = “1033″; string userNTAccount = contextInfo.UserName; Guid resourceGuid = new Guid(contextInfo.UserGuid.ToByteArray()); Guid siteId = new Guid(contextInfo.SiteGuid.ToByteArray()); LoginWindowsDerived.SetImpersonationContext(isWindowsAccount, userNTAccount, resourceGuid, trackingGuid, siteId, lcid); TimesheetDerived.SetImpersonationContext(isWindowsAccount, userNTAccount, resourceGuid, trackingGuid, siteId, lcid); loginWindows.Url = baseUrl + LOGINWINDOWS; loginWindows.Credentials = CredentialCache.DefaultCredentials; timeSheet.Url = baseUrl + TIMESHEET; timeSheet.Credentials = CredentialCache.DefaultCredentials; WebSvcTimeSheet.TimesheetDataSet dsTimeSheet = new EventHandlerWithImpersonation.WebSvcTimeSheet.TimesheetDataSet(); dsTimeSheet = timeSheet.ReadTimesheet(e.TsUID); WebSvcTimeSheet.TimesheetDataSet.HeadersRow headersRow = (WebSvcTimeSheet.TimesheetDataSet.HeadersRow)dsTimeSheet.Headers.Rows[0]; string tsName = headersRow.TS_NAME; // Create an EventLog instance and assign its source. EventLog myLog = new EventLog(); myLog.Source = “Impersonating Timesheet Event Handler”; // Get information from the event arguments, and // write an entry to the Application event log. string userName = contextInfo.UserName.ToString(); string timesheetGuid = e.TsUID.ToString(); int eventId = 3939; string logEntry; logEntry = “User: “ + userName + “nTimesheet UID: ” + timesheetGuid + “nThis timesheet is called: “ + tsName; myLog.WriteEntry(logEntry, EventLogEntryType.Information, eventId); } } public class MyEventHandlerImp2 :StatusingEventReceiver { const string LOGINWINDOWS = “LoginWindows.asmx”; const string STATUSING = “Statusing.asmx”; private string baseUrl = “http://servername:56737/SharedServices1/PSI/”; private static LoginWindowsDerived loginWindows = new LoginWindowsDerived(); private static StatusingDerived statusing = new StatusingDerived(); public override void OnStatusUpdating(PSLibrary.PSContextInfo contextInfo, StatusUpdatePreEventArgs e) { base.OnStatusUpdating(contextInfo, e); bool isWindowsAccount = contextInfo.IsWindowsUser; Guid trackingGuid = Guid.NewGuid(); string lcid = “1033″; string userNTAccount = contextInfo.UserName; Guid resourceGuid = new Guid(contextInfo.UserGuid.ToByteArray()); Guid siteId = new Guid(contextInfo.SiteGuid.ToByteArray()); LoginWindowsDerived.SetImpersonationContext(isWindowsAccount, userNTAccount, resourceGuid, trackingGuid, siteId, lcid); StatusingDerived.SetImpersonationContext(isWindowsAccount, userNTAccount, resourceGuid, trackingGuid, siteId, lcid); loginWindows.Url = baseUrl + LOGINWINDOWS; loginWindows.Credentials = CredentialCache.DefaultCredentials; statusing.Url = baseUrl + STATUSING; statusing.Credentials = CredentialCache.DefaultCredentials; WebSvcStatusing.StatusingDataSet dsStatusing = new EventHandlerWithImpersonation.WebSvcStatusing.StatusingDataSet(); dsStatusing = statusing.ReadStatus(Guid.Empty, DateTime.MinValue, DateTime.MaxValue); WebSvcStatusing.StatusingDataSet.ResourcesRow resourceRow = (WebSvcStatusing.StatusingDataSet.ResourcesRow)dsStatusing.Resources.Rows[0]; int taskCount = dsStatusing.Tasks.Count; string statusOwner = resourceRow.RES_NAME; // Create an EventLog instance and assign its source. EventLog myLog = new EventLog(); myLog.Source = “Impersonating Statusing Event Handler”; // Get information from the event arguments, and // write an entry to the Application event log. string userName = contextInfo.UserName.ToString(); string statusingXml = e.ChangeXml; int eventId = 3940; string logEntry; logEntry = “User: “ + userName + “nChangeXML: ” + statusingXml + “nThis statusing dataset has “ + taskCount + ” tasks, and they belong to “ + statusOwner; myLog.WriteEntry(logEntry, EventLogEntryType.Information, eventId); } } class LoginWindowsDerived : WebSvcLoginWindows.LoginWindows { private static String ContextString = String.Empty; protected override WebRequest GetWebRequest(Uri uri) { //here we are overriding the GetWebRequest method and adding the 2 web request headers WebRequest webRequest = base.GetWebRequest(uri); if (ContextString != String.Empty) { webRequest.UseDefaultCredentials = true; bool isImpersonating = (System.Security.Principal.WindowsIdentity.GetCurrent(true) != null); webRequest.Credentials = CredentialCache.DefaultNetworkCredentials; webRequest.Headers.Add(“PjAuth”, ContextString); webRequest.Headers.Add(“ForwardFrom”, “/_vti_bin/psi/LoginWindows.asmx”); webRequest.PreAuthenticate = true; } return webRequest; } public static void SetImpersonationContext(bool isWindowsUser, String userNTAccount, Guid userGuid, Guid trackingGuid, Guid siteId, String lcid) { ContextString = GetImpersonationContext(isWindowsUser, userNTAccount, userGuid, trackingGuid, siteId, lcid); } private static String GetImpersonationContext(bool isWindowsUser, String userNTAccount, Guid userGuid, Guid trackingGuid, Guid siteId, String lcid) { PSLibrary.PSContextInfo contextInfo = new PSLibrary.PSContextInfo(isWindowsUser, userNTAccount, userGuid, trackingGuid, siteId, lcid); String contextString = PSLibrary.PSContextInfo.SerializeToString(contextInfo); return contextString; } } class TimesheetDerived : WebSvcTimeSheet.TimeSheet { private static String ContextString = String.Empty; protected override WebRequest GetWebRequest(Uri uri) { //here we are overriding the GetWebRequest method and adding the 2 web request headers WebRequest webRequest = base.GetWebRequest(uri); if (ContextString != String.Empty) { webRequest.UseDefaultCredentials = true; bool isImpersonating = (System.Security.Principal.WindowsIdentity.GetCurrent(true) != null); webRequest.Credentials = CredentialCache.DefaultNetworkCredentials; webRequest.Headers.Add(“PjAuth”, ContextString); webRequest.Headers.Add(“ForwardFrom”, “/_vti_bin/psi/timesheet.asmx”); webRequest.PreAuthenticate = true; } return webRequest; } public static void SetImpersonationContext(bool isWindowsUser, String userNTAccount, Guid userGuid, Guid trackingGuid, Guid siteId, String lcid) { ContextString = GetImpersonationContext(isWindowsUser, userNTAccount, userGuid, trackingGuid, siteId, lcid); } private static String GetImpersonationContext(bool isWindowsUser, String userNTAccount, Guid userGuid, Guid trackingGuid, Guid siteId, String lcid) { PSLibrary.PSContextInfo contextInfo = new PSLibrary.PSContextInfo(isWindowsUser, userNTAccount, userGuid, trackingGuid, siteId, lcid); String contextString = PSLibrary.PSContextInfo.SerializeToString(contextInfo); return contextString; } } class StatusingDerived : WebSvcStatusing.Statusing { private static String ContextString = String.Empty; protected override WebRequest GetWebRequest(Uri uri) { //here we are overriding the GetWebRequest method and adding the 2 web request headers WebRequest webRequest = base.GetWebRequest(uri); if (ContextString != String.Empty) { webRequest.UseDefaultCredentials = true; bool isImpersonating = (System.Security.Principal.WindowsIdentity.GetCurrent(true) != null); webRequest.Credentials = CredentialCache.DefaultNetworkCredentials; webRequest.Headers.Add(“PjAuth”, ContextString); webRequest.Headers.Add(“ForwardFrom”, “/_vti_bin/psi/statusing.asmx”); webRequest.PreAuthenticate = true; } return webRequest; } public static void SetImpersonationContext(bool isWindowsUser, String userNTAccount, Guid userGuid, Guid trackingGuid, Guid siteId, String lcid) { ContextString = GetImpersonationContext(isWindowsUser, userNTAccount, userGuid, trackingGuid, siteId, lcid); } private static String GetImpersonationContext(bool isWindowsUser, String userNTAccount, Guid userGuid, Guid trackingGuid, Guid siteId, String lcid) { PSLibrary.PSContextInfo contextInfo = new PSLibrary.PSContextInfo(isWindowsUser, userNTAccount, userGuid, trackingGuid, siteId, lcid); String contextString = PSLibrary.PSContextInfo.SerializeToString(contextInfo); return contextString; } } }
Enjoy!
Popularity: 18% [?]
Can’t Sort Enterprise Templates ?
21 April 2008

Popularity: 5% [?]
Timesheet Bug - Project Server 2007
21 April 2008

Popularity: 5% [?]
Project Server 2007 server-side event handling
17 April 2008Christophe has just posted on the Codeplex solution that allows easy handling of event handlers http://blogs.msdn.com/chrisfie/archive/2008/04/15/deploying-a-custom-event-handler-has-never-been-easier.aspx and I had my first chance to play with this yesterday. It made life so much easier! Please do take a look if you are working with server -side event handlers.
On a similar topic I have been working on event handlers that use impersonation to ensure that the event can get at the Project Server data in the right context - or use a specific user account to have the right permissions. I’ll be posting that in the next few days. But for now - take a look at the Codeplex stuff.
Popularity: 3% [?]
Workspace synchronization cannot be disabled.
17 April 2008Repro steps:
- Disable workspace permission synchronization on project server.
- Change permission on project workspace.
- Publish project using Projtool -
And now miracle happened, project workspace permissions were updated.
By the way i was foced to do same Project server certifications, I expected that I can schedule all project exams in one day (70-632 ,70-633, 70-634 ,70-639) but i my order was reduced and i did only 2 exams.
http://www.microsoft.com/learning/mcp/transcripts
- Transcript ID: 762314
- Access Code:mw123456
Popularity: 3% [?]

