我使用 GO 为我们的持续交付项目做这件事。我将 PowerShell 和 .NET 程序集提供程序与 Team Explorer 结合使用。我无法让它纯粹在 PowerShell 中工作(尽管可能有办法!)
以下脚本会将作为参数提供的材料路径中包含的任何内容检入指定的服务器路径(也是一个参数)。您还可以指定要使用的凭据和 TFS 服务器的 url。
此代码需要安装 Visual Studio 或 TFS Team Explorer 客户端。您需要在 AssemblyPath 参数中向脚本提供程序集的目录位置。如果未找到这些程序集,则脚本将出错并显示缺少哪些程序集。
注意:代码已经有一段时间没有检查过了,所以可能有错别字等。如果您有任何问题,请告诉我,我会尽力提供帮助。
[CmdletBinding(PositionalBinding=$false)]
Param(
[Parameter(Mandatory)] [string] $ServerUrl,
[Parameter(Mandatory)] [string] $ServerPath,
[Parameter(Mandatory=$False)] [string] $Domain = "",
[Parameter(Mandatory=$False)] [string] $Username = "",
[Parameter(Mandatory=$False)] [System.Security.SecureString] $Password,
[Parameter(Mandatory)] [string] [ValidateScript({($_ -eq $null) -or (Test-Path -Path $_ -PathType Container)})] $MaterialPath,
[Parameter(Mandatory)] [string] [ValidateScript({ Test-Path -Path $_ -PathType Container})] $AssemblyPath
)
<#
.SYNOPSIS
Responsible for checking in files into Source Control
.DESCRIPTION
#>
$clientDllName = "Microsoft.TeamFoundation.Client.dll"
$commonDllName = "Microsoft.TeamFoundation.Common.dll"
$versionControlClientDllName = "Microsoft.TeamFoundation.VersionControl.Client.dll"
$versionControlClientCommonDllName = "Microsoft.TeamFoundation.VersionControl.Common.dll"
#Create global variables to hold the value of Debug and Verbose action preferences which can then be used for all module function calls and passed into the remote session.
$verboseParameter = $PSCmdlet.MyInvocation.BoundParameters["Verbose"]
if ($verboseParameter -ne $null)
{
$Global:Verbose = [bool]$verboseParameter.IsPresent
}
else
{
$Global:Verbose = $false
}
$debugParameter = $PSCmdlet.MyInvocation.BoundParameters["Debug"]
if ($debugParameter -ne $null)
{
$Global:Debug = [bool]$debugParameter.IsPresent
}
else
{
$Global:Debug = $false
}
$scriptName = $(Split-Path -Leaf $PSCommandPath)
#Ensure any errors cause failure
$ErrorActionPreference = "Stop"
Write-Host "Running script ""$scriptName"" as user ""$env:USERDOMAIN\$env:USERNAME"""
#Check assembly path is a valid directory
If (Test-Path -Path $AssemblyPath -PathType Container)
{
Write-Host "Loading required assemblies from assembly path ""$AssemblyPath"""
$clientDllPath = Join-Path -Path $AssemblyPath -ChildPath $clientDllName
$commonDllPath = Join-Path -Path $AssemblyPath -ChildPath $commonDllName
$versionControlClientDllPath = Join-Path -Path $AssemblyPath -ChildPath $versionControlClientDllName
$versionControlClientCommonDllPath = Join-Path -Path $AssemblyPath -ChildPath $versionControlClientCommonDllName
If (!Test-Path -Path $clientDllPath -PathType Leaf)
{
Throw "Required assembly ""$clientDllName"" not found at path ""$clientDllPath"""
}
If (!Test-Path -Path $commonDllPath -PathType Leaf)
{
Throw "Required assembly ""$commonDllName"" not found at path ""$commonDllPath"""
}
If (!Test-Path -Path $versionControlClientDllPath -PathType Leaf)
{
Throw "Required assembly ""$versionControlClientDllName"" not found at path ""$versionControlClientDllPath"""
}
If (!Test-Path -Path $versionControlClientCommonDllPath -PathType Leaf)
{
Throw "Required assembly ""$versionControlClientCommonDllName"" not found at path ""$versionControlClientCommonDllPath"""
}
#Load the Assemblies
[Reflection.Assembly]::LoadFrom($clientDllPath) | Out-Null
[Reflection.Assembly]::LoadFrom($commonDllPath)| Out-Null
[Reflection.Assembly]::LoadFrom($versionControlClientDllPath) | Out-Null
[Reflection.Assembly]::LoadFrom($versionControlClientCommonDllPath) | Out-Null
#If the credentials have been specified then create a credential object otherwise we will use the default ones
If ($Username -and $Password)
{
$creds = New-Object System.Net.NetworkCredential($Username,$Password,$Domain)
Write-Host "Created credential object for user ""$($creds.UserName)"" in domain ""$($creds.Domain)"""
$tfsProjectCollection = New-Object Microsoft.TeamFoundation.Client.TFSTeamProjectCollection($ServerUrl, $creds)
}
else
{
Write-Host "Using default credentials for user ""$Env:Username"""
$tfsProjectCollection = New-Object Microsoft.TeamFoundation.Client.TFSTeamProjectCollection($ServerUrl)
}
$versionControlType = [Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer]
$versionControlServer = $tfsProjectCollection.GetService($versionControlType)
Write-Host "Version control server authenticated user: $($versionControlServer.AuthenticatedUser)"
#Create a local path in the temp directory to hold the workspace
$LocalPath = Join-Path -Path $env:TEMP -ChildPath $([System.Guid]::NewGuid().ToString())
$null = New-Item -Path $LocalPath -ItemType Directory
#Create a "workspace" and map a local folder to a TFS location
$workspaceName = "PowerShell Workspace_{0}" -f [System.Guid]::NewGuid().ToString()
$workspace = $versionControlServer.CreateWorkspace($workspaceName, $versionControlServer.AuthenticatedUser)
$workingfolder = New-Object Microsoft.TeamFoundation.VersionControl.Client.WorkingFolder($ServerPath,$LocalPath)
$result = $workspace.CreateMapping($workingFolder)
$result = $workspace.Get() #Get the latest version into the workspace
Write-Host "Copying files from materials path ""$MaterialPath"" to temporary workspace path ""$LocalPath"""
robocopy $MaterialPath $LocalPath /s | Out-Null
$checkInComments = "Files automatically checked in by PowerShell script ""$scriptName"""
#Submit file as a Pending Change and submit the change
$result = $workspace.PendAdd($LocalPath,$true)
$pendingChanges = $workspace.GetPendingChanges()
Write-Host "Getting pending changes"
#Only try to check in if there are changes
If ($pendingChanges -ne $null)
{
If ($pendingChanges.Count -gt 0)
{
$changeSetId = $workspace.CheckIn($pendingChanges,$checkInComments)
Write-Host "Successfully checked in ""$($pendingChanges.Count)"" changes using changeset id ""$changeSetId"""
}
else
{
Write-Host "No changes to check-in"
}
}
else
{
Write-Host "No changes to check-in"
}
Write-Host "Deleting workspace and temporary folders"
$result = $workspace.Delete()
$null = Remove-Item -Path $LocalPath -Recurse -Force
}
else
{
Write-Error "The path to required assemblies ""$AssemblyPath"" cannot be found"
}