public static class EnumFlagExtensions
{
// https://stackoverflow.com/questions/4171140/how-to-iterate-over-values-of-an-enum-having-flags
public static IEnumerable<T> GetUniqueFlags<T>(this T value)
where T : Enum
{
// if it's not a flag enum, return empty
Debug.Assert(value.GetType().IsDefined(typeof(FlagsAttribute), false),
"Not a \"Flags\" enum type");
if (!value.GetType().IsDefined(typeof(FlagsAttribute), false))
yield break;
var valueLong = Convert.ToUInt64(value, CultureInfo.InvariantCulture);
foreach (var enumValue in value.GetType().GetEnumValues())
{
if (
enumValue is T flag // cast enumValue to T
// convert flag to ulong
&& Convert.ToUInt64(flag, CultureInfo.InvariantCulture) is ulong bitValue
&& (bitValue & (bitValue - 1)) == 0 // is this a single-bit value?
&& (valueLong & bitValue) != 0 // is the bit set?
)
{
yield return flag;
}
}
}
}
May 5, 2021
c# GetUniqueFlags for Flags Enum
Use this to get unique flags from a combined flags enum value
April 1, 2021
Double String Format Extensions
For the Microsoft documentation see see here
Makes writing numeric types as a formatted number much easier. Here it is set for double types:
Makes writing numeric types as a formatted number much easier. Here it is set for double types:
void Main()
{
Console.WriteLine(1234.567.ToFixedDpFormat(2)); // => 1234.57
Console.WriteLine(1234.567.ToNumSigDigitsFormat(3)); // => 1.23E+03
Console.WriteLine(1234.567.ToCulturalFormat(2)); // => 1,234.57
Console.WriteLine(1234.567.ToCurrencyFormat()); // => £1,234.57
Console.WriteLine(1234d.ToFixedDpFormat(2)); // => 1234.00
Console.WriteLine(1.2340.ToNumSigDigitsFormat(3)); // => 1.23
Console.WriteLine(123445677.345234.ToCulturalFormat(2));// => 123,445,677.35
Console.WriteLine(1234345.567.ToCurrencyFormat()); // => £1,234,345.57
}
namespace Common.Extensions.DoubleToStringFormatting
{
public static class DoubleToStringExtensions
{
public static string ToFixedDpFormat(this double number, int numDP = 0)
{
var res = number.ToString($"F{numDP}"); // ToFixedDpFormat(1234.567,2) (en - US) -> 1234.57
return res;
}
public static string ToNumSigDigitsFormat(this double number, int numSigDig = 3)
{
var res = number.ToString($"G{numSigDig}"); // ToNumSigDigitsFormat(123.4546) en-US -> 124.0
return res;
}
// Prettifies the string according to cultural aesthetics and the specified num of DP
public static string ToCulturalFormat(this double number, int numDP = 2)
{
var res = number.ToString($"N{numDP}");
return res;
}
// Converts to a currency (using the default cultural currency sign)
public static string ToCurrencyFormat(this double number, int numDP = 2)
{
var res = number.ToString($"C{numDP}"); // ToCurrencyFormat(123.456), en-US -> $123.46
return res;
}
}
}
Something similar can be used for float,decimal and int types as well.
March 11, 2021
C# Windows File Explorer Openers
This class will Open Windows File Explorer and get it to open a directory and optionally select a specified file in the directory
/// <summary>
/// Windows Explorer Helperes
/// </summary>
public class FileExplorerOpener
{
/// <summary>
/// Open Windows File Explorer, in it open a directory and select
/// a specific file
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public bool OpenDirectoryAndSelectFile(string filePath)
{
var fi = new FileInfo(filePath);
var outcome = fi.Exists;
if (outcome)
{
var argument = "/select, \"" + fi.FullName + "\"";
Process.Start("explorer.exe", argument);
}
return outcome;
}
/// <summary>
/// Open Windows Explorer, in it open the directory or if
/// a file path is passed in, the directory in which the
/// file is located
/// </summary>
/// <param name="inputPath">Directory or file path</param>
public void OpenFileDirectory(string inputPath)
{
string path = System.IO.Path.GetDirectoryName(inputPath);
if (System.IO.Directory.Exists(path))
{
Process.Start(path);
}
}
}
March 4, 2021
Search File Contents with LinqPad
Searching the contents of some file or files in LinqPad (a line at a time) in C# or even just finding a file:
A similar one but this uses a LinqPad HyperLinq object to use Notepad++ to open the file at the given line number.
Directory.EnumerateFiles(
@"C:\Path\To\Search\Directory\", // Target of search
"*.txt", // Specify file or files to search
SearchOption.AllDirectories).
// SearchOption.AllDirectories - recusively search subdirectories
// SearchOption.TopDirectoryOnly - search specified directory only
// Next line records a line of text, the line number, and the file
SelectMany(file => File.ReadAllLines(file).Select((text,n) => new {text,lineNumber=n+1,file})).
// Here we search the text
// Use Regex for the search OR use string methods Contains(), StartsWith, EndsWith ...
Where(line => Regex.IsMatch(line.text, @"Searching for this text", RegexOptions.IgnoreCase)
&& line.text.Contains("ERROR") ).
Dump("Matches found")
When debugging you can always use Skip() and Take() to reduce the number of lines searched.A similar one but this uses a LinqPad HyperLinq object to use Notepad++ to open the file at the given line number.
// https://npp-user-manual.org/docs/command-prompt/
var notepadppPath = @"C:\Program Files (x86)\Tools\Notepad++\notepad++.exe";
Directory.EnumerateFiles(
@"C:\Repos\", // Directory
"*.csproj", SearchOption.AllDirectories) // File names
.SelectMany(file => File.ReadAllLines(file).Select((text, n) =>
new
{
file = new Hyperlinq(() => Process.Start(notepadppPath,
file+" -n"+(n+1).ToString()), file),
lineNumber = n + 1,
text
}))
.Where(x => // WHat you are looking for in the file
// Regex.IsMatch(line.text, @"^.*tlpNotifySystemShutdown.*$"))
x.text.Contains("DownloadProcess.Contracts") // 1.0.1
|| x.text.Contains("Foobar.Client") // 13.15.0
|| x.text.Contains("DownloadProcess.Client") // 1.2.0
|| x.text.Contains("XxxZipCreator.") // 5.1.0
|| x.text.Contains("Sloopy.Crial.Messages") // 1.6.3
)
.Dump("Matches found");
Here is another example:
Directory.EnumerateFiles(
@"C:\Path\To\Search\Directory\",
"*.cs", SearchOption.AllDirectories)
.SelectMany(file => File.ReadAllLines(file).Select((text, n) => new { text, lineNumber = n + 1, file }))
.Where(line => line.text.Contains("[CallerMemberName"))
.Dump("Matches found")
February 24, 2021
DateTime String Format Extensions
Bear in mind that a DateTime should generally be stored in Universal format and converted to local format when be displayed in a GUI or used in a report. This handy extension for date time format strings saves having to remember their obscure format codes or look them up every time.
// See here for more info
// https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings
public static class DateTimeToStringExtender
{
public static bool ParseGeneralShortDateTime(this string dateTimeStr, out DateTime dateTime)
{
var format = "g"; // Standard short date time format: "dd/MM/yyyy HH:mm:ss" for UK
bool result = false;
CultureInfo provider = CultureInfo.CurrentCulture;
result = DateTime.TryParseExact(dateTimeStr.Trim(), format, provider, DateTimeStyles.None, out dateTime);
return result;
}
/// <summary>
/// Convert a DateTime to a YearMonthDay string of the form yyyy/MM/dd
/// </summary>
/// <param name="dt">target</param>
/// <returns>YearMonthDay string of the form yyyyMMdd</returns>
public static string ToYyyyMmDdString(this DateTime dt, char separator = char.MinValue)
{
string format = "yyyyMMdd";
if (!char.IsControl(separator))
{
format = "yyyy" + separator + "MM" + separator + "dd";
}
var res = dt.ToString(format);
return res;
}
/// <summary>
/// Convert a DateTime to a YearMonthDay string of the form DdMmYyyy
/// </summary>
/// <param name="dt">target</param>
/// <returns>YearMonthDay string of the form DdMmYyyy</returns>
public static string ToDdMmYyyyString(this DateTime dt, char separator = char.MinValue)
{
string format = "ddMMyyyy";
if (!char.IsControl(separator))
{
format = "dd" + separator + "MM" + separator + "yyyy";
}
return dt.ToString(format);
}
/// <summary>
/// Convert a DateTime to a YearMonthDay string of the form yyyyMMdd_HHmmss where the hour is in the 24 hour format
/// </summary>
/// <param name="dt">target</param>
/// <returns>YearMonthDay string of the form yyyyMMdd_HHmmss</returns>
public static string ToYyyyMmDd_HhMmSsString(this DateTime dt)
{
return dt.ToString("yyyyMMdd_HHmmss");
}
/// <summary>
/// Convert a DateTime to a YearMonthDay string of the form yyyyMMdd_HHmmss_ffffff where the hour is in the 24 hour format
/// Useful for creating randomised filenames based upon the date
/// </summary>
/// <param name="dt">target</param>
/// <returns>YearMonthDay string of the form yyyyMMdd_HHmmss_ffffff</returns>
public static string To_YyyyMmDd_HhMmSs_ffffff(this DateTime dt)
{
return dt.ToString("yyyyMMdd_HHmmss_ffffff");
}
/// <summary>
/// Convert a DateTime to a YearMonthDay string of the form yyyyMMdd_HHmmss where the hour is in the 24 hour format
/// </summary>
/// <param name="dt">target</param>
/// <returns>YearMonthDay string of the form yyyyMMdd_HHmmss</returns>
public static string ToYyyyMmDd_HhMmSsString(this DateTime dt, char dateSeparator = char.MinValue, char timeSeparator = char.MinValue)
{
string format = "yyyyMMdd_HHmmss";
if (!char.IsLetterOrDigit(dateSeparator) && !char.IsControl(dateSeparator))
{
format = "yyyy" + dateSeparator + "MM" + dateSeparator + "dd" + "_" + "HH" + timeSeparator + "mm" + timeSeparator + "ss";
}
return dt.ToString(format);
}
/// <summary>
/// Emits a date time (culture independent) string of the form
/// "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'"
/// (eg.: "Sun, 09 Mar 2008 16:05:07 GMT").
/// Works on universal date times only
/// </summary>
/// <param name="dateTime">target date time to convert to a string</param>
/// <returns>dateTime formatted as a string</returns>
public static string ToRfc1123FormatString(this DateTime dateTime)
{
string result = dateTime.ToUniversalTime().ToString("r");
return result;
}
/// <summary>
/// Convert a DateTime to a string of the form "2008-03-09 16:05:07Z"
/// where the '-' character is culture dependant
/// </summary>
/// <param name="dt">target</param>
/// <returns>string of the form "2008-03-09 16:05:07Z" where '-' character is culture dependant</returns>
public static string ToUniversalSortableString(this DateTime dt)
{
return dt.ToUniversalTime().ToString("u");
}
// 2009-06-15T13:45:30 --> Monday, June 15, 2009 8:45:30 PM (for en-US)
public static string ToUniversalFull(this DateTime dateTime)
{
var res = dateTime.ToUniversalTime().ToString("U");
return res;
}
/// <summary>
/// Emits a sortable date time (culture independent) string of the form "yyyy'-'MM'-'dd'T'HH':'mm':'ss" (eg.: "2008-03-09T16:05:07"")
/// </summary>
/// <param name="dateTime">target date time to convert to a string</param>
/// <returns>dateTime formatted as a string</returns>
public static string ToSortableFormatString(this DateTime dateTime)
{
string result = dateTime.ToString("s");
return result;
}
/// <summary>
/// Emits a result date time format string using a pattern that preserves
/// time zone information and emits a result string that complies with
/// ISO 8601 ("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffK"), preserves
/// the DateTime kind.
/// </summary>
/// <param name="dateTime">target date time to convert to a string</param>
/// <returns>dateTime formatted as a string</returns>
// 2009-06-15T13:45:30 (DateTimeKind.Utc) -->; 2009-06-15T13:45:30.0000000Z
// 2009-06-15T13:45:30 (DateTimeKind.Local) --> 2009-06-15T13:45:30.0000000-07:00 (depending on the time zone)
// 2009-06-15T13:45:30 (DateTimeKind.Unspecified) --> 2009-06-15T13:45:30.0000000
public static string ToRoundTripFormatString(this DateTime dateTime)
{
string result = dateTime.ToString("o");
return result;
}
static readonly string[] formats = {
// Extended formats
"o",
"yyyy-MM-ddTHH:mm:ss.ffffffZ",
"yyyy-MM-ddTHH:mm:ss.fffffZ",
"yyyy-MM-ddTHH:mm:ss.ffffZ",
"yyyy-MM-ddTHH:mm:ss.fffZ",
"yyyy-MM-ddTHH:mm:ss.ffZ",
"yyyy-MM-ddTHH:mm:ss.fZ",
"yyyy-MM-ddTHH:mm:ssZ"
};
public static DateTime ParseToIso8601DateTime(this string str)
{
return DateTime.ParseExact(str, formats,
CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
}
}
February 16, 2021
Compare Files Using Visual Studio
Go to the command window:
Tools.DiffFiles {file1path} {file2path}
You can get the file paths using Windows Explorer, select the file with the right mouse button whilst holding down shift and then select the menu option "Copy as path"
Tools.DiffFiles {file1path} {file2path}
You can get the file paths using Windows Explorer, select the file with the right mouse button whilst holding down shift and then select the menu option "Copy as path"
Extract MSI files (without installing)
Extract MSI files (without installing)
With “Admin” permission use the following command line:
msiexec /a drive:\filepath\to\MSI\file /qb TARGETDIR=drive:\filepath\to\target\folderFor example to extract “Product.Setup.msi” files:
msiexec /a Product.Setup.msi /qb TARGETDIR=C:\Downloads\Product.Setup\Extracted
Subscribe to:
Posts (Atom)