January 8, 2023

Powershell AfterLogin & CheckIpAddressChange

AfterLogin.ps1
#$host.UI.RawUI.ForegroundColor = "Green"
Write-Host "*** After Login Prepartion ***"  -Foregroundcolor Green
$host.UI.RawUI.WindowTitle =  "*** After Login Prepartion ***"
Set-Variable -Name "AzureStorageEmulatorExe" -Value "C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe"
Write-Output "*** Start Azure Storage Emulator ***"
& $AzureStorageEmulatorExe start
#Write-Host "*** LoggING into Azure ***"  -Foregroundcolor Green
#& az login --tenant 12345567-8910-47ff-0a65-2765a99ebbce
#Write-Host "*** LoggED into Azure ***"  -Foregroundcolor Green
& $AzureStorageEmulatorExe status
& "C:\Users\...\Documents\BatchFiles\CheckIpAddressChange.ps1"
Pause
CheckIpAddressChange.ps1
$currIpAddress = (Invoke-WebRequest -uri https://ifconfig.me/ip).Content
$prevIpAddress = "155.15.12.31"
$arkpdFirewallAccess = https://.../resource/subscriptions/resourceGroups/networking

#$host.UI.RawUI.ForegroundColor = "Green"
Write-Output "*** Checking for IP Address Change ***"  -Foregroundcolor Green
Write-Output "My current  IP address: $($currIpAddress)"
Write-Output "My previous IP address: $($prevIpAddress)"
$lastDifferentIpAddress = "15.17.107.14"
Write-Output "My last different IP address: $($lastDifferentIpAddress)"
Write-Output "if it changes, re-run ~\Scripts\IpRestrictionTool\allow-my-ip.ps1"
Write-Output "Also navigate to '$($arkpdFirewallAccess)' to update the firewall rule"

Powershell - Find My Ip Address

Clear
$currIpAddress = (Invoke-WebRequest -uri https://ifconfig.me/ip).Content
$prevIpAddress = "155.171.12.2"
Write-Output ""
Write-Output "My current  IP address: $($currIpAddress)"
Write-Output "My previous IP address: $($prevIpAddress)"
Write-Output "if it changes, re-run ~\Scripts\IpRestrictionTool\allow-my-ip.ps1"

December 11, 2022

Json Parsing Tests - ExpandoObject or Json strings

Setting Up Jason Parsing Tests Using Dynamic Objects Or Strings

[Test]
public void SomeTestUsingExpandoObject()
{
  // arrange
  const string getItemEventDataValue = @"{
      ""_PrimaryId"": ""F:\\dasda\\ToMO-005775.json"",
      ""_SecondaryId"": ""123456"",
      ""RetrievalResult"": ""Processed Successfully""
    }";
  dynamic indexItemRaw = new ExpandoObject();
  indexItemRaw.id = sourceIndexItemId;
  indexItemRaw.version = sourceIndexItemVersion.ToString(CultureInfo.InvariantCulture);
  dynamic source = new ExpandoObject();
  source.getItemEventData = getItemEventDataValue;
  indexItemRaw.source = source;

  // act
  IEnumerable<ClaimDto> claimsEnum = someMapper.Map(JObject.FromObject(indexItemRaw));
  var claimDtos = claimsEnum.ToList();
  
  //assert
  ...
}

[Test]
public void SomeTestUsingJSonStringOnly()
{
  //How to set up unit tests using strings to set up the data, instead of dynamic objects.
  //Sometimes it can be simpler, especially if you retrieve the raw data from a run
  //Here is the above test, arranged using a string as an example
  //In this case I thought it was more complicated to set everything up as a string
  //(because one of the json string object entries (the "getItemEventData") was itself a json string)
  // arrange
  string rawJToken = @"
  {
    ""id"": ""{sourceIndexItemId}"",
    ""version"": ""1.0"",
    ""source"": {
      ""getItemEventData"": ""{
         \""PrimaryId\"": \""F:\\\\dasda\\\\ToMO-005775.json\"",
         \""SecondaryId\"": \""123456\""
         \""RetrievalResult\"": \""Processed Successfully\""
      }""
    }
  }";
  rawJToken = rawJToken.Replace("{sourceIndexItemId}", sourceIndexItemId);
  JToken jtoken = JToken.Parse(rawJToken);

  //act
  IEnumerable<ClaimDto> claimsEnum = someMapper.Map(jtoken);
  var claimDtos = claimsEnum.ToList();

  //assert
  ...
}

December 4, 2022

Plant UML

Quite often I need to examine some existing code to find a solution to a problem. Sometimes this requires going in detail about what calls what and when. However, usually the code your looking at has many calls to many other objects. We don't want the details of every single call, just the important ones. Here sequence diagrams are very useful to document this visually. I prefer to use PlantUML for this because it allows you to write the diagram as text, PlantUml takes care of spacing everything appropriately. You can just get your object name/type and the method called on it from your IDE.
PlantUML is found at this web address: https://www.plantuml.com/ .
Here is some good documentation on how to use it: https://crashedmind.github.io/PlantUMLHitchhikersGuide/ .
Here is an example of using Plant UML to create a sequence diagram in UML:

Here is the resulting image, click on it to open it full size:

Linqpad Notepad++ Hyperlink Extension

When searching through some files using LinqPad it can be useful to print out the results as a hyperlink that will open the file in Notepad++ at a particular line number.
public static class NotepadppExtension
{
    // Usage
    //string filePath = "X:/some/path/file.txt";
    //filePath.CreateNotePadppHyperLink(lineNumber);

    private const string NotePadppPath = @"C:\Program Files\Notepad++\notepad++.exe";
    private static bool onceOnly = false;

    public static Hyperlinq CreateNotepadppHyperLink(this string filePath, int lineNumber)
    {
        if (!onceOnly)
        {
            onceOnly = true;
            Debug.Assert(File.Exists(NotePadppPath), $"Notepad++.exe Path: \"{NotePadppPath}\" is wrong");
        }
        ProcessStartInfo psi = new ProcessStartInfo()
        {
            FileName = NotePadppPath,
            WorkingDirectory = Path.GetDirectoryName(NotePadppPath),
            //Arguments = " " + filePath + " -n" + lineNumber.ToString() + " ",
        };
        psi.ArgumentList.Add(filePath);
        psi.ArgumentList.Add("-n" + lineNumber.ToString());
        var filelink = new Hyperlinq(() => Process.Start(psi), filePath);

        return filelink;
    }
}
Usage
string filePath = .... ;
filePath.CreateNotePadppHyperLink(lineNumber);
A search files example in Linq
void Main()
{
	Directory.EnumerateFiles(
	@"X:\Backup\Documents\Journals\", 
	"*.log", SearchOption.AllDirectories)
		.SelectMany(file => TryFileReadLines(file).Select((text,n)=> 
                 new {Text=text,LineNumber=n+1, Link=file.CreateNotepadppHyperLink(n+1)}))
		.Where(line => 
		    //Regex.IsMatch(line.text, @"CallSearcherBase")  && 
		    line.Text.Contains("\"Search for this text\"", StringComparison.OrdinalIgnoreCase) )	
		.Dump("Matches found");
}

August 8, 2022

String Replace with StringComparison

I found this https://stackoverflow.com/questions/244531/is-there-an-alternative-to-string-replace-that-is-case-insensitive/13847351#comment31063745_244933 I added a few defensive checks.
public static string Replace(
    this string src,
    string oldValue,
    string newValue,
    StringComparison comparison)
{
    if (string.IsNullOrEmpty(oldValue))
        throw new ArgumentException("String cannot be of zero length or null.", "oldValue");
        
    if (string.IsNullOrEmpty(newValue)) // It can be an empty string though
        throw new ArgumentException("String cannot be null.", "newValue");

    // skip the loop entirely if oldValue and newValue are the same
    if (string.Compare(oldValue, newValue, comparison) == 0)
        return src;

    if (oldValue.Length > src.Length)
        return src;

    int index = src.IndexOf(oldValue, comparison);
    if (index == -1)
        return src;

    var sb = new StringBuilder(src.Length);

    int previousIndex = 0;

    while (index != -1)
    {
        sb.Append(src.Substring(previousIndex, index - previousIndex));
        sb.Append(newValue);
        index += oldValue.Length;

        previousIndex = index;
        index = src.IndexOf(oldValue, index, comparison);
    }

    sb.Append(src.Substring(previousIndex));

    return sb.ToString();
}

July 12, 2022

xUnit vs MSTest vs NUnit

There is a good comparison of the 3 unit test libraries:

https://xunit.net/docs/comparisons