WorkItem/Query/WorkItem_Query.ps1

<#
.SYNOPSIS
Exports a saved work item query to XML.
 
.DESCRIPTION
Work item queries can be exported to XML files (.WIQ extension) in order to be shared and reused. Visual Studio Team Explorer has the ability to open and save WIQ files. Use this cmdlet to generate WIQ files compatible with the format supported by Team Explorer.
 
.PARAMETER Query
Name of the work item query to be exported. Wildcards are supported.
 
.PARAMETER Folder
Full path of the folder containing the query(ies) to be exported. Wildcards are supported.
 
.PARAMETER Destination
Path to the target directory where the exported work item query (WIQL file) will be saved. The original folder structure (as defined in TFS/VSTS) will be preserved.
 
.PARAMETER Encoding
XML encoding of the generated WIQL files. If omitted, defaults to UTF-8.
 
.PARAMETER Collection
Specifies either the name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to. If omitted, it defaults to the connection opened by Connect-TfsTeamProject (if any).
 
For more details, see the Get-TfsTeamProject cmdlet.
 
.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.
 
.INPUTS
Microsoft.TeamFoundation.Client.TfsTeamProjectCollection
System.String
System.Uri
 
.EXAMPLE
Export-TfsWorkItemQuery
.LINK
https://www.visualstudio.com/en-us/docs/work/reference/process-templates/define-work-item-query-process-template
 
.NOTES
For queries made against Team Services, the WIQL length must not exceed 32K characters. The system won't allow you to create or run queries that exceed that length.
#>

Function Export-TfsWorkItemQuery
{
    [CmdletBinding(DefaultParameterSetName='Export to output stream', SupportsShouldProcess=$true)]
    [OutputType('xml')]
    Param
    (
        [Parameter(ValueFromPipeline=$true, Position=0)]
        [SupportsWildcards()]
        [string] 
        $Query = "**/*",

        [Parameter()]
        [ValidateSet('Personal', 'Shared', 'Both')]
        [string]
        $Scope = 'Both',
    
        [Parameter(ParameterSetName="Export to file", Mandatory=$true)]
        [string]
        $Destination,
    
        [Parameter(ParameterSetName="Export to file")]
        [string]
        $Encoding = "UTF-8",
    
        [Parameter(ParameterSetName="Export to file")]
        [switch]
        $FlattenFolders,
    
        [Parameter(ParameterSetName="Export to file")]
        [switch]
        $Force,
    
        [Parameter(ParameterSetName="Export to output stream")]
        [switch]
        $AsXml,
    
        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        if($PSCmdlet.ParameterSetName -eq 'Export to output stream')
        {
            $Encoding = 'UTF-16'
        }
        else
        {
            if (-not (Test-Path $Destination -PathType Container))
            {
                _Log "Destination path '$Destination' not found."

                if ($Force)
                {
                    _Log "-Force switch specified. Creating output directory."

                    if($PSCmdlet.ShouldProcess($Destination, 'Create output directory'))
                    {
                        New-Item $Destination -ItemType Directory | _Log
                    }
                }
                else
                {
                    throw "Invalid output path $Destination"
                }
            }
        }

        $queries = Get-TfsWorkItemQuery -Query $Query -Scope $Scope -Project $Project -Collection $Collection
        
        if (-not $queries)
        {
            throw "No work item queries match the specified `"$Query`" pattern supplied."
        }

        foreach($q in $queries)
        {
            $xml = [xml]@"
<?xml version="1.0" encoding="$Encoding"?>
<!-- Original Query Path: $($q.Path) -->
<WorkItemQuery Version="1">
  <TeamFoundationServer>$($q.Project.Store.TeamProjectCollection.Uri)</TeamFoundationServer>
  <TeamProject>$($q.Project.Name)</TeamProject>
  <Wiql><![CDATA[$($q.QueryText)]]></Wiql>
</WorkItemQuery>
"@

            if (-not $Destination)
            {
                if ($AsXml)
                {
                    Write-Output $xml
                }
                else 
                {
                    Write-Output $xml.OuterXml
                }
                continue
            }

            if ($FlattenFolders)
            {
                $queryPath = $q.Name
            }
            else
            {
                $queryPath = $q.Path.Substring($q.Path.IndexOf('/')+1)
            }

            $fileName = _GetAbsolutePath (Join-Path $Destination "$queryPath.wiql")

            _Log "Exporting query $($q.Name) to path '$fileName'"

            if((Test-Path $fileName) -and (-not $Force))
            {
                throw "File $fileName already exists. To overwrite an existing file, use the -Force switch"
            }

            if($PSCmdlet.ShouldProcess($fileName, "Save query '$($q.Name)'"))
            {
                $xml.Save($fileName)
            }
        }
    }
}
<#
.SYNOPSIS
Gets the definition of one or more work item saved queries.
 
.PARAMETER Query
Specifies the path of a saved query. Wildcards are supported.
 
.PARAMETER Project
Specifies either the name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to. If omitted, it defaults to the connection opened by Connect-TfsTeamProject (if any).
 
For more details, see the Get-TfsTeamProject cmdlet.
 
.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.
 
.INPUTS
Microsoft.TeamFoundation.WorkItemTracking.Client.Project
System.String
#>

Function Get-TfsWorkItemQuery
{
    [CmdletBinding()]
    [OutputType('Microsoft.TeamFoundation.WorkItemTracking.Client.QueryDefinition')]
    Param
    (
        [Parameter(Position=0)]
        [ValidateNotNull()]
        [SupportsWildcards()]
        [Alias("Path")]
        [object]
        $Query = '**/*',

        [Parameter()]
        [ValidateSet('Personal', 'Shared', 'Both')]
        [string]
        $Scope = 'Both',

        [Parameter(ValueFromPipeline=$true)]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

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

        $tp = Get-TfsTeamProject -Project $Project -Collection $Collection
        $qh = $tp.GetQueryHierarchy2($true)
        $qh.GetChildrenAsync().Wait()

        $rootFolders = ($qh.GetChildren() | Where-Object {$Scope -eq 'Both' -or $_.IsPersonal -eq ($Scope -eq 'Personal')})
        
        $rootFolders | _GetQueriesRecursively | Where-Object {($_.Path -like $Query) -or ($_.Name -like $Query) -or ($_.RelativePath -like $Query)} | Sort-Object ParentPath, Name

    }
}
<#
.SYNOPSIS
Gets the definition of one or more work item saved queries.
 
.PARAMETER Query
Specifies the path of a saved query. Wildcards are supported.
 
.PARAMETER Project
Specifies either the name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to. If omitted, it defaults to the connection opened by Connect-TfsTeamProject (if any).
 
For more details, see the Get-TfsTeamProject cmdlet.
 
.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.
 
.INPUTS
Microsoft.TeamFoundation.WorkItemTracking.Client.Project
System.String
#>

Function Get-TfsWorkItemQueryFolder
{
    [CmdletBinding()]
    [OutputType('Microsoft.TeamFoundation.WorkItemTracking.Client.QueryFolder')]
    Param
    (
        [Parameter(Position=0)]
        [ValidateNotNull()]
        [SupportsWildcards()]
        [Alias("Path")]
        [object]
        $Folder = '**/*',

        [Parameter()]
        [ValidateSet('Personal', 'Shared', 'Both')]
        [string]
        $Scope = 'Both',

        [Parameter()]
        [timespan]
        $Timeout = '00:00:10',

        [Parameter(ValueFromPipeline=$true)]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

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

        $tp = Get-TfsTeamProject -Project $Project -Collection $Collection
        $qh = $tp.GetQueryHierarchy2($false)
        $qh.GetChildrenAsync().Wait()

        $qh = $tp.GetQueryHierarchy2($true)
        $qh.GetChildrenAsync().Wait()

        $rootFolders = ($qh.GetChildren() | Where-Object {$Scope -eq 'Both' -or $_.IsPersonal -eq ($Scope -eq 'Personal')})
        
        $rootFolders | _GetQueryFoldersRecursively | Where-Object {($_.Path -like $Folder) -or ($_.Name -like $Folder)} | Sort-Object ParentPath, Name
    }
}
<#
.SYNOPSIS
Create a new work items query in the given Team Project.
 
.PARAMETER Query
Specifies the path of the new work item query.
When supplying a path, use a slash ("/") between the path segments. Leading and trailing slashes are optional. The last segment in the path will be the query name.
 
.PARAMETER Project
Specifies either the name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to. If omitted, it defaults to the connection opened by Connect-TfsTeamProject (if any).
 
For more details, see the Get-TfsTeamProject cmdlet.
 
.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.
 
.INPUTS
System.String
#>

Function New-TfsWorkItemQuery
{
    [CmdletBinding(ConfirmImpact='Medium', SupportsShouldProcess=$true)]
    [OutputType('Microsoft.TeamFoundation.WorkItemTracking.Client.QueryDefinition')]
    Param
    (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
        [Alias("Name")]
        [Alias("Path")]
        [string]
        $Query,

        [Parameter()]
        [string]
        $Folder,

        [Parameter()]
        [ValidateSet('Personal', 'Shared')]
        [string]
        $Scope = 'Personal',

        [Parameter(Mandatory=$true)]
        [string]
        $Definition,

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection,

        [Parameter()]
        [switch]
        $Force,

        [Parameter()]
        [switch]
        $SkipSave,

        [Parameter()]
        [switch]
        $Passthru
    )

    Begin
    {
        _RegisterQueryHelper
    }

    Process
    {
        $tp = Get-TfsTeamProject -Project $Project -Collection $Collection
        $qh = $tp.GetQueryHierarchy2($true)
        $qh.GetChildrenAsync().Wait()

        $rootFolder = ($qh.GetChildren() | Where-Object IsPersonal -eq ($Scope -eq 'Personal'))
        $fullPath = _NormalizeQueryPath -Path "$Folder/$Query" -RootFolder $rootFolder.Name -ProjectName $tp.Name
        $queryPath = $fullPath.Substring(0, $fullPath.LastIndexOf('/'))
        $queryName = $fullPath.Substring($fullPath.LastIndexOf('/')+1)
        $relativeQueryPath = $fullPath.Substring($rootFolder.Name.Length + $tp.Name.Length + 2)
        $relativeFolderPath = $queryPath.Substring($rootFolder.Name.Length + $tp.Name.Length + 2)

        if (-not $PSCmdlet.ShouldProcess($queryName, "Create work item query under folder '$queryPath'"))
        {
            return
        }

        _Log "New-TfsWorkItemQuery: Check if query '$relativeQueryPath' exists"

        $existingQuery = Get-TfsWorkItemQuery -Query $relativeQueryPath -Scope $Scope -Project $Project -Collection $Collection

        if ($existingQuery)
        {
            if (-not $Force)
            {
                throw "Work item query '$fullPath' already exists. To overwrite an existing query, use the -Force switch"
            }

            _Log "New-TfsWorkItemQuery: Existing query '$fullPath' will be overwritten"

            $existingQuery.Delete()
            $existingQuery.Save()
        }

        _Log "New-TfsWorkItemQuery: Creating query '$queryName' in folder '$queryPath'"

        $queryFolder = Get-TfsWorkItemQueryFolder -Folder $relativeFolderPath -Scope $Scope -Project $Project -Collection $Collection

        if (-not $queryFolder)
        {
            _Log "New-TfsWorkItemQuery: Destination folder $queryFolder not found"

            if ($Force)
            {
                _Log "New-TfsWorkItemQuery: -Force switch specified. Creating missing folder"
                $queryFolder = New-TfsWorkItemQueryFolder -Path $queryPath -Project $tp.Name -Passthru
            }
            else
            {
                throw "Invalid or non-existent work item query folder $queryPath."
            }
        }

        if ($Definition -match "select \*")
        {
            Write-Warning "New-TfsWorkItemQuery: Queries containing 'SELECT *' may not work in Visual Studio. Consider replacing * with a list of fields."
        }

        $q = New-Object 'Microsoft.TeamFoundation.WorkItemTracking.Client.QueryDefinition2' -ArgumentList $queryName, $Definition, $queryFolder

        if (-not $SkipSave)
        {
            $q.Save()
        }
        else
        {
            _Log "New-TfsWorkItemQuery: -SkipSave switch specified. Newly created query will not be saved."
        }

        if ($Passthru -or $SkipSave)
        {
            return $q
        }
    }
}
<#
.SYNOPSIS
    Create a new work items query in the given Team Project.
 
.PARAMETER Path
    Specifies the path of the new work item query folder.
    When supplying a path, use a slash ("/") between the path segments. Leading and trailing backslashes are optional. The last segment in the path will be the query name.
 
.PARAMETER Project
    Specifies either the name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to. If omitted, it defaults to the connection opened by Connect-TfsTeamProject (if any).
 
For more details, see the Get-TfsTeamProject cmdlet.
 
.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.
 
.INPUTS
    System.String
#>

Function New-TfsWorkItemQueryFolder
{
    [CmdletBinding(ConfirmImpact='Medium', SupportsShouldProcess=$true)]
    [OutputType('Microsoft.TeamFoundation.WorkItemTracking.Client.QueryDefinition')]
    Param
    (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
        [string]
        [Alias("Name")]
        [Alias("Path")]
        $Folder,

        [Parameter()]
        [ValidateSet('Personal', 'Shared')]
        [string]
        $Scope = 'Personal',

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection,

        [switch]
        $Passthru
    )

    Begin
    {
        _RegisterQueryHelper
    }

    Process
    {
        if($PSCmdlet.ShouldProcess($Folder, 'Create work item query folder'))
        {
            $tp = Get-TfsTeamProject -Project $Project -Collection $Collection
            #$tpc = $tp.Store.TeamProjectCollection
            #$store = $tp.Store

            if ($Scope -eq 'Shared')
            {
                $rootFolder = 'Shared Queries'
            }
            else
            {
                $rootFolder = 'My Queries'
            }

            $normalizedPath = _NormalizeQueryPath -Path $Folder -RootFolder $rootFolder -ProjectName $tp.Name

            _Log "New-TfsWorkItemQueryFolder: Creating folder '$Folder'"

            $queryFolder = [TfsCmdlets.QueryHelper]::CreateFolder($tp.QueryHierarchy, $normalizedPath)

            if ($Passthru)
            {
                return $queryFolder
            }
        }
    }
}
<#
.SYNOPSIS
    Deletes one or more work item queries from the specified Team Project..
 
.PARAMETER Query
    Specifies the path of a saved query. Wildcards are supported.
 
.PARAMETER Project
    Specifies either the name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to. If omitted, it defaults to the connection opened by Connect-TfsTeamProject (if any).
 
For more details, see the Get-TfsTeamProject cmdlet.
 
.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.
 
.INPUTS
    Microsoft.TeamFoundation.WorkItemTracking.Client.Project
    System.String
#>

Function Remove-TfsWorkItemQuery
{
    [CmdletBinding(ConfirmImpact='High', SupportsShouldProcess=$true)]
    Param
    (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
        [Alias("Path")]
        [ValidateNotNull()] 
        [object]
        $Query,

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        $queries = Get-TfsWorkItemQuery -Query $Query -Project $Project -Collection $Collection

        foreach($q in $queries)
        {
            if ($PSCmdlet.ShouldProcess($q.Path, "Delete Query"))
            {
                $q.Delete()
            }
        }
    }
}
<#
.SYNOPSIS
    Deletes one or more work item queries from the specified Team Project..
 
.PARAMETER Query
    Specifies the path of a saved query. Wildcards are supported.
 
.PARAMETER Project
    Specifies either the name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to. If omitted, it defaults to the connection opened by Connect-TfsTeamProject (if any).
 
For more details, see the Get-TfsTeamProject cmdlet.
 
.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.
 
.INPUTS
    Microsoft.TeamFoundation.WorkItemTracking.Client.Project
    System.String
#>

Function Remove-TfsWorkItemQueryFolder
{
    [CmdletBinding(ConfirmImpact='High', SupportsShouldProcess=$true)]
    Param
    (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
        [Alias("Path")]
        [ValidateNotNull()] 
        [object]
        $Folder,

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [switch]
        $Force,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        $folder = Get-TfsWorkItemQueryFolder -Folder $Folder -Project $Project -Collection $Collection

        if (($folder.Count -ne 0) -and (-not $Force))
        {
            throw "Folder is not empty. To delete a folder and its contents, use the -Force switch"
        }

        if ($PSCmdlet.ShouldProcess($folder, "Delete work item query folder"))
        {
            $folder.Delete()
            $folder.Project.Hierarchy.Save()
        }
    }
}
<#
 
.SYNOPSIS
    Changes the value of a property of an Area.
 
.PARAMETER Area
    Specifies the name, URI or path of an Area. Wildcards are permitted. If omitted, all Areas in the given Team Project are returned.
To supply a path, use a backslash ('\') between the path segments. Leading and trailing backslashes are optional.
When supplying a URI, use URIs in the form of 'vstfs:///Classification/Node/<GUID>' (where <GUID> is the unique identifier of the given node)
 
.PARAMETER NewName
    Specifies the new name of the area. Enter only a name, not a path and name. If you enter a path that is different from the path that is specified in the area parameter, Rename-Tfsarea generates an error. To rename and move an item, use the Move-Tfsarea cmdlet.
 
.PARAMETER Project
    Specifies either the name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to. If omitted, it defaults to the connection opened by Connect-TfsTeamProject (if any).
 
For more details, see the Get-TfsTeamProject cmdlet.
 
.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.
 
.INPUTS
    Microsoft.TeamFoundation.WorkItemTracking.Client.Project
    System.String
#>

Function Rename-TfsWorkItemQuery
{
    [CmdletBinding(ConfirmImpact='Medium')]
    [OutputType('Microsoft.TeamFoundation.WorkItemTracking.Client.QueryDefinition')]
    Param
    (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
        [ValidateNotNull()] 
        [Alias("Path")]
        [object]
        $Query,

        [Parameter()]
        [string]
        $NewName,

        [Parameter()]
        [string]
        $Definition,

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection,

        [Parameter()]
        [switch]
        $Passthru
    )

    Process
    {
        $result = Set-TfsWorkItemQuery -Query $Query -NewName $NewName -Project $Project -Collection $Collection -Passthru:$Passthru.IsPresent

        if ($Passthru)
        {
            return $result
        }
    }
}
<#
 
.SYNOPSIS
    Changes the value of a property of a work item query.
 
.PARAMETER Query
    Specifies the path of a work item saved query.
 
.PARAMETER NewName
    Specifies the new name of the query. Enter only a name, not a path and name. If you enter a path that is different from the path that is specified in the area parameter, Rename-TfsWorkItemQuery generates an error. To rename and move an item, use the Move-TfsWorkItemQuery cmdlet instead.
 
.PARAMETER Project
    Specifies either the name of the Team Project or a previously initialized Microsoft.TeamFoundation.WorkItemTracking.Client.Project object to connect to. If omitted, it defaults to the connection opened by Connect-TfsTeamProject (if any).
 
For more details, see the Get-TfsTeamProject cmdlet.
 
.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.
 
.INPUTS
    Microsoft.TeamFoundation.WorkItemTracking.Client.QueryDefinition
    System.String
#>

Function Set-TfsWorkItemQuery
{
    [CmdletBinding(ConfirmImpact='Medium', SupportsShouldProcess=$true)]
    [OutputType('Microsoft.TeamFoundation.WorkItemTracking.Client.QueryDefinition')]
    Param
    (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true)]
        [ValidateNotNull()] 
        [Alias("Path")]
        [object]
        $Query,

        [Parameter()]
        [string]
        $NewName,

        [Parameter()]
        [string]
        $Definition,

        [Parameter()]
        [object]
        $Project,

        [Parameter()]
        [object]
        $Collection
    )

    Process
    {
        $q = Get-TfsWorkItemQuery -Query $Query -Project $Project -Collection $Collection

        if (-not $q)
        {
            throw "Invalid or non-existent work item query $queries"
        }

        if ($q.Count -ne 1)
        {
            throw "Ambiguous query name '$Query'. $($q.Count) queries were found matching the specified name/pattern:`n`n - " + ($q -join "`n - ")
        }

        if ($NewName -and $PSCmdlet.ShouldProcess($Query, "Rename work item query to '$NewName'"))
        {
            isDirty = $true
            $q.Name = $NewName
        }

        if ($Definition -and $PSCmdlet.ShouldProcess($Query, "Change work item query definition to '$Definition'"))
        {
            isDirty = $true
            $q.QueryText = $Definition
        }

        if ($isDirty)
        {
            $q.Project.QueryHierarchy.Save()
        }

        return $q
    }
}
Function _NormalizeQueryPath($Path, $RootFolder, $ProjectName)
{
    if([string]::IsNullOrWhiteSpace($Path))
    {
        return [string]::Empty
    }

    $newPath = [System.Text.RegularExpressions.Regex]::Replace($Path, '\\+|/{2,}', '/')

    if ($newPath.StartsWith("/"))
    {
        $newPath = $newPath.Substring(1)
    }

    if ($newPath.EndsWith('/'))
    {
        $newPath = $newPath.Substring(0, $newPath.Length-1)
    }

    $pattern = "($ProjectName/)?($RootFolder/)?(.+)"
    $match = [regex]::Match($newPath, $pattern)

    return "$ProjectName/$RootFolder/$($match.Groups[$match.Groups.Count-1])"
}

Function _RegisterQueryHelper()
{
    if (([System.Management.Automation.PSTypeName]'TfsCmdlets.QueryHelper').Type)
    {
        return
    }

    Add-Type -Language CSharp -ReferencedAssemblies 'Microsoft.TeamFoundation.WorkItemTracking.Client' `
        -TypeDefinition @'
${File:CSharp\QueryHelper.cs}
'@

}

Function _GetQueryFoldersRecursively
{
    Param
    (
        [Parameter(ValueFromPipeline=$true)]
        [Microsoft.TeamFoundation.WorkItemTracking.Client.QueryFolder2]
        $Folder
    )
    
    Process
    {
        $Folder.GetChildrenAsync().Wait()

        $Folder.GetChildren() | Where-Object {$_ -Is [Microsoft.TeamFoundation.WorkItemTracking.Client.QueryFolder2]} | ForEach-Object {
            Write-Output $_
            _GetQueryFoldersRecursively $_
        }
    }
}

Function _GetQueriesRecursively
{
    Param
    (
        [Parameter(ValueFromPipeline=$true)]
        [Microsoft.TeamFoundation.WorkItemTracking.Client.QueryFolder2]
        $Folder
    )
    
    Process
    {
        $Folder.GetChildrenAsync().Wait()

        foreach($i in $Folder.GetChildren())
        {
            if ($i -is [Microsoft.TeamFoundation.WorkItemTracking.Client.QueryFolder2])
            {
                _GetQueriesRecursively $i
            }
            else
            {
                Write-Output $i
            }
        }
    }
}