Project.CreateProjectFromTemplate - Méthode

Crée un projet à partir d'un modèle spécifié. Le nouveau projet porte le nom de projet spécifié.

Espace de noms :  WebSvcProject
Assembly :  ProjectServerServices (dans ProjectServerServices.dll)

Syntaxe

'Déclaration
<SoapDocumentMethodAttribute("https://schemas.microsoft.com/office/project/server/webservices/Project/CreateProjectFromTemplate", RequestNamespace := "https://schemas.microsoft.com/office/project/server/webservices/Project/",  _
    ResponseNamespace := "https://schemas.microsoft.com/office/project/server/webservices/Project/",  _
    Use := SoapBindingUse.Literal, ParameterStyle := SoapParameterStyle.Wrapped)> _
Public Function CreateProjectFromTemplate ( _
    templateUid As Guid, _
    projectName As String _
) As Guid
'Utilisation
Dim instance As Project
Dim templateUid As Guid
Dim projectName As String
Dim returnValue As Guid

returnValue = instance.CreateProjectFromTemplate(templateUid, _
    projectName)
[SoapDocumentMethodAttribute("https://schemas.microsoft.com/office/project/server/webservices/Project/CreateProjectFromTemplate", RequestNamespace = "https://schemas.microsoft.com/office/project/server/webservices/Project/", 
    ResponseNamespace = "https://schemas.microsoft.com/office/project/server/webservices/Project/", 
    Use = SoapBindingUse.Literal, ParameterStyle = SoapParameterStyle.Wrapped)]
public Guid CreateProjectFromTemplate(
    Guid templateUid,
    string projectName
)

Paramètres

  • templateUid
    Type : System.Guid

    Le GUID du modèle de projet.

Valeur renvoyée

Type : System.Guid
Le GUID du projet créé.

Remarques

CreateProjectFromTemplate crée un nouveau projet dans les tables de données brouillon. L'utilisateur actuel doit avoir des autorisations spécifiées dans le tableau des autorisations.

La méthode CreateProjectFromTemplate conserve les informations mise en forme dans un modèle de projet, tel que le format de police ou de l'échelle de temps. Vous pouvez définir la mise en forme des informations pour un projet avec Project Professional ; la mise en forme n'est pas disponible dans les méthodes PSI publiques ou les jeux de données. CreateProjectFromTemplate Obtient un ProjectDataSet à partir du modèle de projet dans la base de données provisoire, crée un nouveau ProjectDataSetet modifie le nom de la tâche récapitulative du projet au nom du projet demandé. Il ajoute ensuite de toutes les lignes de DataTable vers la nouvelle ProjectDataSet, à l'exception des dates d'affectation et puis crée un nouveau projet avec un GUID différent.

Si le modèle comprend les tâches qui ont des notes, les notes de tâche ne pas afficher lorsque vous créez un nouveau projet à l'aide de CreateProjectFromTemplate et puis ouvrez le projet dans Microsoft Office Project Professional. Vous pouvez utiliser Project Professional pour créer un modèle qui contient des remarques sur les tâches et publier le modèle de projet. La table MSP_TASKS dans la base de données publiée inclut la colonne TASK_RTF_NOTES , qui comporte des données pour le modèle. Une fois par programme, vous créez et enregistrez un nouveau projet basé sur ce modèle, la colonne TASK_RTF_NOTES contient des données de texte pour les notes de tâche, pas les données au format RTF (Rich Text Format).

Le problème est que TASK_RTF_NOTES est de type de données image de données au format RTF. Services web PSI dans l'application de service Project Server ne peut pas gérer les données au format RTF. Pour ajouter des remarques sur les tâches dans les projets qui sont créés par programmation dans Project Server à partir d'un modèle, vous devez accéder directement à la table MSP_TASKS pour effectuer les opérations suivantes :

  • Ajouter les données au format RTF à la colonne TASK_RTF_NOTES pour la tâche correspondante.

  • Définir la colonne TASKS_HAS_NOTES à 1 (true).

Notes

Aucune méthode n'est actuellement disponible pour ajouter par programme des notes de tâche dans un modèle à un projet créé à partir de ce modèle.

Vous ne pouvez pas utiliser l'Interface PSI (Project Server) pour créer des champs personnalisés locaux dans les projets. Toutefois, la PSI prend en charge la modification des valeurs de champ personnalisé local sur tâches, ressources et affectations.

Paramètres d'affichage, tels que les champs ajoutés, ne sont pas copiés dans le nouveau projet à partir du modèle.

Autorisations Project Server

Autorisation

Description

NewProject

Permet à un utilisateur de créer un nouveau projet. Autorisation globale.

OpenProjectTemplate

Permet à un utilisateur d'ouvrir des modèles de projet. Autorisation globale.

Exemples

L'exemple suivant crée un modèle de recherche ce modèle par nom et vérifie le nom du projet pour les caractères qui ne sont pas valides. L'exemple crée un projet basé sur ce modèle et publie le projet. Il est nécessaire créer un modèle, car Project Server n'a pas les modèles par défaut qui sont garanties pour mettre en place.

En règle générale, vous souhaite présenter une liste de modèles et leur ID unique, qui permet de choisir le modèle de votre choix. Dans certains cas, vous souhaiterez trouver un projet ou un modèle par son nom. Qui est présenté ici. Vous devez disposer le nom exact du projet pour le trouver.

Pour plus d'informations sur l'exécution de cet exemple de code critiques, voir Prerequisites for WCF-based code samples in Project 2013.

using System;
using System.Text;
using System.Xml;
using System.ServiceModel;
using PSLibrary = Microsoft.Office.Project.Server.Library;

namespace CreateProjectFromTemplate
{
    class Program
    {
        private const string ENDPOINT_PROJECT = "basicHttp_Project";
        private const string ENDPOINT_QUEUESYSTEM = "basicHttp_QueueSystem";
        private static SvcProject.ProjectClient projectClient;
        private static SvcQueueSystem.QueueSystemClient queueSystemClient;

        static void Main(string[] args)
        {
            try
            {
                ConfigClientEndpoints(ENDPOINT_PROJECT);
                ConfigClientEndpoints(ENDPOINT_QUEUESYSTEM);

                // Create a template to use. Normally, you would already have a template 
                // stored in PWA that you would use, but this example creates a template.

                Console.WriteLine("Creating template");
                SvcProject.ProjectDataSet templateDs = new SvcProject.ProjectDataSet();
                SvcProject.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;

                if (IsNameValid(templateRow.PROJ_NAME))
                {
                    templateDs.Project.AddProjectRow(templateRow);
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("\nThe project name contains characters that are not valid:" 
                                      + "\n\t{0}", templateRow.PROJ_NAME);
                    QuitTheApp();
                }

                // Add two tasks to the template.
                int numTasks = 2;
                SvcProject.ProjectDataSet.TaskRow task = null;

                for (int i = 0; i < numTasks; i++)
                {
                    task = templateDs.Task.NewTaskRow();
                    task.PROJ_UID = templateRow.PROJ_UID;
                    task.TASK_UID = Guid.NewGuid();
                    task.TASK_DUR_FMT = (int)PSLibrary.Task.DurationFormat.Day;
                    task.TASK_DUR = 4800; // The task duration is 8 hours.
                    task.TASK_NAME = "T" + (i + 1).ToString() + " in template";
                    task.TASK_START_DATE = System.DateTime.Now.AddDays(i + 1);
                    templateDs.Task.AddTaskRow(task);
                }

                // Write the new template information to the database.
                Console.WriteLine("\n\nSaving template to database");
                Guid jobId = Guid.NewGuid();
                DateTime startTime = DateTime.Now;

                projectClient.QueueCreateProject(jobId, templateDs, false);

                // Wait for the Project Server Queuing System to create the project.
                if (Helpers.WaitForQueue(SvcQueueSystem.QueueMsgType.ProjectCreate,
                    queueSystemClient, startTime))
                {
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine("\nTemplate created:\n\t{0}", templateRow.PROJ_NAME);
                    Console.ResetColor();
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("\nThe template was not created:\n\t{0}.\nThe queue wait time exceeded 30 seconds",
                        templateRow.PROJ_NAME);
                    Console.ResetColor();
                    QuitTheApp();
                }

                // Find the template by name.
                //    You could just use the GUID to create the project from a template, 
                //    but this example shows how to get the GUID from the template name.
                // Note: If you have a template on the enterprise server already, you can use
                // the ReadProjectStatus method to get a list of published templates.
                //    projectSvc.ReadProjectStatus(Guid.Empty, SvcProject.DataStoreEnum.PublishedStore, 
                //                                 String.Empty, (int) PSLibrary.Project.ProjectType.Template);
                Console.WriteLine("Finding the template by name");
                SvcProject.ProjectDataSet readTemplateDs = projectClient.ReadProjectStatus(Guid.Empty,
                    SvcProject.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 newProjectUid = projectClient.CreateProjectFromTemplate(readTemplateDs.Project[0].PROJ_UID,
                                                                             projectName);
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("Project created:\n\t{0}\n\t{1}", newProjectUid.ToString(), projectName);
                Console.ResetColor();

                // Publish the project, to make it visible in PWA.
                jobId = Guid.NewGuid();
                projectClient.QueuePublish(jobId, newProjectUid, true, string.Empty);
                startTime = DateTime.Now;

                if (Helpers.WaitForQueue(SvcQueueSystem.QueueMsgType.ProjectPublish,
                                         queueSystemClient, startTime))
                {
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine("Project published");
                    Console.ResetColor();
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("\nThe project was not published.\nThe queue wait time exceeded 30 seconds");
                    Console.ResetColor();
                }

            }
            catch (FaultException fault)
            {
                // Use the WCF FaultException, because the ASMX SoapException does not 
                // exist in a WCF-based application.
                WriteFaultOutput(fault);
            }
            finally
            {
                QuitTheApp();
            }
        }

        // Check the project name for invalid characters.
        private static bool IsNameValid(string projName)
        {
            bool result = true;
            char[] badChars = PSLibrary.Project.InvalidCharacters();

            Console.WriteLine("Check project name for Project.InvalidCharacters:");
            Console.ForegroundColor = ConsoleColor.Yellow;
            foreach (char c in badChars)
            {
                Console.Write(c);
                Console.Write(" ");
            }
            Console.ResetColor();

            // The name is not valid if it is empty or contains leading or trailing white space.
            if (String.IsNullOrEmpty(projName) || String.Compare(projName, projName.Trim(), StringComparison.Ordinal) != 0)
            {
                return false;
            }

            // The name is also not valid if it contains one of the invalid characters.
            if (badChars != null)
            {
                if (projName.IndexOfAny(badChars) != -1)
                {
                    return false;
                }
            }
            return result;
        }

        // Extract a PSClientError object from the WCF FaultException object, and
        // then display the exception details and each error in the PSClientError stack.
        private static void WriteFaultOutput(FaultException fault)
        {
            string errAttributeName;
            string errAttribute;
            string errOut;
            string errMess = "".PadRight(30, '=') + "\r\n"
                + "Error details: " + "\r\n";

            PSLibrary.PSClientError error = Helpers.GetPSClientError(fault, out errOut);
            errMess += errOut;

            PSLibrary.PSErrorInfo[] errors = error.GetAllErrors();
            PSLibrary.PSErrorInfo thisError;

            for (int i = 0; i < errors.Length; i++)
            {
                thisError = errors[i];
                errMess += "\r\n".PadRight(30, '=') + "\r\nPSClientError output:\r\n";
                errMess += thisError.ErrId.ToString() + "\n";

                for (int j = 0; j < thisError.ErrorAttributes.Length; j++)
                {
                    errAttributeName = thisError.ErrorAttributeNames()[j];
                    errAttribute = thisError.ErrorAttributes[j];
                    errMess += "\r\n\t" + errAttributeName
                        + ": " + errAttribute;
                }
            }
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(errMess);
            Console.ResetColor();
        }


        // Use the endpoints defined in app.config to configure the client.
        private static void ConfigClientEndpoints(string endpt)
        {
            if (endpt == ENDPOINT_PROJECT)
                projectClient = new SvcProject.ProjectClient(endpt);
            else if (endpt == ENDPOINT_QUEUESYSTEM)
                queueSystemClient = new SvcQueueSystem.QueueSystemClient(endpt);
        }

        // Quit the application.
        private static void QuitTheApp()
        {
            Console.ResetColor();
            Console.WriteLine("\nPress any key to exit...");
            Console.ReadKey(true);
            Environment.Exit(1);
        }
    }

    // Helper methods: WaitForQueue and GetPSClientError.
    class Helpers
    {
        // Wait for the queue jobs to complete.
        public static bool WaitForQueue(SvcQueueSystem.QueueMsgType jobType,
            SvcQueueSystem.QueueSystemClient queueSystemClient,
            DateTime startTime)
        {
            const int MAX_WAIT = 30;    // Maximum wait time, in seconds.
            int numJobs = 1;            // Number of jobs in the queue.
            bool completed = false;     // Queue job completed.
            SvcQueueSystem.QueueStatusDataSet queueStatusDs =
                new SvcQueueSystem.QueueStatusDataSet();

            int timeout = 0;            // Number of seconds waited.
            Console.Write("Waiting for job: {0} ", jobType.ToString());

            SvcQueueSystem.QueueMsgType[] messageTypes = { jobType };
            SvcQueueSystem.JobState[] jobStates = { SvcQueueSystem.JobState.Success };

            while (timeout < MAX_WAIT)
            {
                System.Threading.Thread.Sleep(1000);    // Sleep one second.

                queueStatusDs = queueSystemClient.ReadMyJobStatus(
                    messageTypes,
                    jobStates,
                    startTime,
                    DateTime.Now,
                    numJobs,
                    true,
                    SvcQueueSystem.SortColumn.QueuePosition,
                    SvcQueueSystem.SortOrder.LastOrder);

                timeout++;
                Console.Write(".");
            }
            Console.WriteLine();

            if (queueStatusDs.Status.Count == numJobs)
                completed = true;
            return completed;
        }

        /// <summary>
        /// Extract a PSClientError object from the ServiceModel.FaultException,
        /// for use in output of the GetPSClientError stack of errors.
        /// </summary>
        /// <param name="e"></param>
        /// <param name="errOut">Shows that FaultException has more information 
        /// about the errors than PSClientError has. FaultException can also contain 
        /// other types of errors, such as failure to connect to the server.</param>
        /// <returns>PSClientError object, for enumerating errors.</returns>
        public static PSLibrary.PSClientError GetPSClientError(FaultException e,
                                                               out string errOut)
        {
            const string PREFIX = "GetPSClientError() returns null: ";
            errOut = string.Empty;
            PSLibrary.PSClientError psClientError = null;

            if (e == null)
            {
                errOut = PREFIX + "Null parameter (FaultException e) passed in.";
                psClientError = null;
            }
            else
            {
                // Get a ServiceModel.MessageFault object.
                var messageFault = e.CreateMessageFault();

                if (messageFault.HasDetail)
                {
                    using (var xmlReader = messageFault.GetReaderAtDetailContents())
                    {
                        var xml = new XmlDocument();
                        xml.Load(xmlReader);

                        var serverExecutionFault = xml["ServerExecutionFault"];
                        if (serverExecutionFault != null)
                        {
                            var exceptionDetails = serverExecutionFault["ExceptionDetails"];
                            if (exceptionDetails != null)
                            {
                                try
                                {
                                    errOut = exceptionDetails.InnerXml + "\r\n";
                                    psClientError =
                                        new PSLibrary.PSClientError(exceptionDetails.InnerXml);
                                }
                                catch (InvalidOperationException ex)
                                {
                                    errOut = PREFIX + "Unable to convert fault exception info ";
                                    errOut += "a valid Project Server error message. Message: \n\t";
                                    errOut += ex.Message;
                                    psClientError = null;
                                }
                            }
                            else
                            {
                                errOut = PREFIX + "The FaultException e is a ServerExecutionFault, "
                                    + "but does not have ExceptionDetails.";
                            }
                        }
                        else
                        {
                            errOut = PREFIX + "The FaultException e is not a ServerExecutionFault.";
                        }
                    }
                }
                else // No detail in the MessageFault.
                {
                    errOut = PREFIX + "The FaultException e does not have any detail.";
                }
            }
            errOut += "\r\n" + e.ToString() + "\r\n";
            return psClientError;
        }
    }
}

Lorsque vous exécutez l'exemple CreateProjectFromTemplate , la fenêtre de la console affiche la sortie suivante :

Creating template
Check project name for Project.InvalidCharacters:
' # : ; < > / | ? \ . * " ~ % & { } +

Saving template to database
Waiting for job: ProjectCreate ..............................

Template created:
        Its a wonderful template! 3-50 PM
Finding the template by name
Create the new project from the template
Project created:
        b9d0272e-62db-e111-b1ce-00155d146f2c
        Created from Its a wonderful template! 3-50 PM at 3-50 PM
Waiting for job: ProjectPublish ..............................
Project published

Press any key to exit...

Pour voir l'action du gestionnaire FaultException , modifiez le code qui appelle le modèle et les vérifications pour les caractères non valides. Le code suivant présente le caractère « + » dans le nom et les commentaires de l'appel à la méthode IsNameValid :

                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;

                templateDs.Project.AddProjectRow(templateRow);
                //if (IsNameValid(templateRow.PROJ_NAME))
                //{
                //    templateDs.Project.AddProjectRow(templateRow);
                //}
                //else
                //{
                //    Console.ForegroundColor = ConsoleColor.Red;
                //    Console.WriteLine("\nThe project name contains characters that are not valid:" 
                //                      + "\n\t{0}", templateRow.PROJ_NAME);
                //    QuitTheApp();
                //}

Voir aussi

Référence

Project classe

Project - Membres

WebSvcProject - Espace de noms