Patrick Smacchia [MVP C#]

Sponsors

The Lounge

Wicked Cool Jobs

News

  • NDepend v3 is fully integrated in Visual Studio, and is now available for download! Software dependencies visualization, 82 .NET software metrics, continuous rule validations, assembly version diff, declarative code queries and more ! http://ndepend.com

Advertisement

Reveal hidden API usage tricks from any .NET application

Normal 0 21 false false false FR X-NONE X-NONE

How many times did you use a .NET application and ended-up wondering: how the heck did they implement that particular feature? I would like to present here a way to reveal some of the best kept secrets of a .NET code base.

 

Let’s take a concrete example. Suppose that you noticed that in the NDepend UI, the search dialog comes with a convenient eyes candy: when searching for the name of a code element by patterns, the pattern(s) are highlighted in the result. In the screenshot below we are searching for .NET framework types where the name contains both patterns Form and Dia (case insensitive). Btw, notice how a CQL query is generated with 2 CQL clauses NameLike “regex”. This is the kind of featurettes that makes me happy Smile:

 

 

Now suppose that in your application you also have the need to measure the width of a string. After a few seconds googling, you’ll find out the MeasureString(…) methods implemented in the 2.NET Framework classes System.Drawing.Graphics  and System.Windows.Forms.TextRenderer. Let’s prototype a bit and then … disappointment: All these MeasureString(…) methods are not accurate at all (I learnt afterthought in this article that this lack of accuracy came from GDI+ problem with font-anti aliasing).

 

But still you know that it is possible since the NDepend UI comes with accurate string width measurement. Here, you’ll certainly end up digging deeper into web search … or … you can use the following trick.

 

 

The idea is to compare your application code with the NDepend code. This sounds absurd, there is nothing to compare right? Actually, the trick is that we focus the comparison on the API usage.

 

First let’s compare your assemblies with the NDepend assemblies:

 

Second, go to the search panel and ask for tier methods used recently. Tier methods are methods from tier assemblies (like the .NET Framework assemblies) that are used by an application. Normally, used recently means that one is asking for tier methods that were not used by the older version of the code and that are now used. We are in fact hi-jacking this feature to ask for .NET framework methods used by NDepend and not used by your application. Let’s focus the search on the System.Drawing.dll assembly since the astute used by NDepend implementation certainly resides there. Here are the methods not used by the application but used by NDepend. Let’s notice the CharacterRange structure and the Graphics.MeasureCharacterRanges(...) method :

 

 

Typing MeasureCharacterRanges CharacterRange in google will immediately point you to this CodeProject article that will explain you how to use this API to have accurate string width measurement. Of course, you could have found this article directly by Googling but here, the cool thing is that this way, you directly target the exact accuracy you need. If it works for a lambda application I don’t need prototyping, it’ll work for my application too. And also try that: typing string width measurement in google only points to MeasureString() inaccurate implementations!

 

 

API used only by your application

The same trick can be used to know types used only by your application. You just need to use the option not used anymore instead of the option used recently.

 

Win32 P/Invoked API

In the same vein, you might want to spy which win32 API is used by an application (through P/Invoke). Here you just ask for methods tagged with the DllImport attribute.

 

Legal issue

I found this trick particularly powerful. It works even if the code of the application has been obfuscated (and actually, the NDepend code is obfuscated!).

 

Most commercial application End User License Agreement (EULA) specifies that the application shouldn’t be decompiled by the end-user to preserve intellectual property. Ironically, the NDepend EULA specifies this point clearly:

 

If the licensed right of use for this SOFTWARE PRODUCT(S) is purchased by you with any intent to reverse engineer, decompile, create derivative works, and the exploitation or unauthorized transfer of (…)Any sale or resale of intellectual property or created derivatives so obtained will be prosecuted to the fullest extent of all local, federal and international law.

 

In this post I don’t provide a good moral example. I wanted to present a relevant/real-world illustration with something that our team learnt the hard way.

 

Anyway, respect the EULA of other applications as you would like your own EULA being respected and use this trick only on applications you can legaly decompile and re-engineer.

 

 


Posted Mon, Aug 31 2009 10:15 AM by Patrick Smacchia

[Advertisement]

Comments

DotNetShoutout wrote Reveal hidden API usage tricks from any .NET application - Patrick Smacchia - CodeBetter.Com
on Mon, Aug 31 2009 3:03 PM

Thank you for submitting this cool story - Trackback from DotNetShoutout

Marcel wrote re: Reveal hidden API usage tricks from any .NET application
on Tue, Sep 1 2009 3:05 AM

Actually, MSDN does mention the MeasureCharacterRanges method on the MeasureString reference page. But I doubt if I would have explored it further...

Nice find!

Pierre Arnaud wrote re: Reveal hidden API usage tricks from any .NET application
on Wed, Sep 23 2009 2:40 PM

Following your link, I was pleasantly surprised to reach my article on Code Project (Bypass MeasureString limitations). I must admit that I no longer use GDI+. It was too painful, inefficient and buggy. I finally settled on the AntiGrain library for my own projects, the most visible one being Creative Docs .NET (http://www.creativedocs.net). And since I paint my character glyphs myself (OpenType font glyph decoding done in a mix of managed C# code and native C++), I can fix my own bugs when they arise ;-)

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Devlicio.us