Posts
67
Comments
120
Trackbacks
0
August 2011 Entries
SmartAssembly 6.1 Review

It’s been quite a while since I’ve done a GeeksWithBlogs.net Influencers review. This time, I had the opportunity to check out Red Gate’s SmartAssembly 6.1, which is a integrated collection of tools for modifying and manipulating assemblies. Now that phrase, while accurate, is quite a mouthful. So what all does it actually do?

SmartAssembly has the ability to:

  1. Do strong name signing;
  2. Add automated error reporting;
  3. Add feature usage reporting;
  4. Merge dependencies (e.g. libraries) into the main assembly (which lets you then apply obfuscation, etc., to them as well);
  5. Embed dependencies into the main assembly (letting you compress and encrypt them in the process, making deployment faster and maintenance nicer);
  6. Automatically prune unneeded metadata like the names of events, properties, and methods (making the assembly smaller such that it’ll run faster and also be much harder to understand if decompiled);
  7. Obfuscate the names of classes, methods (including properties), and fields, with varying levels of configurability;
  8. Obfuscate control flow (modifying the order that code runs in (without messing up how it works) such that the logic becomes very hard to understand;
  9. Have a proxy created at runtime for accessing methods, properties, and fields in external assemblies, which makes any attempts to modify the assembly render it non-working;
  10. Compress and encrypt resources;
  11. Encode non-constant strings, which is useful if you need to store sensitive information such as passwords, SQL queries, etc., in your code;
  12. Apply several other protections and optimizations (e.g. sealing classes that aren’t inherited from);
  13. Generate debugging information which will let you debug your modified assembly in your IDE; and
  14. Integrate into your build process.

Which of these you can use depends on the type of assembly you’re working with; various features aren’t available due to technology limitations, e.g. the automated error reporting and feature usage aren’t available on Xbox 360 XNA games since there’s no external internet access. For a list of feature compatibility, go to the Release notes - version 6.xx and scroll down to “Known limitations”, which includes a helpful chart of what is available in what.

Well, the first thing I expect many people will notice is that it does obfuscation. But I don’t want to talk about that first, since SmartAssembly does a lot of other really neat stuff that probably gets overlooked. One thing I found really interesting was the Automated Error Reporting functionality. You just check a box and it automatically adds a wrapper for unhandled exceptions that lets your users send in anonymous error reports either to the free service that Red Gate operates or, if you have SmartAssembly Pro, to your own server using the web service software they provide: Setting up a custom web server for reporting . The thing I really liked about it is that it works with Windows Phone 7 (both Silverlight and XNA), which is my primary development target these days. You get a full stack trace, including the values of various variables (try saying that five times fast :) ), along with a lot of in-depth information, such as the version of the app, the OS (including version), the CLR version, and a hash of the UserHostAddress (which should help you to sort out which reports come from which users). You can set flags on them, save the reports for browsing later, and mark your progress. This is an example of a saved report:

SmartAssemblyExceptionReport

As you can see, it provides a lot of helpful information, including the exception message (in my case, the fact that I haven’t implemented the “Open” button yet, which is something I knew). The other thing Automated Error Reporting will do is try to recover from the exception if possible. In the case of my unimplemented “Open” button, it popped up the little notification message box telling me there was a problem, asking me if I’d like to send details about it in to help improve the software, and then continued on as though I hadn’t pressed the problematic button. This is one of those features that I know I’d normally overlook or pay little attention to, which is why I’m making a big deal about it. The quality of its implementation, the ease of applying it (as simple as just checking a box), and the value that it adds to a .NET application makes SmartAssembly worth its price on this feature alone in my opinion. Have a look at some of the walkthroughs and videos for more information; they’re short and interesting.

On to obfuscation. If you don’t know what obfuscation is, it’s basically the application of various techniques in order to make it very hard if not impossible for someone to take your .NET program and see its source code using a disassembly tool like ildasm.exe or .NET Reflector. I did several tests of its obfuscation capabilities based on projects I’ve completed, that I’m actively working on, and that I just use for testing. My experiences were mostly good.

I struggled a bit getting my WP7 Silverlight app to obfuscate properly and still work correctly. The obfuscated version was having issues with parsing XAML, which is not surprising given that XAML data binding relies on reflection to work properly and obfuscation messes around with all sorts of things.

It turned out that my problem was event handler methods. Specifically, in various places in my XAML, I was handling events with methods in my code-behind class for the Page that weren’t marked public. For Silverlight projects, SmartAssembly automatically excludes anything marked public from name mangling; anything else gets mangled by default. The solution in this case was to either mark those methods public and let SmartAssembly automatically exclude them, to go and mark them manually (when you put a check next to an assembly in the Obfuscation area, a link called “Exclusions” appears next to it, letting you go in and exclude any namespaces, class names, methods (including custom property getters and setters), and fields that you want from having their names mangled), or to apply custom attributes to them. The last solution is probably the best to go with since once it’s all setup, it’ll just work no matter what you change or refactor in your code.

Once I fixed that issue, almost everything worked. I also had an issue with a third-party control that I was using. I was hoping to be able to merge it and obfuscate it (either name mangling, control flow obfuscation, or both), but it was not meant to be. SmartAssembly recommends against trying to merge third party libraries, suggesting that you embed them instead. Embedding isn’t an option for WP7 though, so I had to modify how I was using the control. Initially I had it as a project within my solution and was including it as a reference as a project. What I did instead was build it as a separate DLL and apply obfuscation to it with a separate SmartAssembly project. I then included a reference to the obfuscated, pre-built DLL and it worked like a charm. Many would consider that a ‘best practice’ way of doing such a thing anyway (seeing as you’re rarely, if ever, going to be changing that third party code so rebuilding it all the time makes no sense), so it was a double benefit in that regard. With that issue resolved, everything worked great.

Next I tested a WP7 XNA app that I’m working on. Once I set up the SmartAssembly project, it worked perfectly the very first time. The error reporting was very simple to integrate and a really pleasant surprise (I created an intentional exception, which you can see in the screen shot above, just to test it). It’s something I will definitely be making use of and something I highly recommend to everyone. Do note that if you setup the automated error reporting to email you for every error report, it will indeed do this. If you publish something and a lot of people get errors in one particular place (which might be very common when doing a beta test, for example), you can expect to get a lot of emails as a result. So I recommend dedicating a special email address for that feature, if you choose to use it, so that you don’t wake up to find your personal inbox chock full of messages. :) (This did not happen to me, but I could easily see it happening by accident, especially for something that you’re just doing a private beta for such that you might not think to use a special email address for it.)

The last thing I tested was my PC XNA sandbox app. I have over half a dozen “sandbox” apps that I use to test out various things in different languages and technologies. I most recently used my PC XNA sandbox app to do some stress testing on SpriteBatch draw calls. So it was already setup to not run particularly well, making it a good measuring platform for how SmartAssembly’s various components affect performance. I modified the project to use a WeakReference to track when GC collections occurred, added in a pointless allocation of 5000 bytes every frame, then used a StreamWriter to write out GC data every time a collection occurred; specifically: the current count of collections, current total game time, the time difference (delta) from the last GC collection, and the average time delta between collections. It was already setup to display the current frame rate. For the SmartAssembly-modified version, I initially set it to use Automated Error Reporting, Obfuscation (Types/Methods Name Mangling set to “I want to obfuscate using only Unicode unprintable characters.” and Fields Name Mangling set to “I want to use standard renaming, so that all the fields in a class have a different name.”), Control Flow Obfuscation, and to seal all classes that are not inherited (under Other Optimizations).

The results? The original Release build (run as a standalone program outside of Visual Studio) and the SmartAssembly-modified version of that Release build ran virtually identically. Both maintained the same frame rate hovering between 34 and 35 fps. I stopped both after they hit a GC count of 21 (I didn’t track any GCs that occurred during the LoadContent phase, just during gameplay). The original Release build hit its 21st GC at 61.950 seconds in with an average delta of 2.950 seconds. The SA version hit its 21st GC at 62.067 seconds in with an average delta of 2.956 seconds. Yep, the SA version actually won (though just barely; it could easily be due to my computer doing stuff in the background). Since the test was to see if it hurt performance, and (with several runs of each just to avoid obvious anomalies) they both ran virtually the same, it seemed clear to me that it didn’t.

Just for kicks, I created another SmartAssembly version, this time with everything enabled except for Generate Debugging Information, Strings Encoding, and Strong Name Signing. I also turned up obfuscation to its maximum levels. I also ran this one several times just to confirm the results weren’t anomalous. This build runs an initial GC much earlier than the other tests (after ~1.7 seconds versus ~2.7 seconds for the previous two builds), but then runs virtually the same as the others. An example run hit its 21st GC at 61.065 seconds in with an average delta of 2.908 seconds. But if you exclude the first collection and average the other 20, you wind up with an average delta of 2.969 seconds. The other builds also showed a slightly early first GC so I’m willing to call them functionally identical. What all these tests told me is that this is a great way to protect my programs without any noticeable performance hits.

The last thing I want to talk about is the ability to automatically integrate a SmartAssembly project into your build pipeline. You can add SmartAssembly in to the MSBuild process or into a ClickOnce deployment. I’ve done this for a couple of projects already and it’s quite easy and very smooth. Some projects (e.g. XNA games) generate extra content that needs to be copied into the output directory (for XNA games, any of your content folders along with their XNB files). You can either configure an MSBuild Copy Task to do that for you (just add it in with the SmartAssembly Task into the AfterBuild target) or you can do it by hand or some other way. So just take note that SmartAssembly (when integrated into MSBuild at least; I haven’t tested ClickOnce) only creates the assembly or assemblies that it is operating on at its destination and that it’s up to you to setup a mechanism for copying any other content files that your assembly depends on.

Just as with ANTS Memory Profiler, I found I really liked SmartAssembly. It’s easy to work with, the help materials and learning videos are really good, and it makes a variety of otherwise complicated tasks very easy to do. There’s a 14-day, fully functional free trial for it, so if you’re on the fence, go check it out and see what you think.

(n.b. While I was finishing up this review, version 6.2 was released. The release notes indicate that the changes are very small and shouldn’t have an impact on anything I discussed above. They do mention the provision of sample error reports, which I think is a great addition since it lets you see what you’ll be getting from error reports without having to spend time creating your own.)

Posted On Friday, August 26, 2011 5:57 PM | Comments (0)
Interpolation Sample for XNA

One thing I’ve always enjoyed in Silverlight/WPF are the easing functions ( http://msdn.microsoft.com/en-us/library/ee308751.aspx ). The easing functions are commonly used to provide interesting looking animations via key frame-based interpolation.

XNA has a few, limited bits of interpolation built in (primarily Lerp (i.e. linear interpolation) and SmoothStep (i.e. cubic interpolation)). For a sprite animation project that I’ve since set aside (it’s not dead, but it’s been back-burnered for a while now), I replicated most of the Silverlight/WPF easing function (I never got around to figuring out BounceEase and ElasticEase) so that I could use them in XNA. I decided I’d make them available to all of you to use as well. They’re great for spicing up menus and other animations.

The important part of the sample is the Interpolation.cs/Interpolation.vb file; that contains the static class and the two enums that combine together to provide the interpolation. There are two solutions: Interpolation Sample and Interpolation Visualizer. Sample is a basic demonstration of how to use some of the functionality within an XNA game to do things like animate a sprite’s tint color, scale, and position. Visualizer is a WPF app that lets you see what the different enum values produce (and for a few, what the “formula value” does). The code is dual licensed under the MIT License and the Microsoft Public License. You can get it here: C# - Interpolation_SampleCS.zip VB - Interpolation_SampleVB.zip. The zip files contain both the Interpolation Sample and the Interpolation Visualizer despite the names. Note that the Interpolation Visualizer will need to be built once before you MainWindow.xaml will display properly in the designer due to its use of data binding. Until you build it, it’ll probably tell you that there are errors since it can’t use reflection to find things in an assembly that doesn’t exist yet.

Enjoy!

Posted On Saturday, August 6, 2011 3:23 PM | Comments (0)
Dxt Conversion Content Pipeline Extension Sample

I’ve been slowly creating a new WP7 game over these past few months. In the process, I began experimenting with Dxt compression. It’s a very nice feature, especially on the phone where high DPIs make Dxt’s artifacts less visible. One thing I didn’t like, though, was the way that XNA’s default Texture Processor handles resizing to power of two.

When using Dxt compression with the Reach graphics profile, you need to use textures that are power of two sized (e.g. 32x64). Dxt itself requires that the dimensions be divisible by four (it breaks up your image into 4x4 chunks of data in order to compress it), but it’s easier for graphics cards with limited power (such as on netbooks and mobile devices) to process them when the dimensions are restricted to being a power of two as well.

XNA’s built-in Texture Processor has an option to resize your images to power of two dimensions. Unfortunately, the way it does so is by scaling your image. This can produce both odd stretching effects and also a blurry look to the result even when you compensate for the stretching. So I’ve created a quick Content Pipeline extension that resizes the image by padding it rather than by scaling it. I’m quite satisfied with the result and so I thought I’d share it with all of you to make do with as you see fit. The code is licensed under the terms of the Microsoft Public License. You can also instead use it under the terms of the MIT License (a copy of which is included in the zip file) if that works better for you.

I’ve extended the dual licensing to nearly all of my samples and have updated the ones that are affected to include a copy of both licenses. I learned recently that for some people I know the MIT License is more convenient and I like to be as accommodating as I can. If you fit in to that group, feel free to re-download any samples you are interested in to make sure the MIT License is included (my only known exclusion was for a back-port I did of a code sample that was licensed exclusively under the Ms-PL).

To use the Convert To Dxt Processor, build it, and add a reference to it to your game’s content project. Then set your image files to use the Convert To Dxt Processor. You can do this via Solution Explorer by right-clicking on the image file(s) and choosing “Properties” then changing the Content Processor from “Texture – XNA Framework” to “Convert To Dxt Processor”. If your image was not previously a “power of two” sized image, you will need to use an overload of SpriteBatch.Draw that takes a sourceRectangle parameter and use as a source rectangle something like: “new Rectangle(0, 0, width, height)” where width and height are the original width and height of the image. The sample game that is included shows this in more detail.

Without further ado, the samples:

C#: Dxt_CPE_SampleCS.zip

VB: Dxt_CPE_SampleVB.zip

And just so you can see the difference, a sample screenshot:

DxtCPESampleResults

The left hand column (both rows) is the original image without any Dxt Compression or other adjustment. The middle column is the XNA Framework Texture processor. The right hand column is the custom processor I developed. The top row illustrates the images without any scaling or source rectangles used. The bottom row illustrates the XNA Framework processor’s results with scaling applied to obtain the original size and my custom processor with a source rectangle used to clip the image to its original size.

The text along the bottom shows the resulting XNB size for the Windows version using a Release configuration. The comments in the code explain why the size differences appear here and the different way in which they would manifest themselves in a WP7 build. Note that for Debug configuration the Dxt XNBs will be the same size (32.18 KB) and the original XNB will be 143.93KB. The image in question is 160x230 such that it winds up being a 256x256 XNB with power of two adjustment. So even with jumping from 36800 pixels to 65536 pixels, we still wind up with compression such that the image will only occupy 22.36% of the memory that the non-Dxt image does and we end up with reasonably good savings in storage space (for comparison, the original PNG is 43KB). So definitely consider using Dxt compression for your XNA games (both WP7 and PC/Xbox). The memory savings are quite good without much loss in quality.

Posted On Monday, August 1, 2011 10:24 AM | Comments (2)
Bob Taco Industries is an ISV focused on game and app development for Microsoft platforms headed up by Michael B. McLaughlin. Mike is a Microsoft Visual C++ MVP (previously an XNA/DirectX MVP from 2011-2013), a developer, a writer, a consultant, and a retired lawyer. If you're a developer who is just getting started, consider checking out the BTI website's section for developers for links to code samples and other helpful sites.
Tag Cloud