Recibir los servicios de Visual Studio Team usando la línea de comandos que pasan / Credenciales de inicio de sesión con TF.EXE

StackOverflow https://stackoverflow.com//questions/21005274

Pregunta

¿Alguien ha tenido éxito obteniendo el último código fuente de los Servicios de Visual Studio Team Services (anteriormente Visual Studio Online Online, Servicio de la Fundación Equipo) Versión ¡Servidor de control de la versión usando la línea de comandos y pasando las credenciales programáticamente?

-i he descubierto que no puede usar las credenciales de identificación de Windows que usa para iniciar sesión en Equipo Explorer o el sitio web de VSO en la línea de comandos. Debe crear credenciales alternativas para el perfil de usuario en los servicios del equipo.

-i he descubierto que si omite / login en tf.exe, aparece el cuadro de diálogo de inicio de sesión de los servicios del equipo y le pide que escriba sus credenciales de identificación de Windows (a menos que ya estén en caché en su equipo de equipo o en Visual Studio ( o incluso posiblemente cachés de credenciales de navegador y ventanas)

-i he descubierto que el trabajo de credenciales alternativos usando la versión Java de TF.EXE - Equipo Explorer en todas partes Cliente de línea de comandos (TEE CLC). TEE CLC en realidad utiliza las credenciales de inicio de sesión que pasa y le permite conectarse. Lo mismo no parece ser posible con el TF.EXE en C: \ Archivos de programa (X86) \ Microsoft Visual Studio 12.0 \ Common7 \ IDE \ pero que instale Java en este entorno de compilación está en contra de la política. Por lo tanto, el TEE CLC no es una opción viable.

tf get $/MyProj /collection:https://myaccount.visualstudio.com/DefaultCollection /login:user:pass 

El comando anterior simplemente ignora las credenciales de inicio de sesión. Si tiene las credenciales de identificación de Windows en caché o devuelve el mensaje de error TF30063: no está autorizado para acceder a MyAccount.visualStudio.com (que no es cierto, porque las credenciales funcionan con el cliente de java)

¿Hay alguna otra alternativa que no requiera instalar Java?

¿Fue útil?

Solución

Recibí una respuesta de Microsoft Support: los créditos AA para VSO no funcionan con tf.exe en este momento.TEE CLC o el código del modelo de objeto son las únicas alternativas actualmente.Estamos mirando a hacer esto en el futuro.

Código de modelo de objeto se refiere al microsoft.teamfoundation.versioncontrol.client espacio de nombres en la DLL por el mismo nombre.Terminé escribiendo una aplicación rápida de consola C # para descargar el código más reciente sin instalar Java.Un beneficio adicional de este enfoque es que no requiere crear un espacio de trabajo desechado.

Si usa el código a continuación para crear un ejecutable llamado tfsget.exe, se puede llamar desde la línea de comandos como esta:

tfsget https://myvso.visualstudio.com/DefaultCollection $/MyProj/Folder c:\Projects login password

y agregué un interruptor silencioso para suprimir listar cada archivo que se puede usar como:

tfsget https://myvso.visualstudio.com/DefaultCollection $/MyProj/Folder c:\Projects login password silent

Aquí está el código, espero que esto ayude hasta que MS actualiza 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;
        }
    }
}

Otros consejos

Aquí hay un fragmento que usa. net tfs bibliotecas & powershell que funcionó para nosotros - tf.exe no juega bien con VSOautorización.Curioso si alguien más tiene éxito usando esta ruta.Estamos usando adfs , por lo que el proceso de PowerShell se ejecuta como usuario con el que queremos autenticar.

TF Obtén el último área de trabajo.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

Esto podría extenderse fácilmente para admitir TfsClientCredentials ( i.e. Credenciales de acceso alternativo ).Prefiero el enfoque de PowerShell ya que no requiere compilación o un exe extra para copiar alrededor.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top