Project.CreateProjectFromTemplate method
Cria um projeto a partir de um modelo especificado. O novo projeto tem o nome do projeto especificado.
Namespace: WebSvcProject
Assembly: ProjectServerServices (in ProjectServerServices.dll)
Syntax
'Declaração
<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
Type: System.GuidO GUID do modelo de projeto.
projectName
Type: System.StringO nome do novo projeto.
Valor retornado
Type: System.Guid
O GUID do projeto criado.
Comentários
CreateProjectFromTemplate cria o novo projeto em tabelas de dados de rascunho. O usuário atual deve ter ambas as permissões especificadas na tabela de permissões.
O método CreateProjectFromTemplate persiste qualquer informação de formatação em um modelo de projeto, como o formato da fonte ou de escala de tempo. Você pode definir informações de formatação para um projeto com o Project Professional; formatação não está disponível no métodos da PSI públicos ou conjuntos de dados. CreateProjectFromTemplate obtém um ProjectDataSet do modelo de projeto no banco de dados de rascunho, cria um novo ProjectDataSete altera o nome de tarefa de resumo do projeto para o nome do projeto solicitada. Ele adiciona todas as linhas de DataTable para o novo ProjectDataSet, exceto as datas de atribuição e, em seguida, cria um novo projeto com um GUID diferente.
Se o modelo inclui as tarefas que têm anotações, as anotações das tarefas não mostrar quando você cria um novo projeto usando CreateProjectFromTemplate e, em seguida, abra o projeto no Microsoft Office Project Professional. Você pode usar o Project Professional para criar um modelo que contém as anotações da tarefa e publique o modelo de projeto. A tabela MSP_TASKS no banco de dados publicado inclui a coluna de TASK_RTF_NOTES , que tem o modelo de dados. Depois de criar programaticamente e salvar um novo projeto baseado nesse modelo, a coluna TASK_RTF_NOTES contém dados de texto para as notas de tarefa, e não os dados RTF (Rich Text Format).
O problema é que TASK_RTF_NOTES é do tipo de dados image para dados RTF. Os serviços da web PSI no aplicativo de serviço do Project Server não podem manipular dados RTF. Para adicionar anotações das tarefas em projetos programaticamente criados no Project Server a partir de um modelo, você deve acessar diretamente a tabela de MSP_TASKS para fazer o seguinte:
Adicione os dados RTF à coluna TASK_RTF_NOTES para a tarefa específica.
Defina a coluna TASKS_HAS_NOTES como 1 (true).
Observação
No momento a nenhum método está disponível para adicionar as anotações das tarefas de maneira programática em um modelo a um projeto criado a partir desse modelo.
Você não pode usar o Project Server Interface (PSI) para criar campos personalizados locais em projetos. No entanto, a PSI oferece suporte a valores de campo personalizado local em recursos, tarefas e atribuições de edição.
Configurações de exibição, como campos adicionados, não são copiadas no novo projeto do modelo.
Permissões do Project Server
Permissão |
Descrição |
---|---|
Permite que um usuário crie um novo projeto. Permissão global. |
|
Permite que um usuário abrir os modelos de projeto. Permissão global. |
Examples
O exemplo a seguir cria um modelo, localiza esse modelo pelo nome e verifica se o nome do projeto para caracteres que não são válidos. O exemplo cria um projeto com base nesse modelo e, em seguida, publica o projeto. É necessário criar um modelo, pois o Project Server não tem quaisquer modelos padrão que são garantidos estar em vigor.
Normalmente, você faria apresentar uma lista de modelos e suas identificações exclusivas e usá-la para escolher o modelo desejado. Em alguns casos, você talvez queira localizar um projeto ou o modelo por nome. Que é demonstrado aqui. Você deve ter o nome exato do projeto para localizá-lo.
For critical information about running this code sample, see 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;
}
}
}
Quando você executa o exemplo CreateProjectFromTemplate , a janela do console mostra a seguinte saída:
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 a ação do manipulador FaultException , altere o código que nomeia o modelo e verificações para caracteres inválidos. O código a seguir apresenta o caractere '+' no nome e comentários a chamada para o 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();
//}