Recevez les plus récents des services d'équipe Visual Studio à l'aide des informations d'identification de transmission / de connexion de ligne de commande avec TF.EXE
-
20-12-2019 - |
Question
Quelqu'un a-t-il eu du succès de recevoir le dernier code source des services d'équipe Visual Studio (anciennement Visual Studio Online, Service de la Fondation de l'équipe) Serveur de contrôle de la version à l'aide de la ligne de commande et de transmettre des informations d'identification par programme?
-J'ai découvert que vous ne pouvez pas utiliser les informations d'identification de l'ID Windows que vous utilisez pour vous connecter à Equipe Explorer ou au site Web de la VSO dans la ligne de commande. Vous devez créer des informations d'identification alternatives pour le profil d'utilisateur dans les services d'équipe.
-J'ai découvert que si vous omettez la boîte de connexion / connexion dans Tf.exe, la boîte de dialogue de connexion des services à l'équipe apparaît et vous demande de saisir vos informations d'identification de Windows ID (à moins qu'ils ne soient déjà mis en cache dans votre explorateur d'équipe ou votre studio Visual ( ou même éventuellement des caches de transmission de navigateurs et Windows)
-J'ai découvert que les travaux d'identification alternative utilisant la version Java de Tf.exe - Equipe Explorer partout Client de ligne de commande (TEE CLC). Tee CLC utilise effectivement les informations d'identification / connexion que vous transmettez et vous permet de vous connecter. La même chose ne semble pas être possible avec le TF.EXE dans C: \ Fichiers du programme (X86) \ Microsoft Visual Studio 12.0 \ Common7 \ Ide \ mais l'installation de Java sur cet environnement de construction est contre la politique. Donc, la tee CLC n'est pas une option viable.
tf get $/MyProj /collection:https://myaccount.visualstudio.com/DefaultCollection /login:user:pass
La commande ci-dessus ignore simplement les informations d'identification / connexion si vous avez les informations d'identification de l'ID Windows Cached ou renvoie le message d'erreur TF30063: vous n'êtes pas autorisé à accéder à myAccount.visualstudio.com (ce qui n'est pas vrai, car les informations d'identification fonctionnent. avec le client Java)
Y a-t-il d'autres alternatives qui ne nécessitent pas d'installer Java?
La solution
J'ai une réponse de Microsoft Support: Les crédits AA pour VSO ne fonctionnent pas avec TF.EXE pour le moment.TEE CLC ou utiliser le code de modèle d'objet sont les seules alternatives actuellement.Nous cherchons à faire cela à l'avenir.
Le code de modèle d'objet fait référence à la
Si vous utilisez le code ci-dessous pour créer un exécutable appelé tfsget.exe, on peut appeler à partir de la ligne de commande comme celle-ci:
tfsget https://myvso.visualstudio.com/DefaultCollection $/MyProj/Folder c:\Projects login password
Et j'ai ajouté un interrupteur silencieux pour supprimer la liste de chaque fichier pouvant être utilisé comme:
tfsget https://myvso.visualstudio.com/DefaultCollection $/MyProj/Folder c:\Projects login password silent
Voici le code, j'espère que cela vous aide jusqu'à ce que MS met à jour TF.EXE
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
namespace TfsGet
{
class Program
{
static void Main(string[] args)
{
var tfsParams = TfsDownloadParams.Create(args);
var tpc = new TfsTeamProjectCollection(new Uri(tfsParams.ServerUrl), tfsParams.Credentials);
CheckAccess(tpc, tfsParams);
Download(tpc, tfsParams);
}
private static void CheckAccess(TfsTeamProjectCollection tpc, TfsDownloadParams tfsParams)
{
try
{
tpc.Authenticate();
}
catch
{
Console.WriteLine("TFS Authentication Failed");
Console.WriteLine("Server Url:{0}", tfsParams.ServerUrl);
Console.WriteLine("Project Path:{0}", tfsParams.ServerProjectPath);
Console.WriteLine("Target Path:{0}", tfsParams.TargetPath);
Environment.Exit(1);
}
}
static void Download(TfsTeamProjectCollection tpc, TfsDownloadParams tfsParams)
{
var versionControl = tpc.GetService<VersionControlServer>();
// Listen for the Source Control events.
versionControl.NonFatalError += Program.OnNonFatalError;
var files = versionControl.GetItems(tfsParams.ServerProjectPath, VersionSpec.Latest, RecursionType.Full);
foreach (Item item in files.Items)
{
var localFilePath = GetLocalFilePath(tfsParams, item);
switch (item.ItemType)
{
case ItemType.Any:
throw new ArgumentOutOfRangeException("ItemType.Any - not sure what to do with this");
case ItemType.File:
if (!tfsParams.Silent) Console.WriteLine("Getting: '{0}'", localFilePath);
item.DownloadFile(localFilePath);
break;
case ItemType.Folder:
if (!tfsParams.Silent) Console.WriteLine("Creating Directory: {0}", localFilePath);
Directory.CreateDirectory(localFilePath);
break;
}
}
}
private static string GetLocalFilePath(TfsDownloadParams tfsParams, Item item)
{
var projectPath = tfsParams.ServerProjectPath;
var pathExcludingLastFolder = projectPath.Substring(0, projectPath.LastIndexOf('/')+1);
string relativePath = item.ServerItem.Replace(pathExcludingLastFolder, "");
var localFilePath = Path.Combine(tfsParams.TargetPath, relativePath);
return localFilePath;
}
internal static void OnNonFatalError(Object sender, ExceptionEventArgs e)
{
var message = e.Exception != null ? e.Exception.Message : e.Failure.Message;
Console.Error.WriteLine("Exception: " + message);
}
}
public class TfsDownloadParams
{
public string ServerUrl { get; set; }
public string ServerProjectPath { get; set; }
public string TargetPath { get; set; }
public TfsClientCredentials Credentials { get; set; }
public bool Silent { get; set; }
public static TfsDownloadParams Create(IList<string> args)
{
if (args.Count < 5)
{
Console.WriteLine("Please supply 5 or 6 parameters: tfsServerUrl serverProjectPath targetPath userName password [silent]");
Console.WriteLine("The optional 6th 'silent' parameter will suppress listing each file downloaded");
Console.WriteLine(@"Ex: tfsget ""https://myvso.visualstudio.com/DefaultCollection"" ""$/MyProject/ProjectSubfolder"" ""c:\Projects Folder"", user, password ");
Environment.Exit(1);
}
var tfsServerUrl = args[0]; //"https://myvso.visualstudio.com/DefaultCollection";
var serverProjectPath = args[1]; // "$/MyProject/Folder Path";
var targetPath = args[2]; // @"c:\Projects\";
var userName = args[3]; //"login";
var password = args[4]; //"passsword";
var silentFlag = args.Count >= 6 && (args[5].ToLower() == "silent"); //"silent";
var tfsCredentials = GetTfsCredentials(userName, password);
var tfsParams = new TfsDownloadParams
{
ServerUrl = tfsServerUrl,
ServerProjectPath = serverProjectPath,
TargetPath = targetPath,
Credentials = tfsCredentials,
Silent = silentFlag,
};
return tfsParams;
}
private static TfsClientCredentials GetTfsCredentials(string userName, string password)
{
var networkCreds= new NetworkCredential(userName, password);
var basicCreds = new BasicAuthCredential(networkCreds);
var tfsCreds = new TfsClientCredentials(basicCreds)
{
AllowInteractive = false
};
return tfsCreds;
}
}
}
Autres conseils
Voici un extrait en utilisant. Bibliothèques NET TFS &
tf obtenir le dernier espace de travail.ps1
$path = "C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\ReferenceAssemblies\v2.0"
Add-Type -Path "$path\Microsoft.TeamFoundation.Client.dll"
Add-Type -Path "$path\Microsoft.TeamFoundation.VersionControl.Client.dll"
Add-Type -Path "$path\Microsoft.TeamFoundation.VersionControl.Common.dll"
$collection = "https://mycorp.visualstudio.com/defaultcollection"
$tpc = [Microsoft.TeamFoundation.Client.TfsTeamProjectCollectionFactory]::GetTeamProjectCollection($collection)
$vc = $tpc.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
# retrieve workspace by path
$projectPath = "$/MyApp/MyBranch"
$workspacePath = "C:\Projects\MyApp\MyBranch"
$workspace = $vc.GetWorkspace($workspacePath)
# get full download every time (tf get /force /recursive)
function DownloadAllFiles([Microsoft.TeamFoundation.VersionControl.Client.Workspace] $workspace, [string] $projectPath) {
$recursionType = [Microsoft.TeamFoundation.VersionControl.Client.RecursionType]::Full
$versionSpec = [Microsoft.TeamFoundation.VersionControl.Client.LatestVersionSpec]::Instance
$itemSpec = new-object Microsoft.TeamFoundation.VersionControl.Client.ItemSpec($projectPath,$recursionType)
$getRequest = New-Object Microsoft.TeamFoundation.VersionControl.Client.GetRequest($projectPath,$recursionType,$versionSpec)
$getOptions = [Microsoft.TeamFoundation.VersionControl.Client.GetOptions]::GetAll -bor [Microsoft.TeamFoundation.VersionControl.Client.GetOptions]::Overwrite
$workpaceStatus = $workspace.Get($getRequest, $getOptions)
write-output $workpaceStatus
}
# get delta download - changes only (retrieves all mapped items)
function DownloadWorkspaceUpdates([Microsoft.TeamFoundation.VersionControl.Client.Workspace] $workspace) {
$workpaceStatus = $workspace.Get()
write-output $workpaceStatus
}
# get delta download - changes only (retrieves specific mapped items)
function DownloadWorkspaceUpdates([Microsoft.TeamFoundation.VersionControl.Client.Workspace] $workspace, [string] $projectPath) {
$recursionType = [Microsoft.TeamFoundation.VersionControl.Client.RecursionType]::Full
$versionSpec = [Microsoft.TeamFoundation.VersionControl.Client.LatestVersionSpec]::Instance
$itemSpec = new-object Microsoft.TeamFoundation.VersionControl.Client.ItemSpec($projectPath,$recursionType)
$getRequest = New-Object Microsoft.TeamFoundation.VersionControl.Client.GetRequest($projectPath,$recursionType,$versionSpec)
$getOptions = [Microsoft.TeamFoundation.VersionControl.Client.GetOptions]::Overwrite
$workpaceStatus = $workspace.Get($getRequest, $getOptions)
write-output $workpaceStatus
}
# force latest download (slower)
DownloadAllFiles -workspace $workspace -projectPath $projectPath
# download deltas (fast), all mappings
DownloadWorkspaceUpdates -workspace $workspace
# download deltas (fast), specific mapping
DownloadWorkspaceUpdates -workspace $workspace -projectPath $projectPath
Ceci pourrait facilement être étendu pour prendre en charge TfsClientCredentials
( i.e. ALTERNATE ACCÈS DEVENTIONS ).Je préfère l'approche PowerShell car elle ne nécessite pas de compilation ni d'extra extra de copier autour de vous.