Hace tiempo escribí un post en mi blog acerca de cómo generar campos personalizados de empresa mediante el api CSOM de Powershell. Progresando en esta misma idea, he empezado a generar un fichero .psm1 en el que ir desarrollando diferentes funciones que permitan realizar todas las operaciones CRUD sobre los diferentes tipos de objetos de Project Server / Online.

Por el momento, la librería tiene una función para crear los campos personalizados a través de la información que se reciba como parámetro de entrada:

PowerShell
Editar script|Remove
function Create-CustomField{ 
    Param( 
            [parameter(Mandatory=$true)]$projContext,  
            [parameter(Mandatory=$true)]$Id, 
            [parameter(Mandatory=$true)]$Name, 
            [parameter(Mandatory=$false)]$Description, 
            [parameter(Mandatory=$true)]$FieldType, 
            [parameter(Mandatory=$true)]$EntityType, 
            [parameter(Mandatory=$false)]$LookupTable, 
            [parameter(Mandatory=$true)]$IsWorkflowControlled, 
            [parameter(Mandatory=$true)]$IsRequired, 
            [parameter(Mandatory=$false)]$IsEditableInVisibility, 
            [parameter(Mandatory=$false)]$IsMultilineText 
 
    ) 
 
    [Microsoft.ProjectServer.Client.CustomFieldCreationInformation]$customFieldInfo = New-Object Microsoft.ProjectServer.Client.CustomFieldCreationInformation; 
    #Mandatory fields 
    $customFieldInfo.Id = $Id 
    $customFieldInfo.Name = $Name 
    $customFieldInfo.FieldType = $FieldType 
    $customFieldInfo.EntityType = $EntityType 
    $customFieldInfo.IsWorkflowControlled = $IsWorkflowControlled 
    $customFieldInfo.IsRequired = $IsRequired 
 
    #Non Mandatory fields 
    if($Description -ne $null) 
    { 
        $customFieldInfo.Description = $Description 
    } 
 
    if($IsEditableInVisibility -ne $null) 
    { 
        $customFieldInfo.IsEditableInVisibility = $IsEditableInVisibility 
    } 
 
    if($IsMultilineText -ne $null) 
    { 
        $customFieldInfo.IsMultilineText = $IsMultilineText 
    } 
 
    if($LookupTable -ne $null) 
    { 
        $customFieldInfo.LookupTable = $LookupTable 
    } 
     
    $newCustomField = $projContext.CustomFields.Add($customFieldInfo); 
    $projContext.CustomFields.Update() 
    $projContext.ExecuteQuery() 
}
 La llamada se realizaría desde un fichero .ps1 parecido a este, tiene comentarios que explican las llamadas paso a paso:
PowerShell
Editar script|Remove
#Add in libraries 
#Project CSOM 
Add-Type -Path 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.ProjectServer.Client.dll' 
#add SharePoint Online DLL 
Add-Type -Path 'C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll' 
 
Import-Module .\Functions.psm1 
 
$PWAInstanceURL = "http://yourpwainstance" 
$PWAUserName = "domain\administradoruser 
 
Host -AsSecureString "what is the source pwa password?" 
 
$projContext = New-Object Microsoft.ProjectServer.Client.ProjectContext($PWAInstanceURL#[Microsoft.SharePoint.Client.SharePointOnlineCredentials]$spocreds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($PWAUserName, $PWAUserPassword); 
[System.Net.NetworkCredential]$spocreds = New-Object System.Net.NetworkCredential($PWAUserName$PWAUserPassword); 
$projContext.Credentials = $spocreds 
$projContext.Load($projContext.CustomFields) 
 
[Microsoft.ProjectServer.Client.EntityTypes] $entityTypes = $projContext.EntityTypes 
$projContext.Load($entityTypes) 
 
$projContext.ExecuteQuery() 
 
$myFieldType = [Microsoft.ProjectServer.Client.CustomFieldType]::TEXT 
$Id = "0000783f-de84-434b-9564-284e5b7b3f44" #create a new GUID for the new field 
 
 Create-CustomField -projContext $projContext -Id $Id -Name "Nuevo Campo" -FieldType $myFieldType -EntityType $entityTypes.ProjectEntity -IsWorkflowControlled $true -IsRequired $false -IsMultilineText $true