TF.EXEを使用したコマンドライン渡し/ログイン認証情報を使用してVisual Studioチームサービスの最新の最新情報

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

質問

は、Musical Studio Team Services(以前のVisual Studio Online、Team Foundation Service)バージョン管理サーバーから、コマンドラインを使ってプログラムで資格情報を渡すことができましたか?

-iチームエクスプローラまたはコマンドラインのVSOのWebサイトへのログインに使用するWindows ID認証情報を使用できないことを検出しました。チームサービスでユーザープロファイルの代替認証情報を作成する必要があります。

i tf.exeで/ loginを省略した場合、チームサービスのログインダイアログが表示され、Windows IDの資格情報を入力するように求められていることがわかりました(Team ExplorerまたはVisual Studioですでにキャッシュされていない限り(またはおそらくブラウザとWindows認証情報のキャッシュでさえ)

-iは、JavaバージョンのTF.EXE - Team Explorer Everywhereコマンドラインクライアント(TEE CLC)を使用した代替信任状作業を見つけました。 TEE CLCは実際に渡した/ログイン認証情報を使用して接続できます。 C:\ Program Files(x86)\ Microsoft Visual Studio 12.0 \ Common7 \ IDE \のTF.exeでも同様ではないようですが、このビルド環境に対するJavaのインストールはポリシーに対するものです。そのため、TEE CLCは実行可能なオプションではありません。

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

上記のコマンドは、Windows IDの認証情報がキャッシュされている場合、またはエラーメッセージTF30063を返す場合は、/ログイン認証情報を無視します。「認証情報が機能しているため、これは当てはまりません。 Javaクライアントを使って

Javaをインストールする必要がない他の選択肢はありますか?

役に立ちましたか?

解決

私はマイクロソフトサポートからの答えを得ました: vsoのAA CRESは現時点でtf.exeでは動作しません。TEE CLCまたはオブジェクトモデルコードを使用することは、現在唯一の代替案です。私たちは将来これをすることを見ています。

オブジェクトモデルコードとは、DLL内の Microsoft.TeamFoundation.VersionControl.Client.Client 名前空間を同じ名前で参照します。Javaをインストールせずに最新のコードをダウンロードするためのクイックC#コンソールアプリを書き始めました。このアプローチの追加の利点は、スローアウェイワークスペースを作成する必要がないということです。

以下のコードを使用してtfsget.exeという実行可能ファイルを作成する場合は、このようなコマンドラインから呼び出すことができます。

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

と私は使用できる各ファイルのリストを抑制するためのサイレントスイッチを追加しました:

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

これはコードです、これがMSアップデートまで助けることを願っています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;
        }
    }
}
.

他のヒント

これはスニペットです。 Net TFSライブラリ PowerShell 統合 - tf.exe はVSOとうまくいかない承認他の誰かがこの経路を使って成功した場合は興味があります。 adfs を使用しているので、PowerShellプロセスは私たちが認証したいユーザーとして実行されます。

tf最新のWorkspace.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
.

これはTfsClientCredentialsをサポートするように簡単に拡張できます( i.e。代替アクセス認証情報)。私はそれがコンパイルまたはコピーする追加のEXEを必要としないので、PowerShellアプローチを好む。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top