I´d like to update a label that was applied to a branch programmatically. While searching for a method that would do the trick, I found the VersionControlServer.CreateLabel()-Method. https://msdn.microsoft.com/en-us/library/microsoft.teamfoundation.versioncontrol.client.versioncontrolserver.createlabel(v=vs.120).aspx
I tried it like this, but it doesn´t seem to work:
TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(new Uri(tfsuri));
var vcs = tfs.GetService<VersionControlServer>();
string labelscope = "$/MyProjects/" + machinenumber;
var specifiedBranch = vcs.QueryLabels(label, labelscope, null, true);
string branch = specifiedBranch[0].Items[0].ServerItem;
ItemSpec newItemSpec = new ItemSpec(branch, RecursionType.Full);
string newItem = specifiedBranch[0].Items[0].ServerItem;
newItemSpec.Item = newItem;
VersionSpec versSpec = new LabelVersionSpec(label);
LabelItemSpec newLabelItemSpec = new LabelItemSpec(newItemSpec, versSpec, false);
LabelItemSpec[] newLabelItemSpecList = new LabelItemSpec[1] { newLabelItemSpec };
string labelOwner = vcs.AuthenticatedUser;
string labelName = label.Insert(6, "ed");
VersionControlLabel labelToUpdate = new VersionControlLabel(vcs, labelName, labelOwner, branch, null);
vcs.CreateLabel(labelToUpdate, newLabelItemSpecList, LabelChildOption.Replace);
What I exactly want to do is to update the old label name from "Deploy" to "Deployed". I know how to do this with TF.exe, but it should work without TF.exe.
Does anyone has an code example how to use the CreateLabel()-Methode for updateting a existing label?
-- UPDATE --
I changed
LabelItemSpec newLabelItemSpec = new LabelItemSpec(newItemSpec, versSpec, true);
to
LabelItemSpec newLabelItemSpec = new LabelItemSpec(newItemSpec, versSpec, false);
Now a new Label is created for the same branch. I cann delete the old label with VersionControlServer.DeleteLabel. Then I get the result that I was looking for, But I still would like to know how to update correctly.
Renaming Labels is not supported by TFS. You can only create a new Label based on the old Label you want to remove. Details please see this link: Rename Label in Team Foundation Server
You could also verify this in VersionControlLabel Class.
Name Gets the name of this label.
It's only be able to get the name not set the name.
Update
For the LabelChildOption options in VersionControlServer::CreateLabel Method , there are three options:
Replace: Any item that you specify in your request that’s already in the label will be replaced by what you have specified.
Anything that’s not in the label already will be added to the
label, and existing items that aren’t modified by your request will
remain as they were.
Merge: Leave unmodified items that are in your request but that already exist in the label. Any item in your request that’s not
already in the label will be added to the label, and existing items
in the label that aren’t specified in your label will remain
unchanged.
Fail: Labels have the notion of a scope. The Fail option says that the call to create or update the label should fail if there is
at least one label by the same name that exists at a scope that would
be below the scope of the new label.
The update label only means update the itemSpecs parameter which means the item specs included in the label. So it's used to update the ItemSpec for the label – Which Files, Folder we want to Label.
Related
I am using the vanilla library of keepass simply by adding the .exe file to my project.
From my code I am accessing PwDatabase like so:
var dbpath = #"\\MyPath\To\PersonalVault\PersonalVault.kdbx";
var masterpw = "myPassword";
var ioConnInfo = new IOConnectionInfo { Path = dbpath };
var compKey = new CompositeKey();
compKey.AddUserKey(new KcpPassword(masterpw));
var db = new KeePassLib.PwDatabase();
db.Open(ioConnInfo, compKey, null);
From there I want to access and read the custom string field that I have previously manually added from the Advanced tab of entry on the UI:
var entry = db.RootGroup.FindEntry(new KeePassLib.PwUuid(KeePassLib.Utility.MemUtil.HexStringToByteArray("97A51FE92F700D4FB665DC6AA7C9D67D")), true);
var customString = entry.Strings.Where(lookingFor => lookingFor.Key.Equals("customString")).FirstOrDefault().Value;
However I end up with a null value here.
Any suggestion on how I can read this or is it simply not exposed through the vanilla KeePass.exe?
The "Entry" tab on KeePass.exe UI shows data stored in PwEntry (KeePass source code is downloadable here) with reserved key names. Reserved key names are shown in code sample below.
The "Advanced" tab on KeePass.exe UI stores strings with custom key names. So, when reading them in code, entry.Strings.ReadSafe("myCustomString") works (assuming that a custom string with that key name is present in the password entry). Below is the code that I tried and it works.
var pwUuid = new KeePassLib.PwUuid(KeePassLib.Utility.MemUtil.HexStringToByteArray("F3A8DC6E93571944B485AA947C68FB5E"));
var entry = db.RootGroup.FindEntry(pwUuid, true);
// Reserved key names ("Entry" tab on KeyPass.exe)
Console.WriteLine($"Title : {entry.Strings.ReadSafe("Title")}");
Console.WriteLine($"UserName: {entry.Strings.ReadSafe("UserName")}");
Console.WriteLine($"Password: {entry.Strings.ReadSafe("Password")}");
Console.WriteLine($"URL : {entry.Strings.ReadSafe("URL")}");
Console.WriteLine($"Notes : {entry.Strings.ReadSafe("Notes")}");
// Custom key names ("Advanced" tab on KeePass.exe)
Console.WriteLine($"myCustomString: {entry.Strings.ReadSafe("myCustomString")}");
This also made me wonder about clashes between reserved and custom key names. As expected KeePass.exe UI does show an error if I try to create a custom key with a reserved key name.
I am trying to run code from the Autodesk help
http://help.autodesk.com/view/RVT/2014/ENU/?guid=GUID-B6FB80F2-7A17-4242-9E95-D6056090E85B
private void CreateViewFilter(Autodesk.Revit.DB.Document doc, View view)
{
List<ElementId> categories = new List<ElementId>();
categories.Add(new ElementId(BuiltInCategory.OST_Walls));
ParameterFilterElement parameterFilterElement =
ParameterFilterElement.Create(doc, "Comments = foo", categories);
FilteredElementCollector parameterCollector = new FilteredElementCollector(doc);
Parameter parameter = parameterCollector.OfClass(typeof(Wall)).FirstElement().get_Parameter("Comments");
List<FilterRule> filterRules = new List<FilterRule>();
filterRules.Add(ParameterFilterRuleFactory.CreateEqualsRule(parameter.Id, "foo", true));
parameterFilterElement.SetRules(filterRules);
OverrideGraphicSettings filterSettings = new OverrideGraphicSettings();
// outline walls in red
filterSettings.SetProjectionLineColor(new Color(255, 0, 0));
view.SetFilterOverrides(parameterFilterElement.Id, filterSettings);
}
When I open a view and run the code more than once, I get the following error
Revit encounterd a argumentException. The given value for name is already in use as a filter element name parmeter name: name at ParameterFilterElement parameterFilterElement = ParameterFilterElement.Create(doc, "Comments= foo", categories). I can't see where this happened in the code.(OBS I change the get_parameter to lookupparameter in the original code above because the first is deprecated)
According to the docs, the second parameter to the Create method is name. The error message states that you are already using the name "Comments = Foo". So I think your best bet is to dynamically generate the name or provide a way for a user to specify the name.
After a little bit thinking I get it. Actually I should do that from the beginging. Anyway the prgram create filter and It is now in the view so when I run the command again there is already one. Thank you.
FilteredElementCollector Lincoln = new FilteredElementCollector(doc);
Lincoln.OfCategory(BuiltInCategory.OST_RvtLinks); Autodesk.Revit.DB.View CurrentView = uiDoc.ActiveView;
ICollection<ElementId> Toggle_On = Lincoln.ToElementIds(); Toggle_On.Clear();
ICollection<ElementId> Toggle_Off = Lincoln.ToElementIds(); Toggle_Off.Clear();
List<Element> Processed = new List<Element>();
List<string> Revit_On = new List<string>(); List<string> Revit_Off = new List<string>();
List<string> Revit_Names = new List<string>();
foreach (Element One_Link in Lincoln)
{
string Revit_Name = One_Link.Name;
if (!Revit_Names.Contains(Revit_Name))//prevents processing same link twice;/but does NOT change anyway!!!!
{
Revit_Names.Add(Revit_Name);
Boolean Is_Hidden = One_Link.IsHidden(CurrentView);//
if (Is_Hidden)
{
Toggle_On.Add(One_Link.Id); Revit_On.Add(One_Link.Name);
}//this apparently does detect what is hidden;
else
{
Toggle_Off.Add(One_Link.Id); Revit_Off.Add(One_Link.Name);
}
}
}
Transaction Do_Toggle = new Transaction(doc, "DoToggle");
Do_Toggle.Start();
if (!Toggle_Off.Count.Equals(0)) { CurrentView.HideElements(Toggle_Off); }
if (!Toggle_On.Count.Equals(0)) { CurrentView.UnhideElements(Toggle_On); }
Do_Toggle.Commit();
Is somehow the transaction failing? Undo is not available, so it doesn't think it has done anything that might need to be undone. Note that this EXACT code is used in another one of my addins (in which multiple optional sub-programs are controlled by picking radio options on a form). But when I am trying to use the code in a standalone version, it fails (without errors). Note also that I've inserted multiple TaskDialog entries to verify that it is indeed finding the RvtLinks that are either visible or hidden in the current view. But it is simply refusing to actually change their visibility. If I run the dialog controlled version, everything toggles, but if I immediately run the standalone, nothing toggles (proving it isn't uneditable pinned links). I have made this option available to users by making "Toggle Links" the default so they can call up my collected program and just hit a carriage return, but I need this to be a true standalone.
You code confuses me. For instance, why do you initialise the Toggle_On and Toggle_Off collections with member values, only to clear them immediately afterwards?
In any case, you use of the transaction does not follow the recommended pattern of enclosing it in a using statement.
Please refer to The Building Coder topic group on Handling Transactions and Transaction Groups for more information on using transactions in the Revit API.
I have an Editable ComboBox. The user enters text and presses a Save button. Their text is turned into a string.
I need it at Run Time to Create a new User Setting to the app.config with the name of their string. (I think this part works now).
Then another ComboBox's Selected Item is saved to the Setting. (Object reference not set error).
This is to create a custom preset that will save each control state, checkboxes, textboxes, etc. in the program.
// Control State to be Saved to Setting
Object comboBox2Item = ComboBox2.SelectedItem;
// User Custom Text
string customText = ComboBox1.Text;
// Create New User Setting
var propertyCustom = new SettingsProperty(customText);
propertyCustom.Name = customText;
propertyCustom.PropertyType = typeof(string);
Settings.Default.Properties.Add(propertyCustom);
// Add a Control State (string) to the Setting
Settings.Default[customText] = (string)comboBox2Item;
At this part I get an error.
Settings.Default[customText] = (string)comboBox2Item;
Exception:Thrown: "Object reference not set to an instance of an object."
I have tried setting ComboBox1.Text to an Object instead of string, with same error. The text and string is also not null.
Object customText = ComboBox1.Text;
Here's a visual of what I'm trying to do
Original Answer:
I haven't tried adding a new setting to the file but i have had to update it. Here is some code that I use to save and retrieve the saved changes to the file. I know it doesn't directly answer the question but should point you in the right direction as to what classes to look at and use.
I'll try to update to directly answer this question once I get some breathing time.
public static void UpdateConfig(string setting, string value, bool isUserSetting = false)
{
var assemblyPath = AppDomain.CurrentDomain.BaseDirectory;
var assemblyName = "AssemblyName";
//need to modify the configuration file, launch the server with those settings.
var config =
ConfigurationManager.OpenExeConfiguration(string.Format("{0}\\{1}.exe", assemblyPath, "AssemblyName"));
//config.AppSettings.Settings["Setting"].Value = "false";
var getSection = config.GetSection("applicationSettings");
Console.WriteLine(getSection);
var settingsGroup = isUserSetting
? config.SectionGroups["userSettings"]
: config.SectionGroups["applicationSettings"];
var settings =
settingsGroup.Sections[string.Format("{0}.Properties.Settings", assemblyName)] as ClientSettingsSection;
var settingsElement = settings.Settings.Get(setting);
settings.Settings.Remove(settingsElement);
settingsElement.Value.ValueXml.InnerText = value;
settings.Settings.Add(settingsElement);
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("appSettings");
Edited Answer:
I did a quick google search and found an accepted answer on the MSDN forum.MSDN question. You have to call save on the properties class in order for the add to take affect. Think of a database transaction, until you call commit, it doesn't take effect.
So what appears to be missing in your code is: Properties.Settings.Default.Save(); which should be the very next line after your Settings.Default.Properties.Add(propertyCustom);
I have C# code that creates a Visio Application instance, then opens some existing stencils so I can get the Shape Masters I need for my drawing. Visio 2013 changed things so I need 2 different stencils open. The issue is that I get 2 drawings open in Visio, 1 per stencil. When I build my document and save it, I can close it but there is still another empty drawing open. I also get an empty blank page in my active document where I am creating the drawing.
Visio.Application va = new Visio.Application();
va .Documents.Add(#"");
Visio.Documents vdocs = va.Documents;
const string templateNameU = "BASFLO_M.VSTX";
const string ConnectorStencilNameU = "BASFLO_M.VSSX";
const string RectangleStencilNameU = "BASIC_U.VSS";
const string stencilNameU = "CONNEC_U.VSSX";
const string connectorMasterNameU = "Dynamic Connector";
const string RectangleMasterNameU = "Rounded Rectangle";
Visio.Master connectorMaster = null;
Visio.Master rectangleMaster = null;
// open the templates we need
Visio.Document vc = vdocs.OpenEx(RectangleStencilNameU, short)Visio.VisOpenSaveArgs.visOpenDocked);
va.Documents.Add(templateNameU);
I have tried closing all the open drawings with:
foreach (Visio.Document d in va.Documents)
{
va.Documents[d.Name].Close();
}
va.ActiveDocument.Close();
but that is messy. The for loop for some reason doesn't close the active document. Is there a way to add multiple stencils to the same document and/or page so I am only working with one page? Is there a way to delete the blank page without resorting to a for loop to get the page name to delete it? I have looked through the API and don't see a way.
It looks like you are creating two documents.. i.e. the first (empty) one with va.Documents.Add("") and then the second one based on the template using va.Documents.Add(templateNameU).
If you don't want the first one, just don't create it.. Means, you can create new document, then open stencils, then draw, then close everything, like this:
var doc = va.Documents.Add(templateNameU)
var stn1 = va.Documents.Open(<first stencil>)
var stn2 = va.Documents.Open(<second stencil>)
// ... do stuff with the doc and then close everything...
doc.Close();
stn1.Close();
stn2.Close();
Am I missing something?
BTW, to get "Dynamic connector" you don't need to open the "Connector Stencil", it contains a specific dynamic connector. To get the default connector, you can just use Application.ConnectorToolDataObject
Also, you can connect shapes using shape.AutoConnect (this will also use the default connector)
Also, you don't need to open the stencil specifically actually. If it is part of the template, it will be opened automatically for you when you create a new drawing based on that template (so you can get them using Application.Documents[].
Maybe helpful? (draw 2 rectangles and connect them):
var doc = va.Documents.Add("BASICD_M.VSTX");
var stencil = va.Documents["BASIC_M.VSSX"];
var rectMaster = stencil.Masters["Rounded Rectangle"];
var rect1 = va.ActivePage.Drop(rectMaster, 1, 1);
var rect2 = va.ActivePage.Drop(rectMaster, 3, 1);
rect1.AutoConnect(rect2, Visio.VisAutoConnectDir.visAutoConnectDirNone);