Monthly Archives: July 2016

How To Disable Annoying Chrome Shortcuts

If you’re like me, you love using the keyboard and abhor the mouse. So much work gets put into keyboard shortcuts. However, the person who designed the keyboard shortcuts for Chrome must have been drunk at the time. Here are two shortcuts that I commonly mistake for one another when going fast:

Ctrl+Shift+Tab – Switch to previous tab
Ctrl+Shift+Q – Close the entire browser (and apparently clear all cookies, making you curse as you think about how many sites you use where you’re logged in…)

Guess which one I’m commonly hitting nowadays?

Luckily, there’s a way to disable this shortcut.

1. Enter chrome://extensions in your address bar
2. Scroll to the end of the page and click “Keyboard Shortcuts”
3. On a stupid extension you have, add the shortcut Ctrl+Shift+Q to one of the fields that doesn’t matter (Ex. activate extension). I used the Animation Policy extension.

You’re welcome :).

Performance of Constructors versus Object Initialization in C#

If you work in C#, you might see several different ways of constructing a new object around your codebase – constructors and general object initialization.

Constructor:
var t = new Obj(var1, var2, …)
Object initialization:
var t = new Obj() {
Var1 = var1,
Var2 = var2,
  …
}
(Or maybe a mix of both)
At my work, I primarily see object initialization used. I continued the practice because, well, it was the style of the code. However, I was curious as to how big the performance impact of object initialization was (it’s going to be slower because it creates the object first with default values), so I created a little test program and checked out the generated assembly.
class Program
{
    static void Main(string[] args)
    {
        TestClass var1 = new TestClass(“hi”, “hello”, “sup”);
        TestClass var2 = new TestClass()
        {
            Data1 = “hi”,
            Data2 = “hello”,
            Data3 = “sup”
        };
    }
}
public class TestClass
{
    public TestClass()
    {
    }
    public TestClass(string data1, string data2, string data3)
    {
        Data1 = data1;
        Data2 = data2;
        Data3 = data3;
    }
    public string Data1 { get; set; }
    public string Data2 { get; set; }
    public string Data3 { get; set; }
}
You can view the assembly by starting the program, pause the program, and go to Debug->Windows->Disassembly.
Here’s the assembly for the constructor case:
TestClass var1 = new TestClass(“hi”, “hello”, “sup”);
01252DC5  mov         ecx,57E0FB0h
01252DCA  call        00EE30F4
01252DCF  mov         dword ptr [ebp-48h],eax
01252DD2  push        dword ptr ds:[3BA2330h]
01252DD8  push        dword ptr ds:[3BA2334h]
01252DDE  mov         edx,dword ptr ds:[3BA232Ch]
01252DE4  mov         ecx,dword ptr [ebp-48h]
01252DE7  call        01250D00
01252DEC  mov         eax,dword ptr [ebp-48h]
01252DEF  mov         dword ptr [ebp-40h],eax
EAX-EDX are just general data registers. We call our constructor, push the parameters onto the stack, and then move the data into the right place. Simple and clean.
However, here’s the code for the object initialization version:
TestClass var2 = new TestClass()
{
Data1 = “hi”,
Data2 = “hello”,
Data3 = “sup”
};
01252DF2  mov         ecx,57E0FB0h
01252DF7  call        00EE30F4
01252DFC  mov         dword ptr [ebp-4Ch],eax
01252DFF  mov         ecx,dword ptr [ebp-4Ch]
01252E02  call        01250CF8
01252E07  mov         edx,dword ptr ds:[3BA232Ch]
01252E0D  mov         ecx,dword ptr [ebp-4Ch]
01252E10  cmp         dword ptr [ecx],ecx
01252E12  call        01250D10
01252E17  nop
01252E18  mov         edx,dword ptr ds:[3BA2330h]
01252E1E  mov         ecx,dword ptr [ebp-4Ch]
01252E21  cmp         dword ptr [ecx],ecx
01252E23  call        01250D20
01252E28  nop
……
Eesh. It generates a lot of extra code just to assign members, including a surprising no-op. Not sure why that’s there, but it was enlightening to see how much more code is generated versus the constructor method.
Now, you’re probably thinking “Well, what’s the harm? Most machines these days can handle a few extra cycles, and my app isn’t fighting for performance!” Well, there’s a few reasons you should use constructors:
  • If you have a pretty complex object, and you’re purely initializing many of them using the second technique, this extra binary space and time is gonna add up.
  • Constructors provide a good way to enforce proper object construction. A good constructor is going to make sure all required data points are entered.
However, there are good reasons to go about with object initialization:
  • Creating a ton of different constructors is tedious and messy. Any time you add a new field, that’s quite a bit more work.
  • It looks cleaner code wise. You can see that member X is assigned value Y, and not have to consult the constructor definition.
I also learned that our code base primarily used object initialization because one of the developers was a pretty heavy JavaScript developer, so it makes sense to keep that style. However, now that I’ve learned this, I’m primarily going to go with constructors from now on.

How to fix stdole error with Visual Studio opening web pages

So I’ve hit an error the first time I open up a *html file in Visual Studio. You’ll see the following message if you’re in the same boat as me:

An exception has been encountered. This may be caused by an extension.

You can get more information by examining the file ‘C:\Users\<USERNAME>\AppData\Roaming\Microsoft\VisualStudio\14.0\ActivityLog.xml’.

vs_dialog

You’ll see this line in the ActivityLog.xml:

System.IO.FileNotFoundException: Could not load file or assembly ‘stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’ or one of its dependencies. The system cannot find the file specified. File name: ‘stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’ at Microsoft.VisualStudio.JavaScript.Web.Extensions.Interop.HTMLEditor.HTMLTreeHelperFactory.Create(ITextBuffer buffer) at Microsoft.VisualStudio.JavaScript.Web.Extensions.Interop.HTMLEditor.HTMLTreeHelperFactory.<>c__DisplayClass0_0.<GetOrCreate>b__0() at Microsoft.VisualStudio.Utilities.PropertyCollection.GetOrCreateSingletonProperty[T](Object key, Func`1 creator) at Microsoft.VisualStudio.JavaScript.Web.Extensions.Interop.HTMLEditor.HTMLTreeHelperFactory.GetOrCreate(ITextBuffer buffer) at Microsoft.VisualStudio.JavaScript.Web.Extensions.Classification.SPARegionTagger..ctor(ITextView view, ITextBuffer sourceBuffer, ISPASupportedTagProvider tagNameProver) at Microsoft.VisualStudio.JavaScript.Web.Extensions.Classification.SPARegionTaggerProvider.<>c__DisplayClass2_0`1.<CreateTagger>b__0() at Microsoft.VisualStudio.Utilities.PropertyCollection.GetOrCreateSingletonProperty[T](Object key, Func`1 creator) at Microsoft.VisualStudio.JavaScript.Web.Extensions.Classification.SPARegionTaggerProvider.CreateTagger[T](ITextView textView, ITextBuffer buffer) at Microsoft.VisualStudio.Text.Tagging.Implementation.TagAggregator`1.GatherTaggers(ITextBuffer textBuffer) WRN: Assembly binding logging is turned OFF. To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1. Note: There is some performance penalty associated with assembly bind failure logging. To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].

The emphasis on stdole is mine. You’ll probably go digging around for actual solutions. You’ll probably find the following when trying to dig up a solution:

Issue with TypeScript – Uninstall/Reinstall Tools and Windows SDK, then clear VS cache

as well as a few other solutions that I can’t seem to find in my history. No solution worked so far. Thankfully, I fixed it with the simplest solution (but not the best):

c:\>dir /s stdole.dll

I copied the one from here:

Directory of c:\Program Files (x86)\Microsoft.NET\Primary Interop Assemblies

07/07/2015 12:51 AM 32,416 stdole.dll
1 File(s) 32,416 bytes

to the folder where devenv.exe resides (usually C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE). I’m going to make a forum post later to get a non-hacky solution to the issue, but for now, this is what worked for me.