├── CSOMUtils.psm1 ├── LICENSE ├── Project-REST-Basic-Operations.yml ├── README.md ├── ReST.ps1 ├── SECURITY.md ├── createproject.ps1 ├── getprojectscsom.ps1 ├── getprojectsodata.ps1 ├── getresources.ps1 ├── getstatusassignments.ps1 ├── updateproject.ps1 └── updateprojectcustomfieldvalues.ps1 /CSOMUtils.psm1: -------------------------------------------------------------------------------- 1 | function Create-CustomField{ 2 | Param( 3 | [parameter(Mandatory=$true)]$projContext, 4 | [parameter(Mandatory=$true)]$Id, 5 | [parameter(Mandatory=$true)]$Name, 6 | [parameter(Mandatory=$false)]$Description, 7 | [parameter(Mandatory=$true)]$FieldType, 8 | [parameter(Mandatory=$true)]$EntityType, 9 | [parameter(Mandatory=$false)]$LookupTable, 10 | [parameter(Mandatory=$true)]$IsWorkflowControlled, 11 | [parameter(Mandatory=$true)]$IsRequired, 12 | [parameter(Mandatory=$false)]$IsEditableInVisibility, 13 | [parameter(Mandatory=$false)]$IsMultilineText 14 | 15 | ) 16 | 17 | [Microsoft.ProjectServer.Client.CustomFieldCreationInformation]$customFieldInfo = New-Object Microsoft.ProjectServer.Client.CustomFieldCreationInformation; 18 | #Mandatory fields 19 | $customFieldInfo.Id = $Id 20 | $customFieldInfo.Name = $Name 21 | $customFieldInfo.FieldType = $FieldType 22 | $customFieldInfo.EntityType = $EntityType 23 | $customFieldInfo.IsWorkflowControlled = $IsWorkflowControlled 24 | $customFieldInfo.IsRequired = $IsRequired 25 | 26 | #Non Mandatory fields 27 | if($Description -ne $null) 28 | { 29 | $customFieldInfo.Description = $Description 30 | } 31 | 32 | if($IsEditableInVisibility -ne $null) 33 | { 34 | $customFieldInfo.IsEditableInVisibility = $IsEditableInVisibility 35 | } 36 | 37 | if($IsMultilineText -ne $null) 38 | { 39 | $customFieldInfo.IsMultilineText = $IsMultilineText 40 | } 41 | 42 | if($LookupTable -ne $null) 43 | { 44 | $customFieldInfo.LookupTable = $LookupTable 45 | } 46 | 47 | $newCustomField = $projContext.CustomFields.Add($customFieldInfo); 48 | $projContext.CustomFields.Update() 49 | $projContext.ExecuteQuery() 50 | } 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Project-REST-Basic-Operations 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | MIT License 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining 8 | a copy of this software and associated documentation files (the 9 | "Software"), to deal in the Software without restriction, including 10 | without limitation the rights to use, copy, modify, merge, publish, 11 | distribute, sublicense, and/or sell copies of the Software, and to 12 | permit persons to whom the Software is furnished to do so, subject to 13 | the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 22 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE 25 | -------------------------------------------------------------------------------- /Project-REST-Basic-Operations.yml: -------------------------------------------------------------------------------- 1 | ### YamlMime:Sample 2 | sample: 3 | - name: 'Project add-in: REST Basic Operations' 4 | path: '' 5 | description: The Project REST Basic Operations demonstrates how to create and update a project using REST API. 6 | readme: '' 7 | generateZip: FALSE 8 | isLive: TRUE 9 | technologies: 10 | - Office Add-in 11 | azureDeploy: '' 12 | author: NadinMerali 13 | platforms: [] 14 | languages: 15 | - REST API 16 | extensions: 17 | products: 18 | - Project 19 | scenarios: [] 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | products: 4 | - office-project 5 | - office-365 6 | languages: 7 | - powershell 8 | extensions: 9 | contentType: samples 10 | platforms: 11 | - REST API 12 | createdDate: 11/23/2015 8:07:26 PM 13 | --- 14 | # Project REST Basic Operations 15 | 16 | The Project REST Basic Operations demonstrates how to create and update a project using REST API. 17 | 18 | ## Prerequisites 19 | To use this Project Online REST code sample, you need the following: 20 | * An Office 365 tenant with a Project license 21 | * PowerShell v4.0 22 | * Latest MSAL .Net library. It is available as a Nuget Package from [here](https://www.nuget.org/packages/Microsoft.Identity.Client/) 23 | * For the files downloaded, please run "Unblock-File *" to unblock accessing the file. 24 | 25 | ## Modules 26 | * [CreateProject](/createproject.ps1) 27 | * [UpdateProject](/updateproject.ps1) 28 | * [UpdateProjectCustomFields](/updateprojectcustomfieldvalues.ps1) 29 | 30 | ## How the sample affects your tenant data 31 | This sample runs REST API methods that create, read, update, or delete data. When running commands that delete or edit data, the sample creates sample data. The sample data is created or edited so that your actual tenant data is unaffected. 32 | 33 | ## Additional resources 34 | * [JavaScript library and REST reference for Project Server 2013](https://msdn.microsoft.com/en-us/library/office/jj712612.aspx) 35 | * [SharePoint and Project Online SDK](https://www.nuget.org/packages/Microsoft.SharePointOnline.CSOM) 36 | 37 | ## Copyright 38 | Copyright (c) 2016 Microsoft. All rights reserved. 39 | 40 | 41 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information, see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 42 | -------------------------------------------------------------------------------- /ReST.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 3 | See LICENSE in the project root for license information. 4 | #> 5 | 6 | $ErrorActionPreference = "Stop" # http://technet.microsoft.com/en-us/library/dd347731.aspx 7 | Set-StrictMode -Version "Latest" # http://technet.microsoft.com/en-us/library/dd347614.aspx 8 | 9 | # PS helper methods to call ReST API methods targeting Project Online tenants 10 | $global:accessHeader = '' 11 | $global:digestValue = '' 12 | 13 | [Reflection.Assembly]::LoadFrom("$($PSScriptRoot)\Microsoft.Identity.Client.dll") | Out-Null 14 | 15 | function Get-AuthToken([Uri] $Uri) 16 | { 17 | # NOTE: Create an azure app and update $clientId,$tenantId and $redirectUri below 18 | $clientId = "" 19 | $tenantId = "" 20 | $redirectUri = "" 21 | # user's PJO login account 22 | $user = "" 23 | $scopes = New-Object System.Collections.Generic.List[string] 24 | # Project.Write Permission scope for app eg:"https://contoso.sharepoint.com/Project.Write" 25 | $writeScope = "" 26 | $scopes.Add($writeScope) 27 | $pcaConfig = [Microsoft.Identity.Client.PublicClientApplicationBuilder]::Create($clientId).WithTenantId($tenantId).WithRedirectUri($redirectUri); 28 | 29 | $authenticationResult = $pcaConfig.Build().AcquireTokenInteractive($scopes).WithPrompt([Microsoft.Identity.Client.Prompt]::NoPrompt).WithLoginHint($user).ExecuteAsync().Result; 30 | 31 | return $authenticationResult 32 | } 33 | 34 | # Gets Auth Token using MSAL library. 35 | function Set-SPOAuthenticationTicket([string] $siteUrl) 36 | { 37 | $siteUri = New-Object Uri -ArgumentList $siteUrl 38 | 39 | $authResult = Get-AuthToken -Uri $siteUri 40 | if ($authResult -ne $null) 41 | { 42 | $global:accessHeader = $authResult.CreateAuthorizationHeader() 43 | } 44 | 45 | if ([String]::IsNullOrEmpty($global:accessHeader)) 46 | { 47 | throw 'Could not obtain authentication ticket based on provided credentials for specified site' 48 | } 49 | } 50 | 51 | function Build-ReSTRequest([string] $siteUrl, [string]$endpoint, [string]$method, [string]$body = $null) 52 | { 53 | $url = ([string]$siteUrl).TrimEnd("/") + "/_api/" + $endpoint 54 | $req = [System.Net.WebRequest]::Create($url) 55 | $req.Timeout = 120000 56 | $req.Method = $method 57 | 58 | [bool]$isReadOnly = (('GET','HEAD') -contains $req.Method) 59 | [bool]$isDigestRequest = $endpoint -contains 'contextinfo' 60 | 61 | if ([String]::IsNullOrEmpty($body)) 62 | { 63 | $req.ContentLength = 0; 64 | } 65 | else 66 | { 67 | $req.ContentLength = $body.Length 68 | $req.ContentType = "application/json" 69 | } 70 | 71 | # set Authorization header 72 | $req.Headers.Add("Authorization", $global:accessHeader) 73 | # handle ETag 74 | $req.Headers.Add("If-Match", "*") 75 | 76 | if (-not $isDigestRequest) 77 | { 78 | if (-not $isReadOnly) 79 | { 80 | $req.Headers.Add("X-RequestDigest", $global:digestValue) 81 | } 82 | } 83 | 84 | if (-not [String]::IsNullOrEmpty($body)) 85 | { 86 | $writer = New-Object System.IO.StreamWriter $req.GetRequestStream() 87 | $writer.Write($body) 88 | $writer.Close() 89 | $writer.Dispose() 90 | } 91 | 92 | return $req 93 | } 94 | 95 | function Set-DigestValue([string]$siteUrl) 96 | { 97 | $request = Build-ReSTRequest $siteUrl 'contextinfo' 'POST' $null 98 | if ($request -eq $null) 99 | { 100 | throw 'Could not obtain a request digest value based on provided credentials for specified site' 101 | } 102 | 103 | try 104 | { 105 | $resp = $request.GetResponse() 106 | $reader = [System.Xml.XmlReader]::Create($resp.GetResponseStream()) 107 | if ($reader.ReadToDescendant("d:FormDigestValue")) 108 | { 109 | $global:digestValue = $reader.ReadElementContentAsString() 110 | } 111 | else 112 | { 113 | throw 'Could not obtain a request digest value based on provided credentials for specified site' 114 | } 115 | } 116 | finally 117 | { 118 | if ($reader -ne $null) 119 | { 120 | $reader.Close() 121 | $reader.Dispose() 122 | } 123 | if ($resp -ne $null) 124 | { 125 | $resp.Close() 126 | $resp.Dispose() 127 | } 128 | } 129 | } 130 | 131 | function Post-ReSTRequest([string]$siteUrl, [string]$endpoint, [string]$body = $null) 132 | { 133 | $request = Build-ReSTRequest $siteUrl $endpoint 'POST' $body 134 | $resp = $request.GetResponse() 135 | if ($resp -ne $null) 136 | { 137 | $reader = New-Object System.IO.StreamReader $resp.GetResponseStream() 138 | $reader.ReadToEnd() 139 | $reader.Dispose() 140 | } 141 | } 142 | 143 | function Patch-ReSTRequest([string]$siteUrl, [string]$endpoint, [string]$body) 144 | { 145 | $request = Build-ReSTRequest $siteUrl $endpoint 'PATCH' $body 146 | $resp = $request.GetResponse() 147 | if ($resp -ne $null) 148 | { 149 | $reader = New-Object System.IO.StreamReader $resp.GetResponseStream() 150 | $reader.ReadToEnd() 151 | $reader.Dispose() 152 | } 153 | } 154 | 155 | function Get-ReSTRequest([string]$siteUrl, [string]$endpoint) 156 | { 157 | $request = Build-ReSTRequest $siteUrl $endpoint 'GET' 158 | $resp = $request.GetResponse() 159 | if ($resp -ne $null) 160 | { 161 | $reader = New-Object System.IO.StreamReader $resp.GetResponseStream() 162 | $reader.ReadToEnd() 163 | $reader.Dispose() 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /createproject.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 3 | See LICENSE in the project root for license information. 4 | #> 5 | 6 | 7 | # Creates a Project using ReST API 8 | param 9 | ( 10 | # SharepointOnline project site collection URL 11 | $SiteUrl = $(throw "SiteUrl parameter is required") 12 | ) 13 | # Load ReST helper methods 14 | . .\ReST.ps1 15 | 16 | # Set up the request authentication 17 | Set-SPOAuthenticationTicket $siteUrl 18 | Set-DigestValue $siteUrl 19 | 20 | # Project parameters as JSON payload 21 | $projectid = [Guid]::NewGuid() 22 | $body = "{ 23 | 'parameters': { 24 | 'Id': '$projectid', 25 | 'Name': 'Project_$projectid', 26 | 'Description': 'Created from PowerShell using REST API' 27 | } 28 | }" 29 | 30 | # ReST request to create a project 31 | Post-ReSTRequest $SiteUrl "ProjectServer/Projects/Add" $body 32 | 33 | # Wait till new project is finally ready in SharepointOnline. 34 | While ($true) 35 | { 36 | Start-Sleep -Seconds 1 37 | Write-Host "Querying new project's readiness" 38 | $result = Get-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')" 39 | if ($result) 40 | { 41 | Write-Host "Project is ready" 42 | break; 43 | } 44 | } 45 | 46 | # ReST request to check out the project 47 | Post-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/checkOut" $null 48 | 49 | # Task parameters as JSON payload 50 | $taskid = [Guid]::NewGuid() 51 | $body = "{ 52 | 'parameters': { 53 | 'Id': '$taskid', 54 | 'Name': 'Task_$taskid', 55 | 'Notes': 'Created from PowerShell using REST API', 56 | 'Start': '2016-01-04T08:00:00', 57 | 'Duration': '5d' 58 | } 59 | }" 60 | 61 | # ReST request to create a task 62 | Post-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/Draft/Tasks/Add" $body 63 | 64 | # Resource parameters as JSON payload 65 | $resourceid = [Guid]::NewGuid() 66 | $body = "{ 67 | 'parameters': { 68 | 'Id': '$resourceid', 69 | 'Name': 'Resource_$resourceid' 70 | } 71 | }" 72 | 73 | # ReST request to create a local resource 74 | Post-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/Draft/ProjectResources/Add" $body 75 | 76 | # Enterprise resource parameters as JSON payload 77 | $enterprise_resourceid = [Guid]::NewGuid() 78 | $body = "{ 79 | 'parameters': { 80 | 'Id': '$enterprise_resourceid', 81 | 'Name': 'EnterpriseResource_$enterprise_resourceid' 82 | } 83 | }" 84 | 85 | # ReST request to create an enterprise resource 86 | Post-ReSTRequest $SiteUrl "ProjectServer/EnterpriseResources/Add" $body 87 | 88 | # ReST request to add an enterprise resource to the project team 89 | Post-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/Draft/ProjectResources/AddEnterpriseResourceById('$enterprise_resourceid')" 90 | 91 | # Assignment parameters as JSON payload 92 | $body = "{ 93 | 'parameters': { 94 | 'ResourceId': '$resourceid', 95 | 'TaskId': '$taskid', 96 | 'Notes': 'Created from PowerShell using REST API' 97 | } 98 | }" 99 | 100 | # ReST request to create an assignment for the local resource 101 | Post-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/Draft/Assignments/Add" $body 102 | 103 | # Assignment parameters as JSON payload 104 | $body = "{ 105 | 'parameters': { 106 | 'ResourceId': '$enterprise_resourceid', 107 | 'TaskId': '$taskid', 108 | 'Notes': 'Created from PowerShell using REST API' 109 | } 110 | }" 111 | 112 | # ReST request to create an assignment for the enterprise resource 113 | Post-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/Draft/Assignments/Add" $body 114 | 115 | # ReST request to publish and check-in the project 116 | Post-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/Draft/publish(true)" $null 117 | -------------------------------------------------------------------------------- /getprojectscsom.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 3 | See LICENSE in the project root for license information. 4 | #> 5 | 6 | 7 | # Get list of projects using CSOM ReST API 8 | param 9 | ( 10 | # SharepointOnline project site collection URL 11 | $SiteUrl = $(throw "SiteUrl parameter is required") 12 | ) 13 | # Load ReST helper methods 14 | . .\ReST.ps1 15 | 16 | # Set up the request authentication 17 | Set-SPOAuthenticationTicket $siteUrl 18 | Set-DigestValue $siteUrl 19 | 20 | # Get list of projects using CSOM ReST API 21 | Get-ReSTRequest $SiteUrl "ProjectServer/Projects" -------------------------------------------------------------------------------- /getprojectsodata.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 3 | See LICENSE in the project root for license information. 4 | #> 5 | 6 | 7 | # Get list of projects using OData ReST API 8 | param 9 | ( 10 | # SharepointOnline project site collection URL 11 | $SiteUrl = $(throw "SiteUrl parameter is required") 12 | ) 13 | # Load ReST helper methods 14 | . .\ReST.ps1 15 | 16 | # Set up the request authentication 17 | Set-SPOAuthenticationTicket $siteUrl 18 | Set-DigestValue $siteUrl 19 | 20 | # Get list of projects using OData ReST API 21 | Get-ReSTRequest $SiteUrl "ProjectData/Projects" -------------------------------------------------------------------------------- /getresources.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 3 | See LICENSE in the project root for license information. 4 | #> 5 | 6 | 7 | # Get list of resources using CSOM ReST API 8 | param 9 | ( 10 | # SharepointOnline project site collection URL 11 | $SiteUrl = $(throw "SiteUrl parameter is required") 12 | ) 13 | # Load ReST helper methods 14 | . .\ReST.ps1 15 | 16 | # Set up the request authentication 17 | Set-SPOAuthenticationTicket $siteUrl 18 | Set-DigestValue $siteUrl 19 | 20 | # Get list of projects using CSOM ReST API 21 | Get-ReSTRequest $SiteUrl "ProjectServer/EnterpriseResources" -------------------------------------------------------------------------------- /getstatusassignments.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 3 | See LICENSE in the project root for license information. 4 | #> 5 | 6 | 7 | # Get list of resources using CSOM ReST API 8 | param 9 | ( 10 | # SharepointOnline project site collection URL 11 | $SiteUrl = $(throw "SiteUrl parameter is required"), 12 | $ResourceId = $(throw "ResourceId paramter is required") 13 | ) 14 | # Load ReST helper methods 15 | . .\ReST.ps1 16 | 17 | # Set up the request authentication 18 | Set-SPOAuthenticationTicket $siteUrl 19 | Set-DigestValue $siteUrl 20 | 21 | # Get list of projects using CSOM ReST API 22 | Get-ReSTRequest $SiteUrl "ProjectServer/EnterpriseResources('$($ResourceId)')/Assignments" -------------------------------------------------------------------------------- /updateproject.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 3 | See LICENSE in the project root for license information. 4 | #> 5 | 6 | 7 | # Updates a Project using ReST API 8 | param 9 | ( 10 | # SharepointOnline project site collection URL 11 | $SiteUrl = $(throw "SiteUrl parameter is required"), 12 | $projectId = $(throw "projectId parameter is required"), 13 | $taskId, 14 | $resourceId, 15 | $assignmentId 16 | ) 17 | # Load ReST helper methods 18 | . .\ReST.ps1 19 | 20 | # Set up the request authentication 21 | Set-SPOAuthenticationTicket $siteUrl 22 | Set-DigestValue $siteUrl 23 | 24 | # ReST request to check out the project 25 | Post-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/checkOut" $null 26 | 27 | # ReST request to update the project description 28 | $body = "{'Description':'Updated from PowerShell using REST API'}" 29 | Patch-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/Draft" $body 30 | 31 | # ReST request to update the task duration 32 | if (-not [String]::IsNullOrEmpty($taskId)) 33 | { 34 | $body = "{'Duration':'10d'}" 35 | Patch-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/Draft/Tasks('$taskId')" $body 36 | } 37 | 38 | # ReST request to update the resource rate 39 | if (-not [String]::IsNullOrEmpty($resourceId)) 40 | { 41 | $body = "{'StandardRate':'100'}" 42 | Patch-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/Draft/ProjectResources('$resourceId')" $body 43 | } 44 | 45 | # ReST request to update the assignment completion percent 46 | if (-not [String]::IsNullOrEmpty($assignmentId)) 47 | { 48 | $body = "{'PercentWorkComplete':'50'}" 49 | Patch-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/Draft/Assignments('$assignmentId')" $body 50 | } 51 | 52 | # ReST request to publish and check-in the project 53 | Post-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/Draft/publish(true)" $null 54 | 55 | -------------------------------------------------------------------------------- /updateprojectcustomfieldvalues.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 3 | See LICENSE in the project root for license information. 4 | #> 5 | 6 | 7 | # Updates a Project Custom field value using ReST API 8 | param 9 | ( 10 | # SharepointOnline project site collection URL 11 | $SiteUrl = $(throw "SiteUrl parameter is required"), 12 | $projectId = $(throw "projectId parameter is required"), 13 | $customFieldId = $(throw "customFieldId parameter is required"), 14 | $lookupEntryId, #use this parameter for custom fields associated with a lookup table 15 | $customFieldValue #use this parameter for non-lookup custom fields 16 | ) 17 | # Load ReST helper methods 18 | . .\ReST.ps1 19 | 20 | # Set up the request authentication 21 | Set-SPOAuthenticationTicket $siteUrl 22 | Set-DigestValue $siteUrl 23 | 24 | # ReST request to check out the project 25 | Post-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/checkOut" $null 26 | 27 | # Set up the request parameters 28 | # ReST request to update the project custom field 29 | $customFieldInternalName = ([xml] (Get-ReSTRequest $siteUrl "ProjectServer/CustomFields('$customFieldId')")).entry.content.properties.InternalName 30 | if (-not [String]::IsNullOrEmpty($lookupEntryId)) 31 | { 32 | $customFieldValue = ([xml] (Get-ReSTRequest $siteUrl "ProjectServer/CustomFields('$customFieldId')/LookupEntries('$lookupEntryId')")).entry.content.properties.InternalName 33 | } 34 | # ReST request to update the project custom field (see http://msdn.microsoft.com/en-us/library/hh642428(v=office.12).aspx for parameter information) 35 | $body = "{'customFieldDictionary':[{'Key':'$customFieldInternalName','Value':'$customFieldValue', 'ValueType':'Edm.String'}]}" 36 | Post-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/Draft/UpdateCustomFields" $body 37 | 38 | # ReST request to publish and check-in the project 39 | Post-ReSTRequest $SiteUrl "ProjectServer/Projects('$projectid')/Draft/publish(true)" $null 40 | 41 | --------------------------------------------------------------------------------