Метод Project.CreateProjectFromTemplate
Создает проект на основе указанного шаблона. Новый проект имеет имя указанного проекта.
Пространство имен: WebSvcProject
Сборка: ProjectServerServices (в ProjectServerServices.dll)
Синтаксис
'Декларация
<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
'Применение
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
)
Параметры
templateUid
Тип: System.GuidИдентификатор GUID шаблона проекта.
projectName
Тип: System.StringИмя нового проекта.
Возвращаемое значение
Тип: System.Guid
Идентификатор GUID, созданный проект.
Замечания
CreateProjectFromTemplate создает новый проект в таблиц данных черновиков. Текущий пользователь должен иметь оба разрешения, указанные в таблице разрешений.
Метод CreateProjectFromTemplate сохраняются все сведения о форматировании в шаблон проекта, например формата шкала времени или шрифта. Можно задать форматирование данные проекта с помощью Project Professional; форматирование недоступен в открытые методы PSI или наборов данных. CreateProjectFromTemplate возвращает ProjectDataSet из шаблона проекта в базе данных черновиков, создает новый ProjectDataSetи изменяет имя суммарной задачи проекта на запрошенный проекта. Он добавляет все строки DataTable новой ProjectDataSet, за исключением даты назначения и затем создает новый проект с другой код GUID.
Если шаблон содержит задачи, которые заметки, заметок задачи не показывать при создании нового проекта с помощью CreateProjectFromTemplate и затем откройте проект в Microsoft Office Project Professional. Можно использовать Project Professional для создания шаблона, который содержит заметок задачи и опубликовать шаблон проекта. В таблице MSP_TASKS в опубликованной базы данных включает в себя столбец TASK_RTF_NOTES , который содержит данные для шаблона. После создания программным путем и сохраните новый проект на основе этого шаблона, столбец TASK_RTF_NOTES содержит данные текст для заметок задачи, не данные в формате RTF (формат RTF).
Проблема в том, что TASK_RTF_NOTES имеет тип данных image для данные в формате RTF. Веб-службы PSI в приложении-службе Project Server не может обработать данные в формате RTF. Добавление заметки к задачам в проектах, созданных программными средствами на сервере Project Server на основе шаблона, необходимо прямого доступа к таблице MSP_TASKS для выполнения следующих:
Добавьте данные в формате RTF в столбце TASK_RTF_NOTES для определенной задачи.
Значение в столбце TASKS_HAS_NOTES1 (true).
Примечание
В настоящее время отсутствует метод доступен для программного добавления заметок задачи в шаблоне в проект, созданный на основе этого шаблона.
Интерфейс Project Server (PSI) нельзя использовать для создания локальных настраиваемых полей в проектах. Тем не менее PSI поддерживает редактирование значения локальных настраиваемых полей для задач, ресурсов и назначений.
Параметры представления, такие как добавленных полей, не копируются в новый проект на основе шаблона.
Разрешения Project Server
Разрешение |
Описание |
---|---|
Позволяет пользователям для создания нового проекта. Глобальное разрешение. |
|
Позволяет пользователю открывать шаблоны проектов. Глобальное разрешение. |
Примеры
Следующий пример создает шаблон, поиск по имени шаблона и проверяет имя проекта для знаков, которые являются недопустимыми. В примере создается проект на основе этого шаблона и затем публикует проект. Это необходимо для создания шаблона, так как Project Server не имеет любое шаблонов по умолчанию, в которых может быть на месте.
Как правило будет представлен список шаблонов и их уникальные идентификаторы и использовать ее для выберите нужный шаблон. В некоторых случаях может потребоваться найти шаблон проекта или по имени. Показано ниже. Необходимо иметь точное имя проекта, чтобы его найти.
Важные сведения о запуске в этом примере кода Необходимые условия для примеров кода на основе WCF в 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;
}
}
}
При выполнении примера CreateProjectFromTemplate , в окне консоли отображает следующие выходные данные:
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...
Чтобы увидеть действие обработчика FaultException , измените код, имена шаблонов и проверок для недопустимых символов. Следующий код представляет знак «+» в полях имя и комментарии в работе вызов метода 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();
//}