I have a PS script which downloads the latest code from TFS on my local machine but I want it to download a specific labelled code instead of latest.
Below is the script which downloads the latest code present in TFS,
$sourceLocation = "http://vwmaztfsapp:8080/tfs/MatchCollection"
$tfsCollectionUrl = New-Object System.URI($sourceLocation);
$serverPath = "$/Match Web/Installscript Projects/Utility Scripts"
#It gets copied at local path with the above folder sequence
$localPath = "C:\"
$visualStudiopath = 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer'
Add-Type -Path "$visualStudiopath\Microsoft.TeamFoundation.VersionControl.Client.dll"
Add-Type -Path "$visualStudiopath\Microsoft.TeamFoundation.Common.dll"
Add-Type -Path "$visualStudiopath\Microsoft.TeamFoundation.WorkItemTracking.Client.dll"
Add-Type -Path "$visualStudiopath\Microsoft.TeamFoundation.Client.dll"
Add-type -path "$visualStudiopath\Microsoft.TeamFoundation.ProjectManagement.dll"
Add-Type -Path "$visualStudiopath\Microsoft.TeamFoundation.Build.Common.dll"
$tfsCollection = New-Object -TypeName Microsoft.TeamFoundation.Client.TfsTeamProjectCollection -ArgumentList $tfsCollectionUrl
$VersionControl = $tfsCollection.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
$latest = [Microsoft.TeamFoundation.VersionControl.Client.VersionSpec]::Latest
$recursionType = [Microsoft.TeamFoundation.VersionControl.Client.RecursionType]::Full
try
{
foreach ($item in $VersionControl.GetItems($serverPath, $latest,$recursionType).Items)
{
$target = [io.path]::Combine($localPath,$item.ServerItem.Substring(2))
$exists=[System.IO.Directory]::Exists($target)
if($item.ItemType -eq "Folder" -and !$exists)
{
New-Item $target -Type Directory
}
if($item.ItemType -eq "File")
{
$item.DownloadFile($target)
}
}
Write-Host "`n Successfully downloaded all the files to the target folder: " $localPath -ForegroundColor Green
}
catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Break
}
I tried using the Microsoft.TeamFoundation.VersionControl.Client.LabelVersionSpec but was not successful.
Can anyone please guide me to the correct link or script by which I can download the "$/Match Web" code using the label which I had applied on it. This is the label which I had applied on "$/Match Web" branch for e.g. - "PreBuildLabel-MatchEnterpriseBuild1"
#Assael Azran, getting below result in $vs
Try this (works for me):
$vs = New-Object Microsoft.TeamFoundation.VersionControl.Client.LabelVersionSpec($label, $scope);
foreach ($item in $VersionControl.GetItems($serverPath, $vs,$recursionType).Items)
{
.....
}
$label - name of your label
$scope - The scope (project) of the label. To verify that through VisualStudio, navigate to File-> Source control-> Find-> Find Label.
In the "Find Label" form find your label and open it, then you will see the project name (the one under the collection), you can use it as the scope.
LabelVersionSpec Constructor
UPDATE
Upon request of #SRP, this is how you should create a branch from a TFS label:
$vcs = $server.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer]);
$changesetId = $vcs.CreateBranch($sourceBranch, $destBranch,$vs)
VersionControlServer.CreateBranch
Related
I have below PowerShell Script written to check-out the files in TFS by referring the path mentioned in the TFS Path.txt file.
#$TFSCheckoutExe="C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\TF.exe"
$TFSFilePaths=Get-Content "$PSScriptRoot\TFS Path.txt"
$TFSCheckoutExe="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\TF.exe"
$visualStudiopath = 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer'
Add-Type -Path "$visualStudiopath\Microsoft.TeamFoundation.VersionControl.Client.dll"
Add-Type -Path "$visualStudiopath\Microsoft.TeamFoundation.Common.dll"
Add-Type -Path "$visualStudiopath\Microsoft.TeamFoundation.WorkItemTracking.Client.dll"
Add-Type -Path "$visualStudiopath\Microsoft.TeamFoundation.Client.dll"
Add-type -path "$visualStudiopath\Microsoft.TeamFoundation.ProjectManagement.dll"
Add-Type -Path "$visualStudiopath\Microsoft.TeamFoundation.Build.Common.dll"
#TFS Collection Path
$sourceLocation = "http://vwmaztfsapp:8080/tfs/MatchCollection"
#Creating TFS Object
$tfsCollectionUrl = New-Object System.URI($sourceLocation);
$tfsCollection = New-Object -TypeName Microsoft.TeamFoundation.Client.TfsTeamProjectCollection -ArgumentList $tfsCollectionUrl
$VersionControl = $tfsCollection.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
$latest = [Microsoft.TeamFoundation.VersionControl.Client.VersionSpec]::Latest
$recursionType = [Microsoft.TeamFoundation.VersionControl.Client.RecursionType]::Full
Foreach($TFSFilePath in $TFSFilePaths)
{
&$TFSCheckoutExe checkout $TFSFilePath | Out-Null
}
I am getting an error while trying to check-out the file in TFS? (screenshot below)
Can anyone please let me know how can I resolve this error, what am I missing?
In order to checkout a file, you first need a workspace mapping. It must be a server mapping to check out a file, local workspaces don't have a checkout option.
tf vc workspace new /noprompt YourUniqueNameHere /location:server
Then map your local folder to a server in the TFVC reporitory
tf vc workfold /map $/Project/Path c:\A\Local\Directory /workspace YourUniqueNameHere
Then call get or checkout. I'm not 100% you can checkout a file without getting it first.
You can accomplish the same thing without depending on tf.exe in pure powershell. You can find a complete example in my TFVC tasks for Azure Pipelines. You still need a local workspace for this to work:
[string[]] $FilesToCheckout = $ItemSpec -split ';|\r?\n'
$RecursionType = [Microsoft.TeamFoundation.VersionControl.Client.RecursionType]$Recursion
Write-Message "Checking out ItemSpec: $ItemSpec, Recursive: $RecursionType"
Try
{
$provider = Get-SourceProvider
if (-not $provider)
{
return;
}
Foreach ($change in $FilesToCheckout)
{
Write-Message "Checking out: $change"
$provider.Workspace.PendEdit(
#($change),
$RecursionType,
$null,
[Microsoft.TeamFoundation.VersionControl.Client.LockLevel]"Unchanged"
) | Out-Null
}
}
Finally
{
Invoke-DisposeSourceProvider -Provider $provider
}
The code to find a workspace from the local workspace cache can be found in the shared module:
function Get-TfsTeamProjectCollection()
{
$ProjectCollectionUri = Get-VstsTaskVariable -Name "System.TeamFoundationCollectionUri" -Require
$tfsClientCredentials = Get-VstsTfsClientCredentials -OMDirectory $(Find-VisualStudio)
$collection = New-Object Microsoft.TeamFoundation.Client.TfsTeamProjectCollection(
$ProjectCollectionUri,
$tfsClientCredentials)
$collection.EnsureAuthenticated()
return $collection
}
function Get-SourceProvider {
[cmdletbinding()]
param()
Write-Debug "Entering Get-SourceProvider"
$provider = #{
Name = $env:BUILD_REPOSITORY_PROVIDER
SourcesRootPath = $env:BUILD_SOURCESDIRECTORY
TeamProjectId = $env:SYSTEM_TEAMPROJECTID
}
$success = $false
try {
if ($provider.Name -eq 'TfsVersionControl') {
$provider.TfsTeamProjectCollection = Get-TfsTeamProjectCollection
$versionControlServer = $provider.TfsTeamProjectCollection.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
$versionControlServer.add_NonFatalError($OnNonFatalError)
$workstation = [Microsoft.TeamFoundation.VersionControl.Client.Workstation]::Current
$workstation.EnsureUpdateWorkspaceInfoCache($versionControlServer, $versionControlServer.AuthorizedUser)
$provider.VersionControlServer = $versionControlServer;
$provider.Workspace = $versionControlServer.TryGetWorkspace($provider.SourcesRootPath)
if (!$provider.Workspace) {
Write-Message -Type Debug "Unable to determine workspace from source folder: $($provider.SourcesRootPath)"
Write-Message -Type Debug "Attempting to resolve workspace recursively from locally cached info."
$workspaceInfos = $workstation.GetLocalWorkspaceInfoRecursively($provider.SourcesRootPath);
if ($workspaceInfos) {
foreach ($workspaceInfo in $workspaceInfos) {
Write-Message -Type Debug "Cached workspace info discovered. Server URI: $($workspaceInfo.ServerUri) ; Name: $($workspaceInfo.Name) ; Owner Name: $($workspaceInfo.OwnerName)"
try {
$provider.Workspace = $versionControlServer.GetWorkspace($workspaceInfo)
break
} catch {
Write-Message -Type Debug "Determination failed. Exception: $_"
}
}
}
}
if ((!$provider.Workspace) -and $env:BUILD_REPOSITORY_TFVC_WORKSPACE) {
Write-Message -Type Debug "Attempting to resolve workspace by name: $env:BUILD_REPOSITORY_TFVC_WORKSPACE"
try {
$provider.Workspace = $versionControlServer.GetWorkspace($env:BUILD_REPOSITORY_TFVC_WORKSPACE, '.')
} catch [Microsoft.TeamFoundation.VersionControl.Client.WorkspaceNotFoundException] {
Write-Message -Type Debug "Workspace not found."
} catch {
Write-Message -Type Debug "Determination failed. Exception: $_"
}
}
if (!$provider.Workspace) {
Write-Message -Type Warning (Get-LocalizedString -Key 'Unable to determine workspace from source folder ''{0}''.' -ArgumentList $provider.SourcesRootPath)
return
}
if ($provider.Workspace.Location -eq "Server")
{
Write-Warning "Server workspace support is experimental."
}
$provider.Workspace.Refresh()
$success = $true
return New-Object psobject -Property $provider
}
Write-Warning ("Only TfsVersionControl source providers are supported for TFVC tasks. Repository type: $provider")
return
} finally {
if (!$success) {
Invoke-DisposeSourceProvider -Provider $provider
}
Write-Message -Type Debug "Leaving Get-SourceProvider"
}
This code should contain enough information to build a new workspace too if you'd want that.
I need to create a script that does the following:
Copies all files in a folder to an FTP site.
If the copy was successful move the files to an archive.
The archive should be a freshly created folder with today's date (so we know when they were transmitted).
I've tried to cannibalise other scripts to get something to work but I'm not getting anywhere so I need some help I've been working on this for hours.
I'm using the WinSCP DLL only because my other (working) script uses SFTP which needs it. I know normal FTP doesn't but I couldn't find any easily transferrable code so trying to modify that instead.
So, here's the code I have, which doesn't even run, never mind run properly, can someone help me get it right? Sorry it's a bit of a mess.
param (
$localPath = "c:\test\source",
$remotePath = "/upload",
$folder = ($_.CreationTime | Get-Date -Format yyyyMMdd)
# not sure this works but don't see how to point the destination
# to the newly created folder
$backupPath = "c:\test\destination\$folder"
)
try
{
# Load WinSCP .NET assembly
Add-Type -Path "C:\Windows\System32\WindowsPowerShell\v1.0\WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::ftp
HostName = "xxxxxxxx"
UserName = "xxxxxxxx"
Password = "xxxxxxxx"
}
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
# Upload files, collect results
$transferResult = $session.PutFiles($localPath, $remotePath)
# Iterate over every transfer
foreach ($transfer in $transferResult.Transfers)
{
# Success or error?
if ($transfer.Error -eq $Null)
{
# If today's folder doesn't exist, create it
if (!(Test-Path $BackupPath))
{
New-Item -ItemType Directory -Force -Path $BackupPath
}
Write-Host ("Upload of {0} succeeded, moving to Uploaded folder" -f
$transfer.FileName)
# Upload succeeded, move source file to backup
Move-Item $transfer.FileName $backupPath
}
else
{
Write-Host ("Upload of {0} failed: {1}" -f
$transfer.FileName, $transfer.Error.Message)
}
}
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
exit 0
}
catch [Exception]
{
Write-Host ("Error: {0}" -f $_.Exception.Message)
exit 1
}
So there's the code. I'm happy to use built in PowerShell for the FTP side to simplify it, I just want it to work.
I'm not sure what's your concern with the code. It looks pretty much ok, except for a syntax error, when setting $folder:
Why are you even trying to use $_.CreationTime as folder timestamp? Just use current date:
$folder = (Get-Date -Format "yyyyMMdd")
See Formatting timestamps in PowerShell in WinSCP documentation.
Also I do not see a point of setting $folder and $backupPath in the params block. Move it after the params block. If you want this anyway, you are missing a comma after the $folder assignment.
Other than that, your code should work.
You cannot simplify it by using the built-in PowerShell (or rather .NET) FTP functionality, as it does not have as powerful commands as WinSCP .NET assembly.
I'd write the code as:
$localPath = "C:\source\local\path\*"
$remotePath = "/dest/remote/path/"
$folder = (Get-Date -Format "yyyyMMdd")
$backupPath = "C:\local\backup\path\$folder"
# If today's folder doesn't exist, create it
if (!(Test-Path $BackupPath))
{
New-Item -ItemType Directory -Force -Path $BackupPath | Out-Null
}
try
{
# Load WinSCP .NET assembly
Add-Type -Path "WinSCPnet.dll"
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::ftp
HostName = "ftp.example.com"
UserName = "username"
Password = "password"
}
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
# Upload files, collect results
$transferResult = $session.PutFiles($localPath, $remotePath)
# Iterate over every transfer
foreach ($transfer in $transferResult.Transfers)
{
# Success or error?
if ($transfer.Error -eq $Null)
{
Write-Host ("Upload of $($transfer.FileName) succeeded, " +
"moving to backup")
# Upload succeeded, move source file to backup
Move-Item $transfer.FileName $backupPath
}
else
{
Write-Host ("Upload of $($transfer.FileName) failed: " +
"$($transfer.Error.Message)")
}
}
}
finally
{
# Disconnect, clean up
$session.Dispose()
}
exit 0
}
catch [Exception]
{
Write-Host "Error: $($_.Exception.Message)"
exit 1
}
Based on Moving local files to different location after successful upload.
I am trying to download a folder child from a given TFS project.
All i have done so far is connecting to the server using a url https://.visualstudio.com , username, a password and listing all the projects.
This is my code so far:
Add-Type -Path "$path1\Microsoft.TeamFoundation.Client.dll"
Add-Type -Path "$path1\Microsoft.TeamFoundation.Common.dll"
Add-Type -Path "$path1\Microsoft.TeamFoundation.WorkItemTracking.Client.dll"
Add-Type -Path "$path1\Microsoft.TeamFoundation.VersionControl.Client.dll"
Add-Type -Path "$path1\Microsoft.TeamFoundation.ProjectManagement.dll"
Add-Type -Path "$path2\Microsoft.TeamFoundation.PowerTools.PowerShell.dll"
$tfsurl = 'https://something.visualstudio.com'
$username = 'someuser#outlook.com'
$password = 'somepasswd'
$_tfs_server =[Microsoft.TeamFoundation.Client.TfsTeamProjectCollectionFactory]::GetTeamProjectCollection($tfs_uri)
$cred = New-Object System.Net.NetworkCredential($username,$password)
$_tfs_server.Credentials = $cred
$_tfs_server.EnsureAuthenticated()
if($_tfs_server.HasAuthenticated){
Write-Host -ForegroundColor Green "Connected to Team Foundation Server [" $tfs_uri "]"
$tfsConfigurationServer = [Microsoft.TeamFoundation.Client.TfsConfigurationServerFactory]::GetConfigurationServer($tfs_uri)
$tpcService = $tfsConfigurationServer.GetService("Microsoft.TeamFoundation.Framework.Client.ITeamProjectCollectionService")
$sortedCollection = $tpcService.GetCollections() | Sort-Object -Property Name
foreach($col in $sortedCollection){
Write-Host $col.Name
}
$cssService = $_tfs_server.GetService("Microsoft.TeamFoundation.Server.ICommonStructureService3")
$sortedProjects = $cssService.ListAllProjects() | Sort-Object -Property Name
Write-Host "Listing Projects"
foreach($project in $sortedProjects){
Write-Host (" - " + $project.Name)
}
}
else {
return;
}
https://i.stack.imgur.com/iCXNQ.jpg
Simple code to get files from source control:
$teamProjectCollection=new-object Microsoft.TeamFoundation.Client.TfsTeamProjectCollection($tfsCollectionUrl,$cret)
$teamProjectCollection.EnsureAuthenticated()
$VersionControl = $teamProjectCollection.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
$workspace = $VersionControl.CreateWorkspace("BasicSccExamplePS", $VersionControl.AuthorizedUser);
$workspace.Map("$/Agile2015/ClassLibrary2", "D:\\temp\\BasicSccExample")
$workspace.Get()
To check whether folder/file exists, you can use GetItems() method:
$items=$VersionControl.GetItems("$/ScrumStarain/CustomCode/Properties2");
Write-Output $items.Items.Count
If($items.Items.Count -ne 0)
{
}
Hi all I got the below script to download a file from TFS, using powershell script, but I need to download entire solution how can I achieve that
cls
$tfsCollectionUrl = New-Object System.URI("http://localhost:8080/tfs/defaultcollection");
[Microsoft.TeamFoundation.Client.TfsTeamProjectCollection] $tfsCollection = Get-TfsServer $tfsCollectionUrl
$VersionControl = $tfsCollection.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
$DestinationFile = [IO.Path]::GetTempFileName()
$VersionControl.DownloadFileByUrl('$/MyFirstProject/WebApplication1/WebApplication1/WebForm1.aspx.cs', $DestinationFile)
Invoke-Item $DestinationFile
Also this is not checking whether he is having permission to download , I would like to prompt for username and password instead of downloading directly. Can I achieve the same for bitbucket too if so how can I
The same code converted to powershell
connect to tfs and download the files present in it VS2010
For credential use the above logic
Write-Host "Enter source location "
$sourceLocation = Read-Host
$tfsCollectionUrl = New-Object System.URI($sourceLocation);
Write-Host "Enter server path "
$serverPath = Read-Host
Write-Host "Enter local path to download"
$localPath = Read-Host
[Microsoft.TeamFoundation.Client.TfsTeamProjectCollection] $tfsCollection = Get-TfsServer $tfsCollectionUrl
$VersionControl = $tfsCollection.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
$latest = [Microsoft.TeamFoundation.VersionControl.Client.VersionSpec]::Latest
$recursionType = [Microsoft.TeamFoundation.VersionControl.Client.RecursionType]::Full
try
{
foreach ($item in $VersionControl.GetItems($serverPath, $latest,$recursionType).Items)
{
$target = [io.path]::Combine($localPath,$item.ServerItem.Substring(2))
$exists=[System.IO.Directory]::Exists($target)
if($item.ItemType -eq "Folder" -and !$exists)
{
New-Item $target -Type Directory
}
if($item.ItemType -eq "File")
{
$item.DownloadFile($target)
}
}
Write-Host "`n Successfully downloaded all the files to the target folder: " $localPath -ForegroundColor Green
}
catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Break
}
An easy way is to have a workspace mapping multiple projects and run the tf get command from Powershell.
You can also manage workspace with tf workspace command line.
The simple way is that:
Create a workspace
Map a workspace
Get all files.
Sample code:
$tfsCollectionUrl = New-Object System.URI("[team project collection url");
$username="[user name]"
$password="[password]"
$domain="[domain]"
$cret = new-object System.Net.NetworkCredential($username, $password, $domain)
$teamProjectCollection=new-object Microsoft.TeamFoundation.Client.TfsTeamProjectCollection($tfsCollectionUrl,$cret)
$teamProjectCollection.EnsureAuthenticated()
$VersionControl = $teamProjectCollection.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
$workspace = $VersionControl.CreateWorkspace("BasicSccExamplePS", $VersionControl.AuthorizedUser);
$workspace.Map("[file or folder server path, for example:$/TestTeam/FolderA]", "[local path]")
$workspace.Get()
You can find that it lets you to provide the credential, so you could let user to provide username, password, then connect to TFS with that account.
Regards
I want to update 2 workspaces from two different tfs in one script using powershell.
The first Workspace is updating without any Problems. After the update is finished powershell connects to the second Workspace, but isn't updating the local data like the first time.
I guess the old Connection might still block the pipe or something like that, but I haven't found any cmd to clean the pipe. My code looks like this:
param(
[string]$TestTFS = "http://TestTFS",
[string]$ProdTFS = "http://ProdTFS",
[string]$Teamproject="$\TeamprojectPath",
[string]$LocalTestWorkspace="C:\LocalTestWorkspacePath",
[string]$LocalProdWorkspace="C:\LocalProdWorkspacePath"
)
# Import Microsoft.TeamFoundation.PowerShell Snapin
Add-PSSnapin Microsoft.TeamFoundation.PowerShell
# Connect to production-TFS
$ProdEnvServer = Get-TfsServer -Name $ProdTFS
Write-Host "tfsConnect ="$ProdEnvServer
# Get prod teamprojekt
Get-TfsChildItem $Teamprojekt -Server $ProdEnvServer
# Update files in local prod workspace
Update-TfsWorkspace -Force -Recurse $LocalProdWorkspace
# Connect to test-TFS
$TestEnvServer = Get-TfsServer -Name $TestTFS
Write-Host "tfsConnect ="$TestEnvServer
# Get test teamprojekt
Get-TfsChildItem $Teamprojekt -Server $TestEnvServer
# Update files in local test workspace
Update-TfsWorkspace -Force -Recurse $LocalTestWorkspace
After 3 months and noone coming up with an answer. I just assume that the Cmdlets don't work as they should. The only option here seems to be a Workaround.
# Copy Team Project from Prod to Test TFS
param([string]$TestTFS = "http://TestTFS",
[string]$ProdTFS = "http://ProdTFS",
[String]$Teamproject="$/Teamproject",
[String]$LocalTestWorkspace="C:\LocalTestWorkspacePath",
[String]$LocalProdWorkspace="C:\LocalProdWorkspacePath")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.VersionControl.Client")
try
{
clear
$LocalTestProjectPath = $LocalTestWorkspace + $Teamproject.Substring(1)
$LocalProdProjectPath = $LocalProdWorkspace + $Teamproject.Substring(1)
# Connect to production-TFS
Write-Host "Getting latest of $ProdTFS"
$tfsColProd = [Microsoft.TeamFoundation.Client.TfsTeamProjectCollectionFactory]::GetTeamProjectCollection($ProdTFS)
[Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer] $vcsProd = $tfsColProd.GetService([type] "Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer")
# TryGetWorkspace is sometimes buggy and doesn't return an existing workspace
# Delete existing workspace manually before if that happens
$workspaceProd = $vcsProd.TryGetWorkspace($LocalProdWorkspace)
$isProdTempWorkspace = $false
# create Workspace if it doesn't exists
if (-not $workspaceProd) {
Write-Host "No workspace found, creating temporary for prod"
$workspaceProd = $vcsProd.CreateWorkspace("Temp_" + [System.Guid]::NewGuid().ToString())
$workspaceProd.Map($Teamproject, $LocalProdProjectPath)
$isProdTempWorkspace = $true
}
$itemSpecFullTeamProj = New-Object Microsoft.TeamFoundation.VersionControl.Client.ItemSpec($Teamproject, "Full")
$fileRequest = New-Object Microsoft.TeamFoundation.VersionControl.Client.GetRequest($itemSpecFullTeamProj,
[Microsoft.TeamFoundation.VersionControl.Client.VersionSpec]::Latest)
$workspaceProd.Get($fileRequest, [Microsoft.TeamFoundation.VersionControl.Client.GetOptions]::GetAll)
if ($isProdTempWorkspace) {
Write-Host "Deleting temporary workspace for prod"
$workspaceProd.Delete()
}
Write-Host "Getting latest of $TestTFS"
$tfsColTest = [Microsoft.TeamFoundation.Client.TfsTeamProjectCollectionFactory]::GetTeamProjectCollection($TestTFS)
$vcsTest = $tfsColTest.GetService([type] "Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer")
# TryGetWorkspace is sometimes buggy and doesn't return an existing workspace
# Delete existing workspace manually before if that happens
[Microsoft.TeamFoundation.VersionControl.Client.Workspace] $workspaceTest = $vcsTest.TryGetWorkspace($LocalTestWorkspace)
$isTestTempWorkspace = $false
# create Workspace if it doesn't exists
if (-not $workspaceTest) {
Write-Host "No workspace found, creating temporary for test"
$workspaceTest = $vcsTest.CreateWorkspace("Temp_" + [System.Guid]::NewGuid().ToString())
$workspaceTest.Map($Teamproject, $LocalTestProjectPath)
$isTestTempWorkspace = $true
}
$workspaceTest.Get($fileRequest, [Microsoft.TeamFoundation.VersionControl.Client.GetOptions]::GetAll)
# Remove local test folder and copy prod folder into test workspace
Write-Host "Copying over Prod to Test"
# Delete updated test project folder
Remove-Item -Path $LocalTestProjectPath -Force -Recurse
# Copy prod folder to test workspace
Copy-Item -Path $LocalProdProjectPath -Destination $LocalTestProjectPath -Force -Recurse
# Calling tfpt is the only thing that works
Write-Host "Comparing for changes"
$ps = new-object System.Diagnostics.Process
$ps.StartInfo.Filename = $env:TFSPowerToolDir + "tfpt.exe"
$ps.StartInfo.Arguments = "online /adds /deletes /diff /noprompt /recursive $LocalTestProjectPath"
$ps.StartInfo.RedirectStandardOutput = $false # careful, only output works, has hanging problems (2k Buffer limit)
$ps.StartInfo.RedirectStandardError = $false
$ps.StartInfo.UseShellExecute = $false
$ps.Start()
$ps.WaitForExit()
# Check in new test project folder into test environment
$wsCheckinParams = New-Object Microsoft.TeamFoundation.VersionControl.Client.WorkspaceCheckInParameters(
#($itemSpecFullTeamProj),"Update project to production environment version")
# CheckIn better manually to check for errors
$workspaceTest.CheckIn($wsCheckinParams)
if ($isTestTempWorkspace) {
Write-Host "Deleting temporary workspace for test"
$workspaceTest.Delete()
Remove-Item -Path D:\Development -Force -Recurse
}
}
catch [System.Exception]
{
Write-Host "Exception: " ($Error[0]).Exception
EXIT $LASTEXITCODE
}
My approach is very similar to Zittelrittel. Just send the path and it will automatically figure out the workspace.
This will not work in PowerShell ISE (x86), I had to use the 64-bit version!
Add-PSSnapin Microsoft.TeamFoundation.PowerShell
Write-Host "Updating Workspace1, please wait..."
Update-TfsWorkspace -item C:\dev\Workspace1\code -Recurse | Format-Table
Write-Host "Updating Workspace2, please wait..."
Update-TfsWorkspace -item C:\dev\Workspace1\code -Recurse | Format-Table
In your calls to update TFS workspace, pipe the result to out-null. This should effectively remove any data that would otherwise be stored in the pipeline.
Update-TfsWorkspace -Force -Recurse $LocalProdWorkspace | Out-Null
Update-TfsWorkspace -Force -Recurse $LocalTestWorkspace | Out-Null