Visual Studio 2015 build drop location - c#

Our company recently updated TFS to 2015 update 1. After that context menu item named Drop folder disappeared from completed builds. I found nothing about it and how to bring it back. When I click Open on completed build, VS opens web version of TFS where I forced to click through the menus and copy drop folder path manually. So I decided to write a simple extension that will add this item to the menu.
Some googling brought me to this page. But it seems that the example code is quite old and not working in VS2015:
IVsTeamFoundationBuild vsTfBuild = (IVsTeamFoundationBuild)GetService(typeof(IVsTeamFoundationBuild));
IBuildDetail[] builds = vsTfBuild.BuildExplorer.CompletedView.SelectedBuilds;
Property SelectedBuilds is always empty. I suppose that it relates to old window from VS2010. It returns items that are instance of IBuildDetail interface.
So I found this piece of code here:
var teamExplorer = (ITeamExplorer)ServiceProvider.GetService(typeof(ITeamExplorer));
var page = teamExplorer.CurrentPage;
var buildsPageExt = (IBuildsPageExt)page.GetExtensibilityService(typeof(IBuildsPageExt));
var build = buildsPageExt.SelectedBuilds[0];
Here build is the instance of IBuildModel interface. It lacks DropLocation property.
Is there any way to found drop location of selected build? Or maybe latest build?

You can use IBuildDedetail.DropLocation in .NET client libraries for Visual Studio Team Services (and TFS). Basic code for your reference:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
namespace BuildAPI
{
class Program
{
static void Main(string[] args)
{
string project = "http://xxx.xxx.xxx.xxx";
TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri(project));
IBuildServer ibs = tpc.GetService<IBuildServer>();
var builds = ibs.QueryBuilds("TeamProjectName");
foreach (IBuildDetail ibd in builds)
{
Console.WriteLine(ibd.DropLocation);
Console.ReadLine();
}
}
}
}

So, after digging through TFS API, I ended up with this workaround.
private void MenuItemCallback(object sender, EventArgs e)
{
var context = (ITeamFoundationContextManager)ServiceProvider.GetService(typeof(ITeamFoundationContextManager));
IBuildServer buildServer = context.CurrentContext.TeamProjectCollection.GetService<IBuildServer>();
var teamExplorer = (ITeamExplorer)ServiceProvider.GetService(typeof(ITeamExplorer));
var buildsPageExt = (IBuildsPageExt)teamExplorer.CurrentPage.GetExtensibilityService(typeof(IBuildsPageExt));
var menuCommand = (MenuCommand)sender;
if (menuCommand.CommandID.Guid == CommandSetCompleted)
{
foreach (var buildDetail in buildsPageExt.SelectedBuilds)
Process.Start("explorer.exe", GetBuild(buildServer, buildDetail).DropLocation);
}
if (menuCommand.CommandID.Guid == CommandSetFavorite)
{
var definitions = buildsPageExt.SelectedFavoriteDefinitions.Concat(buildsPageExt.SelectedXamlDefinitions).ToArray();
foreach (var build in GetLatestSuccessfulBuild(buildServer, definitions))
Process.Start("explorer.exe", build.DropLocation);
}
}
private IBuildDetail GetBuild(IBuildServer buildServer, IBuildModel buildModel)
{
Uri buildUri = new Uri(buildModel.GetType().GetProperty("UriToOpen").GetValue(buildModel).ToString());
return buildServer.GetBuild(buildUri);
}
private IBuildDetail[] GetLatestSuccessfulBuild(IBuildServer buildServer, IDefinitionModel[] buildDefinitions)
{
var spec = buildServer.CreateBuildDetailSpec(buildDefinitions.Select(bd => bd.Uri));
spec.MaxBuildsPerDefinition = 1;
spec.QueryOrder = BuildQueryOrder.FinishTimeDescending;
spec.Status = BuildStatus.Succeeded;
var builds = buildServer.QueryBuilds(spec);
return builds.Builds;
}

Related

Registry.LocalMachine.OpenSubKey() returns a result different from Registry Editor

I'm trying to Create an installer for my CAD plugin, and need to get the AutoCAD install location. but the return values of RegistryKey.GetSubKeyNames() is different from what I see in Registry Editor.
string registry_key = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
using (Microsoft.Win32.RegistryKey key = Registry.LocalMachine.OpenSubKey(registry_key))
{
foreach (string subkey_name in key.GetSubKeyNames())
{
Console.WriteLine(subkey_name);
}
}
output:
AddressBook
Autodesk Application Manager
Autodesk Content Service
Autodesk Material Library 2015
Autodesk Material Library Base Resolution Image Library 2015
Connection Manager
DirectDrawEx
DXM_Runtime
f528b707
Fontcore
...
In Registry Editor:
animizvideocn_is1
AutoCAD 2015
Autodesk 360
Connection Manager
...
AutoCAD 2015 is what i need
Your installer seems to be a 32 bit application, or at least runs as a 32 bit process.
Therefore, Windows redirects
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
to
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
To access the non redirected node, follow the instructions here.
This might be not a direct answer to your question, but i had to do the same thing. I was not looking at the registry, but the Program Files directory. It will then add the netload command to the autoload lisp file. It will install a list of Plugin dlls to all installed autocad versions. This can easily be changed... Hopefully it helps.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace AMU.AutoCAD.Update
{
public class AutoCadPluginInstaller
{
private static readonly Regex AutoloadFilenameRegex = new Regex("acad([\\d])*.lsp");
public void Install(IEnumerable<string> pluginFiles)
{
var acadDirs = this.GetAcadInstallationPaths();
var autoloadFiles = acadDirs.Select(this.GetAutoloadFile);
foreach (var autoloadFile in autoloadFiles)
this.InstallIntoAutoloadFile(autoloadFile, pluginFiles);
}
private void InstallIntoAutoloadFile(string autoloadFile, IEnumerable<string> pluginFiles)
{
try
{
var content = File.ReadAllLines(autoloadFile).ToList();
foreach (var pluginFile in pluginFiles)
{
var loadLine = this.BuildLoadLine(pluginFile);
if(!content.Contains(loadLine))
content.Add(loadLine);
}
File.WriteAllLines(autoloadFile, content);
}
catch (Exception ex)
{
//log.Log();
}
}
private string BuildLoadLine(string pluginFile)
{
pluginFile = pluginFile.Replace(#"\", "/");
return $"(command \"_netload\" \"{pluginFile}\")";
}
private IEnumerable<string> GetAcadInstallationPaths()
{
var programDirs =
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
var autoDeskDir = Path.Combine(programDirs, "Autodesk");
if (!Directory.Exists(autoDeskDir))
return null;
return Directory.EnumerateDirectories(autoDeskDir)
.Where(d => d.Contains("AutoCAD"));
}
private string GetAutoloadFile(string acadDir)
{
var supportDir = Path.Combine(acadDir, "Support");
var supportFiles = Directory.EnumerateFiles(supportDir);
return supportFiles.FirstOrDefault(this.IsSupportFile);
}
private bool IsSupportFile(string path)
=> AutoloadFilenameRegex.IsMatch(Path.GetFileName(path));
}
}
(see here: https://gist.github.com/felixalmesberger/4ff8ed27f66f872face4368a13123fff)
You can use it like this:
var installer = new AutoCadPluginInstaller();
installer.Install(new [] {"Path to dll"});
Have fun.

The name 'CrossMedia' does not exist in the current context C# error

I am writing code for a media plug-in in Xamarin Studio, and apparently I have the following error when I try to build the app:
"The name 'CrossMedia' does not exist in the current context"
I have been trying to find a fix for the problem. Below, is the code.
using System;
using Relate.Model;
using Xamarin.Forms;
using System.IO;
namespace Relate.Views
{
public partial class EditMemberPage : ContentPage
{
public EditMemberPage()
{
InitializeComponent();
}
async void TakeaPhoto_OnClicked(object sender, EventArgs e)
{
if (CrossMedia.Current.IsCameraAvailable && CrossMedia.Current.IsTakePhotoSupported)
{
// Supply media options for saving our photo after it's taken.
var mediaOptions = new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory = "Receipts",
Name = $"{DateTime.UtcNow}.jpg"
};
// Take a photo of the business receipt.
var file = await CrossMedia.Current.TakePhotoAsync(mediaOptions);
}
if (CrossMedia.Current.IsCameraAvailable && CrossMedia.Current.IsTakeVideoSupported)
{
// Supply media options for saving our video after it's taken.
var mediaOptions = new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory = "Videos",
Name = $"{DateTime.UtcNow}.mp4"
};
// Record a video
var file = await CrossMedia.Current.TakeVideoAsync(mediaOptions);
}
// Select a photo.
if (CrossMedia.Current.IsPickPhotoSupported)
{
var photo = await CrossMedia.Current.PickPhotoAsync();
}
// Select a video.
if (CrossMedia.Current.IsPickVideoSupported)
{
var video = await CrossMedia.Current.PickVideoAsync();
}
}
async void SaveButton_OnClicked(object sender, EventArgs e)
{
var famMemberItem = (FamMember)BindingContext;
await App.Database.SaveFamMemberAsync(famMemberItem);
await Navigation.PopAsync();
}
}
}
Add using Plugin.Media; to the start of your file
Try initialize the plugin first before using it as said in its documentation.
await CrossMedia.Current.Initialize();
I know this is an old question now but I had the same problem having installed the package using the NuGet Package Manager CLI in VS2017 with:
Install-Package Xam.Plugin.Media
It seemed as though installation was not an issue but I was wrong. What I didn't realise is that it only installed it for the Android project and not for all projects. To do this you have to right click on the Solution at the top and select Manage NuGet Packages for Solution. Click on the Xam.Plugin.Media package and in an adjacent pane it will tell you whether you have it installed for all the projects in the solution with check boxes. If you have any gaps, you can then check the boxes and hit Install to complete the setup. This is mine after I corrected the issue:

Total number of labels inside a module of TFS repository

I need to find out how many labels are there inside each module of a collection in Team Foundation repository.
I am using TFS 2013.
I know we can get it from Visual Studio. But we need a script which gets us the number of labels as output.
Can anyone help me out in getting a C# or a Powershell code to obtain the same?
TIA
You can use .NET Client Libraries to get this: .NET client libraries for Visual Studio Team Services (and TFS)
Code sample:
using System;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
namespace GetLabels
{
class Program
{
static void Main(string[] args)
{
string tfscollection = "http://xxx:8080/tfs/defaultcollection";
TfsTeamProjectCollection ttpc = new TfsTeamProjectCollection(new Uri(tfscollection));
VersionControlServer vcs = ttpc.GetService<VersionControlServer>();
string labelname = null;
string labelscope = "$/";
string owner = null;
bool includeitem = false;
int labelnumber;
VersionControlLabel[] labels = vcs.QueryLabels(labelname,labelscope,owner,includeitem);
labelnumber = labels.Length;
Console.WriteLine(labelnumber);
Console.ReadLine();
}
}
}

test build agents of a build controller using tfs api

I want to automate testing of newly created build agents in TFS.
Now, I have written code to queue builds of particular build definition on TFS.
Problem I am facing is to queue build definition on agents of given controller.
Previously there was one method which I've commented in my code
for doing this, i.e. IbuildRequest.buildagent, but now it has been deprecated in newer tfs api.
Edit:
I have already tested IbuildRequest.BuildController property which tends to randomly pick agent, which is currently free.
What I want to know is can I force build definition to use one build Agent using tfs api.
using System;
using System.Linq;
using System.Security.Principal;
using System.Collections.Generic;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
namespace BuildAgentsTestApp
{
class Program
{
static void Main(string[] args)
{
Uri collectionURI = new Uri("https://tfs-uri");
var tfsCreds = new TfsClientCredentials(new WindowsCredential(), true);
TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(collectionURI,tfsCreds);
WindowsIdentity user = WindowsIdentity.GetCurrent();
tfs.EnsureAuthenticated();
if (tfs.HasAuthenticated)
{
WorkItemStore workItemStore = tfs.GetService<WorkItemStore>();
Project teamProject = workItemStore.Projects["myProjectName"];
IBuildServer buildServer = (IBuildServer)tfs.GetService(typeof(IBuildServer));
IBuildDefinition buildDef = buildServer.GetBuildDefinition(teamProject.Name, "myBuildDefinitionName");
var controller = GetRequestedController(buildServer, "myControllerName");
var AgentsList = GetAgentCollection(controller);
//Queue each build definition
IBuildRequest buildRequest = buildDef.CreateBuildRequest();
buildRequest.GetOption = GetOption.Custom;
//buildRequest.BuildAgent = AgentsList.First();
buildServer.QueueBuild(buildRequest);
}
Console.WriteLine("Build Queued!");
Console.ReadKey();
}
static IBuildController GetRequestedController(IBuildServer reqBuildServer, string reqControllerName)
{
var requiredController = reqBuildServer.QueryBuildControllers()
.Where(ctrl =>
ctrl.Name == reqControllerName
).FirstOrDefault();
return requiredController;
}
static List<IBuildAgent> GetAgentCollection(IBuildController controller)
{
var ListOfAgents = from agent in controller.Agents
select agent;
return ListOfAgents.ToList();
}
}
}

How to set up google-diff-match-patch C# library

So I am a newbie and I couldn't find a proper answer to this on the internet.
After digging a little bit here is what I came up with.
Download google-diff-match-patch from here
One you have extracted it, open up your microsoft visual studio project
Go to View->Solution Explorer or press Ctrl+Alt+L
In solution Explorer right click on your project name and go to Add->Existing Item... or press Shift+Alt+A
In the dialog box that appears locate your diff-match-patch folder and go in csharp directory and select DiffMatchPatch.cs and click on Add
Then in solution explorer right click on References->Add Reference...
Search for System.Web and add it.
Now come back to your program (in my case Form1.cs) and type
using DiffMatchPatch;
Now you are ready to use all the functions of the diff-match-patch library in your C# program
Alternatively, add the Nuget Package DiffMatchPatch and add it to your project.
A Demo Code is as follows :
using System;
using System.IO;
using DiffMatchPatch;
namespace ConsoleApp_DMPTrial
{
class Program
{
static void Main(string[] args)
{
var dmp = DiffMatchPatchModule.Default;
string file1Content = "";
string file2Content = "";
using (StreamReader sr = new StreamReader("file1.json"))
{
file1Content = sr.ReadToEnd();
}
using (StreamReader sr = new StreamReader("file2.json"))
{
file2Content = sr.ReadToEnd();
}
var diffs = dmp.DiffMain(file1Content, file2Content);
dmp.DiffCleanupSemantic(diffs);
for (int i = 0; i < diffs.Count; i++)
{
Console.WriteLine(diffs[i]);
}
Console.ReadLine();
}
}
}

Categories

Resources