Set Windows Wallpaper from Bing

The other day, I was looking and a colleague’s beautiful wallpaper and thought it would be nice to set a daily wallpaper but without the fuss of finding one every day. I found some sample scripts to get the Bing daily image and other scripts to set the wallpaper to an image.  Here’s my version written in C# with LinqPad.

NDepend Review

https://www.ndepend.com version 2017.3.1 Professional Edition

NDepend is a static code analysis tool to improve code quality, visualize dependencies and reduce technical debt.

What’s included

What you get is a zip file with the contents of the NDepend application suite for which the contents can be dropped into a folder of your liking.  Included in the package are the following files in the root folder:

  • Console.exe – Command line version of the NDepend for use by Continuous Integration (CI) tools and build servers.
  • PowerTools.exe – Interactive command line as an example of how the API can be used by developers, the source code is included in the NDepend.PowerTools.SourceCode subfolder
  • VisualStudioExtension.Installer.exe – Installs the extension for Visual Studio
  • VisualNDepend.exe – Standalone version of NDepend

There is an Integration subfolder with detailed information on how to configure NDepend with your favorite Continuous Integration (CI) servers.  (You are using a CI server, right?)  On the web site, there are extensions and configurations for many of the most popular CI servers including TeamCity, CruiseControl.NET, FinalBuilder and others.  Visual Studio Team Services and TFS 2017 support is by an extension downloaded from the Visual Studio Marketplace.  Upon a full analysis, a web page is created with details from the analysis which is great for inclusion into a CI system.

NDepend rules are written in a LINQ syntax, each rule is displayed when looking at the issues.  The LINQ syntax also contains suggestions on how to correct the issue which I found helpful when the suggestion was not clear.  The rules can also be disabled on a per-project basis.

Here’s and example of the LINQ syntax (note the description section):

// <Name>High issues (grouped per rules)</Name>
let issues = Issues.Where(i => i.Severity == Severity.High)
let rules = issues.ToLookup(i => i.Rule)
from grouping in rules
let r = grouping.Key
let ruleIssues = grouping.ToArray()
orderby ruleIssues.Length descending
let debt = ruleIssues.Sum(i => i.Debt)
let annualInterest = ruleIssues.Sum(i => i.AnnualInterest)
let breakingPoint = debt.BreakingPoint(annualInterest)
select new { r,
ruleIssues,
debt,
annualInterest,
breakingPoint,
Category = r.Category
}

//<Description>
// Issues with a High severity level should be fixed quickly, but can wait until the next scheduled interval.
//
// **Debt**: Estimated effort to fix the rule issues.
//
// **Annual Interest**: Estimated annual cost to leave the rule issues unfixed.
//
// **Breaking Point**: Estimated point in time from now, when leaving the
// rule issues unfixed cost as much as fixing the issues.
// A low value indicates easy-to-fix issues with high annual interest.
// This value can be used to prioritize issues fix, to significantly
// reduce interest with minimum effort.
//
// **Unfold** the cell in *ruleIssues* column to preview all its issues.
//
// **Double-click a rule** to edit the rule and list all its issues.
//
// More documentation: http://www.ndepend.com/docs/technical-debt
//</Description>

 

Installation and First Use

The first thing I did was to install the Visual Studio extension which was not the best move. My favorite add-in is ReSharper but the installation of NDepend broke ReSharper and caused by Visual Studio to become very unstable. After several install/uninstall rounds I figured out that I can disable the automatic analysis in favor of a request based analysis which made VS more stable but still had issues.  With the newest version of NDepend, I was able to install the extension in Visual Studio 2017 and the extension did not cause any instability issues. This review is based on the standalone version which worked just fine for all the tests I ran.

For the purposes of this review, I will be using a project called SchemaZen found at https://github.com/sethreno/schemazen as it was a project for which I was working on and it has unit tests which I thought was important for the analysis.  I needed to make a few changes to the project, I wanted a command timeout command line parameter and I wanted table, foreign keys and other table schemas to be in the same folder.

The process followed for this review:

  • Pull the latest version from GitHub
  • Load in VS2017, Full Rebuild
  • NDepend – First Analysis
  • Perform the code changes
  • Rebuild
  • NDepend – Second Analysis

First Analysis

NDepend-FirstAnalysis

The information provided on the first analysis is pretty informative.  Let’s break down some of the key points.

Code counts and diffs between versions (more on that in the second analysis).

NDepend-CodeCounts

The Debt, Coverage, Complexity and overall code quality section.  This project is pretty good with a C rating but of course it could be better and the time to get to a B is just a few hours.  The 258 issues is comprised of 26 high ranked items.

NDepend-Debt

A click on the High Issues produces this list:

NDepend-Issues

Long functions and classes are a part of this solution so I understand the list of issues.

Second Analysis

I added my code changes with the following result:

NDepend-SecondAnalysis

It appears my changes were good for functionality but bad for the long term stability of the application.

Observations

From a first use standpoint one might conclude that NDepend is just for simple information but the benefits are from long term use.  The ability to see positive and negative changes over time help to make concrete plans to clean up the code where without such a tool the time spent might be a full time challenge. Incorporating NDepend in the build process would help the development staff understand how the smallest of changes affect the long-term stability of the application.

Architecture is a key factor in maintaining the application in the long term, the Dependency Matrix view helps show the areas where the code is used and how much.

NDepend-DepMatrix

Conclusion

The analysis provided by NDepend is excellent even for smaller projects.  I found it most useful at first to use it on a smaller project until I better understood the interface and information provided. When I analyzed our huge internal application the results were overwhelming (over 2K types, 574K IL Instructions, etc.). This is where NDepend could help over time as that initial run would be used as the baseline for future analysis. The stand alone NDepend application is fast and churned through our application in about a minute. In our application, the dependency matrix was very useful in determining how to refactor the code to reduce direct coupling of classes and methods.  From a code review perspective, NDepend can help get our team to focus on direct coupling more as well as object relationships.  I still believe in code reviews and will still push to have the development team perform them as they are good learning tool as well as a good way to provide complete business benefit. NDepend is an excellent tool for wrangling the code into best practices and bringing to light potential long-term code issues without spending weeks or months of time manually analyzing the code base.

Dispose in .NET

Recently we were working on merging PDFs on our web site where we ran into a strange problem. The user could run the merged reports once but upon the second time the server would get a “File Locked” error. Here’s the original code:

public static string CreateMergedPdf(string targetPdf, List<string> pdfFiles)
{
    using (FileStream stream = new FileStream(targetPdf, FileMode.Create))
    {
       Document pdfDoc = new Document(PageSize.LETTER);
       PdfCopy pdf = new PdfCopy(pdfDoc, stream);
       pdfDoc.Open();

       foreach (string file in pdfFiles)
       {
          pdf.AddDocument(new PdfReader(file));
       }

       if (pdfDoc != null)
       {
          pdfDoc.Close();
       }
    }

    return targetPdf;
}

Seems simple enough but we obviously aren’t cleaning up our work as the files are still locked.  After searching for all places where we were referencing disposable objects. We finally came up with this:

public string CreateMergedPdf(string targetPdf, List<string> pdfFiles)
{
   using (var stream = new FileStream(targetPdf, FileMode.Create))
   {
      using (var pdfDoc = new Document(PageSize.LETTER))
      {
         using (var pdf = new PdfCopy(pdfDoc, stream))
         {
            pdf.Open();
            pdfDoc.Open();
            foreach (var file in pdfFiles)
            {
               var reader = new PdfReader(file);
               pdf.AddDocument(reader);
               reader.Dispose();
            }
            pdf.Close();
         }
         pdfDoc.Close();
       }
       stream.Close();
   }

   return targetPdf;
}

 

The lessons learned were clear by the end, you must close and dispose when you are able. Another thing to note was the

pdf.AddDocument(new PdfReader(file));

was from an example, causing us to waste time looking for the last remnant of the locking situation.

LinqPad – Get Disk Information

Getting hardware information can sometimes be hard when writing in .NET, the Framework keeps many of the deails away from the developer.  One day I needed to know if a drive letter existed and what type of drive it was.  I found many ways to do this but the one I liked the best is extremely simple from a code perspective:

Assemblies:
System.Management
System.Management.Instrumentation

var drive = "C";
var disk = new ManagementObject("Win32_LogicalDisk.DeviceID=\"" + drive + ":\"");
disk.Get();
disk.Dump();

LinqPad – Enum to String

Converting an enum item to s string in C# is pretty simple, but we had a situation where the enum was not what we wanted to display to the user on the web.  Looking around I found several examples of how to get the displayed version to be more user-friendly.  Here is an example:

public enum SysModeType
{
 Student,
 Admin,
 Preceptor,
 Undefined
}

We wanted to show “Administrator” on the web site but internally we were using “Admin”. We could do a search and replace for all Admin entries but there were other implications to the enum question in my mind. What if I wanted to display “Student Teacher” or “Intern/Unpaid” or any other combination of things that are not compatible with C# syntax.  I came up with several solutions and then went once step forward to test the performance of each.  The link is what worked and what didn’t.  I leave it to you to decide which one works for you.

LinqPad File: Utility – Enum to string.linq

LinqPad – Active Directory User Groups

The other day I needed to know the Active Directory groups a user had assigned.  Not being an operations person, I couldn’t go and use the tools on the server.  I decided there must be an easy way to get this done.  After a bit of searching, I came up with this LinqPad script using some assemblies Microsoft provided.

Assemblies:
System.DirectoryServices
System.DirectoryServices.ActiveDirectory
System.DirectoryServices.AccountManagement
System.DirectoryServices.Protocols

string username = 'hlord'; 
string domain = 'MyDomain'; 

var domainGroups = new List<string>(); 
var domainContext = new PrincipalContext(ContextType.Domain, domain); 
var user = UserPrincipal.FindByIdentity(domainContext, username); 
var authGroups = user.GetAuthorizationGroups();
authGroups.All(g => {
		if (!string.IsNullOrEmpty(g.Name) && !domainGroups.Contains(g.Name))
			domainGroups.Add(g.Name);
		return true;
	});

domainGroups.Sort();
domainGroups.Dump();

LinqPad File: LDAP – User Groups.linq

.NET Compiled in Debug? How do you know?

Recently I had a need to find out if the build was in Debug mode. Our build process produced debug code in production, causing all kinds of issues so I went out into the web to find a way of determining if an assembly (or executable) was created in debug.  It was much harder than I initially thought to get this information.

The article posted at The Black Box of .NET had the answer I was looking for.