WinRT – A gift from the past…

Just came across this enlightening blog post while asking Google if Microsoft was going to abandon .NET : http://www.guardian.co.uk/technology/blog/2012/feb/17/winrt-windows-8-microsoft-programming

EDIT I found another developer blog with similar concerns: http://realworldsa.blogspot.com/2011/09/today-microsoft-killed-net-good-bye-wcf.html

I realize I’ve been complaining off and on – sometimes rather dramatically – that Microsoft is making some really terrible decisions of late. The aforementioned article helps at least give an explanation to one of those decisions:

WinRT was developed by the people who write drivers and kernels. Those people are undoubtedly C++ developers who do not consider the .NET dialects “real languages.” Which is really unfortunate, because C++ is about the worst language (short of assembly) for writing maintainable, reliable, testable, or portable code. The only upside is that if you are good at it and spend orders of magnitude more time coding, your code will be more efficient.

Windows 8 Metro apps are meant to work on both desktop and tablet PCs (even though they must be compiled separately for each platform…) Tablet PC will have seriously limited horsepower, and clock cycles equate directly to battery life. So… we go back to using C++, and impose limitations worse than PocketPC to all hardware platforms. (Bad news – C++ is only more efficient if you are good at it) (Also, HTML5/JavaScript is a really bad place to invest significant development effort when literally every new release of web browsers has resulted in breaking changes)

What should have happened is optimization of .NET for efficiency. Not pushing business application developers to become experts in memory management, pointers, references and clock cycles.

 

WinRT seems to be what the developers of Win32 wish they had done back in 1998, rather than a proper evolution of development technologies.

 

(By the way, I’ve said it before but I feel the need to mention again – Metro (aka “Windows Store” aka “Windows-8-UI”) apps can not and will never replace desktop apps. And desktop apps are not and will never be “legacy” despite some people throwing around the term. Certain parties at Microsoft would love to get a 30% cut of all developer profits, so phasing out desktop apps is certainly a bullet point in their PowerPoint, but reality will hopefully keep this at bay)

The stats now: Microsoft is alienating it’s largest user base by forcing a tablet interface onto a PC. They are alienating manufacturers by developing their own hardware and licensing portions of the OS to “chosen” companies. They are alienating mobile users and developers by essentially abandoning Windows Phone 7 and providing no upgrade path. And finally they are alienating the vast majority of developers with massive restrictions and profit cuts.

Handling Invalid Enum values in a DataContractSerializer

This all started when I was trying to serialize a CodeDom graph (actually a CodeNamespace object) using a DataContractSerializer. I hit the dreaded “Enum value ‘20482’ is invalid for type…”

image

(Note: this error was the showstopper after many other errors)

The problem: System.CodeDom.MemberAttributes should have the [Flags] attribute, but it does not. the value of 20482 is the bitwise OR of MemberAttributes.Final (2) and MemberAttributes.Private (20480). One solution was to go through all object in the CodeDom tree with attributes and force it to a single value – this is not really acceptable. Unfortunately, since we are dealing with a .NET Framework type, there is really no way to fix the type itself.

The solution: Fix the serializer… Read on for details.

Continue reading

Determining current laptop battery drain in .NET

My laptop battery’s lifetime has dropped significantly of late, and I wanted some means of determining the actual current being used by the system – sort of like a Power Meter for the laptop battery. I‘ve actually been looking for such a tool off and on for months. I’ve seen things you have to pay for, things that are quite old, and things you can do yourself in C++…

Well I don’t want to pay for something that tells me the power usage in mw (milliwatts). Nor do I want something with “Vista” style. Nor do I want to deal with c++.

1. Performance Monitor

Not sure why I didn’t think to look here – maybe because it’s a big mess – but it turns out the power utilization in mW is in a couple places in windows Performance Monitor:

Under Power Meter –> Power:

image

Do not use the _Total option – at least on my machine it is incorrect. Use all instances, then look to see which instance corresponds to your actual battery. (note: this only works while your laptop is running on battery power. “Power Meter” returns 0 when you are on AC power)

 

You can also use Battery Status –> Discharge Rate. There is also a Charge Rate that will have a value when the battery is charging. The only catch is that access to Battery Status requires Administrator privs.

 

2. .NET Performance Counter – Forms control

Forget WMI queries and System.Management – Be lazy! Visual Studio has a Server Explorer tab that allows you to easily add performance counters to your Windows Forms project.

Open Server Explorer –> You computer –> Performance Counters

image

Find Power Meter, expand Power, and drag whichever power meters you need onto your form. (In my case I just needed Power Meter (0).

image

This will add performanceCounter1 to your project. To get the current power usage in mW, just access performanceCounter1.NextValue().

 

3. .NET Performance Counter – Code

Even easier, once you know the Category (“Power Meter”), Counter (“Power”) and Instance (“Power Meter (0)”), you can create the performance counter in code like so:

(Add a textbox and a button to your form), use this as the button event handler

        private void button1_Click(object sender, EventArgs e)
        {
            var powerCounter = new System.Diagnostics.PerformanceCounter("Power Meter", "Power", "Power Meter (0)", true);
            textBox1.Text = powerCounter.NextValue().ToString();
        }

 

Chances are I will release a (free, open source) tool based on this, but it’s painfully simple to just get that current value. (Now to start seeing the effect of the backlight, and hard drive, and cpu load…)

Getting a poorly designed ClickOnce application to Run As Administrator

(Updated 5/10/2012 – I originally claimed that it was “trivial” to make a ClickOnce app require elevation – a commenter pointed out that ClickOnce does not support the requireAdministrator execution level at all. This does not let the vendor off the hook – they should not have used ClickOnce to deploy software that requires features ClickOnce does not support… FYI – there are workarounds from the deployment side)

One of our vendors distributes a couple tools as ClickOnce applications, but these applications perform privileged tasks that do not work with UAC enabled. A ClickOnce application cannot be elevated, nor can it be specified that it requires elevation, so the only way this application would have ever passed testing is if UAC was disabled on the developers’ machines, or Visual Studio is run as administrator)

Rant: UAC has been around since Windows Vista was released in 2006. As of this writing, that would be 6 years. Windows 7 has been out for 3 years. As much as some people might dislike the extra dialogs, UAC is a very good thing, and should not be disabled. There is no excuse for applications that do not handle UAC correctly. Adding the appropriate application manifest is not difficult, and when using ClickOnce it is practically trivial (5/10/2012: Errata: ClickOnce Doesn’t support UAC – I was thinking about Full Trust) and if an application requires elevation it should be distributed standalone or with an MSI setup project.

Don’t use ClickOnce for applications that require elevation; Add the Application Manifest with a setup project to require elevation; or better yet modify your app to not require elevation at all, but do not just pretend it doesn’t exist. 6 years… come on!

Ok, now that my rant is out of the way, if you are in a similar situation – a ClickOnce app that needs elevation to run, but doesn’t request it is a real pain in the butt.

image

“Run as Administrator” is conspicuously missing from the context menu:
image

Continue reading

Fairly robust Regular Expression to scrape an ISBN

I’m working on an app that given the URL for a book, needs to scrape the page looking for an ISBN. I have seen several of these out there, but I didn’t think they would be quite robust enough.

 

The main difficulty is the format – an ISBN can be 10 or 13 digits, optionally broken into sections separated by hyphens. (One could use spaces, but you have to draw the line somewhere…) The saving grace is that in every site I’ve sampled, (once the html tags are stripped out), the text “isbn” precedes the number itself. This should be the case even for simple tables (the two <td> elements are normally in the same row, thus consecutive). Then there is the hyphen issue. ISBN legitimately supports variable length groups.

So I have two (.NET style – remove the string “?<isbn>” from them to get a standard regex) Regular Expressions – one for ISBN-10 and one for ISBN-13.

Here they are defined in c#

            Regex rexIsbnNum10 = new Regex(@"isbn(.{0,3}10)?[^\w]{1,10}(?\d-?\d-?\d-?\d-?\d-?\d-?\d-?\d-?\d-?\d\b)");
            Regex rexIsbnNum13 = new Regex(@"isbn(.{0,3}13)?[^\w]{1,10}(?\d-?\d-?\d-?\d-?\d-?\d-?\d-?\d-?\d-?\d-?\d-?\d-?\d\b)");

To use them, you grab the contents of the web page, strip out the html tags, make it lowercase for simplicity (or use case-insensitive regexs), apply regexIsbnNum10.Matches() to the string, and you should have all the ISBN-10 values nicely enumerated. Likewise for ISBN-13.

 

Using the ISBN-13 as an example, this regex will match:

ISBN 978-0130190772
ISBN-13: 978-0130190772
ISBN13: 978-0130190772
ISBN: 978-0130190772
ISBN-13: 9-78-01301-9077-2
ISBN-13 — 9-7-8-0-1-3-0-1-9-0-7-7-2

It will not match if there are less than or greater than 13 numbers, or if the “ISBN” and the “13” and more than 3 character apart, or if the ISBN-13 is more than 10 characters away from the number itself (or letter / number falls in between)

Getting a poorly designed ClickOnce application to Run As Administrator

One of our vendors distributes a couple tools as ClickOnce applications, but these applications perform privileged tasks that do not work with UAC enabled.

Rant: UAC has been around since Windows Vista was released in 2006. As of this writing, that would be 6 years. Windows 7 has been out for 3 years. As much as some people might dislike the extra dialogs, UAC is a very good thing, and should not be disabled. There is no excuse for applications that do not handle UAC correctly. Adding the appropriate application manifest is not difficult, and when using ClickOnce it is practically trivial.

Add the Application Manifest to require elevation; or better yet modify your app to not require elevation at all, but do not just pretend it doesn’t exist. 6 years… come on!

Ok, now that my rant is out of the way, if you are in a similar situation – a ClickOnce app that needs elevation to run, but doesn’t request it is a real pain in the butt.

image

“Run as Administrator” is conspicuously missing from the context menu:
image

Continue reading

How to embed an application manifest in a CodeDom generated assembly

When using CodeDom to generate executables (using CodeCompileUnit.CompileAssemblyFromDom for example), you can easily embed your custom application manifest using the CompilerParameters.CompilerOptions string, like so:

            CompilerParameters cp = new CompilerParameters();
            cp.GenerateExecutable = true;
            cp.GenerateInMemory = false;
            cp.TreatWarningsAsErrors = false;
            cp.OutputAssembly = "RandomFileName.exe";
            cp.CompilerOptions = "/optimize+ /debug- /win32manifest:RandomFileName.exe.manifest";

The relevant option being /win32manifest. Make sure you create the manifest before attempting to compile, obviously.

And use the CompileParameters in CompileAssemblyFromDom();

FYI – There are other ways to do this, but they would involve finding and running some command line utilities. This is by far the easiest, and most elegant way I could find.

Creating a Custom Tool (Single File Generator) for Visual Studio 2010

A Single File Generator or “Custom Tool” is a COM “extension” for Visual Studio that takes a project file as input, and spits out some code. (One example is the .settings files) Visual Studio automatically includes the code in your project, and updates it every time you save.

I developed a tool that reads an Office 2010 Ribbon XML file and produces an interface will all the callbacks in your file (because implementing callback signatures is a bear).

Unfortunately, Microsoft’s documentation on the subject is incomplete and obsolete. If you search the web, you will find contradictory information…
I didn’t want my assembly in the GAC, nor did want to have to register the COM object globally. I didn’t want to create a setup project, or use any fancy generated code… I just wanted it to work.

So here are some tips that should get you going.

  1. First of all, there is no need to use the Visual Studio extensibility project template for this. Just create a standard Class Library in the .NET language of your choice.
  2. Add a reference to Microsoft.VisualStudio.Shell.10.0 and Microsoft.VisualStudio.Shell.Interop to your project. (If you do not have these, you probably need to download the Visual Studio 2010 SP1 SDK)
  3. In the Project Properties, in the Application tab, click “Assembly Information…” and check the “Make Assembly COM Visible” box.
  4. Do NOT select “Register for COM interop” on the Build tab
  5. On the signing tab, check sign the assembly, and select or create a key
  6. Add the following using statements to your class file:
    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio.Shell.Interop;
    using Microsoft.VisualStudio;
    
  7. Add the ComVisible attribute
  8. Add a Guid to the class (use the Tools Menu-> Create GUID and select Item 5 for c#, item 6 for vb.net, hit copy)
  9. Make your class implement the IVsSingleFileGenerator interface.
  10. It should look like this:
        [ComVisible(true)]
        [Guid("FAKEGUID-FFF6-4FF3-FFF7-FFFFRFRFRF45")]
        public class Generator : IVsSingleFileGenerator
        {
    
  11. DO NOT USE THIS GUID. YOU MUST GENERATE YOUR OWN
  12. Implement the IVsSingleFileGenerator interface’s two methods – Generate and DefaultExtension (see the documentation for more details)
  13. Build it!
  14. Now for the part where the documentation falls apart – registering and using this bad boy.

  15. The easiest way to register this is using the Visual Studio local registry at HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0
    Note: on 32-bit systems, this may be at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0 – I am using the 64-bit
    There should be plenty of sub-keys under this key. If there are not, perhaps you need to look in a different version, or bit-ness
  16. First, you need to add the COM information like so
    Windows Registry Editor Version 5.00
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\CLSID\{FAKEGUID-FFF6-4FF3-FFF7-FFFFRFRFRF45}]
    "InprocServer32"="C:\\Windows\\SysWOW64\\mscoree.dll"
    "ThreadingModel"="Both"
    "Class"="DemoSFGen.Generator"
    "Assembly"="DemoSFGen, Version=1.0.0.0, Culture=neutral, PublicKeyToken=faketokenfffff88"
    "CodeBase"="file:///C:\\Users\\username\\Documents\\Visual Studio 2010\\Projects\\sfgen\\sfgen\\bin\\Debug\\sfgen.dll"
    

    Replace the GUID after CLSID with the GUID you generated earlier; replace the Class with your Namespace.ClassName; replace Assembly with the information from your dll (I used ILSpy – I’m sure there’s an easier way); replace CodeBase with the full path to your dll.

  17. Next, add the registry info to tell Visual Studio about the Generator:
    Windows Registry Editor Version 5.00
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Generators\{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}\DemoSFGen]
    "CLSID"="{FAKEGUID-FFF6-4FF3-FFF7-FFFFRFRFRF45}"
    "GeneratesDesignTimeSource"=dword:00000001
    @="Nice Name For your Generator"
    

    The GUID after \Generators\ corresponds to the languages in Visual Studio. See the docs for registering single file generators for a couple (or have a look in the registry).
    The Key name under the language guid (DemoSFGen in this case) is (I believe) how you will refer to the Custom Tool
    The value of CLSID needs to match your generated GUID

  18. Run Visual Studio, open a (different) project, and select an appropriate input file (text, xml, etc) In the properties for the file, add the name of the Custom Tool (“DemoSFGen”).
  19. Right click on the file, and select “Run Custom Tool”
  20. If everything worked, you will now be able to expand the file, and see your generated source underneath it. If there was a problem, Visual Studio may or may not display an error…

I know that Custom Tools aren’t the most often created things in the world, but hopefully these steps can at least get you up and running when you do try.

Viewing and editing Sharepoint properties on a Word document… again

I have posted before about a method of editing the SharePoint Document properties on a Word document in Office 2010 (and Office 2007). I just found something that completely blew my mind. I spent hours and hours battling with CustomXMLParts, Protected and Readonly documents, and a Save-As dialog… and found out that all that effort was pretty much wasted.

Behold:
_Document.ContentTypeProperties Property
Microsoft.Office.Interop.Word.Document.ContentTypeProperties

ContentTypeProperties is a collection of MetaProperty objects representing (possibly among other things) the SharePoint properties displayed in the server document properties panel. And you can edit them.

So instead of a mess of XML xpath, namespaces, exception handling and “_x0020_”‘s , if you want to edit a sharepoint list column called “Task Id”, you would do the following:

doc.ContentTypeProperties["Task Id"].Value = "task1";

(Yes, you still might need some exception handling…)

The CustomXMLParts will be updated appropriately, and when you save it to sharepoint, the properties will be populated.

Have a look at the members of the MetaProperty object:
.Name = sharepoint internal column name: “Task Id”
.Id = escaped column name: “Task_x0020_Id”
The other properties are what you would expect.

Please note that this will only work if the word document has been “touched” by SharePoint. See my next post for a quick (and undocumented) method of getting those properties attached in Word 2010.

Definitive complete list of Office Ribbon Callback Signatures for 2007 and 2010

Microsoft’s documentation for programming the Office Ribbon is pretty sparse at best. There are two pages you can get Callback signatures:
1. Customizing the 2007 Office Fluent Ribbon for Developers (Part 3 of 3)
2. Introduction to the Office 2010 Backstage View for Developers

Notice that neither of these documents sound like where you would expect callback signatures “part 3 of 3”, and “introduction to the…” Also, the backstage introduction article contains rehashes of most of the office 2007 callbacks in a painfully verbose fashion.

I am here to help.
How about an excel spreadsheet containing the callbacks, associated control, source (2007 vs 2010) and the signatures in 4 different languages? Did I mention the data is already in a table and sorted by callback name?

Here you go:
Full Office Ribbon Callback List
Update: I have uploaded this file to a public SkyDrive so it can be viewed online, since I have needed to make some changes:
Office Ribbon Callbacks

This document is not a control -> callback mapping. The typical use case is:
I am building Office customizations using xml.
I need to implement X callback, but do not know the signature.
I look up the callback by name, then make sure it is the correct one for my control.

Also, I didn’t quite finish reconciling some discrepencies between the 2010 and 2007 documentation – for example, in 2007 the getImage is supposed to return an IPictureDisp – which is a real pain in the butt. My experience showed that returning a bitmap worked anyway, and now the 2010 documentation says getImage returns System.Drawing.Bitmap. I have switched to using Bitmap because it is so much cleaner, but I figured I should leave them both in there.

I am open to suggestions – just trying to fill what I consider a documentation gap.