lørdag den 25. juli 2015

Project Server - People Picker App (Addin)

Do you also miss the user type custom field in Project Server?


Don't worry, The People Picker App is now available in the SharePoint Store.
Simply install the App from the SharePoint Store and add the People Picker to you PDP.
Now no project manager will be able to type an incorrect user name.

Project Seach App (Addin) - FREE

Do you also spend a lot of time searching for your project in Project Online. Is it time consuming to find the correct PDP or navigate to the project site.

Now the Project Search app is available in Project Online. And it is currently free to install on any Project Online environment.

To install the app simply search for "Project Search" in the SharePoint store and install it on your PWA.






Insert the Project Seach App Part to any page on the PWA. For example the front page.

Save the page and start searching for Projects.

fredag den 22. maj 2015

MS Project Cannot Change Start Date (2007/2010/2013/2016)

Jumping Start Dates

Start date always jumps back to specific date in MS Project plan when you try to change it.
This is an issue I have not seen before, but to be honest it is a long time since I last touched a project plan.

Problem
Whenever I try to change Task 03 to something earlier then the 26th. The date is just resets to 26 without any explanation.

Reason
The reason is that there is a binding on the phases. Most likely with a lag of minus some days.

This binding forces the task to not being able to start earlier than the phase start.

Now this is somehow obvious, it becomes more comeplex if the task have an actual start date (if a team member have reported time on the task through Timesheet or MyTasks).
In this scenario the phase appear to start on the 23th. However, it actually starts on the 26th.
Now I cannot move new tasks within the phase before the original start date of the phase (the 26th).

This makes sense, but from the Gant Chart it is not very clear,

Solution
Well, if you understand the problem the solution is simple.
Remove the binding from the phases, In fact this is not a real binding anyway, because the task actually started at a time where it sould not be possible.

Or you can ask your team member to register his time at another date. This is of cause only a solution if the team member did not do the work at the reported date.



lørdag den 9. maj 2015

Project Server 2010 -> 2013 migration - Large databases -> Slow Convertto-SPProjectDatabase

The last couple of days i have tried to migrate a Project Server 2010 to Project Server 2013. The Project Server 2010 contained some quite large databases compared to what I normally encounter.
The shrinked database sizes was:
 - Archive:      75 GB
 - Draft:        40 GB
 - Published:    50 GB
 - Reporting:    20 GB
 - Content:       2 GB
As you properly already know the migration process contains the following steps:

 Mount-SPContentDatabase –Name ProjectServer_PWA –WebApplication http://projectserver/ -NoB2BSiteUpgrade  
 $wa = get-SPWebApplication http://projectserver  
 $wa.UseClaimsAuthentication = $true  
 $wa.Update()  
 (Get-SPWebApplication http://projectserver).migrateUsers($true)  
 Set-SPSite –Identity http://projectserver/TECHPWA -SecondaryOwnerAlias "CONTOSO\Administrator"  
 Upgrade-SPSite -Identity http://projectserver/TECHPWA -versionupgrade  
 Convertto-SPProjectDatabase -WebApplication http://projectserver -Dbserver projectserver -ArchiveDbname TechPWA_Archive -DraftDbname TechPWA_Draft –PublishedDbname TechPWA_Published –ReportingDbname TechPWA_Reporting –ProjectServiceDbname TechPWA_ProjectWebApp  
 Mount-SPProjectDatabase –Name "ProjectServer_PWA_ProjectWebApp" –WebApplication http://projectserver  
 Upgrade-SPProjectDatabase -Name "ProjectServer_PWA_ProjectWebApp" -WebApplication http://projectserver  
 Mount-SPProjectWebInstance -DatabaseName "ProjectServer_PWA_ProjectWebApp" -SiteCollection " http://projectserver/TechPWA" -DatabaseServer "projectserver"  
 Upgrade-SPProjectWebInstance -Identity "http://projectserver/TechPWA"  
 Enable-SPFeature -Identity TechPWAsite -URL "http://projectserver/TechPWA"  
 Test-SPProjectWebInstance –Identity http://projectserver/TechPWA  

At the step where I consolidate the four Project Server 2010 databases (Convertto-SPProjectDatabase) I started to encounter some problems.

Firstly the new ProjectWebApp database started at the size of 5 MB and slowly increased with 5 MB every 30 sec until it reached 40 MB.
Now the size jumped to 54.000 MB and everything stalled. The database size was static, the memory did not increase, the CPU was idle and the Powershell just keep hanging. for this reason i tried to restart the Powershell command several times also on different servers, always the same result.
After around 1½ day the Convertto-SPProjectDatabase finally finished with an error:

 Convertto-SPProjectDatabase : INIT METADATA ERROR!  
 At least one mismatch found between SQL schema for view  
 MSP_EpmProject_UserView and reporting metadata. Schema column: Project Number.  
 Metadata column: NULL  
 Call to MSP_Epm_CheckIntrinsicAttributes failed for Projects  
 INIT METADATA ERROR.  
 At line:1 char:1  
 + Convertto-SPProjectDatabase -WebApplication http://projectserver -Dbserver  
 ppm2013 ...  
 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
 ~~~  
   + CategoryInfo     : InvalidOperation: (Microsoft.Offic...baseImpleme  
   ntor:ConvertToProjec...baseImplementor) [ConvertTo-SPProjectDatabase], Sql  
  Exception  
   + FullyQualifiedErrorId : Microsoft.Office.Project.Server.Cmdlet.PSCmdletC  
   onvertToProjectServiceDatabase  

I do not know the reason for the error (somthing with the schema for a custom field column not being correct). However, simply modify the stored procedure "MSP_Epm_CheckIntrinsicAttributes" to never return an error solved the problem.
So if you encounter this problem, simply execute the modified version of the Stored Procedure below:

 USE [ProjectServer_ProjectWebApp]/[ProjectServer_Reporting]
 GO  
 /****** Object: StoredProcedure [dbo].[MSP_Epm_CheckIntrinsicAttributes]  Script Date: 5/9/2015 4:02:14 PM ******/  
 SET ANSI_NULLS ON  
 GO  
 SET QUOTED_IDENTIFIER ON  
 GO  
 ALTER PROCEDURE [dbo].[MSP_Epm_CheckIntrinsicAttributes]  
   @EntityTypeUID       [uniqueidentifier],   
   @AttributeIsTimephased   [FLAG]          
 AS  
 BEGIN  
   DECLARE @TableName     [NAME]  
   DECLARE @UserViewName   [NAME]  
   DECLARE @OlapViewName   [NAME]  
   DECLARE @ErrorMessage   nvarchar(1000)  
   DECLARE @SchemaColumn   [NAME]  
   DECLARE @MetadataColumn  [NAME]  
   IF @AttributeIsTimephased = 0  
   BEGIN  
    SELECT @TableName = EntityNonTimephasedTableName  
    FROM MSP_EpmMetadataEntities  
    WHERE MSP_EpmMetadataEntities.EntityTypeUID = @EntityTypeUID  
    SET @UserViewName = @TableName + '_UserView'  
    SET @OlapViewName = @TableName + '_OlapView_00000000-0000-0000-0000-000000000000'  
    SELECT TOP 1  
      @SchemaColumn = SchemaInfo.ColumnName,  
      @MetadataColumn = MetadataAttribute.ColumnName  
    FROM  
    (  
      SELECT ColumnName = syscolumns.name  
      FROM dbo.syscolumns  
      INNER JOIN dbo.sysobjects ON  
       syscolumns.id = sysobjects.id  
      WHERE sysobjects.name = @UserViewName  
    ) AS SchemaInfo  
    FULL OUTER JOIN  
    (  
      SELECT ColumnName = MSP_EpmMetadataAttribute.AttributeColumnName  
      FROM MSP_EpmMetadataAttribute  
      WHERE  
       MSP_EpmMetadataAttribute.EntityTypeUID = @EntityTypeUID  
       AND MSP_EpmMetadataAttribute.AttributeIsTimephased = 0  
       AND dbo.MFN_Epm_ExtendedAttributeIsExposedInView(MSP_EpmMetadataAttribute.AttributeTypeUID, 1) = 1  
    ) AS MetadataAttribute ON  
      SchemaInfo.ColumnName = MetadataAttribute.ColumnName  
    WHERE  
      SchemaInfo.ColumnName IS NULL  
      OR MetadataAttribute.ColumnName IS NULL  
    IF (@SchemaColumn IS NOT NULL) OR (@MetadataColumn IS NOT NULL)  
    BEGIN  
      SET @ErrorMessage = 'At least one mismatch found between SQL schema for view ' + @UserViewName + ' and reporting metadata. Schema column: ' + ISNULL(@SchemaColumn, 'NULL') + '. Metadata column: ' + ISNULL(@MetadataColumn, 'NULL')  
      GOTO LblError  
    END  
    SELECT TOP 1  
      @SchemaColumn = SchemaInfo.ColumnName,  
      @MetadataColumn = MetadataAttribute.ColumnName  
    FROM  
    (  
      SELECT ColumnName = syscolumns.name  
      FROM dbo.syscolumns  
      INNER JOIN dbo.sysobjects ON  
       syscolumns.id = sysobjects.id  
      WHERE sysobjects.name = @OlapViewName  
    ) AS SchemaInfo  
    FULL OUTER JOIN  
    (  
      SELECT ColumnName = MSP_EpmMetadataAttribute.AttributeColumnName  
      FROM MSP_EpmMetadataAttribute  
      WHERE  
       MSP_EpmMetadataAttribute.EntityTypeUID = @EntityTypeUID  
       AND MSP_EpmMetadataAttribute.AttributeIsTimephased = 0  
       AND dbo.MFN_Epm_ExtendedAttributeIsExposedInView(MSP_EpmMetadataAttribute.AttributeTypeUID, 0) = 1  
    ) AS MetadataAttribute ON  
      SchemaInfo.ColumnName = MetadataAttribute.ColumnName  
    WHERE  
      SchemaInfo.ColumnName IS NULL  
      OR MetadataAttribute.ColumnName IS NULL  
    IF (@SchemaColumn IS NOT NULL) OR (@MetadataColumn IS NOT NULL)  
    BEGIN  
      SET @ErrorMessage = 'At least one mismatch found between SQL schema for view ' + QUOTENAME(@OlapViewName) + ' and reporting metadata. Schema column: ' + ISNULL(@SchemaColumn, 'NULL') + '. Metadata column: ' + ISNULL(@MetadataColumn, 'NULL')  
      GOTO LblError  
    END  
    SELECT TOP 1  
      @SchemaColumn = SchemaInfo.ColumnName,  
      @MetadataColumn = MetadataAttribute.ColumnName  
    FROM  
    (  
      SELECT ColumnName = syscolumns.name  
      FROM dbo.syscolumns  
      INNER JOIN dbo.sysobjects ON  
       syscolumns.id = sysobjects.id  
      WHERE sysobjects.name = @TableName  
    ) AS SchemaInfo  
    FULL OUTER JOIN  
    (  
      SELECT ColumnName = MSP_EpmMetadataAttribute.AttributeColumnName  
      FROM MSP_EpmMetadataAttribute  
      WHERE  
       MSP_EpmMetadataAttribute.EntityTypeUID = @EntityTypeUID  
       AND MSP_EpmMetadataAttribute.AttributeIsTimephased = 0  
       AND MSP_EpmMetadataAttribute.PresentInTable = 1  
    ) AS MetadataAttribute ON  
      SchemaInfo.ColumnName = MetadataAttribute.ColumnName  
    WHERE  
      SchemaInfo.ColumnName IS NULL  
      OR MetadataAttribute.ColumnName IS NULL  
    IF (@SchemaColumn IS NOT NULL) OR (@MetadataColumn IS NOT NULL)  
    BEGIN  
      SET @ErrorMessage = 'At least one mismatch found between SQL schema and reporting metadata. Schema column: ' + ISNULL(@SchemaColumn, 'NULL') + '. Metadata column: ' + ISNULL(@MetadataColumn, 'NULL')  
      GOTO LblError  
    END  
   END  
   ELSE  
   BEGIN  
    SELECT @TableName = EntityTimephasedTableName  
    FROM MSP_EpmMetadataEntities  
    WHERE MSP_EpmMetadataEntities.EntityTypeUID = @EntityTypeUID  
    SET @UserViewName = @TableName + '_UserView'  
    SET @OlapViewName = @TableName + '_OlapView_00000000-0000-0000-0000-000000000000'  
    SELECT TOP 1  
      @SchemaColumn = SchemaInfo.ColumnName,  
      @MetadataColumn = MetadataAttribute.ColumnName  
    FROM  
    (  
      SELECT ColumnName = syscolumns.name  
      FROM dbo.syscolumns  
      INNER JOIN dbo.sysobjects ON  
       syscolumns.id = sysobjects.id  
      WHERE sysobjects.name = @UserViewName  
    ) AS SchemaInfo  
    FULL OUTER JOIN  
    (  
      SELECT ColumnName = MSP_EpmMetadataAttribute.AttributeColumnName  
      FROM MSP_EpmMetadataAttribute  
      WHERE  
       MSP_EpmMetadataAttribute.EntityTypeUID = @EntityTypeUID  
       AND MSP_EpmMetadataAttribute.AttributeIsTimephased = 1  
       AND dbo.MFN_Epm_ExtendedAttributeIsExposedInView(MSP_EpmMetadataAttribute.AttributeTypeUID, 1) = 1  
    ) AS MetadataAttribute ON  
      SchemaInfo.ColumnName = MetadataAttribute.ColumnName  
    WHERE  
      SchemaInfo.ColumnName IS NULL  
      OR MetadataAttribute.ColumnName IS NULL  
    IF (@SchemaColumn IS NOT NULL) OR (@MetadataColumn IS NOT NULL)  
    BEGIN  
      SET @ErrorMessage = 'At least one mismatch found between SQL schema for view ' + @UserViewName + ' and reporting metadata. Schema column: ' + ISNULL(@SchemaColumn, 'NULL') + '. Metadata column: ' + ISNULL(@MetadataColumn, 'NULL')  
      GOTO LblError  
    END  
    SELECT TOP 1  
      @SchemaColumn = SchemaInfo.ColumnName,  
      @MetadataColumn = MetadataAttribute.ColumnName  
    FROM  
    (  
      SELECT ColumnName = syscolumns.name  
      FROM dbo.syscolumns  
      INNER JOIN dbo.sysobjects ON  
       syscolumns.id = sysobjects.id  
      WHERE sysobjects.name = @OlapViewName  
    ) AS SchemaInfo  
    FULL OUTER JOIN  
    (  
      SELECT ColumnName = MSP_EpmMetadataAttribute.AttributeColumnName  
      FROM MSP_EpmMetadataAttribute  
      WHERE  
       MSP_EpmMetadataAttribute.EntityTypeUID = @EntityTypeUID  
       AND MSP_EpmMetadataAttribute.AttributeIsTimephased = 1  
       AND dbo.MFN_Epm_ExtendedAttributeIsExposedInView(MSP_EpmMetadataAttribute.AttributeTypeUID, 0) = 1  
    ) AS MetadataAttribute ON  
      SchemaInfo.ColumnName = MetadataAttribute.ColumnName  
    WHERE  
      SchemaInfo.ColumnName IS NULL  
      OR MetadataAttribute.ColumnName IS NULL  
    IF (@SchemaColumn IS NOT NULL) OR (@MetadataColumn IS NOT NULL)  
    BEGIN  
      SET @ErrorMessage = 'At least one mismatch found between SQL schema for view ' + QUOTENAME(@OlapViewName) + ' and reporting metadata. Schema column: ' + ISNULL(@SchemaColumn, 'NULL') + '. Metadata column: ' + ISNULL(@MetadataColumn, 'NULL')  
      GOTO LblError  
    END  
    SELECT TOP 1  
      @SchemaColumn = SchemaInfo.ColumnName,  
      @MetadataColumn = MetadataAttribute.ColumnName  
    FROM  
    (  
      SELECT ColumnName = syscolumns.name  
      FROM dbo.syscolumns  
      INNER JOIN dbo.sysobjects ON  
       syscolumns.id = sysobjects.id  
      WHERE sysobjects.name = @TableName  
    ) AS SchemaInfo  
    FULL OUTER JOIN  
    (  
      SELECT ColumnName = MSP_EpmMetadataAttribute.AttributeColumnName  
      FROM MSP_EpmMetadataAttribute  
      WHERE  
       MSP_EpmMetadataAttribute.EntityTypeUID = @EntityTypeUID  
       AND MSP_EpmMetadataAttribute.AttributeIsTimephased = 1  
       AND MSP_EpmMetadataAttribute.PresentInTable = 1  
    ) AS MetadataAttribute ON  
      SchemaInfo.ColumnName = MetadataAttribute.ColumnName  
    WHERE  
      SchemaInfo.ColumnName IS NULL  
      OR MetadataAttribute.ColumnName IS NULL  
    IF (@SchemaColumn IS NOT NULL) OR (@MetadataColumn IS NOT NULL)  
    BEGIN  
      SET @ErrorMessage = 'At least one mismatch found between SQL schema and reporting metadata. Schema column: ' + ISNULL(@SchemaColumn, 'NULL') + '. Metadata column: ' + ISNULL(@MetadataColumn, 'NULL')  
      GOTO LblError  
    END  
   END  
   RETURN 0  
 LblError:  
   --PRINT @ErrorMessage  
   RETURN 0  
 END  

This stored procedure exists both in the 2010 reporting database and in the ProjectWebApp database. I modified it in both databases, but I guess it is the one in ProjectWebApp that is coursing problems.

tirsdag den 28. april 2015

MS Project Apps cannot load

I recently developed our first MS Project app and expirenced a problem where the app could not load.


APP ERROR
This app could not be started. Close this dialog to ignore the problem or click "Restart" to try again.

Solution

The solution is to enable Protective Mode in you version of Internet Explorer.
After this, the app should load fine.


According to Microsoft it is a requirement that Protective Mode is enabled in Internet Explorer for Office Apps to work.

The app shown is a MS Project App and is named Project Blog News. Download it here: https://store.office.com/.../project-blog

fredag den 3. april 2015

MS SQL Server Query Performance

Our company have a rather complex add-in to Project Server. For some time we have been struggling with performance issues and no matter how much we tuned the SQL procedures, after some time they would always become slow in a production environment. 

Today I came across a tool in SQL Server Management Studio which very easily can pinpoint which queries are running slow. In our case we discovered that one query was very slow and slowed all other queries.
This tool is called Activity Monitor and is build into most versions of Management Studio.
Note: Activity Monitor requires SysAdmin permissions to be used.


The tool is very simple to use. Simply open SQL Server Management Studio and connect to your database.

  Click on the Activity Monitor icon.

Here you will see a number of sections showing different information about the server.  Overview shows IO, wait time, etc. Processes shows information about which processes/connections is using the server. Resources Waits can tell you where a potential bottleneck is. Data File I/O is shows which databases is using a lot of IO.

However, the one I find really interesting is the "Recent Expensive Queries". This tells you which queries are running slowly. The database, average process time, etc.
In a production environment it was very easy to pinpoint where our problem was.
Only regret is, we did not know about this tool earlier.