Statusing.ReadStatusForResource メソッド
指定した割り当てのまたは指定したリソースのすべての割り当ては、状態管理データを取得します。リソースの偽装は必要ありません。
名前空間: WebSvcStatusing
アセンブリ: ProjectServerServices (ProjectServerServices.dll 内)
構文
'宣言
<SoapDocumentMethodAttribute("https://schemas.microsoft.com/office/project/server/webservices/Statusing/ReadStatusForResource", RequestNamespace := "https://schemas.microsoft.com/office/project/server/webservices/Statusing/", _
ResponseNamespace := "https://schemas.microsoft.com/office/project/server/webservices/Statusing/", _
Use := SoapBindingUse.Literal, ParameterStyle := SoapParameterStyle.Wrapped)> _
Public Function ReadStatusForResource ( _
resid As Guid, _
assnid As Guid, _
mindate As DateTime, _
maxdate As DateTime _
) As StatusingDataSet
'使用
Dim instance As Statusing
Dim resid As Guid
Dim assnid As Guid
Dim mindate As DateTime
Dim maxdate As DateTime
Dim returnValue As StatusingDataSet
returnValue = instance.ReadStatusForResource(resid, _
assnid, mindate, maxdate)
[SoapDocumentMethodAttribute("https://schemas.microsoft.com/office/project/server/webservices/Statusing/ReadStatusForResource", RequestNamespace = "https://schemas.microsoft.com/office/project/server/webservices/Statusing/",
ResponseNamespace = "https://schemas.microsoft.com/office/project/server/webservices/Statusing/",
Use = SoapBindingUse.Literal, ParameterStyle = SoapParameterStyle.Wrapped)]
public StatusingDataSet ReadStatusForResource(
Guid resid,
Guid assnid,
DateTime mindate,
DateTime maxdate
)
パラメーター
resid
型: System.Guidリソースの GUID。
assnid
型: System.Guid割り当ての GUID です。Guid.emptyは、すべての割り当てを返します。
mindate
型: System.DateTime日付範囲の開始。DateTime.MinDateを使用すると、最初からを選択します。
maxdate
型: System.DateTime日付範囲の最後。DateTime.MaxDateを使用すると、最後に指定します。
戻り値
型: WebSvcStatusing.StatusingDataSet
StatusingDataSet を返します。
注釈
プロジェクト サーバーのアクセス許可
権限 |
説明 |
---|---|
ユーザーを読み取り、リソースのための状態を更新できます。グローバル アクセス権。 |
例
WCF と手動でスケジュールされたタスクの例: UpdateStatus_ManualTasksの例は、テスト アプリケーションは、手動でスケジュールされたタスクまたは自動のタスクに対して、次を。
解析、プロジェクト名、タスクの名前、数、作業時間、optionalassigned リソース、およびオプションのステータスは、コメントします。
リソースが指定されていない場合は、アプリケーションのユーザーは、タスクに割り当てられていると仮定します。
指定したタスクに割り当てられているユーザーの GUID を取得します。
取得し、割り当てのデータを検証します。1 つだけのリソースが割り当てられていると仮定します。
UpdateStatusメソッドは、 changeXml文字列を作成します。簡単なテストでは、変換は時間を % 完了 (最大 100) に報告されます。アプリケーション ユーザーが別のリソースを指定する場合、 changeXmlの文字列内のAssn要素にResID属性を追加します。
UpdateStatusを呼び出すし、 SubmitStatusForResource、1 つの割り当ての呼び出しです。
ReadStatusForResourceを取得、更新されたStatusingDataSetを呼び出します。
アプリケーションは、データセットとchangeXmlの値は、XML ファイルは、テストで使用するためにも書き込みます。
UpdateStatusのテスト アプリケーションを使用するのには、次の手順で行います。
テスト プロジェクトを作成、2 つの手動でスケジュールされたタスクの追加、設定、タスクの期間と開始日、およびリソースとして自分自身と他の 1 人のユーザーを追加します。他のユーザーに 1 つのタスクをし、他のタスクを割り当てます。
たとえば、プロジェクトがテスト プロジェクトの名前 T1 と T2 では、タスクの名前し、し、各タスクの期間を 3 日に設定します。ユーザー名がユーザーの 1 と、他のユーザーが、ユーザー 2 と仮定します。T1 をユーザー 1 にユーザー 2 に T2 を割り当てるとします。
WCF エンドポイントの構成は、app.config ファイルを作成します。Microsoft Visual Studio 2010プロジェクトでのコード サンプルを使用して、app.config ファイルを作成する方法については、 Project 2013 での WCF ベースのコード サンプルの前提条件を参照してください。
さまざまなパラメーターを使用して、テストを実行します。パラメーターについて、次のコードは、 Usageメソッドを参照してください。たとえば、コマンド プロンプトウィンドウで、次のテストを実行します。
UpdateStatus -p "Test project" -t "T1" -hours 6 -c "This is a comment"
出力を示しています。
Updating status for User 1 on task 'T1': 6 hours Manually scheduled task
UpdateStatus -p "Test project" -t "T1" -hours 6 -r "User 2" -c "This is a comment"
ユーザー 2 に割り当てられていないタスク T1、アプリケーションThe assignment on task 'T1' is for User 1, not for User 2を表示するようにします。
UpdateStatus -p "Test project" -t "T2" -hours 6 -r "User 2" -c "This is a comment"
出力を示しています。
Updating status for User 2 on task 'T2': 6 hours Manually scheduled task
各テストでは、後にProject Web Appのステータスの更新の承認センターを確認してください。
注意
追加すると、手動でスケジュールされたタスクの開始日、または期間がない、既定値は 8 時間の作業。まだタスクにリソースを割り当てるし、ステータスを更新できます。たとえば、T3 は、タスクの開始日や期間、いいえ、 UpdateStatusテスト アプリケーションを使用して、6 時間の作業時間の割り当てられたリソースを設定する場合は、Project Server T3 のプロジェクトの開始日に開始日を設定し、し実績作業時間を 6 時間に設定を追加します。同意した後、ステータスの更新、 Project Professional 2010で [ガント チャート] ビューには、実績作業時間] 列と、[残存作業時間] 列を追加できます。T3 の作業時間は 8 時間、実績作業時間は 6 時間、および残存作業時間、2 時間が。詳細ペインで、リソース配分状況] ビューまたは [タスク配分状況] ビューに[実績作業時間の行を追加する場合は、6 時間の実績作業時間も表示できます。
完全な Visual Studio のソリューションは、 Project 2010 SDK のダウンロードです。
using System;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Security.Principal;
using System.Xml;
using PSLibrary = Microsoft.Office.Project.Server.Library;
namespace Microsoft.SDK.Project.Samples.UpdateStatus
{
class Program
{
private const string ENDPOINT_PROJECT = "basicHttp_Project";
private const string ENDPOINT_RESOURCE = "basicHttp_Resource";
private const string ENDPOINT_STATUSING = "basicHttp_Statusing";
// Change the output directory for your computer.
private const string OUTPUT_FILES = @"C:\Project\Samples\Output\";
private const string XML_FILE1 = "UpdateStatus_jc_BasicProjectInfo.xml";
private const string XML_FILE2 = "UpdateStatus_jc_FullProjectInfo.xml";
private const string XML_FILE3 = "UpdateStatus_jc_ChangeXml.xml";
private const string XML_FILE4 = "UpdateStatus_jc_NewStatus.xml";
private static SvcProject.ProjectClient projectClient;
private static SvcResource.ResourceClient resourceClient;
private static SvcStatusing.StatusingClient statusingClient;
private static string projectName = string.Empty; // Project name.
private static string taskName = string.Empty; // Task name.
private static string resName = string.Empty; // Assigned resource name.
private static string requestedResName = string.Empty; // Requested resource name.
private static string appUserName = string.Empty; // Application user name.
private static DateTime minDate = DateTime.Today; // Minimum date for statusing data.
private static DateTime maxDate = DateTime.Today; // Maximum date for statusing data.
private static decimal hoursWorked = 0.0M; // Number of hours worked on the assignment.
private static string comment = string.Empty; // Comment for status submission.
private static bool showUsage = false;
private static StreamWriter writer;
static void Main(string[] args)
{
string outFilePath1 = OUTPUT_FILES + XML_FILE1;
string outFilePath2 = OUTPUT_FILES + XML_FILE2;
string outFilePath3 = OUTPUT_FILES + XML_FILE3;
string outFilePath4 = OUTPUT_FILES + XML_FILE4;
writer = new StreamWriter(outFilePath3);
Guid projUid = Guid.Empty; // GUID of the project.
Guid taskUid = Guid.Empty; // GUID of the task.
Guid assnUid = Guid.Empty; // GUID of the assignment.
Guid resUid = Guid.Empty; // GUID of the assigned resource.
Guid requestedResUid = Guid.Empty; // GUID of the requested resource, for submitting status.
Guid myUid = Guid.Empty; // GUID of the application user.
double regularWork = 0; // Assignment working time at the regular rate,
// in thousandths of minutes.
bool isTaskManual = false; // Specifies whether the task is manually scheduled.
if (!ParseCommandLine(args))
{
Usage();
ExitApp();
}
try
{
ConfigClientEndpoints(ENDPOINT_PROJECT);
ConfigClientEndpoints(ENDPOINT_RESOURCE);
ConfigClientEndpoints(ENDPOINT_STATUSING);
WindowsIdentity winId = WindowsIdentity.GetCurrent();
appUserName = winId.Name;
myUid = resourceClient.GetCurrentUserUid();
Console.WriteLine("User: {0}; PWA GUID: {1}", appUserName, myUid.ToString());
// Get the basic information for the project.
SvcProject.ProjectDataSet projectDs = projectClient.ReadProjectStatus(
Guid.Empty, SvcProject.DataStoreEnum.PublishedStore, projectName,
(int)PSLibrary.Project.ProjectType.Project);
Console.WriteLine("XML output for ReadProjectStatus:\n\t{0}",
outFilePath1);
projectDs.WriteXml(outFilePath1);
projUid = projectDs.Project[0].PROJ_UID;
if (projUid == Guid.Empty)
throw (new ArgumentException(
string.Format("\nThe project '{0}' does not exist.", projectName)));
// Get the full information for the project.
projectDs = projectClient.ReadProject(projUid,
SvcProject.DataStoreEnum.PublishedStore);
Console.WriteLine("XML output for ReadProject:\n\t{0}", outFilePath2);
projectDs.WriteXml(outFilePath2);
bool isCurrentUser; // Specifies whether the assignment is for the current user.
// Get requested resource GUID. Exit if the requested resource is not a project resource.
if (string.IsNullOrEmpty(requestedResName))
{
// The current user is the requested resource.
isCurrentUser = true;
// Use a Linq query over the typed ProjectDataSet to check whether
// the app user is a resource on the project.
var query = from r in projectDs.ProjectResource
where r.RES_UID == myUid
select new { r.RES_NAME };
foreach (var resRow in query)
{
requestedResName = resRow.RES_NAME;
requestedResUid = myUid;
}
}
else
{
isCurrentUser = false;
var query = from r in projectDs.ProjectResource
where r.RES_NAME == requestedResName
select new { r.RES_UID };
foreach (var resRow in query)
{
requestedResUid = resRow.RES_UID;
}
}
if (requestedResUid == Guid.Empty)
{
if (string.IsNullOrEmpty(requestedResName))
requestedResName = appUserName;
throw (new ArgumentException(
string.Format("\nThe resource '{0}' is not on the project '{1}'",
requestedResName, projectName)));
}
// Get the assignment data for the task.
for (int i = 0; i < projectDs.Assignment.Count; i++)
{
if (projectDs.Assignment[i].TASK_NAME == taskName)
{
taskUid = projectDs.Assignment[i].TASK_UID;
assnUid = projectDs.Assignment[i].ASSN_UID;
resUid = projectDs.Assignment[i].RES_UID;
regularWork = projectDs.Assignment[i].ASSN_WORK;
minDate = projectDs.Assignment[i].ASSN_START_DATE;
maxDate = projectDs.Assignment[i].ASSN_FINISH_DATE;
// Get the assigned resource name.
for (int j = 0; j < projectDs.ProjectResource.Count; j++)
{
if (projectDs.ProjectResource[j].RES_UID == resUid)
{
resName = projectDs.ProjectResource[j].RES_NAME;
break;
}
}
// Is the task manually scheduled?
for (int t = 0; t < projectDs.Task.Count; t++)
{
if (projectDs.Task[t].TASK_UID == taskUid)
{
isTaskManual = projectDs.Task[t].TASK_IS_MANUAL;
break;
}
}
break;
}
}
ValidateAssignment(isCurrentUser, resUid, myUid, assnUid, requestedResUid);
string changeXml = CreateChangeXml(projUid, assnUid, resUid,
hoursWorked, regularWork, isCurrentUser);
Console.WriteLine("XML output for ChangeXml:\n\t{0}", outFilePath3);
writer.WriteLine(changeXml);
Console.ForegroundColor = ConsoleColor.Yellow;
string yellowString = "\nUpdating status for {0} on task '{1}': {2} hours\n\t";
yellowString += (isTaskManual) ? "Manually scheduled task" : "Auto-scheduled task";
Console.WriteLine(yellowString, resName, taskName, hoursWorked);
Console.ResetColor();
statusingClient.UpdateStatus(changeXml);
Guid[] assignments = { assnUid };
statusingClient.SubmitStatusForResource(resUid, assignments, comment);
SvcStatusing.StatusingDataSet statusingDs =
statusingClient.ReadStatusForResource(resUid, assnUid, minDate, maxDate);
Console.WriteLine("\nXML output for ReadStatusForResource:\n\t{0}", outFilePath4);
statusingDs.WriteXml(outFilePath4);
}
catch (FaultException fault)
{
// Use the WCF FaultException, because the ASMX SoapException does not
// exist in a WCF-based application.
Console.ForegroundColor = ConsoleColor.Red;
WriteFaultOutput(fault);
Console.WriteLine();
showUsage = true;
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(ex.Message);
Console.WriteLine();
showUsage = true;
}
finally
{
writer.Close();
Console.ResetColor();
if (showUsage) Usage();
ExitApp();
}
}
// Validate the assignment and the resource.
private static void ValidateAssignment(bool isCurrentUser, Guid resUid, Guid myUid,
Guid assnUid, Guid requestedResUid)
{
if (!isCurrentUser && resUid == myUid)
throw (new ArgumentException(
string.Format("\nThe assignment on task '{0}' is for {1}, not for {2}",
taskName, resName, requestedResName)));
if (assnUid == Guid.Empty)
throw (new ArgumentException(
string.Format("\nNo assignment for {0} on task '{0}'", resName, taskName)));
if (requestedResUid != resUid)
throw (new ArgumentException(
string.Format("\nResource '{0}' does not match assignment on task '{1}'",
requestedResName, taskName)));
}
/// <summary>Create a ChangeXml string for the UpdateStatus method.</summary>
/// <param name="projUid">Project GUID</param>
/// <param name="assnUid">Assignment GUID</param>
/// <param name="resUid">Resource GUID</param>
/// <param name="hoursWorked">Number of hours worked.</param>
/// <param name="totalRegHours">
/// Total assigned hours at the regular rate, in thousandths of minutes.</param>
/// <param name="isCurrentUser">True if the assignment is for the current user.</param>
/// <returns></returns>
private static string CreateChangeXml(Guid projUid, Guid assnUid, Guid resUid,
decimal hoursWorked, double totalRegHours, bool isCurrentUser)
{
StringBuilder cXmlBuilder = new StringBuilder("<Changes>");
cXmlBuilder.AppendFormat("<Proj ID=\"{0}\">", projUid.ToString());
cXmlBuilder.AppendFormat("<Assn ID=\"{0}\"", assnUid.ToString());
// If the assignment is not for the current user, add the ResID attribute,
// and then close the Assn element.
if (isCurrentUser)
cXmlBuilder.Append(">");
else
cXmlBuilder.AppendFormat(" ResID=\"{0}\">", resUid.ToString());
// Specify the process ID (PID) for percent work complete.
// The "Supported Project Fields and Field Information for Statusing ChangeXML"
// SDK article shows the PID value is 251658274.
string pidPctWorkComplete = PSLibrary.AssnConstID.s_apid_pct_wrk_complete.ToString(
CultureInfo.InvariantCulture);
// Calculate the percent work complete.
int pctComplete = Convert.ToInt32(100 * hoursWorked /
Convert.ToDecimal(totalRegHours / 1000 / 60));
if (pctComplete > 100) pctComplete = 100;
cXmlBuilder.AppendFormat("<Change PID=\"{0}\">{1}</Change>", pidPctWorkComplete,
pctComplete.ToString());
cXmlBuilder.Append("</Assn></Proj></Changes>");
return cXmlBuilder.ToString();
}
// 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.
public static void ConfigClientEndpoints(string endpt)
{
if (endpt == ENDPOINT_PROJECT)
projectClient = new SvcProject.ProjectClient(endpt);
else if (endpt == ENDPOINT_RESOURCE)
resourceClient = new SvcResource.ResourceClient(endpt);
else if (endpt == ENDPOINT_STATUSING)
statusingClient = new SvcStatusing.StatusingClient(endpt);
}
// Parse the command line. Return true if there are no errors.
private static bool ParseCommandLine(string[] args)
{
int i;
bool error = false;
int argsLength = args.Length;
for (i = 0; i < argsLength; i++)
{
if (error) break;
if (args[i].StartsWith("-") || args[i].StartsWith("/"))
args[i] = "*" + args[i].Substring(1).ToLower();
switch (args[i])
{
case "*projectname":
case "*p":
if (++i >= argsLength) return false;
projectName = args[i];
break;
case "*taskname":
case "*t":
if (++i >= argsLength) return false;
taskName = args[i];
break;
case "*resourcename":
case "*r":
if (++i >= argsLength) return false;
requestedResName = args[i];
break;
case "*hours":
case "*h":
if (++i >= argsLength) return false;
hoursWorked = Convert.ToDecimal(args[i]);
break;
case "*comment":
case "*c":
if (++i >= argsLength) return false;
comment = args[i];
break;
case "*?":
default:
error = true;
break;
}
}
return !error;
}
private static void Usage()
{
string example = "Usage: UpdateStatus -p \"Project Name\" -t \"Task name\" -h 3"
+ "\r\n\t\t[-r \"Resource Name\"] [-d 6/29/2011] [-c \"This is a comment\"]";
Console.WriteLine(example);
Console.WriteLine(" -projectName | -p: Name of the project.");
Console.WriteLine(" -taskName | -t: Name of the assigned task.");
Console.WriteLine(" -hours | -h: Number of hours worked.");
Console.WriteLine(" -resourceName | -r: Resource name. Default is the current user.");
Console.WriteLine(" -date | -d: Date of the work. Default is non-timephased.");
Console.WriteLine(" -comment | -c: Comment for submitted status.");
}
private static void ExitApp()
{
Console.Write("\nPress any key to exit... ");
Console.ReadKey(true);
Environment.Exit(0);
}
}
// Helper method: GetPSClientError.
class Helpers
{
/// <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;
}
}
}