Project.ReadProjectStatus Method

Gets the status of the specified project.

Namespace:  [Project Web service]
Service reference: http://ServerName:32843/[Project Service Application GUID]/PSI/Project.svc
Web service reference: http://ServerName/ProjectServerName/_vti_bin/PSI/Project.asmx?wsdl

<SoapDocumentMethodAttribute("", RequestNamespace := "",  _
	ResponseNamespace := "",  _
	Use := SoapBindingUse.Literal, ParameterStyle := SoapParameterStyle.Wrapped)> _
Public Function ReadProjectStatus ( _
	projGuid As Guid, _
	dataStore As DataStoreEnum, _
	projName As String, _
	projType As Integer _
) As ProjectDataSet
Dim instance As Project
Dim projGuid As Guid
Dim dataStore As DataStoreEnum
Dim projName As String
Dim projType As Integer
Dim returnValue As ProjectDataSet

returnValue = instance.ReadProjectStatus(projGuid, _
	dataStore, projName, projType)


Type: System.Guid
The GUID of the project. Default is Guid.Empty.
Type: [Project Web service].DataStoreEnum
The database in which the project data is located (Drafts, Published, or Archive). Defaults to PublishedStore.
Type: System.String
The name of the project. The default is String.Empty, to get all projects visible to the user.
Type: System.Int32
The type of project. Specify by using Project.ProjectType and cast to an int. The default is Project.

Return Value

Type: [Project Web service].ProjectDataSet
The status and permissions of the current user determines the list of projects that are visible. The ProjectDataSet schema contains only the Project table, with the following fields: PROJ_UID, PROJ_NAME, PROJ_TYPE, PROJ_CHECKOUTDATE, PROJ_SESSION_DESCRIPTION, WPROJ_LAST_PUB, PROJ_LAST_SAVED, CREATED_DATE, ENTERPRISE_PROJECT_TYPE_UID, ENTERPRISE_PROJECT_TYPE_NAME, and PROJ_WINPROJ_VERSION_NUMBER.

Because it takes into account the user permissions, the ReadProjectStatus method is the preferred method for obtaining a list of projects. This method populates only certain fields in the Project table. To populate other fields in the Project table, the Task table, or other tables, use ReadProject with the GUID of the desired project.

The ReadProjectStatus method enables you to get a project by using the name. You must use the full name of the project. To get a project by name only, set projGuid to Guid.Empty, specify the dataStore, pass the project name in projName, and specify the project type. The example in CreateProjectFromTemplate uses the ReadProjectStatus method to retrieve the template.

Project Server Permissions




Allows a user to view the Project Center in Project Web App. Global permission.


Allows a user to open the specified project. Required only if they do not have ViewProjectCenter. Category permission.

Example for WCF:   The ReadMyProjects example does the following:

  1. Gets the GUID of the current user.

  2. Reads the list of all projects visible to the user, by using ReadProjectStatus.

  3. Reads each project in the list, by using ReadProject.

  4. If the project owner matches the current user:

    1. Copies the project row to a ProjectDataSet that has the same schema created by ReadProjectStatus.

    2. Copies the project row to a second ProjectDataSet that has the complete schema.

    3. Adds selected task data in the project to the TaskDataTable.

  5. Writes each output ProjectDataSet to an XML file, for comparison of the schemas.

  6. For example output of the exception handler, see the Code Example for WCF section in Project Server Error Codes.


If there are a large number of projects to read, a query of the Reporting database can be more efficient. Alternately, a PSI extension can do all of the calls to ReadProjectStatus and ReadProject on the server, and return just the final ProjectDataSet.

For information about using the code sample in a Microsoft Visual Studio 2010 project and creating an app.config file for configuration of the WCF endpoints, see Prerequisites for WCF-Based Code Samples.

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

namespace Microsoft.SDK.Project.Samples.ReadMyProjects
    class Program
        private const string ENDPOINT_PROJECT = "basicHttp_Project";
        private const string ENDPOINT_RESOURCE = "basicHttp_Resource";

        // Change the output directory for your computer.
        private const string OUTPUT_FILES = @"C:\Project\Samples\Output\";
        private const string XML_FILE = "MyProjects.xml";
        private const string XML_FILE2 = "MyProjects2.xml";

        private static SvcProject.ProjectClient projectClient;
        private static SvcResource.ResourceClient resourceClient;
        static void Main(string[] args)
            string outFilePath = OUTPUT_FILES + XML_FILE;
            string outFilePath2 = OUTPUT_FILES + XML_FILE2;


                Guid myUid = resourceClient.GetCurrentUserUid();
                Console.WriteLine("My GUID: {0}", myUid.ToString());

                // Get the list of all projects visible to the user.
                SvcProject.ProjectDataSet projectDs = projectClient.ReadProjectStatus(
                    Guid.Empty, SvcProject.DataStoreEnum.WorkingStore,
                    string.Empty, (int)PSLibrary.Project.ProjectType.Project);

                SvcProject.ProjectDataSet tempProjDs = null;

                // Create an empty ProjectDataSet for projects the user owns.
                // By cloning the projectDs object, you get the same schema 
                // that is created by ReadProjectStatus.
                SvcProject.ProjectDataSet myProjectsDs = 

                // Create an empty ProjectDataSet that contains the complete schema.
                SvcProject.ProjectDataSet myProjectsDs2 = new SvcProject.ProjectDataSet();

                Console.WriteLine("Projects I own:");

                for (int i = 0; i < projectDs.Project.Count; i++)
                    tempProjDs = projectClient.ReadProject(projectDs.Project[i].PROJ_UID,

                    if (tempProjDs.Project[0].ProjectOwnerID == myUid)
                        Console.WriteLine("\t" + tempProjDs.Project[0].PROJ_NAME);

                        // You can add task data to either ProjectDataSet. However,
                        // only myProjectsDs2 contains the complete Project table schema.
                        for (int t = 0; t < tempProjDs.Task.Count; t++)
                            // To get all of the task data, use the following statement
                            // instead of adding a new task row with specific fields.
                            //    (SvcProject.ProjectDataSet.TaskRow)tempProjDs.Task[t]);

                            // Add specific data in a new task row.
                            SvcProject.ProjectDataSet.TaskRow taskRow = 

                            // If you comment-out the following line, you get a constraint error.
                            taskRow.PROJ_UID = tempProjDs.Task[t].PROJ_UID;

                            taskRow.TASK_UID = tempProjDs.Task[t].TASK_UID;
                            taskRow.TASK_NAME = tempProjDs.Task[t].TASK_NAME;
                            taskRow.TASK_IS_MANUAL = tempProjDs.Task[t].TASK_IS_MANUAL;
                    "\nXML output of myProjectsDs and myProjectDs2:\n\t{0}",

                // Write both XML files for comparison of the ProjectDataSet schemas.
            catch (FaultException fault)
                // Use the WCF FaultException, because the ASMX SoapException does not 
                // exist in a WCF-based application.
            catch (Exception ex)
            Console.Write("\nPress any key to exit... ");

        // 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;

        // 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);

    // 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;
                // Get a ServiceModel.MessageFault object.
                var messageFault = e.CreateMessageFault();

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

                        var serverExecutionFault = xml["ServerExecutionFault"];
                        if (serverExecutionFault != null)
                            var exceptionDetails = serverExecutionFault["ExceptionDetails"];
                            if (exceptionDetails != null)
                                    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;
                                errOut = PREFIX 
                                    + "The FaultException e is a ServerExecutionFault, "
                                    + "but does not have ExceptionDetails.";
                            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;

Example for ASMX:   The following example creates a sample project, and then gets the status of all projects in the working store and reports it to the console.

For critical information about running this code sample, see Prerequisites for ASMX-Based Code Samples.

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Web.Services.Protocols;
using System.Threading;
using PSLibrary = Microsoft.Office.Project.Server.Library;

namespace Microsoft.SDK.Project.Samples.ReadProjectStatus
   class Program
      static void Main()
            #region Setup
            const string PROJECT_SERVER_URI = "http://ServerName/ProjectServerName/";
            const string PROJECT_SERVICE_PATH = "_vti_bin/psi/project.asmx";
            const string QUEUESYSTEM_SERVICE_PATH = "_vti_bin/psi/queuesystem.asmx";

            // Set up the web service objects.
            ProjectWebSvc.Project projectSvc = new ProjectWebSvc.Project();

            projectSvc.Credentials = CredentialCache.DefaultCredentials;

            QueueSystemWebSvc.QueueSystem q = new QueueSystemWebSvc.QueueSystem();
            q.Credentials = CredentialCache.DefaultCredentials;

            // Create a sample project.
            Console.WriteLine("Creating sample project");
            Guid projectId = CreateSampleProject(projectSvc, q);
            #region Read Project Status
            // Read all the projects.
            Console.WriteLine("Read the projects");
            ProjectWebSvc.ProjectDataSet readProjDs = projectSvc.ReadProjectStatus(Guid.Empty, ProjectWebSvc.DataStoreEnum.WorkingStore,string.Empty,(int) PSLibrary.Project.ProjectType.Project);
            #region Write out projects
            Console.ForegroundColor = ConsoleColor.DarkCyan;
            foreach (ProjectWebSvc.ProjectDataSet.ProjectRow project in readProjDs.Project)
               Console.WriteLine(project.PROJ_NAME + " was last saved " + project.PROJ_LAST_SAVED);
         #region Exception Handling and Final
         catch (SoapException ex)
            PSLibrary.PSClientError error = new PSLibrary.PSClientError(ex);
            PSLibrary.PSErrorInfo[] errors = error.GetAllErrors();
            string errMess = "==============================\r\nError: \r\n";
            for (int i = 0; i < errors.Length; i++)
               errMess += "\n" + ex.Message.ToString() + "\r\n";
               errMess += "".PadRight(30, '=') + "\r\nPSCLientError Output:\r\n \r\n";
               errMess += errors[i].ErrId.ToString() + "\n";

               for (int j = 0; j < errors[i].ErrorAttributes.Length; j++)
                  errMess += "\r\n\t" + errors[i].ErrorAttributeNames()[j] + ": " + errors[i].ErrorAttributes[j];
               errMess += "\r\n".PadRight(30, '=');
            Console.ForegroundColor = ConsoleColor.Red;
         catch (WebException ex)
            string errMess = ex.Message.ToString() +
               "\n\nLog on, or check the Project Server Queuing Service";
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Error: " + errMess);
         catch (Exception ex)
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Error: " + ex.Message);
            Console.WriteLine("\r\n\r\nPress any key...");
      static private void WaitForQueue(QueueSystemWebSvc.QueueSystem q, Guid jobId)
         QueueSystemWebSvc.JobState jobState;
         const int QUEUE_WAIT_TIME = 2; // two seconds
         bool jobDone = false;
         string xmlError = string.Empty;
         int wait = 0;

         // Wait for the project to get through the queue.
         // Get the estimated wait time in seconds.
         wait = q.GetJobWaitTime(jobId);

         // Wait for it.
         Thread.Sleep(wait * 1000);
         // Wait until it is finished.

            // Get the job state.
            jobState = q.GetJobCompletionState(jobId, out xmlError);

            if (jobState == QueueSystemWebSvc.JobState.Success)
               jobDone = true;
               if (jobState == QueueSystemWebSvc.JobState.Unknown
               || jobState == QueueSystemWebSvc.JobState.Failed
               || jobState == QueueSystemWebSvc.JobState.FailedNotBlocking
               || jobState == QueueSystemWebSvc.JobState.CorrelationBlocked
               || jobState == QueueSystemWebSvc.JobState.Canceled)
                  // If the job failed, error out.
                  throw (new ApplicationException("Queue request " + jobState + " for Job ID " + jobId + ".\r\n" + xmlError));
                  Console.WriteLine("Job State: " + jobState + " for Job ID: " + jobId);
                  Thread.Sleep(QUEUE_WAIT_TIME * 1000);
         while (!jobDone);
      static private Guid CreateSampleProject(ProjectWebSvc.Project projectSvc,QueueSystemWebSvc.QueueSystem q)
         ProjectWebSvc.ProjectDataSet projectDs = new ProjectWebSvc.ProjectDataSet();
         Guid jobId;
         // Create the project.
         ProjectWebSvc.ProjectDataSet.ProjectRow projectRow = projectDs.Project.NewProjectRow();
         projectRow.PROJ_UID = Guid.NewGuid();
         projectRow.PROJ_NAME = "Its a wonderful project at " + 
            DateTime.Now.ToShortDateString().Replace("/", "") + " " + 
            DateTime.Now.ToShortTimeString().Replace(":", "");
         projectRow.PROJ_TYPE = (int)PSLibrary.Project.ProjectType.Project;

         // Add some tasks.
         ProjectWebSvc.ProjectDataSet.TaskRow taskOne = projectDs.Task.NewTaskRow();
         taskOne.PROJ_UID = projectRow.PROJ_UID;
         taskOne.TASK_UID = Guid.NewGuid();
         // The Task Duration format must be specified.
         taskOne.TASK_DUR_FMT = (int)PSLibrary.Task.DurationFormat.Day;
         taskOne.TASK_DUR = 4800;  // 8 hours in duration units (minute/10)
         taskOne.TASK_NAME = "Task One";
         taskOne.TASK_START_DATE = System.DateTime.Now.AddDays(1);

         ProjectWebSvc.ProjectDataSet.TaskRow taskTwo = projectDs.Task.NewTaskRow();
         taskTwo.PROJ_UID = projectRow.PROJ_UID;
         taskTwo.TASK_UID = Guid.NewGuid();
         // The Task Duration format must be specified.
         taskTwo.TASK_DUR_FMT = (int)PSLibrary.Task.DurationFormat.Day;
         taskTwo.TASK_DUR = 4800;  // 8 hours in duration units (minute/10)
         taskTwo.TASK_NAME = "Task Two";
         taskTwo.TASK_START_DATE = System.DateTime.Now.AddDays(1);

         //Add some resources.
         ProjectWebSvc.ProjectDataSet.ProjectResourceRow resourceOne = projectDs.ProjectResource.NewProjectResourceRow();
         resourceOne.PROJ_UID = projectRow.PROJ_UID;
         resourceOne.RES_UID = Guid.NewGuid();
         resourceOne.RES_NAME = "Brynja Sigrídur Blomsterberg";
         resourceOne.RES_INITIALS = "BSB";
         CreateAssignment(projectDs, taskOne.TASK_UID, resourceOne.RES_UID);
         CreateAssignment(projectDs, taskTwo.TASK_UID, resourceOne.RES_UID);

         ProjectWebSvc.ProjectDataSet.ProjectResourceRow resourceTwo = projectDs.ProjectResource.NewProjectResourceRow();
         resourceTwo.PROJ_UID = projectRow.PROJ_UID;
         resourceTwo.RES_UID = Guid.NewGuid();
         resourceTwo.RES_NAME = "Ioannis Xylaras";
         resourceTwo.RES_INITIALS = "IX";
         CreateAssignment(projectDs, taskOne.TASK_UID, resourceTwo.RES_UID);
         CreateAssignment(projectDs, taskTwo.TASK_UID, resourceTwo.RES_UID);

         // Save the project to the database.
         jobId = Guid.NewGuid();
         projectSvc.QueueCreateProject(jobId, projectDs, false);
         WaitForQueue(q, jobId);
         return projectRow.PROJ_UID;
      private static void CreateAssignment(ProjectWebSvc.ProjectDataSet projectDs, Guid taskGuid, Guid resourceGuid)
         ProjectWebSvc.ProjectDataSet.AssignmentRow assnRow = projectDs.Assignment.NewAssignmentRow();
         assnRow.PROJ_UID = projectDs.Project[0].PROJ_UID;
         assnRow.ASSN_UID = Guid.NewGuid();
         assnRow.TASK_UID = taskGuid;
         assnRow.RES_UID = resourceGuid;

Community Additions