Windows backups for an idiot

Today, I’m writing this note about backup procedures for Windows. Up to now, I’ve been backing up my Windows machines (operating currently five) in an ad hoc manner. Cringe you may, but I’d only made a backup once a month or so. Well, for the many decades I’ve been working with computers, I’ve never lost that much, through disk failures, unexpected file deletions, and upgrades. If a machine got trashed, I could mount the driver in another machine, boot a good OS, copy the files I’m interested in, and start afresh with a reformatted/reinstalled OS. But, my luck changed unexpectedly last week.

The recent Windows 10 Creator’s Update (which is actually an upgrade) bit me big time. And, it took me a week to recover from the mess MS dealt me.

It seems that many updates from Microsoft these days are poorly tested. Updates to a box are shoved down your throat whether you like it or not. The “new” Microsoft is repeating the lessons it should have learned with Windows Vista.

Thus, backups are more important now than ever!

Backups in Windows 10

Microsoft says that Windows 10 provides a “backup” through “file history.” But this is NOT a backup. A backup should include system files and partitions, not just your personal files. Windows 10 also provides the “Windows 7 backup”, but I really do not understand why it’s called that, and not “Windows 10 backup.” Is it going to be supported in the future? Maybe not!

Online Backups

An online backup is a good alternative. There are plenty of commercial products available, some of which were reviewed just a few days ago (http://www.pcmag.com/article2/0,2817,2288745,00.asp).  However, online backups have several problems: the services require a yearly subscription; there are limits on the size or duration of the backups saved; transferring data to and from the online service places demands on the internet link; online backup providers may not be reliable in the long run.

Backup to a spare PC on a LAN

Because I have a spare box, several large disks installed in it, with the machine attached to a gigabit LAN, I went with Acronis True Image 2017 to the spare box. The cost of Acronis was $60, which isn’t too bad. On each machine, a script is run to wake up the spare server, run Acronis True Image, then shutdown the server at the end of the backup.

The script is executed by the Windows Task Scheduler, which has the ability to wake up the computer from sleep mode, or start the process when the computer is first turned on. This script is written in Powershell. I would have preferred to write it in Bash, but WSL Bash does not work with the Windows Task Scheduler.

function grep {
    $input | out-string -stream | select-string $args
}

$var = tasklist | grep TrueImageHostNotify.exe

if ($var)
{
    'There is a backup currently running.'
    'Cannot start another backup because it might interfere with existing backup.'
    Exit 1
}
else
{
    'ok'
}

'No backups currently underway.'
' Turning on server...'

.\wol\wol\bin\Debug\netcoreapp1.1\win10-x64\publish\wol.exe -mac 44-8a-5b-ca-6b-be -mount \\llano\e\ -hostname llano

if ($?)
{
    'Backup server is now up.'
}
else
{
    'Wol of the backup server failed for some reason.'
    Exit 1
}


# Invoke backup. Note, the script name is generated by Acronis True Image when you create a backup plan.

&"c:\Program Files (x86)\Acronis\TrueImageHome\TrueImageLauncher.exe" "/script:C8E6E46F-2075-4916-9AE5-04977FDBA37F"
if ($?)
{
}
else
{
    'Acronis True Image launcher failed for some reason.'
    Exit 1
}

# Wait until the backup to begin.
while ($true)
{
    $var = tasklist.exe | grep TrueImageHomeNotify.exe
    if ($var)
    {
        break
    }
    'Waiting for backup to begin'
    Start-Sleep -s 5
}


# Wait for backup to finish.
while ($true)
{
    $var = tasklist.exe | grep TrueImageHomeNotify.exe
    if ($var)
    {
    }
    else
    {
        break
    }
    'Waiting for backup to end'
    Start-Sleep -s 5
}


# Turn off the remote backup server.

'Turning off server...'
$uid = Get-Content .\uid.txt -Raw
$pw = Get-Content .\pw.txt -Raw
.\psshutdown.exe -d '\\llano' -u $uid -p $pw

Exit 0

A simple WOL program in Net Core

To wake up the backup spare box, I wrote a “WOL” program in C# Net Core. It sends out a UDP “magic packet” to wake up the backup server when needed, which must be configured in both the BIOS and the network controller driver to accept WOL packets.

namespace WOL
{
    using System.IO;
    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    using System.Linq;
    using System.Runtime.InteropServices;

    internal class Program
    {
        private static int _count = 1;
        private static int _interval = 1;
        private static byte[] _mac;
        private static bool _sleep = false;
        private static string _mount;
        private static string _hostname;

        public static void Main(string[] args)
        {
            try
            {
                ParseArgs(args);
                if (_mac != null)
                {
                    List<byte> result = new List<byte>();
                    result.AddRange(Enumerable.Repeat((byte) 0xff, 6));
                    result.AddRange(Enumerable.Repeat(_mac, 16).SelectMany(arr => arr));
                    byte[] buffer = result.ToArray();
                    IPEndPoint ep = new IPEndPoint(IPAddress.Broadcast, 9);
                    UdpClient client = new UdpClient();
                    client.EnableBroadcast = true;
                    while (_count > 0)
                    {
                        Console.WriteLine("Sending packet...");
                        client.SendAsync(buffer, buffer.Length, _hostname, 9);
                        if (_count > 1)
                        {
                            Thread.Sleep(_interval * 1000);
                        }
                        _count--;
                    }
                }

                if (_mount != null) Mount(_mount);

                if (_sleep) Sleeper.Suspend();
            }
            catch (MacException e)
            {
                Console.WriteLine(e.Message);
                Environment.Exit(1);
            }
            catch (UsageException)
            {
                Usage();
                Environment.Exit(1);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Environment.Exit(1);
            }
        }

        private static void Mount(string path)
        {
            var x = Directory.GetDirectories(path);
            System.Console.WriteLine(path + " size = " + x.Length);
        }

        private static void Usage()
        {
            Console.WriteLine($@"wol - Wake-On-Lan command-line utility
-c <int>              Number of packets to send to slave machine.
-i <int>              Number of seconds between packets sent.
-mac <string>         MAC address of the slave machine to wake up.
-mount <string>       UNC of the path of a slave file system to check if accessible.
-hostname <string>    Name of the slave computer on the LAN.
-s                    Indicates to place the host machine in sleep.
");
        }

        private static void ParseArgs(string[] args)
        {
            // Just in case, set up something.
            if (args.Length == 0)
            {
                throw new UsageException("No args. Check usage.");
            }
            int argc = 0;
            while (argc < args.Length)
            {
                if (args[argc] == "-mac")
                {
                    argc++;
                    string[] macParts = args[argc].Split(':', '-');
                    if (macParts.Length != 6)
                    {
                        throw new MacException(args[0]);
                    }

                    byte[] mac = new byte[6];
                    for (int i = 0; i < 6; i++)
                    {
                        mac[i] = Byte.Parse(macParts[i], System.Globalization.NumberStyles.HexNumber);
                    }

                    _mac = mac;
                    argc++;
                }
                else if (args[argc] == "-c")
                {
                    argc++;
                    _count = Int32.Parse(args[argc]);
                    argc++;
                }
                else if (args[argc] == "-i")
                {
                    argc++;
                    _interval = Int32.Parse(args[argc]);
                    argc++;
                }
                else if (args[argc] == "-s")
                {
                    argc++;
                    _sleep = true;
                }
                else if (args[argc] == "-mount")
                {
                    argc++;
                    _mount = args[argc];
                    argc++;
                }
                else if (args[argc] == "-hostname")
                {
                    argc++;
                    _hostname = args[argc];
                    argc++;
                }
                else
                    throw new UsageException("Unknown arg. Check command parameters.");
            }
        }
    }

    internal class MacException : ArgumentException
    {
        public MacException(string address)
            : base(address + " is not a valid MAC Address!")
        {
        }
    }
    internal class UsageException : ArgumentOutOfRangeException
    {
        public UsageException(string message)
            : base(message)
        {
        }
    }

    public class Sleeper
    {
        [DllImport("Powrprof.dll", SetLastError = true)]
        static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent);

        public static void Suspend()
        {
            SetSuspendState(false, false, false);
        }
    }
}

 

Enjoy.

Posted in Tip

Hello World from NET Core and NET Standard

What is this Net Core everyone is talking about? Net Core is a cross-platform application framework for C#. With Visual Studio or the Net Core tool set, it’s not too hard to build server applications on any platform that can be deployed to any platform. This is remarkable considering the source code for C#/NET was proprietary code until Nov. 2014 when Net Core and parts of Net Framework were open sourced by Microsoft.

But, doesn’t Mono/Xamarin and Unity all offer a cross-platform application framework for C# as well?? While it’s true that Mono/Xamarin work cross platform, it was written from scratch. Mono was then extended to include bindings for Android, iOS, and other runtimes, and an API for UI common across selected platforms. Unity, as well, is a fork of Mono, with an API for graphics added. It too has differences with Net Framework that have emerged over time. It is expected that Net Standard, described below, will eventually supplant much of the functionality of these different cross-platform application frameworks.

Net Core has changed quite a bit in just the last few months let alone years. The file project.json, which specified the project dependencies, frameworks, targets, and runtimes, is now deprecated. Answers to questions about setting runtimes be found in Stackoverflow.com, but are confusing since they refer to the old project.json file.

First, a small side issue: WSL (Windows for Subsystem Linux)

If you are not interested in installing Visual Studio 2017 or Net Core on Windows, you can use WSL (Windows for Subsystem Linux) to easily develop a Linux from Windows 10.

After enabling developer mode for your Windows desktop, use “lxrun.exe /uninstall” and “lxrun.exe /install” to get a clean, fresh, up-to-date version of Ubuntu running on Windows. To run the shell, start up Powershell or Cmd, then type bash.

It’s also now possible to run X Windows applications in WSL with an X server installed on your Windows 10 desktop (https://sourceforge.net/projects/xming/). See Instructions1 and Instructions2. Some useful X Windows programs would be XTerm (sudo apt install xterm), gFTP (sudo apt install gftp)–just the tip of an iceberg of wonderful software.

Installing Net Core

For Ubuntu, see the instructions at https://www.microsoft.com/net/core#linuxubuntu to install Net Core in WSL.

You can install Visual Studio 2017 with the Net Core option, and develop Net Core applications from Visual Studio if you like.

Note, I’ve had problems getting the command line tool set working sometimes. This was because of multiple Net Core installations. Unfortunately, the newest Net Core package does not uninstall the older versions, at least on Windows. Beyond that, there shouldn’t be anything more to do to install. It all should find the dotnet executable, whichever platform you use.

Writing a Hello World program

To build a “Hello World” application, type the following in a WSL bash shell:

dotnet new console
dotnet restore
dotnet run

The first line creates a “Hello World” program. This may take a while while. The second command line performs essentially a “NuGet”, downloading and installing any additional packages. The third command line compiles and runs the program. Note, the product is a dotnet-dependent CIL/MSIL executable, and requires the “dotnet” executable to run, much like how Mono works.

To build a native OS executable for specific OS target, modify the CSPROJ file with a RuntimeIdentifiers tag.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
   <OutputType>Exe</OutputType>
   <TargetFramework>netcoreapp1.1</TargetFramework>
   <RuntimeIdentifiers>ubuntu.16.04-x64;ubuntu.14.04-x64;win10-x64;osx.10.11-x64</RuntimeIdentifiers>
  </PropertyGroup>
</Project>

Then, use dotnet restore/build with the -r option to build the programs.

dotnet restore -r ubuntu-14.04-x64
dotnet build -r ubuntu-14.04-x64
dotnet restore -r ubuntu-16.04-x64
dotnet build -r ubuntu-16.04-x64
etc.

In the directory bin/Debug/netcoreapp1.1/ubuntu.16.04-x64/ for example, you will find the executable dn. However, the executable is dependent on the dotnet framework being installed on the deployed machine.

To build a self-containing app with the framework contained with the executable, type:

dotnet publish -r ubuntu-14.04.x64
dotnet publish -r ubuntu-16.04.x64
etc.

In the directory bin/Debug/netcoreapp1.1/ubuntu.16.04-x64/publish you will find the executable dn with all the files needed to deploy the application.

Each time you change the target runtime list, use dotnet restore to install dependencies.

Relationship with Net Standard and other frameworks

Over the years, there have been many different implementations of the “NET Framework,” which resulted in different APIs. For example, in Mono/Xamarin/Unity, the Reflection API has several differences with the NET Framework Reflection API. Net Standard is a new base class layer that provides cross compatibility of different frameworks by providing a “shim” (or in my day, a “thunk”) that maps the functionality over the frameworks. The goal is to allow libraries written in one framework to be used in another framework.

Old:

New:

 

Compatibility

.NET Standard 1 1.1 1.2 1.3 1.4 1.5 1.6 2
.NET Core 1 1 1 1 1 1 1 2
.NET Framework (with tooling 1.0) 4.5 4.5 4.5.1 4.6 4.6.1 4.6.2 vNext 4.6.1
.NET Framework (with tooling 2.0) 4.5 4.5 4.5.1 4.6 4.6.1 4.6.1 4.6.1 4.6.1
Mono 4.6 4.6 4.6 4.6 4.6 4.6 4.6 vNext
Xamarin.iOS 10 10 10 10 10 10 10 vNext
Xamarin.Android 7 7 7 7 7 7 7 vNext
Universal Windows Platform 10 10 10 10 10 vNext vNext vNext
Windows 8 8 8.1
Windows Phone 8.1 8.1 8.1
Windows Phone Silverlight 8

Undoubtedly, you have probably seen the above figure showing the compatibility of the various NET Frameworks. But, this illustration simplifies what is actually required. To create a Net Standard library, you must compile for the appropriate Net Standard framework and provide a a list of dependencies for compatibility. See NetStandardLib and NetFrameworkApp in the example I provide.

I constructed a set of examples that check the cross compatibility of Net Core and Net Framework APIs with libraries in Net Core, Framework, and Standard. You can modify it to test out different scenarios.

Similarly, strict Net Standard 1.4 libraries can be called from Xamarin Forms libraries (Profile259), but no higher version number of Net Standard.

It is possible to compile your library to Net Framework, Xamarin, etc. while forcing your code to be Net Standard compliant by adding a <TargetFrameworks> tag to your .csproj file. For example, a <TargetFrameworks>netstandard1.4;net461</TargetFrameworks> tag will generate a Net Standard and Net Framework targets for your library. You could use a higher version number for Net Standard, but you would have to provide an additional target (<TargetFrameworks>) in the CSPROJ file to target the PCL (e.g., http://codinggorilla.domemtech.com/?p=1521), which may lead to other problems.

Examples can be found at https://github.com/kaby76/NetStandardCoreFramworkExamples

Additional Information

https://www.bartwolff.com/Blog/2017/03/20/targeting-multiple-net-platforms-in-a-single-nuget-package-w

http://stackoverflow.com/questions/43109292/reference-a-net-standard-1-6-library-from-a-net-4-6-2-library/43109941

http://www.ben-morris.com/sharing-libraries-between-net-core-and-net-framework-applications/

https://andrewlock.net/understanding-net-core-netstandard-and-asp-net-core/

gigi.nullneuron.net/gigilabs/multi-targeting-net-standard-class-libraries/

Posted in Tip

Where are my MSDN downloads, Microsoft????

Virtually every website nowadays follows a God-awful trend in UI that generally replaces hyperlinked text with illustration-heavy art work arranged in a grid layout, making it not easier but HARDER for people to find a specific page. You cannot search for text on the page as it’s all now pictures; and, each page shows less links as a picture takes up more real estate than simple text.

Microsoft has joined that trend, making it almost impossible to find MSDN subscription downloads (https://msdn.microsoft.com/en-us/subscriptions/downloads). (Thank goodness Google search still works.) When you set your browser to http://msdn.microsoft.com, you get a large page that is nice to look at but shows virtually nothing:

Now, where are the downloads for your MSDN subscription? Click on the “Downloads” tab, and you get three items you can navigate to, none of which help.

All the other menu items in the page are the same–no MSDN downloads. if you click on the “Subscriber portal” in the upper-right, then you get a page with a 6 by 3 grid of icons for various downloads, but none of which say are an OS, or the VS C++ Build Tools:

From The Next Web, “In 2017, websites are likely to start moving back to basics and placing more emphasis on content. Whether that means we remove all of the other distractions we’ve spent years adding, or just making them take up less real estate is yet to be determined. Getting back to the heart of a website — the content — will be prevalent moving forward.” I certainly hope so. Maybe someone could define a measure that identifies when simple text is more appropriate than a grid of illustrations?

Please, let’s go back to the future and just use text where it’s appropriate!

Posted in Tip

Swig, LLVM, LLILC

As I work to enhance Campy, a C# library for GPU programming I wrote, I’m trying to capitalize on some new code from the NET Foundation Projects. These include LLILC, a MS IL compiler based on LLVM. I want to be able to use some of the APIs in LLVM to perform SSA analysis rather than roll my own. But, that turns out to be easier said than done. This note describes some of the issues in building LLILC, LLVM, and SWIG.

Continue reading

Getting Windows Subshell for Linux working

If you’ve been working with Cygwin or MinGW, you may want to step over to Windows Subsystem for Linux (WSL) to take advantage of building and running tools in that environment. While the goal of Cygwin and MinGW has been to provide a Linux command-line tool set to Windows, it’s too easy to run the wrong tool (e.g., forgetting to install a tool in one environment, and picking up the identically named tool in another). In fact, many tools install their own private copy of MinGW (Git for Windows, SourceTree, Vagrant, …), so you find yourself constantly manipulating the search path.

Continue reading

Posted in Tip

Hackintosh for Development

Years ago, I bought a MacIntosh–the original 128K 68000 Motorola CPU  box. Like the Apple 2 before that, I upgraded it as best I could, and tried to develop programs for it. But, it was all not easy. And, it was exceedingly expensive–from the computer, to the upgrades, to the software, to the books detailing how to program the system. The decision by Apple to make the system so closed and so expensive made an impression that hasn’t changed over 30 years. I won’t buy an Apple product.

Unfortunately, if you are software developer, you have to use crap you really don’t want to use. The share of iPhones in the U.S. seems to be increasing, not decreasing, and I want to be able to write software for the iPhone. My dad, sisters, brother, and their families all own these exceedingly expensive cellphones. But, as Apple doesn’t give discounts for developers for their hardware, I decided to put together a hackintosh.

After a week or so, I finally found a hardware/software combination that seems to do the trick. My hackintosh is an Acer Aspire e5-574, with 6 GB memory, and an external 1 TB USB harddrive (Kingwin EZ-Dock 2535). It runs Sierra OS X, which I downloaded from a virtual machined hackintosh. It uses a USB keyboard and mouse as there are no drivers for the integrated keyboard and mouse. There are also no drivers for access to the internal SATA drive, which is why it runs with an external USB drive.

The hack wasn’t easy to set up. I’ve tried setting up El Capitan on two other Intel boxes and had no luck. I found the laptop hack after trying it out with the instructions on TonyMacX86.com. I’ll repeat the steps here.

Step 1: Download Sierra OS X.

  1. Start up an existing Mac.
  2. Download Sierra OS X.
  3. The files for OS X will be in /Applications.

Step 2: Create a bootable USB drive with UniBeast.

  1. Insert a USB thumb drive into the Mac. The USB drive should be 10 GB or more. If it doesn’t recognize the drive, try another.
  2. Open /Applications/Utilities/Disk Utility.
  3. Select the USB drive and erase it. The default should be OS X Extended (Journaled), and GUID Partition Map.
  4. Download Unibeast and run. You will need to sign up for a TonyMacX86.com account. I used UniBeast 7.0.1.
  5. In Unibeast, go through the preliminaries. Then select the destination USB drive, Sierra for the OS Installation, UEFI Boot mode. Then install.
  6. You should download MultiBeast and copy it to the USB drive. I used version 9.0.1.

Step 3: Set up BIOS settings on the laptop.

  1. Use “F2” repeatedly to get to the BIOS screen for the Acer.
  2. The only setting for the Acer laptop that is important is the Secure boot mode. Make sure it is turned off.

Step 4: Install OS X Sierra on the laptop.

  1. Insert the USB thumb drive on the laptop.
  2. Use “F12” to get the boot selector for the Acer laptop.
  3. Boot from the USB drive.
  4. In Clover, select the appropriate drive, then boot.
  5. After a long time, you should see an installation screen fro OS X.
  6. Insert the EZ-Dock drive.
  7. Format the EZ-Dock drive.
  8. Install Sierra on it.
  9. Reboot. Select the new drive. Sierra should come up.

Step 5: Post install

  1. Run MultiBeast on Sierra.
  2. Select Network and add in Atheros2200Ethernet 2.2.0, then install on the Sierra OS.
  3. Pull out the thumb drive, and reboot. It should now work.

Ken

Posted in Tip

C# Twisters–Round 2

More brain twisters. From http://stackoverflow.com/questions/241134/what-is-the-worst-gotcha-in-c-sharp-or-net, http://www.softwire.com/blog/2012/08/13/dont-be-too-lazy-linqs-lazy-evaluation-gotchas/, and others.

11.

static void CSharpPuzzle11()
{
    // Which implementation is faster?
    // Which implementation uses more memory?
    { // Implementation A.
        var before = DateTime.Now;
        int size = 100000;
        string a = string.Empty;
        for (int i = 0; i < size; ++i) a += i.ToString() + " ";
        var after = DateTime.Now;
        Console.WriteLine(a.SizeOf());
        Console.WriteLine(after - before);
    }
    { // Implementation B.
        var before = DateTime.Now;
        int size = 100000;
        StringBuilder a = new StringBuilder();
        for (int i = 0; i < size; ++i) a.Append(i.ToString() + " ");
        var after = DateTime.Now;
        Console.WriteLine(a.SizeOf());
        Console.WriteLine(after - before);
    }
}

12.

class Beer
{
    public bool IsAvailable;
    public bool IsNice;
    public string Name;
}

static void CSharpPuzzle12()
{
    Func<Beer, bool> BeerIsNice = (Beer b) =>
    {
        Console.WriteLine(b.Name);
        return b.IsNice;
    };

    List<Beer> availableBeers = new List<Beer>()
    {
        new Beer { Name = "Old Tom's", IsNice = false, IsAvailable = true },
        new Beer { Name = "Young Dan's", IsNice = true, IsAvailable = false },
        new Beer { Name = "Now Beer", IsNice = false, IsAvailable = true }
    };
    int count = availableBeers.Where(BeerIsNice).Count(); // What is the value of count?
    Console.WriteLine(availableBeers.Where(BeerIsNice).First().Name); // What is the output?
}


13.

private static IEnumerable<char> Keystrokes()
{
    while (true)
    {
        yield return Console.ReadKey(true).KeyChar;
    }
}

static void CSharpPuzzle13()
{
    // Why is keyboard read twice four times?
    System.Console.WriteLine("Enter 'beer'.");
    var firstFourKeystrokes = Keystrokes().Take(4);
    if (firstFourKeystrokes.SequenceEqual(new[] {'b', 'e', 'e', 'r'}))
    {
        System.Console.WriteLine("You entered 'beer'. Getting each char now...");
        firstFourKeystrokes.ToList().ForEach(Console.Write);
    }
}

14.

static void CSharpPuzzle14()
{
    // What's the correct way to create a new GUID?
    var which_one1 = new Guid().ToString();
    var which_one2 = Guid.NewGuid();
}

15.

static void CSharpPuzzle15()
{
    // What happens if you run this code?
    var t = new Program();
    var x = t.MyVar;
}

private int myVar;
public int MyVar
{
    get { return MyVar; }
}

16.

static void CSharpPuzzle16()
{
    // Why don't these work? How do we fix the problem?
    var a = Type.GetType("string");
    var b = Type.GetType("Program");
    var c = Type.GetType("System.Data.Entity.DbContext");
}

17.

static void CSharpPuzzle17()
{
    // Why doesn't this work? How do we fix it?
    for (int i = 0; i < 10; i++)
    {
        ThreadStart ts = delegate { Console.WriteLine(i); };
        new Thread(ts).Start();
    }
}

18.

static IEnumerable<char> CapitalLetters(string input)
{
    if (input == null)
    {
        throw new ArgumentNullException(input);
    }
    foreach (char c in input)
    {
        yield return char.ToUpper(c);
    }
}

static void CSharpPuzzle18()
{
    // Why doesn't this code throw an exception?
    try
    {
        var x = CapitalLetters(null);
        Console.WriteLine("An exception should have been thrown!");
    }
    catch (ArgumentNullException)
    {
        // Expected
    }
}

19.

static void CSharpPuzzle19()
{
    DateTime a = DateTime.Now;
    Thread.Sleep(2000);
    DateTime b = DateTime.Now;
    TimeSpan span = a - b;

    // Which is correct, the first or second line below?
    Console.WriteLine(span.Seconds);
    Console.WriteLine(span.TotalSeconds);
}

20.

static void CSharpPuzzle20()
{
    string my = "my ";
    var t1 = my + "string" == "my string"; //true

    var a = new ArrayList();
    a.Add(my + "string");
    a.Add("my string");

    // uses ==(object) instead of ==(string)
    var t2 = a[1] == "my string"; // True or False?
    var t3 = a[0] == "my string"; // True or False?

    var t4 = my + "string" == "my string"; // True or False?
}

21.

static void CSharpPuzzle21()
{
    // What does this output?
    string prefix1 = "C:\\MyFolder\\MySubFolder";
    string prefix2 = "C:\\MyFolder\\MySubFolder\\";
    string suffix1 = "log\\";
    string suffix2 = "\\log\\";

    Console.WriteLine(Path.Combine(prefix1, suffix1));
    Console.WriteLine(Path.Combine(prefix1, suffix2));
    Console.WriteLine(Path.Combine(prefix2, suffix1));
    Console.WriteLine(Path.Combine(prefix2, suffix2));
}

Posted in Tip

Another Visual Studio Extension for Antlr4 Files: AntlrVSIX

There are several Visual Studio extensions for Antlr: Antlr4Code, ANTLR Language Support, Actipro SyntaxEditor for WPF, and Syntax Highlighting Pack. However, each has problems (works on Antlr3, has advertisements, does not offer a “go to definition” right-click context menu command, etc). So, over the last few days, I implemented a simple VS 2015/2017 extension for Antlr4 grammars. You can find the sources on Github (https://github.com/kaby76/AntlrVSIX). The extension implements “go to definition” and “find all references” for grammar symbols. There are some restrictions, but it’s a start, works well, and is very simple code. Enjoy!

(Edited Jan 14, 2017)

Posted in Tip

CSharp Puzzles for the Agile – Round 1

For those who have free time on their hands, and who would like to work through some brain twisters, here is a list of C# code snippets for your perusal. See https://www.toptal.com/c-sharp/top-10-mistakes-that-c-sharp-programmers-make for more details.

1.

//=============================================================================

private static void CSharpPuzzle1()
{
    Point point1 = new Point(20, 30);
    Point point2 = point1;
    point2.X = 50;
    Console.WriteLine(point1.X);       // What is the output?
    Console.WriteLine(point2.X);       // What is the output?
    Pen pen1 = new Pen(Color.Black);
    Pen pen2 = pen1;
    pen2.Color = Color.Blue;
    Console.WriteLine(pen1.Color);     // What is the output?
    Console.WriteLine(pen2.Color);     // What is the output?
    Console.WriteLine();
}

2.

//=============================================================================

static Pen pen1;
static Point point1;
public static void CSharpPuzzle2()
{
    Console.WriteLine(pen1 == null); // What is the output?
    Console.WriteLine(point1 == null); // What is the output?
    Console.WriteLine(point1 == default(Point));
    // Note: you can't declare an auto of a value type without an initializer!
    //Point p;
    //p.X = 1;
    Console.WriteLine();
}

3.

//=============================================================================

static void CSharpPuzzle3()
{
    string s = "strasse";

    // What is the output?
    Console.WriteLine(s == "straße");
    Console.WriteLine(s.Equals("straße"));
    Console.WriteLine(s.Equals("straße", StringComparison.Ordinal));
    Console.WriteLine(s.Equals("Straße", StringComparison.CurrentCulture));
    Console.WriteLine(s.Equals("straße", StringComparison.OrdinalIgnoreCase));
    Console.WriteLine(s.Equals("straße", StringComparison.CurrentCulture));
    Console.WriteLine(s.Equals("Straße", StringComparison.CurrentCultureIgnoreCase));
    Console.WriteLine(s == "strasse");
    Console.WriteLine(s.Equals("strasse"));
    Console.WriteLine();
}

4.

//=============================================================================

class Account
{
    [Key]
    public string ID { get; set; }
    public string Status { get; set; }
    public decimal Balance { get; set; }
}

static void CSharpPuzzle4()
{
    List<Account> myAccounts = new List<Account>()
    {
	    new Account() { Status = "active", Balance = 1 },
	    new Account() { Status = "inactive", Balance = 2 },
	    new Account() { Status = "active", Balance = 3 }
    };

    // What is the output?
    {
	    decimal total = 0;
	    foreach (Account account in myAccounts)
	    {
	        if (account.Status == "active")
	        {
		        total += account.Balance;
	        }
	    }
	    Console.WriteLine(total);
    }

    // What is the output?
    {
	    decimal total = myAccounts.Sum((account) => (account.Status == "active") ? account.Balance : 0);
	    Console.WriteLine(total);
    }
}

5.

//=============================================================================

class Accounts : DbContext
{
    public Accounts() : base("Accounts.DbConnection") {}

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
	    Database.SetInitializer<Accounts>(new SocialClubInitializer());
	    base.OnModelCreating(modelBuilder);
    }

    public DbSet<Account> _accounts { get; set; }
}

class SocialClubInitializer : DropCreateDatabaseAlways<Accounts>
{
    protected override void Seed(Accounts context)
    {
	    context._accounts.Add(new Account() { ID = "1", Status = "Active", Balance = 1 }); // Note capital "A"
	    context._accounts.Add(new Account() { ID = "2", Status = "Inactive", Balance = 2 });
	    context._accounts.Add(new Account() { ID = "3", Status = "Active", Balance = 3 }); // Note capital "A"
    }
}

static void CSharpPuzzle5()
{
    Accounts dbc = new Accounts();
    dbc.SaveChanges();
    var count = dbc._accounts.Count();
    {
	    decimal total = dbc._accounts.Sum(
	        (account) => (account.Status == "active") ? 
		    (decimal?) account.Balance :
		    0) ?? 0;
	    Console.WriteLine(total); // What is the output?
    }
}

6.

//=============================================================================

static void CSharpPuzzle6()
{
    int[] a = new int[] {1, 3, 5, 7, 9};
    int sum = a.Sum(); // Where is Sum defined?
    int len = a.Length; // Where is Length defined?
}

7.

//=============================================================================

static void CSharpPuzzle7()
{
    // Which implementation is faster?
    // Which implementation uses more memory?
    { // Implementation A.
	    var before = DateTime.Now;
	    int size = 100000000;
	    bool[] a = new bool[size];
	    for (int i = 1; i < size; ++i) a[i] = a[i - 1];
	    var after = DateTime.Now;
	    Console.WriteLine(a.SizeOf());
	    Console.WriteLine(after - before);
    }
    { // Implementation B.
	    var before = DateTime.Now;
	    int size = 100000000;
	    BitArray a = new BitArray(size);
	    for (int i = 1; i < size; ++i) a[i] = a[i - 1];
	    var after = DateTime.Now;
	    Console.WriteLine(a.SizeOf());
	    Console.WriteLine(after - before);
    }
}

8.

//=============================================================================

class SystemResource : IDisposable
{
    public void Dispose()
    {
        // The implementation of this method not described here.
        // ... For now, just report the call.
        Console.WriteLine(0);
    }
}

static void CSharpPuzzle8()
{
    // What is the output?
    using (SystemResource resource = new SystemResource())
    {
        Console.WriteLine(1);
    }
    Console.WriteLine(2);
    {
        SystemResource leak = new SystemResource();
        Console.WriteLine(3);
    }
    Console.WriteLine(4);
}

9.

//=============================================================================

class B { }
class D1 : B { }
class D2 : B { }

static void CSharpPuzzle9()
{
    try
    {
        B o = new D1();
        D2 c = (D2) o;
    }
    catch (Exception) { Console.WriteLine("Exception1"); }

    try
    {
        B o = new D1();
        D2 d = o as D2;
    }
    catch (Exception) { Console.WriteLine("Exception2"); }
}

10.

//=============================================================================

class CSharpPuzzle10
{
    // What does the compiler output for warnings and errors?
    int myId;
    int Id;
    CSharpPuzzle10(int id)
    {
        this.myId = Id;
    }
}
Posted in Tip