C# Variant on Struct

In C#, covariant and contravariant allow implicit conversion for generic type arguments. But they're not applied to struct or other value types including primitive type (except string) and enum.

Only an interface declaration can contain covariant and contravariant generic parameters.

A covariant allows to assign an object that is instantiated with a more derived type argument to an object that is instantiated with a less derived type argument. It's declared with keyword out with the generic type parameter. For example, this declares an interface with a covariant generic parameter: interface ICovariantInterface<out T>.

A contravariant does the reversed. It allows to assign an object that is instantiated with a less derived type argument to an object that is instantiated with a more derived type argument. It's declared with keyword in with the generic type parameter. For example, this declares an interface with a contravariant generic parameter: interface IContravariantInterface<in T>.

There are some built-in covariant and contravariant generic interfaces in C#, such as IEnumerable, IComparable.

Usually I would think that covariant in analogy to class hierarchy. It's similar to that a derived class can be assigned to a base class/interface. For contravariant, it's done in the opposite direction.

But we cannot use struct or other value types in covariant and contravariant. Both covariant and contravariant are applied to reference types. And reference types and value types have different memory layout.

So this is not allowed: IEnumerable<object> baseGeneric = new List<int>();.

Customize IntelliTrace to Collect Enums

This Guillaume Rouchon's post illustrates how to add a custom IntelliTraece event. Mine is to complement it with an enum type and updates in Visual Studio 2015 Update 2.

Let me summarize how to add a custom IntelliTrace event. The file you have to change is in a sub folder of Visual Studio installation folder, <VS installation folder>\Common7\IDE\CommonExtensions\Microsoft\IntelliTrace\14.0.0\en\collectionplan.xml. You need to have admin privilege to do that. This file only affect F5 debugging in Visual Studio. If you are using IntelliTrace standalone collector, you have to pass the collection plan file to the command line.  So you can modify default one that comes with the standalone collector or write your own one.

What you need to do to add a custom event is

  1. Add a category under TracepointProvider/Categories
  2. Add an assembly under TracepointProvider/ModuleSpecifications
  3. Add your own diagnostic event specification under TracepointProvider/DiagnosticEventSpecifications
There are two ways of querying parameter values and returned values. The first is DataQuery. It's a simple declarative way using dot notation to get values of the parameter or the field in the parameter. It only supports primitive types. The other way is ProgrammableDataQuery. You have to provide your own IProgrammableDataQuery implementation to query a complex type.
For enum, we're going to use DataQuery.
We need to specify a type in the data query for enum. Intuition tells us we can use the enum type. But that's not working. The right type should be the underlying integral type. For example, int. The value is also an integral value too.
Let me illustrate it here.
I create a sample console application
using System;
namespace ConsoleApplication1
{
    enum Color
    {
        Red,
        Green,
        Blue
    }
    class Program
    {
        static void Main(string[] args)
        {
            PrintColor(Color.Blue);
        }
        static void PrintColor(Color color)
        {
            Console.WriteLine("Color: " + color);
        }
    }
}

Let's change the collection plan.

1. Add a new category.
<Category Id="enumSample" _locID="category.enumSample">Enum Sample</Category>
2. Add a new module
<ModuleSpecification Id="sample">ConsoleApplication1.exe</ModuleSpecification>
3. Add a diagnostic event specification
We're going to query the parameter color in the method PrintColor.

<DiagnosticEventSpecification>
    <CategoryId>enumSample</CategoryId>
    <SettingsName _locID="settingsName.ConsoleApplication.PrintColor">PrintColor (Color)</SettingsName>      
    <SettingsDescription _locID="settingsDescription.ConsoleApplication.PrintColor">
       Print the color
    </SettingsDescription>
    <Bindings>
        <Binding>
            <ModuleSpecificationId>sample</ModuleSpecificationId>
            <TypeName>ConsoleApplication1.Program</TypeName>
            <MethodName>PrintColor</MethodName>
            <MethodId>ConsoleApplication1.Program.PrintColor(System.Int32):System.Void</MethodId>
            <ShortDescription _locID="shortDescription.PrintColor.Color">Print Color "{0}"</ShortDescription>
            <LongDescription _locID="longDescription.PrintColor.Color">
                Going to print the color in integral value "{0}"
            </LongDescription>
            <DataQueries>
                <DataQuery index="0" type="Int32" name="color" query=""
                    _locID="dataquery.PrintColor.Color" _locAttrData="color"></DataQuery>
            </DataQueries>
        </Binding>
    </Bindings>
</DiagnosticEventSpecification>

Save the file and restart VS. The custom event shows in Tools/Options/IntelliTrace/IntelliTrace Events

IntelliTrace Event Options screenshot

When I debug the program, the custom event appears in the Events table. Look at the description! It shows me the integral value of the enum value.VS Events tab screenshot

How simple it is to add a custom IntelliTrace event! This is helpful to diagnose a piece of code path that're prone to error in changes. When you have your own collection plan for the program, you can just debug the program and let it run, and spot the error from the Events table.

Run Windows Phone 10 Emulator on Compressed Disk

If you are like me, you may have your disk compressed and also try to do some Windows Phone development. I'm starting developing for Windows Phone 10 and have this problem:

The emulator is unable to create a differencing disk

The following screen shot explains that virtual hard disk files must be uncompressed and unencrypted and must not be sparse:

Windows Phone Emulator Error

 

Yes. I do have the whole disk compressed. So as long as I uncompressed the virtual hard disk files, I should be able to run the emulator. But unfortunately, the message box doesn't tell me what the files are and where they are.

So I searched and found a few results. Most aren't helpful. They're for emulators for Windows Phone 8 (e.g. https://msdn.microsoft.com/library/windows/apps/ff626524(v=vs.105).aspx#BKMK_uncompressed). I looked at the paths and uncompress C:\Users\username\AppData\Local\Microsoft\XDE. But I didn't  find the one for Windows Phone 10.

After a few more searching, I found the location for Windows Phone 10 VH:

C:\Program Files (x86)\Windows Kits\10\Emulation

That's it. After uncompress both directories, I could debug my app on Windows Phone 10 Emulator.

Grep in PowerShell

When I start to use PowerShell, I miss grep in bash. Luckily, PowerShell provides Get-ChildItem and  Select-String.

Some helpful parameters in Select-String are -Pattern and -Path.

Both -Pattern and -Path accept a list of string. Each item is separated by comma, for example, *.txt, *.log

-Pattern is the pattern of text you want to search

-Path is the list of files you want to search.

However, Select-String doesn't search files under a directory. You have to pass file paths to it via -Path. We can use Get-ChildItem to get a list of files, and get all files under a directory recursively by using -Recurse

The basic pattern to use both cmdlet for greping is as follow:

Get-ChildItem -Recurse -Path C:\Path\To\Folder -Include *.txt | Select-String "SearchText"

I create a script in my GitHub (https://github.com/kceiw/PowerScript/blob/master/scripts/GrepShell.ps1) so that I can reuse it.

This script is not signed though. If you want to use it, you need to change your execution policy to allow it to run. See Set-Execution.

Update Owncloud

I recently updated my Owncloud to find that I couldn't access to contacts and calendars from WebDav any more. And after tried a few things, it worked again.

At first when I tried to open the link from the browser, I got this error:

User did not have the required privileges ({DAV:}read) for path "principals/username”

I searched online and found the issue open against owncloud on GitHub. https://github.com/owncloud/core/issues/14048

The workaround mentioned in the issue was already in my Owncloud. But I still had the same issue. I couldn't go further since there's no more workaround and the issue was closed. I thought there must be some errors in upgrading Owncloud, because it's in maintenance mode for quite a long time. But anyway, I got a message about a newer version when I logged in as Admin. I decided to upgrade it manually. It wouldn't be worse.

After I'd done that, the app files_encryption for server side encryption didn't work. From the log, it's about using an undefined function. I removed it from the apps folder since I didn't really need it.

After that, when I logged in to admin, there's a message in my admin page telling me to run command "occ encryption:migrate". I did so. Surprisingly, I could sync to both contacts and calendars.