I have some code to automate the creation of build definitions in TFS.
Now I'd like to have this code invoked whenever a branch is created.
Looking at the API, I see that there is a BranchObjectCreatedEvent in Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer.
So I've added some code to a console app to handle the event.
private static void MonitorBranchCreated()
{
try
{
TfsTeamProjectCollection tfs = InitialiseTfs();
var vcs = tfs.GetService<VersionControlServer>();
var projects = vcs.GetAllTeamProjects(true);
foreach (var project in projects)
{
project.VersionControlServer.BranchObjectCreated += BranchObjectCreated;
}
Console.WriteLine("Subscribed to TFS BranchObjectCreated Event - Awaiting Notification...");
Console.ReadLine();
}
catch (Exception exception)
{
DisplayError(exception);
}
}
private static void BranchObjectCreated(object sender, BranchObjectCreatedEventArgs e)
{
// Create the Build
}
The trouble is that the event never fires when I create a branch from Source Control Explorer in Visual Studio.
The MSDN documentation is limited and I can't find any other examples of usage so I'm hoping somebody might be able to tell me if this is the correct approach.
If so, why might the event not be firing? If not, is there another way I can hook into TFS so that I can handle events related to creation of branches?
When you hook up events to the client API, you only get events that were created by that client. If you were to hook up a BranchObjectCreated listener, then call VersionControlServer.CreateBranch(), then your branch object created listener would be called.
If you want to listen to events on the server (such as when somebody else creates a branch, or you create a branch from a different client), then you need to tie into the server's project alert system.
You can install the Alerts Explorer in the Team Foundation Server Power Tools that will allow you to configure fine-grained alerts on projects that will send you email or call a web method. At this point, you can create a new build that references this new branch.
Related
I am trying to fetch Build Warning from MS Build,(in Build which contain or having number of solutions)
Is it possible to fetch using TFS API, or any TFS DB using QUERY ?
You could use this TFS REST API to get logs of a TFS builds. To get those logs out, you need to fetch those warnings by yourself. There's no API to only get warnings.
Http method: GET
http:/servername"8080/tfs/DefaultCollection/teamproject/_apis/build/builds/391/logs?api-version=2.0
You could also install a TFS ExtendedClient Nuget package to use TFS object model API.
Here is the code snippet:
Like the comment said above, the VNext build definition information couldn't be reached using the old version API. Install this TFS ExtendedClient Nuget package for your project, using the method below to get all build definitions.
using Microsoft.VisualStudio.Services.WebApi;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.TeamFoundation.Build.WebApi;
using Microsoft.TeamFoundation.Core.WebApi;
using Microsoft.VisualStudio.Services.Operations;
private static void GetBuildWarnings()
{
var u = new Uri("http://v-tinmo-12r2:8080/tfs/MyCollection/");
VssCredentials c = new VssCredentials(new Microsoft.VisualStudio.Services.Common.WindowsCredential(new NetworkCredential("username", "password", "domain")));
var connection = new VssConnection(u, c);
BuildHttpClient buildServer = connection.GetClient<BuildHttpClient>();
List<BuildLog> logs = buildServer.GetBuildLogsAsync("teamprojectname",buildId).Result;
foreach (BuildLog log in logs)
{
var list = buildServer.GetBuildLogLinesAsync("A92FB795-A956-45B5-A017-7A7DFB96A040",buildId,log.Id).Result; //A92FB795-A956-45B5-A017-7A7DFB96A040 is the team project Guid
foreach (var line in list)
{
if (l.Contains("[Warning]"))
{
Console.WriteLine(line);
}
}
}
Console.ReadLine();
}
I am trying to use the Azure Runtime Reconfiguration Pattern to allow me to change a appSetting in the normal Web.config file via PowerShell (later by Microsoft Azure Web Sites Management Library).
My problem is that the RoleEnvironment.Changing event is not being called in my MVC app, so the web app is being restarted. I have placed event set up code in the MVC Application_Start as described in the Azure article, i.e.
protected void Application_Start()
{
RoleEnvironment.Changing += RoleEnvironment_Changing;
RoleEnvironment.Changed += RoleEnvironment_Changed;
//normal MVC code etc...
AreaRegistration.RegisterAllAreas();
}
The event handlers are a straight copy of the handled from the Azure article and look like this:
private const string CustomSettingName = "TestConfig";
public static string TestConfigValue;
private static void RoleEnvironment_Changing(object sender,
RoleEnvironmentChangingEventArgs e)
{
RoleLogs.Add("RoleEnvironment_Changing: started");
var changedSettings = e.Changes.OfType<RoleEnvironmentConfigurationSettingChange>()
.Select(c => c.ConfigurationSettingName).ToList();
Trace.TraceInformation("Changing notification. Settings being changed: "
+ string.Join(", ", changedSettings));
if (changedSettings
.Any(settingName => !string.Equals(settingName, CustomSettingName,
StringComparison.Ordinal)))
{
Console.WriteLine("Cancelling dynamic configuration change (restarting).");
RoleLogs.Add("RoleEnvironment_Changing: restarting!");
// Setting this to true will restart the role gracefully. If Cancel is not
// set to true, and the change is not handled by the application, the
// application will not use the new value until it is restarted (either
// manually or for some other reason).
e.Cancel = true;
}
else
{
RoleLogs.Add("RoleEnvironment_Changing: change is OK. Not restarting");
Console.WriteLine("Handling configuration change without restarting. ");
}
}
private static void RoleEnvironment_Changed(object sender,
RoleEnvironmentChangedEventArgs e)
{
RoleLogs.Add("RoleEnvironment_ChangED: Starting");
Console.WriteLine("Updating instance with new configuration settings.");
foreach (var settingChange in
e.Changes.OfType<RoleEnvironmentConfigurationSettingChange>())
{
if (string.Equals(settingChange.ConfigurationSettingName,
CustomSettingName,
StringComparison.Ordinal))
{
// Execute a function to update the configuration of the component.
RoleLogs.Add("RoleEnvironment_ChangED: TestConfig has changed");
Console.WriteLine("TestConfig has changed.");
TestConfigValue = RoleEnvironment.GetConfigurationSettingValue(CustomSettingName);
}
}
}
I have added logs which prove that my RoleEnvironment_Changing and RoleEnvironment_Changed are not being called in the MVC WebApp which means the WebApp is restarted when I change an appSetting via PowerShell. This also means the RoleEnvironment.Changing event never gets to the WebJob.
I am using Azure SDK 2.7.0
Any ideas?
UPDATE
#richag gave me an answer, which made me realise that my problem is because I am using a App Service rather than a Cloud Service. This SO answer and plus this video (see at 5:00mins) talks about the difference (Note: the video is old so the name of the web app is different, but the concept is the same).
I don't really want to change this late in the development, and I have worked round the problem another way. Maybe on the next project and will look at Cloud Services as I can see some positives, like better control of my WebJobs configuration.
From the runtime reconfiguration pattern: "Microsoft Azure Cloud Services roles detect and expose two events that are raised when the hosting environment detects a change to the ServiceConfiguration.cscfg files" These events are not fired if you make changes to app.config/web.config files. Only when the cloud service configuration is changed, i.e. if you upload a new configuration file through the azure portal's configure tab or change a setting directly on the azure portal.
According to the debugger, none of the following events are fired when I update the Azure Portal to change an AppSetting for an ASP.NET WebAPI app:
RoleEnvironment.Changing
RoleEnvironment.Changed
RoleEnvironment.StatusCheck
RoleEnvironment.SimultaneousChanging
RoleEnvironment.SimultaneousChanged
RoleEnvironment.Stopping
Do others have different experience?
I can see custom menu items and custom conversation windows and events inside them but nothing referring to how you'd execute code once a user signs into Lync. Does such an API exist?
I guess my alternative would be creating a Lync Automation object/my own client using the Suppressed ui and building whatever features I want into one of those?
There's nothing you can build into the Lync application, but you could run a separate application which can subscribe to the SignIn state of the user. That way, you'd know when a user signs-in, and could take appropriate action. You wouldn't need to create a SuppressedUI application for that, just something that ran in the background, or taskbar or something.
Here's a bare bones example:
namespace ThoughtStuff
{
class Program
{
static void Main(string[] args)
{
var client = LyncClient.GetClient();
client.StateChanged += client_StateChanged;
}
static void client_StateChanged(object sender, ClientStateChangedEventArgs e)
{
if (e.NewState == ClientState.SignedIn)
{
//do something on sign in
}
}
}
}
You might get errors if you try and attach to Lync in the SDK code using LyncClient.GetClient() if the Lync exe isn't running...but if you know that's likely to be a problem (such as if your application might be running before the user starts Lync), then you can gracefully handle it and retry in code.
I have a custom checkin policy written in c# and I used VSIX project with custom action enabled on install. Installation is working great. If I have the custom checkin policy applied to the team project in TFS 2010 and I uninstalled my policy from the same installer, it is cleaning up the registry and the files, but the source control still have the policy enabled and throws an error Error loading the policy. I want my installer to remove the policy from the source control while uninstalling the policy. How can I achieve this?
I tried to write the following code in OnAfterUninstall event, but it is not doing what I need:
protected override void OnAfterUninstall(IDictionary savedState)
{
base.OnAfterUninstall(savedState);
RemovePolicy();
}
private void RemovePolicy()
{
try
{
TfsTeamProjectCollection projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(projectCollectionUri, new UICredentialsProvider());
projectCollection.EnsureAuthenticated();
VersionControlServer vcs = projectCollection.GetService<VersionControlServer>();
List<TeamProject> lstTeamProject = vcs.GetAllTeamProjects(true).ToList<TeamProject>();
foreach (TeamProject tp in lstTeamProject)
{
List<PolicyEnvelope> tc = tp.GetCheckinPolicies().ToList<PolicyEnvelope>();
var myPolicy = new MyCustomCheckinPolicy();
TeamProject teamProject = vcs.GetTeamProject(tp.Name);
foreach (PolicyType policyType in Workstation.Current.InstalledPolicyTypes)
{
if (policyType.Name == myPolicy.Type)
{
tc.Remove(new PolicyEnvelope(myPolicy, policyType));
teamProject.SetCheckinPolicies(tc.ToArray());
break;
}
}
}
}
catch (Exception ex)
{
throw new InstallException("My Error Message");
}
}
Because a custom checkin policy needs to be installed on all developer workstations that access the TFS Project, having it deregister itself from the TFS Project upon uninstall will actually remove the policy whenever any of these developers uninstalls it. Which isn't what you want I suspect.
There are ways to ensure the policy is distributed to all team members through the Team Foundation Power Tools, that way, should you need to ship an upgrade or a different policy, you'll be sure all members have it. Only do the deregistration manually through the UI.
I am trying to get the network prompt so that user can provide the credentials.
I saw this and It does not help. Could somebody provide a more complete example?
The goal is is to get this from a Word Add-in so that I can create work items in TFS from the function points mentioned in the word document. So, somebody writes the function points in a document, closes it and It would ask for the network credentials so that It can create work items in the TFS.
You want to use the UICredentialsProvider when connecting. Here's an example that shows how you would connect to a TFS 2010 Project Collection:
// Connect to a project collection by Uri
try
{
var projectCollectionUri = new Uri("http://tfs2010:8080/tfs/MyCollection");
var projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(projectCollectionUri, new UICredentialsProvider())
projectCollection.EnsureAuthenticated();
}
catch (TeamFoundationServerUnauthorizedException ex)
{
// handle access denied
}
catch (TeamFoundationServiceUnavailableException ex)
{
// handle service unavailable
}
catch (WebException ex)
{
// handle other web exception
}