Compartir a través de


del método Project.CreateProjectFromTemplate

Crea un proyecto desde una plantilla especificada. El nuevo proyecto tiene el nombre de proyecto especificado.

Espacio de nombres:  WebSvcProject
Ensamblado:  ProjectServerServices (en ProjectServerServices.dll)

Sintaxis

'Declaración
<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
'Uso
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
)

Parámetros

  • templateUid
    Tipo: System.Guid

    El GUID de la plantilla de proyecto.

Valor devuelto

Tipo: System.Guid
El GUID del proyecto creado.

Comentarios

CreateProjectFromTemplate crea el nuevo proyecto en las tablas de datos de borrador. El usuario actual debe tener ambos de los permisos especificados en la tabla de permisos.

El método CreateProjectFromTemplate conserva información del formato en una plantilla de proyecto, como el formato de fuente o de escala de tiempo. Se puede establecer el formato de la información de un proyecto con Project Professional; formato no está disponible en los métodos públicos de PSI o conjuntos de datos. CreateProjectFromTemplate Obtiene una ProjectDataSet de la plantilla de proyecto en la base de datos de borrador, crea un nuevo ProjectDataSety cambia el nombre de tarea de resumen del proyecto para el nombre del proyecto solicitado. A continuación agrega todas las filas de DataTable a la nueva ProjectDataSet, excepto las fechas de asignación y, a continuación, se crea un nuevo proyecto con un GUID diferente.

Si la plantilla incluye las tareas que tienen notas, las notas de tarea no mostrar cuando se crea un nuevo proyecto mediante el uso de CreateProjectFromTemplate y, a continuación, abra el proyecto en Microsoft Office Project Professional. Puede utilizar Project Professional para crear una plantilla que contiene notas de tarea y publicar la plantilla de proyecto. La tabla MSP_TASKS en la base de datos publicados incluye la columna TASK_RTF_NOTES , que tiene datos para la plantilla. Después de crear y guardar un proyecto nuevo basado en la plantilla mediante programación, la columna TASK_RTF_NOTES contiene datos de texto de las notas de la tarea, no los datos RTF (formato de texto enriquecido).

El problema es que TASK_RTF_NOTES es del tipo image de datos para datos RTF. Los servicios web PSI en la aplicación de servicio de Project Server no pueden controlar datos RTF. Para agregar notas de tarea en los proyectos que se crean mediante programación en Project Server desde una plantilla, debe tener acceso directamente a la tabla MSP_TASKS para hacer lo siguiente:

  • Agregue los datos RTF a la columna TASK_RTF_NOTES para la tarea específica.

  • Establezca la columna TASKS_HAS_NOTES a 1 (true).

Nota

Actualmente no hay ningún método está disponible para agregar mediante programación las notas de tarea en una plantilla a un proyecto creado a partir de esa plantilla.

No puede usar Project Server Interface (PSI) para crear campos personalizados locales en proyectos. Sin embargo, la interfaz PSI admite la edición de los valores de campo personalizado local en tareas, recursos y asignaciones.

Configuración de la vista, como los campos agregados, no se copia en el nuevo proyecto de la plantilla.

Permisos de Project Server

Permiso

Descripción

NewProject

Permite que un usuario crear un nuevo proyecto. Permiso global.

OpenProjectTemplate

Permite que un usuario abrir plantillas de proyecto. Permiso global.

Ejemplos

En el siguiente ejemplo se crea una plantilla, busca esa plantilla por su nombre y comprueba el nombre del proyecto para caracteres que no son válidos. En el ejemplo se crea un proyecto basado en esa plantilla y, a continuación, publica el proyecto. Es necesario crear una plantilla, ya que Project Server no tiene ningún plantillas predeterminadas que se garantiza que en su lugar.

Normalmente, podría presentar una lista de plantillas y sus identificadores únicos y usarla para elegir la plantilla que desee. En algunos casos, es posible que desee buscar un proyecto o una plantilla por nombre. Que se muestra a continuación. Debe tener el nombre exacto del proyecto para encontrarlo.

Para obtener información crítica acerca de cómo ejecutar este ejemplo de código, vea 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;
        }
    }
}

Al ejecutar el ejemplo CreateProjectFromTemplate , la ventana de la consola muestra el siguiente resultado:

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...

Para ver la acción del controlador de FaultException , cambie el código que da nombre a la plantilla y comprobaciones de caracteres no válidos. El código siguiente presenta el carácter "+" en el nombre y comentarios de la llamada al método 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();
                //}

Vea también

Referencia

clase Project

Miembros Project

Espacio de nombres WebSvcProject