Find and delete inactive tfs branches - sql-server

Is there any built-in way to find and delete (tf destroy) branches of TFS project that were inactive (I mean there were no check in operations) for a long time, let's say 1 month. Either tfs tools or maybe sql script that can do it would be ok.

You can do it but you need to write a small program that uses the TFS API to check each branch and delete the unused ones.
You can use a simple C# console app and I can tell you from experience that the TFS public API is quite intuitive and easy to use. You can get started with it here.
Here's how to display all the branches.

Unused branches contain element modification history, rather than deleting them writelock the branch and leave it. The space that is recovered is not significant.

Well, whole thing wasn't hard, posting code here, might help someone:
private static string _tfLocation; //location of tf.exe
private static string _tfProject; //our team project
static void Main(string[] args)
{
_tfLocation = ConfigurationManager.AppSettings.Get("tfLocation");
_tfProject = ConfigurationManager.AppSettings.Get("tfProject");
var keepAliveBranches = ConfigurationManager.AppSettings.Get("keepAliveBranches").Split(',').ToList(); //branches that we keep anyway
var latestDate = DateTime.Now.AddMonths(-3); //we delete all branches that are older than 3 months
var folders = ExecuteCommand(string.Format("dir /folders \"{0}\"", _tfProject));
var branches = folders.Split('\r', '\n').ToList();
branches = branches.Where(b => !string.IsNullOrEmpty(b) && b.StartsWith("$")).Select(b => b.Remove(0, 1)).Skip(1).ToList();
branches.ForEach(b => b = b.Remove(0, 1));
foreach (var branch in branches)
{
if (keepAliveBranches.Contains(branch))
continue;
//get latest changeset
var lastChangeset = ExecuteCommand(string.Format("history \"{0}/{1}\" /recursive /stopafter:1 /format:brief /sort:descending /noprompt", _tfProject, branch));
var changesetDate = DateTime.Parse(Regex.Match(lastChangeset, #"\d{2}\.\d{2}\.\d{4}").Value); //get it's date
if (changesetDate < latestDate)
//destroy
ExecuteCommand(string.Format("destroy \"{0}/{1}\" /recursive /stopafter:1 /startcleanup /noprompt /silent", _tfProject, branch));
}
}
//execute console command and get results
private static string ExecuteCommand(string command)
{
var process = new Process()
{
StartInfo = new ProcessStartInfo(_tfLocation)
{
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true,
Arguments = command
},
};
process.Start();
var result = process.StandardOutput.ReadToEnd();
process.WaitForExit();
return result;
}

Related

Programmatically add Checkbox Content Controls to Word document using OpenXML

Is there an easy/straightforward way to dynamically add (not edit the value of) multiple checkbox controls in a .docx document body?
I tried appending a single SdtContentCheckBox after a new paragraph like this but with no luck:
newParagraph.Append(new SdtContentCheckBox());
and also followed the instructions here:
https://www.codeproject.com/Tips/370758/Add-dynamic-content-controls-to-a-word-document and here: How do I create a check box in C# using Open XML SDK
The first one showed only how to add a text content control and the second one straight up resulted in a corrupted .docx file.
Any help would be appreciated!
Closest working code I could find was this:
https://social.msdn.microsoft.com/Forums/office/en-US/f6ce8ecf-0ed8-4f18-958a-a086f212d1e2/how-to-create-a-checked-checkbox-form-field-using-the-sdk?forum=oxmlsdk
public static Paragraph GenerateParagraph()
{
var element =
new Paragraph(
new Run(
new FieldChar(
new FormFieldData(
new FormFieldName(){ Val = "Check1" },
new Enabled(),
new CalculateOnExit(){ Val = BooleanValues.Zero },
new CheckBox(
new AutomaticallySizeFormField(),
new DefaultCheckboxFormFieldState(){ Val = BooleanValues.Zero }))
){ FieldCharType = FieldCharValues.Begin }),
new BookmarkStart(){ Name = "Check1", Id = 0 },
new Run(
new FieldCode(" FORMCHECKBOX "){ Space = "preserve" }),
new Run(
new FieldChar(){ FieldCharType = FieldCharValues.End }),
new BookmarkEnd(){ Id = 0 },
new Run(
new Text("My check box"))
){ RsidParagraphAddition = "00784880", RsidRunAdditionDefault = "00B77989" };
return element;
}
Using this I was able to dynamically add Legacy Checkboxes (i.e. neither Content control nor ActiveX control), but at least it is a start!
If someone knows how to add Checkbox Content controls, feel free to post a reply below and I'll mark it as Correct.
Even though you found yourself the answer, I'll leave this here in case anyone stumbles upon this looking for something related.
There's a tool called Open XML SDK 2.5 Productivity Tool, which you can download from here that allows you to reverse-engineer a word .docx document to obtain the C# code to generate it from scratch.
In order to get the code that you are looking for to generate any kind of word element (a checkbox, a table, a bulleted list...), you need to create a word document with said element and save it.
Then, open it using the Open XML SDK 2.5 Productivity Tool and click on the "Reflect Code" button. The generated code will show you how to create those elements, styles and other formatting included.
With that, I got the code necessary to get a paragraph with a checkbox
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using A = DocumentFormat.OpenXml.Drawing;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
public static Paragraph GenerateCheckboxParagraph(string internalName, int internalId, string textAfterTextbox)
{
var run1 = new Run(
new FieldChar(
new FormFieldData(
new FormFieldName() { Val = internalName },
new Enabled(),
new CalculateOnExit() { Val = OnOffValue.FromBoolean(false) },
new CheckBox(
new AutomaticallySizeFormField(),
new DefaultCheckBoxFormFieldState() { Val = OnOffValue.FromBoolean(false) }))
)
{
FieldCharType = FieldCharValues.Begin
}
);
var run2 = new Run(new FieldCode(" FORMCHECKBOX ") { Space = SpaceProcessingModeValues.Preserve });
var run3 = new Run(new FieldChar() { FieldCharType = FieldCharValues.End });
var run4 = new Run(new Text(textAfterTextbox));
var element =
new Paragraph(
run1,
new BookmarkStart() { Name = internalName, Id = new StringValue(internalId.ToString()) },
run2,
run3,
new BookmarkEnd() { Id = new StringValue(internalId.ToString()) },
run4
);
return element;
}

TFS2015: Full File Path Stored in SQL Database

I'm looking to see if the SQL Database behind TFS2015 (or any version of TFS, in this case 2015 or 2010) stores the full file path for a file. There is information that we include in the Project folder (namely the version number) and while I realize there are better ways to track this information, we have a lot of legacy data that only has the version stored within this path. I want to pull the data into Crystal Reports to strip off the information and then use it.
You want to get a list of folders in TFS Source Control, instead of querying in database, we recommend to achieve it programmatically. The blog below and the sample code associated with it will do what you want:
http://blogs.microsoft.co.il/blogs/shair/archive/2009/02/26/tfs-api-part-16-mapping-source-control-using-versioncontrolserver.aspx
Also, check the code snippet in this case, which should help you:
ICommonStructureService structureService = (ICommonStructureService)Tfscollection.GetService(typeof(ICommonStructureService));
ProjectInfo[] projects = structureService.ListAllProjects();
//combo_projects.ItemsSource = projects;
////Create VersionControlServer object from TFS
//sourceControl = (VersionControlServer)tfs.GetService(typeof(VersionControlServer));
RecursionType recursion = RecursionType.OneLevel;
Item[] items = null;
string path = "$/" + projects[0].Name;//"$/TescoPOC/FetchStoryfromTFS";
ItemSet itemSet = versionControl.GetItems(path, recursion);
items = itemSet.Items;
//Dictionary<string, int> FolderListName = new Dictionary<string, int>();
List<string> FolderListName = new List<string>();
foreach (Item keyItem in items)
{
char[] charSeparators = new char[] { '/' };
//Using split to isolated the Project Name and the File Name
string[] ss = keyItem.ServerItem.Split(charSeparators, StringSplitOptions.None);
if (keyItem != items[0])
{
string filename = keyItem.ServerItem.Replace(path + "/", string.Empty);
if (filename != "BuildProcessTemplates")
{
FolderListName.Add(filename);
//if (FolderListName.ContainsKey(filename))
// FolderListName[filename] = FolderListName[filename] + 1;
//else
// FolderListName.Add(filename, 1);
}
}
}

XPSDocumentWriter - Printing Specific Pages to Specific Trays

I'm currently working on a printing application. This app has the requirement that certain pages need to come from specific trays on the printer. Here's the guts of what I've got so far:
foreach (var dto in dispensersToPrint)
{
var documents = FilterDocumentSections(DispenserDocumentsToPrint.RetrieveByDispenserId(dto.DispenserId));
var groupedDocs = documents.GroupBy(t => t.DocumentTypeId);
var queueName = Properties.Settings.Default.PrinterName;
var queue = RawPrinterHelper.GetPrintQueue(queueName);
var seq = new FixedDocumentSequence();
var xpsWriter = PrintQueue.CreateXpsDocumentWriter(queue);
foreach (var docGroup in groupedDocs)
{
var printTicket = queue.DefaultPrintTicket.Clone();
var printTray = MapPrintTray((DocumentSectionType)docGroup.Key);
if (!printTray.IsNullOrEmpty())
{
printTicket = RawPrinterHelper.ModifyPrintTicket(printTicket, "psk:JobInputBin", printTray);
}
var fixedDoc = new FixedDocument();
fixedDoc.PrintTicket = printTicket;
foreach (var doc in docGroup)
{
var pageContent = new PageContent();
var fixedPage = new FixedPage();
var localFileName = string.Empty;
var unzippedFileName = string.Empty;
//copy files locally
localFileName = CopyFileToLocalMachine(doc.FileName);
//unzip file
unzippedFileName = EmfPrintingHelper.UnzipEmfFile(localFileName);
var itemToPrint = new PrintableEmfImage
{
DataContext = new EmfImageViewModel { FileName = unzippedFileName }
};
fixedPage.Children.Add(itemToPrint);
pageContent.Child = fixedPage;
fixedDoc.Pages.Add(pageContent);
}
var docRef = new DocumentReference();
docRef.SetDocument(fixedDoc);
seq.References.Add(docRef);
}
xpsWriter.Write(seq);
}
At a real high level:
For each Dispenser (Work Order) i need to print; i first start by grouping by the DocumentType (i.e. Print type A to tray 1)
I then create a new FixedDocumentSequence
For each DocumentType; I then create a fixed document. I then modify the print ticket to look at the appropriate tray.
I then build each individual page for each document type; and add them to the FixedDocument
Once the building of the FixedDocument is complete; I append it to the DocumentSequence.
I then send the FixedDocumentSequence to the xpsWriter.
But for some reason; these settings aren't being honored. I get all the documents printing out of the same tray.
Here are some of my observations so far:
The modifying of the print ticket does work; I've verified this by sending a modified printTicket into the xpsWriter; but this applies the settings to the entire job; which is a no go for me.
When querying my print capabilities; i noticed that i only have JobInputBin. I don't quite think this means this printer doesn't support the functionality; as multi-tray printing works from a similar WindowsForms app (which uses PageSettings.PaperSource)
Any ideas on what I could try next? Has anyone been successful doing something like this before?
I'll start off by saying, I don't have access to a printer with trays, so I am unfortunately not capable of testing this solution. That said, I'll direct your attention to an MSDN forum post, here, where the original poster was in pursuit of the same tray-per-page behavior.
Based on your posted code, you may have already seen some of what's in this post, judging by your posted code having at least some implementation of ModifyPrintTicket().
In the post, there are several different users, each citing a solution for their specific version of the problem. However, the one that seems most relevant in this case is the solution regarding namespaces not being correctly accounted for in ModifyPrintTicket() (as posted by
Jo0815). I say 'most relevant' because the poster speaks of the print tray being disregarded. They (wittersworld) provide an alternate implementation to correct the issue. In the post on MSDN, the link to the complete source is broken, but can be located here.
The gist is, on ModifyPrintTicket(), they add a namespaceUri parameter, then withing changed this:
if (node != null)
{
node.Attributes["name"].Value = newValue;
}
to this:
if (node != null)
{
if (newValue.StartsWith("ns0000"))
{
// add namespace to xml doc
XmlAttribute namespaceAttribute = xmlDoc.CreateAttribute("xmlns:ns0000");
namespaceAttribute.Value = namespaceUri;
xmlDoc.DocumentElement.Attributes.Append(namespaceAttribute);
}
node.Attributes["name"].Value = newValue;
}
allowing the user to specify the printer-specific namespace used.
I hope this is helpful.

Winforms ReportViewer passing null for parameters even when the parameters are set

Even though I set the parameters in the code, I keep getting that a parameter must be set error. I have run profiler to see what is being passed to SSRS, and profiler indicates that parameters = null. Yet all of them are set in code. Anyone have any ideas? The code is as follows:
string strReportPath;
Microsoft.Reporting.WinForms.ReportParameter prmFranchiseOID;
Microsoft.Reporting.WinForms.ReportParameter prmSchoolOID;
Microsoft.Reporting.WinForms.ReportParameter prmRoomOID;
Microsoft.Reporting.WinForms.ReportParameter prmOrderDate;
Microsoft.Reporting.WinForms.ReportParameter prmLanguage;
Microsoft.Reporting.WinForms.ReportParameter prmContrast;
List<Microsoft.Reporting.WinForms.ReportParameter> prms = new List<ReportParameter>();
byte[] pdf = null;
try
{
prmFranchiseOID = new Microsoft.Reporting.WinForms.ReportParameter("FranchiseOID", "8D126AA2-2E5C-4B2B-8D19-167027F8C7D8");
prmSchoolOID = new Microsoft.Reporting.WinForms.ReportParameter("SchoolOID", "96FEE335-0CB9-413A-9DDC-78F8C67770C4");
prmRoomOID = new Microsoft.Reporting.WinForms.ReportParameter("RoomOID", "null");
prmOrderDate = new Microsoft.Reporting.WinForms.ReportParameter("OrderDate", DateTime.Now.AddDays(1).Date.ToString());
prmLanguage = new Microsoft.Reporting.WinForms.ReportParameter("Language", "en-CA");
prmContrast = new Microsoft.Reporting.WinForms.ReportParameter("Contrast", "true");
prms.Add(prmFranchiseOID);
prms.Add(prmSchoolOID);
prms.Add(prmRoomOID);
prms.Add(prmOrderDate);
prms.Add(prmLanguage);
prms.Add(prmContrast);
// Note: For Account Holder users, their specified report folder is "/LunchLady/User".
strReportPath = "/LunchLady/Franchise/" + urlReportName;
try
{
rvReport.ServerReport.ReportServerUrl = new System.Uri("https://testsql.thelunchlady.ca/ReportServer");
rvReport.ServerReport.ReportPath = strReportPath;
rvReport.ServerReport.SetParameters(prms);
string ReportType = "PDF";
pdf = rvReport.ServerReport.Render(ReportType);
Thanks
Having done extensive programming on the SSRS controls in ASP.NET, one thing that I've found which may or may not be relevant for WinForms is that each SSRS parameter is actually a collection in itself (due to parameters being able to be multi-select).
So what worked for us is that the collection (prms in your case) was of type
List<IEnumerable<ReportViewer.ReportParameter>> prms
Also when adding parameters using the SetParameters function we added them one at a time:
for (int i = 0; i < prms.Count; i++)
{
rvReport.ServerReport.SetParameters(prms[i]);
}
Again, this is what worked for us in ASP.NET, could be something for you to try.

How to know the order of update with Domain context SubmitChanges?

Suppose I have 3 entities generated from EF, say tab1, tab2 and tab3. In SL app, I call SubmitChanges to save data to DB, all changes will be process by WCF and EF automatically.
Question is: how can I know the order of Update operation in Database?
I need to know this because I have triggers on those tables and need to know the order of the updating.
One thing you can do is to override the PeristChangeSet() in your DomainService and manually control the order of saves. Just do nothing in your regular update/insert statements. Here's some pseudocode for a saving a document exmmple to explain my answer:
[Insert]
public void InsertDocument(MyDocument objDocument) { }
[Update]
public void UpdateDocument(MyDocument objDocument) { }
protected override bool PersistChangeSet()
{
try {
// have to save document first to get its id....
MyDocument objDocumentBeingSaved = null;
foreach (ChangeSetEntry CSE in ChangeSet.ChangeSetEntries.Where(i => i.Entity is MyDocument)) {
var changedEntity = (MyDocument)CSE.Entity;
objDocumentBeingSaved = documentRepository.SaveDocument(changedEntity);
break; // only one doc
}
if (objDocumentBeingSaved == null)
throw new NullReferenceException("CreateDocumentDomainService.PersistChangeSet(): Error saving document information. Document is null in entity set.");
// save document assignments after saving document object
foreach (ChangeSetEntry CSE in ChangeSet.ChangeSetEntries.Where(i => i.Entity is DocumentAssignment)) {
var changedEntity = (DocumentAssignment)CSE.Entity;
changedEntity.DocumentId = objDocumentBeingSaved.Id;
changedEntity.Id = documentRepository.SaveDocumentAssignment(objDocumentBeingSaved, changedEntity);
}
// save line items after saving document assignments
foreach (ChangeSetEntry CSE in ChangeSet.ChangeSetEntries.Where(i => i.Entity is LineItem)) {
var changedEntity = (LineItem)CSE.Entity;
changedEntity.DocumentId = objDocumentBeingSaved.Id;
changedEntity.Id = documentRepository.SaveLineItem(objDocumentBeingSaved, changedEntity);
}
documentRepository.GenerateDocumentNumber(objDocumentBeingSaved.Id);
}
catch {
// ....
throw;
}
return false;
}

Resources