TeamProject/TeamProject.psm1

<#
.SYNOPSIS
    Gets information about one or more team projects.
 
.DESCRIPTION
    The Get-TfsTeamProject cmdlets gets one or more Team Project objects (an instance of Microsoft.TeamFoundation.WorkItemTracking.Client.Project) from the supplied Team Project Collection.
 
.PARAMETER Project
    Specifies the name of a Team Project. Wildcards are supported.
 
.PARAMETER Collection
    Specifies either a URL/name of the Team Project Collection to connect to, or a previously initialized TfsTeamProjectCollection object.

When using a URL, it must be fully qualified. The format of this string is as follows:

http[s]://<ComputerName>:<Port>/[<TFS-vDir>/]<CollectionName>

Valid values for the Transport segment of the URI are HTTP and HTTPS. If you specify a connection URI with a Transport segment, but do not specify a port, the session is created with standards ports: 80 for HTTP and 443 for HTTPS.

To connect to a Team Project Collection by using its name, a TfsConfigurationServer object must be supplied either via -Server argument or via a previous call to the Connect-TfsConfigurationServer cmdlet.

For more details, see the Get-TfsTeamProjectCollection cmdlet.
 
.PARAMETER Server
    Specifies either a URL or the name of the Team Foundation Server configuration server (the "root" of a TFS installation) to connect to, or a previously initialized Microsoft.TeamFoundation.Client.TfsConfigurationServer object.
    For more details, see the -Server argument in the Get-TfsTeamProjectCollection cmdlet.
 
.PARAMETER Credential
    Specifies a user account that has permission to perform this action. The default is the cached credential of the user under which the PowerShell process is being run - in most cases that corresponds to the user currently logged in. To provide a user name and password, and/or to open a input dialog to enter your credentials, call Get-TfsCredential with the appropriate arguments and pass its return to this argument. For more information, refer to https://msdn.microsoft.com/en-us/library/microsoft.teamfoundation.client.tfsclientcredentials.aspx
 
.INPUTS
    Microsoft.TeamFoundation.Client.TfsTeamProjectCollection
    System.String
    System.Uri
 
.NOTES
    As with most cmdlets in the TfsCmdlets module, this cmdlet requires a TfsTeamProjectCollection object to be provided via the -Collection argument. If absent, it will default to the connection opened by Connect-TfsTeamProjectCollection.
 
#>

Function Get-TfsTeamProject
{
    [CmdletBinding(DefaultParameterSetName='Get by project')]
    [OutputType([Microsoft.TeamFoundation.WorkItemTracking.Client.Project])]
    Param
    (
        [Parameter(Position=0, ParameterSetName='Get by project')]
        [object] 
        $Project = '*',

        [Parameter(ValueFromPipeline=$true, Position=1, ParameterSetName='Get by project')]
        [object]
        $Collection,

        [Parameter(Position=0, ParameterSetName="Get current")]
        [switch]
        $Current,

        [Parameter()]
        [object]
        $Credential
    )

    Process
    {
        if ($Current)
        {
            return $global:TfsProjectConnection
        }

        if ($Project -is [Microsoft.TeamFoundation.WorkItemTracking.Client.Project])
        {
            return $Project
        }

        if (($Project -is [uri]) -or ([System.Uri]::IsWellFormedUriString($Project, [System.UriKind]::Absolute)))
        {
            $tpc = Get-TfsTeamProjectCollection $Collection -Credential $Credential
            $css = $tpc.GetService([type]'Microsoft.TeamFoundation.Server.ICommonStructureService')

            $projInfo = $css.GetProject([string] $Project)
            $Project = $projInfo.Name
        }

        if ($Project -is [string])
        {
            $tpc = Get-TfsTeamProjectCollection $Collection -Credential $Credential
            $wiStore = $tpc.GetService([type]'Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemStore')

            return _GetAllProjects $tpc | ? Name -Like $Project | % { $wiStore.Projects[$_.Name] }
        }

        if ($Project -eq $null)
        {
            if ($global:TfsProjectConnection)
            {
                return $global:TfsProjectConnection
            }
        }

        throw "No TFS team project information available. Either supply a valid -Project argument or use Connect-TfsTeamProject prior to invoking this cmdlet."
    }
}

Function _GetAllProjects
{
    param ($tpc)

    $css = $tpc.GetService([type]'Microsoft.TeamFoundation.Server.ICommonStructureService')

    return $css.ListAllProjects() | ? Status -eq WellFormed
}
<#
.SYNOPSIS
    Creates a new team project.
 
#>

Function New-TfsTeamProject
{
    [CmdletBinding(DefaultParameterSetName='Get by project')]
    [OutputType([Microsoft.TeamFoundation.WorkItemTracking.Client.Project])]
    Param
    (
        [Parameter(Position=0, Mandatory=$true)]
        [string] 
        $Project,

        [Parameter(ValueFromPipeline=$true, Position=1)]
        [object]
        $Collection,

        [string]
        $Description,

        [string]
        [ValidateSet('Git', 'TFVC')]
        $SourceControl,

        [object]
        $ProcessTemplate
    )

    Process
    {
        $tpc = Get-TfsTeamProjectCollection $Collection
        $template = Get-TfsProcessTemplate -Collection $tpc -Name $ProcessTemplate
        $client = Get-TfsHttpClient 'Microsoft.TeamFoundation.Core.WebApi.ProjectHttpClient' -Collection $tpc

        $tpInfo = New-Object 'Microsoft.TeamFoundation.Core.WebApi.TeamProject'
        $tpInfo.Name = $Project
        $tpInfo.Description = $Description
        $tpInfo.Capabilities = New-Object 'System.Collections.Generic.Dictionary[[string],System.Collections.Generic.Dictionary[[string],[string]]]'

        $tpInfo.Capabilities.Add('versioncontrol', (New-Object 'System.Collections.Generic.Dictionary[[string],[string]]'))
        $tpInfo.Capabilities['versioncontrol'].Add('sourceControlType', $SourceControl)

        $tpInfo.Capabilities.Add('processTemplate', (New-Object 'System.Collections.Generic.Dictionary[[string],[string]]'))
        $tpInfo.Capabilities['processTemplate'].Add('templateTypeId', ([xml]$template.Metadata).metadata.version.type)


        # Trigger the project creation

        $token = $client.QueueCreateProject($tpInfo).Result

        if (-not $token)
        {
            throw "Error queueing team project creation: $($client.LastResponseContext.Exception.Message)"
        }

        # Wait for the operation to complete

        $operationsClient = Get-TfsHttpClient 'Microsoft.VisualStudio.Services.Operations.OperationsHttpClient' -Collection $tpc

        $opsToken = $operationsClient.GetOperation($token.Id).Result

        while (
            ($opsToken.Status -ne [Microsoft.VisualStudio.Services.Operations.OperationStatus]::Succeeded) -and
            ($opsToken.Status -ne [Microsoft.VisualStudio.Services.Operations.OperationStatus]::Failed) -and 
            ($opsToken.Status -ne [Microsoft.VisualStudio.Services.Operations.OperationStatus]::Cancelled))
        {
            Start-Sleep -Seconds 2
            $opsToken = $operationsClient.GetOperation($token.Id).Result
        }

        if ($opsToken.Status -ne [Microsoft.VisualStudio.Services.Operations.OperationStatus]::Succeeded)
        {
            throw "Error creating team project $Project"
        }

        # Force a metadata cache refresh prior to retrieving the newly created project

        $wiStore = $tpc.GetService([type]'Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemStore')
        $wiStore.RefreshCache()

        return Get-TfsTeamProject -Project $Project -Collection $Collection
    }
}