How to checkout a file in TFS using PowerShell? - powershell

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.

Related

WinSCP Script to Loop through Files

I am using the following slightly modified script (from https://winscp.net/eng/docs/script_local_move_after_successful_upload) to upload files to an SFTP site on AWS...and in a PRD env I will have to have this run through approx 0.5M small files...
param (
$localPath = "C:\FTP\*.DAT",
$remotePath = "/",
$backupPath = "C:\FTP\Complete\"
)
try
{
# Load WinSCP .NET assembly
#Add-Type -Path "WinSCPnet.dll"
$ScriptPath = $(Split-Path -Parent $MyInvocation.MyCommand.Definition)
[Reflection.Assembly]::UnsafeLoadFrom( $(Join-Path $ScriptPath "WinSCPnet.dll") ) | Out-Null
# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::Sftp
HostName = "somewhere.com"
UserName = "user"
SshHostKeyFingerprint = "ssh-rsa 2048 XXXXXXXI"
SshPrivateKeyPath = "C:\blahblah.ppk"
}
$session = New-Object WinSCP.Session
$transferOptions = New-Object WinSCP.TransferOptions
# Look to ignore any file property change errors
$transferOptions.FilePermissions = $Null # This is default
$transferOptions.PreserveTimestamp = $False
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 ($Null -eq $transfer.Error)
{
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
{
Write-Host "Error: $($_.Exception.Message)"
exit 1
}
The scripts works great, but unfortunately only loads one file before disconnecting. The script fails if there is an error loading any of the files, so it is working as expected.
But the error I am getting, is
"Upload of file 'somefile.DAT' was successful, but error occurred while setting the permissions and/or timestamp.
If the problem persists, turn off setting permissions or preserving timestamp. Alternatively you can turn on 'Ignore permission errors' option.
The server does not support the operation.
Error code: 8
Error message from server (US-ASCII): SETSTAT unsupported"
I think I have the following settings possibly configured incorrectly, but I'm not sure what I am doing wrong here....thoughts?
$transferOptions.FilePermissions = $Null # This is default
$transferOptions.PreserveTimestamp = $False
I've actually managed to get this to work by modifying the session and transfer options..
$session.Open($sessionOptions)
$transferOptions = New-Object WinSCP.TransferOptions
# Look to ignore any file property change errors
$transferOptions.PreserveTimeStamp = $false
$transferOptions.FilePermissions = $Null
$transferOptions.AddRawSettings("IgnorePermErrors", "1")
# Upload files, collect results
$transferResult = $session.PutFiles($localPath, $remotePath, $False, $transferOptions)

How to download a specific labelled code from TFS using PowerShell Script?

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

vs2013 create mapping to new source location using powershell

I have been trying to automate the local setup Visual Studio (2013) workspace. I have been able to make the connection to the source location using PowerShell, but I cannot get the local mapping to apply. If I manually map the source location, I can get the local mapping to apply with PowerShell. I have borrowed heavily from other Stack Overflow threads, but I cannot seam to find a way to map the TFS server and map the local paths to the workspace. Thanks!
clear host
[string]$TfsUrl = 'https://xxxx.visualstudio.com'
'.Client', '.VersionControl.Client', '.VersionControl.Common', '.WorkItemTracking.Client', '.Build.Client', '.Build.Common' |
ForEach-Object {
Add-Type -AssemblyName "Microsoft.TeamFoundation$_, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
}
try
{
$uri = New-Object System.Uri -ArgumentList $TfsUrl
$credentialProvider = new-object Microsoft.TeamFoundation.Client.UICredentialsProvider
$collection = [Microsoft.TeamFoundation.Client.TfsTeamProjectCollectionFactory]::GetTeamProjectCollection($uri, $credentialProvider)
$collection.Authenticate()
if ($collection.HasAuthenticated)
{
Write-Host -ForegroundColor Green 'Connection to TFS Successful'
$tfs = '' | Select-Object Collection, VersionControlServer, WorkItemStore, BuildServer, IdentityManagementService
$tfs.Collection = $collection
$tfs
}
}
catch
{
Write-Host -ForegroundColor Red $_.Exception.Message
Write-Host
Write-Host -ForegroundColor Red 'Failed to connect to TFS'
}
$tfsServer = "https://xxxx.visualstudio.com"
$computerName = [system.environment]::machinename
$folderName = "C:\VSTS_WB\xxxx.DuckCreek";
$dir = 'C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\'
Set-Alias tf "$dir\tf.exe"
new-item -itemtype directory -path $folderName -force
cd $folderName
tf workfold "$/xxxx.DuckCreek" $folderName /map
tf workfold "$/xxxx.DuckCreek/BR1/Policy/Source" "C:\Program Files\Duck Creek Technologies" /map
tf workfold "$/xxxx.DuckCreek/BR1/Policy/Source/Shared.x86" "C:\Program Files (x86)\Duck Creek Technologies" /map
tf workfold "$/xxxx.DuckCreek/BR1/Billing/Source" "C:\Program Files\Duck Creek Technologies Billing" /map

How to download a child folder , if exists, for a given TFS project using PowerShell?

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)
{
}

Download entire solution or specific branch from TFS to local folder

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