Important This document may not represent best practices for current development, links to downloads and other resources may no longer be valid. Current recommended version can be found here. ArchiveDisclaimer

Project.CreateProjectFromTemplate Method

Creates a project from a specified template. The new project has the specified project name.

Namespace:  [Project Web service]
Service reference: http://ServerName:32843/[Project Service Application GUID]/PSI/Project.svc
Web service reference: http://ServerName/ProjectServerName/_vti_bin/PSI/Project.asmx?wsdl

[SoapDocumentMethodAttribute("", RequestNamespace = "", 
	ResponseNamespace = "", 
	Use = SoapBindingUse.Literal, ParameterStyle = SoapParameterStyle.Wrapped)]
public Guid CreateProjectFromTemplate(
	Guid templateUid,
	string projectName


Type: System.Guid
The GUID of the project template.
Type: System.String
The name of the new project.

Return Value

Type: System.Guid
The GUID of the created project.

CreateProjectFromTemplate creates the new project in the Draft database. The current user must have both of the permissions specified in the Permissions table.

The CreateProjectFromTemplate method does persist any formatting information in a project template, such as timescale or font format. You can set formatting information for a project with Project Professional; formatting is not available in the public PSI methods or datasets. CreateProjectFromTemplate gets a ProjectDataSet from the project template in the Draft database, creates a new ProjectDataSet, and changes the project summary task name to the requested project name. It then adds all of the DataTable rows to the new ProjectDataSet, except assignment dates, and then creates a new project with a different GUID.

If the template includes tasks that have notes, the task notes do not show when you create a new project by using CreateProjectFromTemplate and then open the project in Microsoft Office Project Professional. You can use Project Professional to create a template that contains task notes, and publish the project template. The MSP_TASKS table in the Published database includes the TASK_RTF_NOTES column, which has data for the template. After you programmatically create and save a new project based on that template, the TASK_RTF_NOTES column contains text data for the task notes, not RTF (Rich Text Format) data.

The problem is that TASK_RTF_NOTES is of data type image for RTF data. The PSI web services in the Project Server service application cannot handle RTF data. To add task notes in projects that are programmatically created on Project Server from a template, you must directly access the MSP_TASKS table to do the following:

  • Add the RTF data to the TASK_RTF_NOTES column for the specific task.

  • Set the TASKS_HAS_NOTES column to 1 (true).


Currently no method is available to programmatically add the task notes in a template to a project created from that template.

You cannot use the Project Server Interface (PSI) to create local custom fields in projects. However, the PSI does support editing local custom field values on tasks, resources, and assignments.

View settings, such as added fields, are not copied into the new project from the template.

Project Server Permissions




Allows a user to create a new project. Global permission.


Allows a user to open project templates. Global permission.

The following example creates a template, finds that template by name, and then creates a new project based on that template. It is necessary to create a template because Project Server does not have any default templates that are guaranteed to be in place.

Typically, you would present a list of templates and their unique IDs, and use that to choose the desired template. In some cases, you might want to find a project or template by name. That is demonstrated here. You must have the exact name of the project to find it.

For critical information about running this code sample, see Prerequisites for ASMX-Based Code Samples.

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Web.Services.Protocols;
using System.Threading;
using PSLibrary = Microsoft.Office.Project.Server.Library;

namespace Microsoft.SDK.Project.Samples.CreateProjectFromTemplate
   class Program
      static void Main(string[] args)
            const string PROJECT_SERVER_URI = "http://ServerName/ProjectServerName/";
            const string PROJECT_SERVICE_PATH = "_vti_bin/psi/project.asmx";
            const string QUEUESYSTEM_SERVICE_PATH = "_vti_bin/psi/queuesystem.asmx";

            Guid jobId;

            // Set up the web service objects.
            ProjectWebSvc.Project projectSvc = new ProjectWebSvc.Project();

            ProjectWebSvc.ProjectDataSet projectDs = new ProjectWebSvc.ProjectDataSet();

            projectSvc.UseDefaultCredentials = true; 

            QueueSystemWebSvc.QueueSystem q = new QueueSystemWebSvc.QueueSystem();
            q.UseDefaultCredentials = true;

            // Create a template to find.
            //  Normally, you would have a template already stored on the
            //    server that you would use, but we create one to 
            //    use in our example.
            Console.WriteLine("Creating template");
            ProjectWebSvc.ProjectDataSet templateDs = new ProjectWebSvc.ProjectDataSet();
            ProjectWebSvc.ProjectDataSet.ProjectRow templateRow = templateDs.Project.NewProjectRow();
            templateRow.PROJ_UID = Guid.NewGuid();
            templateRow.PROJ_NAME = "Its a wonderful template! " + DateTime.Now.ToShortTimeString().Replace(":", "+");
            templateRow.WPROJ_DESCRIPTION = "Temporary template for use in CreateProjectFromTemplate example.";
            templateRow.PROJ_TYPE = (int)PSLibrary.Project.ProjectType.Template;


            // Write the new template information to the database.
            Console.WriteLine("Saving template to database");
            jobId = Guid.NewGuid();
            projectSvc.QueueCreateProject(jobId, templateDs, false);
            WaitForQueue(q, jobId);

            // Find the template by name.
            //    We could just use the GUID to create the project from a template, 
            //    but we want to show how to obtain the GUID from the name.
            // Note: If you have a template on the enterprise server already, you can use
            //    projectSvc.ReadProjectStatus(Guid.Empty, ProjectWebSvc.DataStoreEnum.PublishedStore, String.Empty, (int) PSLibrary.Project.ProjectType.Template);
            //    to get a list of published templates.
            Console.WriteLine("Finding the template by name");
            ProjectWebSvc.ProjectDataSet readTemplateDs = projectSvc.ReadProjectStatus(Guid.Empty, ProjectWebSvc.DataStoreEnum.WorkingStore, templateRow.PROJ_NAME, (int)PSLibrary.Project.ProjectType.Template);

            // Name the project.
            string projectName = "Created from " + readTemplateDs.Project[0].PROJ_NAME + " at " + DateTime.Now.ToShortTimeString().Replace(":", "-");

            // Create the new project on the server and get its GUID.
            Console.WriteLine("Create the new project from the template");
            Guid newProjectGuid = projectSvc.CreateProjectFromTemplate(readTemplateDs.Project[0].PROJ_UID, projectName);
        catch (SoapException ex)
            PSLibrary.PSClientError error = new PSLibrary.PSClientError(ex);
            PSLibrary.PSErrorInfo[] errors = error.GetAllErrors();
            string errMess = "==============================\r\nError: \r\n";
            for (int i = 0; i < errors.Length; i++)
               errMess += "\n" + ex.Message.ToString() + "\r\n";
               errMess += "".PadRight(30, '=') + "\r\nPSCLientError Output:\r\n \r\n";
               errMess += errors[i].ErrId.ToString() + "\n";

               for (int j = 0; j < errors[i].ErrorAttributes.Length; j++)
                  errMess += "\r\n\t" + errors[i].ErrorAttributeNames()[j] + ": " + errors[i].ErrorAttributes[j];
               errMess += "\r\n".PadRight(30, '=');
            Console.ForegroundColor = ConsoleColor.Red;
         catch (WebException ex)
            string errMess = ex.Message.ToString() +
               "\n\nLog on, or check the Project Server Queuing Service";
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Error: " + errMess);
         catch (Exception ex)
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Error: " + ex.Message);
            Console.WriteLine("\r\n\r\nPress any key...");
      static private void WaitForQueue(QueueSystemWebSvc.QueueSystem q, Guid jobId)
         QueueSystemWebSvc.JobState jobState;
         const int QUEUE_WAIT_TIME = 2; // two seconds
         bool jobDone = false;
         string xmlError = string.Empty;
         int wait = 0;

         // Wait for the project to get through the queue.
         // Get the estimated wait time in seconds.
         wait = q.GetJobWaitTime(jobId);

         // Wait for it.
         Thread.Sleep(wait * 1000);
         // Wait until it is finished.

            // Get the job state.
            jobState = q.GetJobCompletionState(jobId, out xmlError);

            if (jobState == QueueSystemWebSvc.JobState.Success)
               jobDone = true;
               if (jobState == QueueSystemWebSvc.JobState.Unknown
               || jobState == QueueSystemWebSvc.JobState.Failed
               || jobState == QueueSystemWebSvc.JobState.FailedNotBlocking
               || jobState == QueueSystemWebSvc.JobState.CorrelationBlocked
               || jobState == QueueSystemWebSvc.JobState.Canceled)
                  // If the job failed, error out.
                  throw (new ApplicationException("Queue request failed \"" + jobState + "\" Job ID: " + jobId + ".\r\n" + xmlError));
                  Console.WriteLine("Job State: " + jobState + " Job ID: " + jobId);
                  Thread.Sleep(QUEUE_WAIT_TIME * 1000);
         while (!jobDone);
© 2016 Microsoft