public static class StringCollectionExtender { // Convert a string collection to a multiline string where // each entry in the collection becomes a line in // multi-line string public static string ToMultilineString( this StringCollection sc) { StringBuilder res = new StringBuilder(); foreach (string str in sc) { res.AppendLine(str); } return res.ToString(); } public static string[] ToStringArray( this StringCollection sc) { string[] res = new string[sc.Count]; sc.CopyTo(res, 0); return res; } // Convert a multiline string to a string collection with each line // of the string becoming a new entry in the collection public static StringCollection MultilineStringToStringCollection( string str) { string[] lines = str.Split('\r'); StringCollection res = new StringCollection(); foreach (string line in lines) { res.Add(line.Trim('\n')); } return res; } }
July 29, 2010
StringCollection Class Extender
A helper class for the StringCollection class.
July 28, 2010
Assembly Version Incrementor
Find and increment the assembly version info in an Assembly info file
public class AssemblyVersionIncrementor { public void IncrementAssemblyVersionString(FileSystemInfo fileInfo) { string[] lines = File.ReadAllLines(fileInfo.FullName); lines = IncrementAssemblyVersionString(lines); File.WriteAllLines(fileInfo.FullName, lines); } internal string[] IncrementAssemblyVersionString(string[] lines) { string[] res = new string[lines.Length]; int ix = 0; foreach (string line in lines) { res[ix++] = IncrementAssemblyVersionString(line); } return res; } // Could be modified to find other types of Version Info by // making the "AssemblyVersion" a parameter internal string IncrementAssemblyVersionString(string line) { string res = line; if (line.Contains("AssemblyVersion")) { string newLine = string.Empty; string str = line; // Check for comments int commentStart = line.IndexOf("//"); // TODO /* ... */ style comments if (commentStart >= 0) { str = line.Substring(0, commentStart); } if (str.Contains("AssemblyVersion")) { int start = str.IndexOf('"') + 1; int end = str.IndexOf('"', start); string assemblyVerStr = str.Substring(start, end - start); Version av = new Version(assemblyVerStr); Version newVer = av.IncrementRevision(); newLine = line.Substring(0, start) + newVer.ToString() + line.Substring(end, line.Length - end); } res = newLine.Length > 0 ? newLine : line; } return res; } }uses the following Version extension class:
internal static class VersionExtender { public static Version Increment(this Version version) { return Increment(version, 0x1L); } public static Version IncrementMajor(this Version version) { return Increment(version, 0x1000000000000L); } public static Version IncrementMinor(this Version version) { return Increment(version, 0x100000000L); } public static Version IncrementBuild(this Version version) { return Increment(version, 0x10000L); } public static Version IncrementRevision(this Version version) { return Increment(version, 0x1L); } // Good demo of using >> and << operators as well private static Version Increment(this Version version, ulong inc) { ulong versnNum = (((ulong)version.Major & 0xFFFF) << 48) + (((ulong)version.Minor & 0xFFFF) << 32) + (((ulong)version.Build & 0xFFFF) << 16) + ((ulong)version.Revision & 0xFFFF); versnNum += inc; UInt16 major = (UInt16)(versnNum >> 48); UInt16 minor = (UInt16)((versnNum >> 32) & 0xFFFF); UInt16 build = (UInt16)((versnNum >> 16) & 0xFFFF); UInt16 revision = (UInt16)(versnNum & 0xFFFF); return new Version(major, minor, build, revision); } }
Labels:
AssemblyVersion,
Bit shift operators,
extension class,
Version
July 21, 2010
Quickly Add Xml To XmlDocument
This line loads an Xml document, looks for the presence of a particular line and if it is not there, adds it to the xml document. This is useful for updating a config file with a particular line of xml. Uses XPath to find the interesting element of the xml file.
public static void UpdateAnXmlNode(string xmlFileName) { XmlDocument xDoc = new XmlDocument(); try { // load the configuration file xDoc.Load(xmlFileName); // find the node of interest from the key XmlNode theNode = xDoc.SelectSingleNode( @"/configuration/xxxConfiguration/moduleGroups/add[@trustName = 'Default']/modules"); bool customXmlLinePresent = false; if (theNode != null) { customXmlLinePresent = theNode.InnerXml.Contains( "XXX.YYY.Sandbox.DebugTree.Module"); } string extraXml = string.Empty; if (!customXmlLinePresent) extraXml += @"<add moduleType=""XXX.YYY.Sandbox.DebugTree.Module, XXX.YYY.Sandbox"" />" + Environment.NewLine; if (extraXml.Length > 0) { theNode.InnerXml += extraXml; xDoc.PreserveWhitespace = true; xDoc.Save(xmlFileName); } } catch (XmlException ex) { DoSomethingWithError(ex); } }
July 16, 2010
FileSystemInfoExtender Class
Extend the FileSystemInfo class with enumerators to iterate through subdirectories, ditto with the DirectoryInfo class.
Now merged into this blog entry
Now merged into this blog entry
Labels:
DirectoryInfo,
extension class,
FileSystemInfo,
IEnumerable,
Iterators,
yield
FileAttributesExtender
Use Flags based enumerated types extender class to extend file attributes and give it Set/group theory like methods
public static class FileAttributesExtender { // Return lhs flags plus rhs flags public static FileAttributes Union(this FileAttributes lhs, FileAttributes rhs) { return lhs | rhs; } // Return flags common to lhs and rhs public static FileAttributes Intersection(this FileAttributes lhs, FileAttributes rhs) { return lhs & rhs; } // Return lhs flags minus rhs flags public static FileAttributes Difference(this FileAttributes lhs, FileAttributes rhs) { FileAttributes common = Intersection(lhs, rhs); int res = (int)lhs - (int)common; return (FileAttributes)(res); } // Return true if lhs contains ALL the flags within rhs public static bool Contains(this FileAttributes lhs, FileAttributes rhs) { FileAttributes common = Intersection(lhs, rhs); return (common == rhs); } // Return true if lhs contains any of the flags within rhs public static bool ContainsAnyOf(this FileAttributes lhs, FileAttributes rhs) { FileAttributes common = Intersection(lhs, rhs); return ((int)common > 0); } // Return true if lhs contains none of the flags within rhs public static bool ContainsNoneOf(this FileAttributes lhs, FileAttributes rhs) { FileAttributes common = Intersection(lhs, rhs); return ((int)common == 0); } // NON-extension methods here public static FileAttributes FromString(string source) { FileAttributes res = (FileAttributes)Enum.Parse(typeof(FileAttributes), source, true); return res; } }
July 9, 2010
Close or Kill a Process
This routine will try and close a process by sending a close message to it's main window. If the process has no GUI or a timeout period is exceeded then the 'Process.Kill()' method will be used to close it.
// Try and close a process. Kill it if the Close takes // too long. // exeLessExtension - Process name (without extension) // msToWaitForCloseMainWindow - Time in milliseconds to // wait for 'CloseMainWindow()' before just killing the // process, Set negative to not kill at all, set to 0 to // kill without calling CloseMainWindow public static void ForceProcessClose( string exeLessExtension, int msToWaitForCloseMainWindow) { Process[] processes = Process.GetProcessesByName(exeLessExtension); if (msToWaitForCloseMainWindow != 0) { foreach (Process p in processes) { if (!p.CloseMainWindow()) { // Process does not have a GUI, use 'Kill()' instead msToWaitForCloseMainWindow = 0; } } } if (msToWaitForCloseMainWindow >= 0) { Thread.Sleep(msToWaitForCloseMainWindow); processes = Process.GetProcessesByName(exeLessExtension); foreach (Process p in processes) { p.Kill(); } } }
July 1, 2010
Using Images in WPF
Using project resources in WPF
- Create sub-directory for resources called say "Resources"
- Add your resources (images, icons etc.) to it.
- Copy the folder structure into the VS project and add the resource files to it.
- Check the Properties of your resources in VS project file to ensure they have a Build Action of 'Resource'
<Image Source="Resources/P4.ico" />Adding an image to a window's resources is very easy:
<Window.Resources> <Image x:Key="P4Icon" Source="Resources/P4.ico" /> </Window.Resources>In code:
Image myImage = new Image();Inserting an image in a button is very easy in WPF:
myImage.Source = new BitmapImage(new Uri("Icons/MyImage.png", UriKind.Relative));
<Button HorizontalAlignment="Left" Margin="5,8,0,10" Name="p4But" Width="34" Click="p4But_Click"> <Image Source="Resources/P4.ico" Width="24" /> </Button>
Start a Process and Capture the Output in c#
Simple sample for running a process synchronously and capturing the output
public string GetEnvironmentVars() { Process process = new Process(); // UseShellExecute must be 'false' when redirecting the output process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.StartInfo.CreateNoWindow = true; process.StartInfo.FileName = "p4"; process.StartInfo.Arguments = " set "; //process.StartInfo.WorkingDirectory = dir; process.Start(); string output = process.StandardOutput.ReadToEnd(); //string error = process.StandardError.ReadToEnd(); // Wait a reasonable ammount of time for it to finish bool res = process.WaitForExit(5000); return res ? output : "Command \"" + process.StartInfo.FileName + process.StartInfo.Arguments + "\" failed to exit:" + Environment.NewLine + output; }
Labels:
c#,
process,
RedirectStandardOutput
Editing Context Menus of Visual Studio 2008
Can add external tools to context menu.
Title: P4 Checkout
Command: C:\Program Files (x86)\Perforce\p4.exe
Arguments: edit $(ItemPath)
Initial Directory: $(ItemDir)
Select "Use Output window"
As shown here:
Title: P4 Revert
Command: C:\Program Files (x86)\Perforce\p4.exe
Arguments: revert $(ItemPath)
Initial Directory: $(ItemDir)
Select "Use Output window"
- Create your external tool using the "Tools=>External Tools" menu option. Your new external tool will be called "External Command n" where 'n' is the external menu item tool location in the external menu items group of the Tools menu
- Open "Tools=>Customize" dialog.
- Select "Context Menus" in the "Toolbars" tab.
- The context menus will appear on the toolbar. Select a context menu from one on the toolbar. Some useful ones are:
- "Project and Solution Context Menus=>Item" - This is the file context menu in the solutions folder
- "Project and Solution Context Menus=>Project" - This is the project context menu in the solutions folder
- "Other Context Menus=>Easy MDI Document Window" - Not obvious. This is the context menu for the tab at the top of a file editor window
- Goto "Command" tab and select "Tools" in the categories tab. From the "Commands:" list select the appropriate "External Command n"
Title: P4 Checkout
Command: C:\Program Files (x86)\Perforce\p4.exe
Arguments: edit $(ItemPath)
Initial Directory: $(ItemDir)
Select "Use Output window"
As shown here:
Title: P4 Revert
Command: C:\Program Files (x86)\Perforce\p4.exe
Arguments: revert $(ItemPath)
Initial Directory: $(ItemDir)
Select "Use Output window"
Subscribe to:
Posts (Atom)