Category Archives: .NET

Helpful Enum Description Attribute

2
Filed under .NET, VB Feng Shui

imageWhen you work with Enums, often, it’s nice to have a description to go along with the value. Of course, you can use reflection to retrieve the name of the enum, and that’s sufficient for many purposes. But sometimes, using the name ends up being awkward, or just won’t work.

For those times, I created an EnumDisplayName Attribute.

First, the attribute definition:

<AttributeUsage(AttributeTargets.Field)> _
Public Class EnumDisplayNameAttribute
    Inherits Attribute

    Public Property DisplayName As String

    Public Sub New(ByVal DisplayName As String)
        Me.DisplayName = DisplayName
    End Sub
End Class

Using it would then look something like this:

Public Class Core
    Public Enum ChimeSoundsEnum
        <EnumDisplayName("None")> _
        None = 0
        <EnumDisplayName("Air Raid")> _
        AirRaid = 1
        <EnumDisplayName("Beeper")> _
        Beeper = 2

Now, all you need is an extension method on Enum to read the DisplayName for a particular enum value:

Imports System.Runtime.CompilerServices

    <Extension()> _
    Public Function DisplayName(ByVal e As [Enum]) As String
        Dim enumType = e.GetType
        If enumType.IsEnum Then
            Dim f = enumType.GetField(e.ToString())
            Dim displayNameAttribute = DirectCast(f.GetCustomAttributes(GetType(EnumDisplayNameAttribute), False).FirstOrDefault(), EnumDisplayNameAttribute)

            If displayNameAttribute IsNot Nothing Then
                Return displayNameAttribute.DisplayName
            End If
        End If
        Return [Enum].GetName(enumType, e)
    End Function

And finally, to read all the DisplayNames for a particular Enum type:

    Public Function GetEnumDisplayNames(ByVal et As Type) As String()
        If et.IsEnum Then
            Dim l = New List(Of String)
            Dim flds = From f In et.GetFields Where f.IsLiteral = True
            For Each f In flds
                Dim desc = DirectCast(f.GetValue(f), [Enum]).DisplayName()
                If Desc IsNot Nothing Then
                    l.Add(desc)
                End If
            Next
            Return l.ToArray
        Else
            Return Nothing
        End If
    End Function

Using that last function, you get back an array of DisplayNames that you can then databind to (for, say the ItemSource of a ListBox).

And finally, using these same techniques, you can create any number of other Enum metadata elements to make enums much more useful and easier to work with. You could have a ShortName attribute, a DataColumn attribute, maybe a PermissionLevel attribute, etc.

Comparing an Int32 to a UInt32

0
Filed under .NET, p/Invoke, RawMouse

imageI’ve been working on a little project to involves raw mouse support lately. If you haven’t ever heard of raw mouse, don’t feel too bad. It’s a pretty esoteric part of Windows that’s been around since the XP (and possibly earlier) days, but isn’t widely used.

Essentially, it’s trivially easy to plug a second mouse into your computer and just use it. The cursor onscreen reacts to both mice equally,  and usually, that’s exactly what you want.

However, what if it’s not?

What if you’re working on a game and you want to be able to see each mouse’s input independently? Windows does such a good job of hiding the mouse plumbing that doing so is impossible using standard mouse access techniques. Even DirectInput can’t do it, although you’d sure swear that a function like this:

Manager.GetDevices(DeviceClass.Pointer, EnumDevicesFlags.AttachedOnly)
shouldn’t have any problems doing so (it doesn’t work, I tried it!)

RawMouse to the Rescue

Turns out, you CAN get at multiple mice independently through the lower level mouse support functions, call the RawMouse layer. Essentially, the way it works is you register a window handle to receive RawMouse messages and then you react to those messages appropriately. But a full discussion of RawMouse will have to wait for another day.

In any case, you’ll be dealing with raw Windows Message blocks and it’s often not particularly easy for .Net languages to directly parse those blocks.

Or is it?

Comparing

At one point, I needed to compare an Int32 value (a signed 32bit integer value) to a UInt32 value (an unsigned 32 bit integer). Sounds straightforward, and often, a simple CType will work. But if the UInt32 value is greater than 2^30, it’ll overflow if you try to use CType on it (unlike C#, where a cast from UInt32 to Int32 just works, sigh).

I knew the Marshal class had all sorts of functions for doing manipulation like this, but in searching around, I was reminded of a little trick I used quite some time ago, when I was first getting into .net, and which had subsequently exited from my consciousness.

It turns out that the Imports System.Runtime.InteropServices namespace includes several attributes that control the layout of structures.

The two in particular we’re interested in is

  • <StructLayout(LayoutKind.Explicit)>
  • <FieldOffset(0)>

The StructLayout attribute is applied to the entire structure and it basically says that you the programmer will be explicitly determining the positioning of the fields (members) of the structure.

The FieldOffset atttribute, on the other hand, is applied to each field in the structure and determines where (using a 0 based offset in bytes) in the entire block of memory that defines the structure, that particular field will be located.

When you put it all together, you get a structure like this:

    <StructLayout(LayoutKind.Explicit)> _
    Public Structure UnionInt32
        <FieldOffset(0)> _
        Public Int32Value As Int32
        <FieldOffset(0)> _
        Public UInt32Value As UInt32
    End Structure

Which, when put simply, just accesses the first 4 bytes of the structure (due to the FieldOffset of both fields set to 0) as either an Int32 value or a UInt32 value.

Using it couldn’t be simpler (or faster).

Dim v as Int32 = -1234
Dim u as UnionInt32
u.Int32Value = v
debug.print u.UInt32Value

The V variable contains your starting signed value, and the debug.print outputs the equivalent unsigned value.

Using this trick can be a godsend when working directly with low level Windows messages (like the RawMouse messages!)

A GOSUB By Any Other Name

3
Filed under .NET, Rants, VB Feng Shui

imageI’ve been using VS2010 for a while now, and there’s definitely a lot to like in this release. Granted, the UI is a little slower than 2008, but that’s mostly because of all the new WPF goodness baked into every nook and granny of the IDE now.

One thing that I’d been looking forward to is multi-line lambdas in VB. C# has had that since 2008 (or possibly before), but VB was always limited to a single line or (more typically) a call to a function, which could be multiline.

Still, when you’re talking about lambdas, you’re typically talking about small chunks of code that you almost never really want to be a separate function, Private or not. It’s just that much more clutter.

VB2010 finally addresses that disparity and you can now do multi-line lambdas in VB.

Dim MyLambda = Function(arg As String) As String
   arg &= ","
   arg &= "More"
   Return arg

'And to call it
Debug.Print(MyLambda("TestArg"))

Now, technically speaking, you might argue that “MyLambda” is an anonymous method. And you’d be right. Anonymous methods, delegates, and lambdas are, essentially, different names for the same thing. Basically, they’re all just ways of “embedding” code into a variable, and then being able to call that code.

In the olden days, you’d use pointers for such folderol, but this is managed .net code, and pointers are all but verboten in these parts.

But wait!

The thing is, it struck me at one point, while recently describing how you might actually use a delegate to a colleague, of the similarities between anonymous functions like the above, and the much maligned VB GOSUB statement (GOTO’s less recognized little brother).

Dim Arg as string = "testArg"
Gosub MyLambda
Debug.print(Arg)
Return

MyLambda:
   arg &= ","
   arg &= "More"
   Return

Don’t get me wrong, I never found GOSUB to be particularly all that clean a construct. I used it on occasion, but not often. You couldn’t pass explicit arguments with GOSUB, and executing a variable GOSUB required the ON x GOSUB statement, which was pretty abysmal to use.

Still, all the makings of a lambda were right there, all along.

Stupid fun with XML Literals

1
Filed under .NET, XML

I’ve been putting the finishing touches on a little command line utility, and wanted to add some nice instruction text etc.

Writing to the Console is certainly simple in .net, but line after line of Console.WriteLine gets old

Then I recalled some tricks using XML Literals in VB.net. A few snips later and I have this:

Private Shared Sub Header()
    Dim v = My.Application.Info.Version.ToString
    Dim x = <info>
MyUtility v<%= v %> - Controller Tool&#13;
(c) 2011 yadda yadda&#13;
</info>
    Output(x.Value)
End Sub

With that, I can enter any number of lines of text I need, I don’t have to worry about quotes or Console.Writeline’s, just a &#13; at the end of each line, and I can substitute in the app’s version number using the familiar ASP <%= notation (notice the variable ‘v’).

Now, if there was just a way to preserve whitespace in XML literals…

Integrating with the New Office Backstage from a VSTO 3 Addin

12
Filed under .NET, Code Garage, Office, VSTO, Word

If you’re like me and want to drop straight to the code, you can download the sample project here.

When it comes to writing addins for Office applications, you really only have 2 choices.

  • Old School – Implementing the IExtensibility2 interface
  • VSTO

The problem is that VSTO addins tend to be one trick ponies. If you want to write a single addin that works in multiple Office applications, or if you want a single addin to work across multiple Office Application versions, you’ll likely run into walls with VSTO. Sure, you could create separate DLL’s for each Office app, and for each target version, but good lord, who wants to do that?

Still, VSTO makes dealing with Ribbons and TaskPanes much easier and can be handy when you need to target a single Office app, say, Word, and when you’re specifically concerned with a single version of the app (or maybe the latest few).

This was the case recently with an addin I was working on.

The Situation

The target application was Word, specifically Word 2010. However, virtually all of the addin was finished by the time VSTO 4 and VS2010 was released. Since we didn’t really want to run the risks of retooling the addin for VSTO 4 (seeing as it’s a brand new platform and we were close to the end of the dev cycle), the decision was made to stick with VSTO 3.

No big deal. VSTO 3 addins run perfectly fine under Word 2010.

The Snag

During the ramp up on Word 2010, however, we discovered the new Backstage view:

image

It’s a really nice extension to the traditional Office File menu. One of the few new elements of Office 2010 that really makes upgrading worthwhile, in my opinion, but that’s another story.

At any rate, it turns out that the Backstage view is extensible via XML, very much like the Ribbon.

Unfortunately, VSTO 3 has no support for the Backstage view.

Customizing the BackStage in the First Place

For me, though, the first question was exactly how do you customize the BackStage? Turns out, it’s fairly simple. If you’ve manually customized the Ribbon before, you’ll recognize the process instantly. John Durant wrote up a short and sweet article on the process here.

Unfortunately, he describes modifying the BackStage by altering the Custom XML package in a document. This makes the BackStage modification document specific. Not the way you want to do it for an addin.

I also found this great article, but it describes modifying the BackStage by implementing an addin using the older style IExtensibility2 model, not VSTO.

More articles, same shortcomings. This was starting to look as hopeless as the Cowboy’s season this year.

I knew that modifying the ribbon via an IExtensibility2 addin was as simple as creating a public function called GetCustomUI, and returning the XML for whatever custom buttons you want added to the Word Ribbon. From the articles mentioned above, it was obvious that the exact same process was used to alter the BackStage. The problem was, there wasn’t any obvious way to get at  the GetCustomUI function in a VSTO addin. All of that XML munging is automagically handled for you by VSTO.

Further, I wanted, if at all possible, to continue to leverage the VSTO Ribbon support. The Visual Studio Ribbon Designer is just too handy to have to go back to manually crafting up the XML for it.

However, I knew that no matter what happened, I was still going to have to manually build the XML for my BackStage customizations. That was ok, though.

The Wrong Way – Wrap RibbonManager

I initially thought I could just create a new object that wrapped RibbonManager.

The main VSTO Connect class (that itself inherits from the VSTO Addin class), exposes the overridable function CreateRibbonExtensibilityObject  that expects a IRibbonExtensibility object as a return value.

So, create a new object, RibbonManagerInterceptor, that implements IRibbonExtensibility, and just wraps the internally created RibbonManager object, and return that, like so:

Private _RibbonExt As Microsoft.Office.Core.IRibbonExtensibility
Protected Overrides Function CreateRibbonExtensibilityObject() As Microsoft.Office.Core.IRibbonExtensibility
    Dim RibbonManager = MyBase.CreateRibbonExtensibilityObject()
    _RibbonExt = New RibbonManagerInterceptor(RibbonManager)
    Return _RibbonExt
End Function

Unfortunately, it won’t work. The VSTO authors make the assumption that the object implementing IRibbonExtensibility is of base type RibbonManager. For instance:

Private ReadOnly Property RibbonExtensibility As IRibbonExtensibility
    Get
        If (Me.ribbonExtensibility Is Nothing) Then
            Me.ribbonExtensibility = Me.CreateRibbonExtensibilityObject
            Dim ribbonExtensibility As RibbonManager = TryCast(Me.ribbonExtensibility,RibbonManager)
            If (Not ribbonExtensibility Is Nothing) Then
                ribbonExtensibility.ServiceProvider = MyBase.HostContext
            End If
        End If
        Return Me.ribbonExtensibility
    End Get
End Property

This is from the Addin class in Microsoft.Office.Tools.Common.v9.0. You’ll notice that the property accepts an IRibbonExtensibility object, but then proceeds to cast it as RibbonManager and if that fails, the addin won’t register the service provider.

What’s worse is that RibbonManager has been marked NotInheritable, so you can’t create a subclass from it to pass this test. Full stop.

Intercepting GetCustomUI

Boiling the basic requirements of an Office addin down, I knew I had to implement IRibbonExtensibility and the GetCustomUI method.

    Public Function GetCustomUI(ByVal RibbonID As String) As String Implements IRibbonExtensibility.GetCustomUI
        Dim xml = _RibbonManager.GetCustomUI(RibbonID)

        If _Connect.Core.WordInstance.Version = "14.0" Then
            '---- only add in backstage support for version 14 (Office 2010)
            Dim bs = <backstage>
                         <tab id="bsSample" label="BackStageSample" insertAfterMso="TabInfo">
                             <firstColumn>
                                 <group id="bsSampleGroup" label="BackStage Sample Group">
                                     <topItems>
                                         <button id="BackStageSample"
                                             label="BackStage Sample Button"
                                             onAction="bsSampleClicked"/>
                                     </topItems>
                                 </group>
                             </firstColumn>
                         </tab>
                     </backstage>
            xml = xml.Replace("</customUI>", bs.ToString & "</customUI>")
            xml = xml.Replace("http://schemas.microsoft.com/office/2006/01/customui", "http://schemas.microsoft.com/office/2009/07/customui")
        End If
        Return xml
    End Function

The first step is to use the underlying RibbonManager object to generate its version of the CustomUI XML. That allows me to continue to use the Ribbon Designer in Visual Studio and the RibbonManager for all the heavy lifting where the Ribbon is concerned.

Next, if I see the addin is hosted by Word v14 (2010), I use the handy inline XML feature of VB.net to create the BackStage custom XML and inject it into the Ribbon XML previously already generated.

And finally, I have to patch the schema used, so that Word knows I’m defining BackStage customizations in the XML as well as Ribbon customizations.

A Better Way

I knew that VSTO was somehow intercepting  all callbacks from Word as defined in the CustomUI XML, and then generating events for the various Ribbon controls, or interrogating control properties. Maybe there was a way to hook into that process.

So, I loaded up Reflector and started spelunking.

It didn’t take long to realize what was going on.

When you set up a custom UI for Word, you define callback functions in the XML that Word will then call when necessary. Those functions must be public functions on the object that implements IRibbonExtensibility and that is exposed as a COM object. Further, those functions are ALWAYS called via IDispatch. For instance, take the following custom UI:

<backstage>
    <tab id="bsSample" label="BackStageSample" insertAfterMso="TabInfo">
        <firstColumn>
            <group id="bsSampleGroup" label="BackStage Sample Group">
                <topItems>
                    <button id="BackStageSample"
                            label="BackStage Sample Button"
                            onAction="bsSampleClicked"/>
                </topItems>
            </group>
        </firstColumn>
    </tab>
</backstage>

The onAction element above defines a function called bsSampleClicked, that Word will call on the IRibbonExtensibility object whenever that button is clicked.

Interestingly, it doesn’t matter that this is for a BackStage object (a button) and not a Ribbon. Word vectors everything through that IRibbonExtensibility object.

So, how does that process work then?

Well, as it turns out, it’s not terribly complicated, but it does require a little work. With .NET, you implement a latebound IDispatch type call by implementing the IReflect interface. That interface contains a number of members that need to be implemented, though most can be stubbed out.

However, you’ll definitely need to implement the GetMethods and InvokeMember functions.

GetMethods returns to the caller an array of MethodInfo objects that describe the all latebound methods that our IRibbonExtensibility object will be supporting. Since we want to continue to allow the RibbonManager to service all of the methods that it needs to handle, you first need to retrieve the RibbonManager’s list of supported methods and then add to it:

    Private Function IReflect_GetMethods(ByVal bindingAttr As BindingFlags) As MethodInfo() Implements IReflect.GetMethods
        Dim ir = DirectCast(_RibbonManager, IReflect)
        Dim r = ir.GetMethods(bindingAttr)
        ReDim Preserve r(UBound(r) + 1)
        Dim mi = BackstageMethodInfo.CheckBoxActionMethod(DirectCast(_RibbonManager, RibbonManager), "bsSampleClicked", Nothing)
        r(UBound(r)) = mi
        Return r
    End Function

Finally, to vector the method call properly, define the InvokeMethod method like so:

    Private Function IReflect_InvokeMember(ByVal name As String, ByVal invokeAttr As BindingFlags, ByVal binder As Binder, ByVal target As Object, ByVal args As Object(), ByVal modifiers As ParameterModifier(), ByVal culture As CultureInfo, ByVal namedParameters As String()) As Object Implements IReflect.InvokeMember
        Dim r As Object
        If name.StartsWith("bs") Then
            '---- it's a Backstage control, just intercept and pass through
            '     to the connect object
            Select Case name.ToLower
                Case "bssampleclicked"
                    _Connect.bsSampleClicked()
                Case Else
            End Select
            Return Nothing
        Else
            Try
                Dim ir = DirectCast(_RibbonManager, IReflect)
                r = ir.InvokeMember(name, invokeAttr, binder, _RibbonManager, args, modifiers, culture, namedParameters)
            Catch ex As Exception
                Throw New TargetInvocationException(ex)
            End Try
            Return r
        End If
    End Function

Here, if the callback function Word is trying to call starts with “bs”, I assume it’s one of my “backstage” callbacks and I drop into the first Select Case.

If not, I forward the call on through to underlying RibbonManager object, so VSTO can continue to work it’s magic.

The actual function that handles the callback, I defined in my VSTO Connect object:

    '---- Testing function
    Friend Sub bsSampleClicked()
        MsgBox("BackStage Sample Button was Clicked")
    End Sub

A Few Side Notes

I put together a small sample addin for Word that illustrates this approach. Download it here.

If you download and unzip the sample project, one of the first things you’re likely to notice is the References folder. For addins like this, I like to copy any referenced dll locally to the project and reference it from there, rather than scattering referenced DLLs all over my system. It makes moving the project to other machines much easier, among other benefits.

You’ll also notice that the DLLs are for Office 2007, as that’s part of the point of this sample; to show that a VSTO 3 addin  can target both 2007 and 2010 and support Ribbons and the Backstage.

One downside to this approach is that VSTO 3 insists  that Office 2007 be installed, even if you’re actually only targeting 2010. You’ll get errors and very specific warnings to that effect if you try to run the project on a machine without Office 2007.

Just make sure you’ve installed Office 2007, then Office 2010, to be able to run the addin against both versions.

COM Visibility

Since addins, even VSTO addin’s, are, at their core, COM dlls, you’ll likely find yourself having to deal with COM interop to some degree. To make that easier, I usually turn OFF COM visibility for the WHOLE PROJECT in the Assembly.vb file:

' Setting ComVisible to false makes the types in this assembly not visible 
' to COM components.  If you need to access a type in this assembly from 
' COM, set the ComVisible attribute to true on that type.
<Assembly: ComVisible(False)> 

And then turn ON COM visibility for each class that actually needs to be visible via COM.

''' <summary>
''' Core object for this addin
''' </summary>
''' <remarks></remarks>
<ComVisible(True)> _
<Guid("8618E3FB-D57B-4875-ABE4-D204E1C1046A")> _
Public Class Core
...

Debugging

To make the project easy to debug, I always set the start action to “Start External Program”, and point it at my WinWord.exe in the Office installation.

image

You may need to change the path to WinWord as applicable to your system.

Sample Project Requirements

To run the sample project, you’ll need the following:

  • Visual Studio 2008
  • Office 2007
  • To test the backstage support, you’ll also need Office 2010 installed (They can be installed side by side except for Outlook).
  • Visual Studio Tools for Office 3.0 (VSTO). I found the installer already on my system at

    c:\Program Files (x86)\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\VSTOR30\vstor30.exe
  • You’ll likely also want the service pack for VSTO. It was located here:

    c:\Program Files (x86)\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\VSTOR30\vstor30sp1-KB949258-x86.exe

The Wrapup

So there you have it. Support for the latest Backstage View in a VSTO 3 based addin. It required a fair bit of poking around under the covers, something that would simply not be possible without Lutz Roeder’s excellent Reflector tool. If you don’t have that in your toolbox, you’re missing out on a fantastic debugging, diagnostic, research, and discovery tool!

In the end, if you need your addin to support multiple Office applications or a wide variety of versions, your best bet will be to go with IExtensibility2 (or possible AddinExpress, though I’ve never used it, and have no idea whether it truly makes things easier for multi targeting or not).

And finally, the standard disclaimer. IWOMM (It works on my machine). If you find bugs or problems, please let me know. Heck, if you know a better way (short of converting to VSTO 4!), I’d love to hear about it! I’m fairly certain that this isn’t the only way to skin this particular cat.

Normal Ol’ DLLs from VB.net

7
Filed under .NET, Arcade, Code Garage, MSBuild, VB Feng Shui

Every once in a while, I find a need to do something a bit off the wall. Recently, I had another one of those situations.

I’ve spent a lot of time working with some of the old arcade emulators that are floating around (the most famous of which is MAME, or Multi Arcade Machine Emulator).

Mame itself is pretty utilitarian, so there are a number of front ends  that are essentially menuing systems to provide a user with an easy to browse interface for selecting games to play and among the more popular front ends is MaLa.

image

MaLa Main screen (using one of many available skins) showing list of games, and a screenshot of the selected game

One nice aspect of MaLa is that it supports plugins, and there are a number of them out there, to control LED lights, play speech, etc.

I had had a few ideas about possible MaLa plugins for awhile, but the MaLa plugin architecture centers around creating a standard Win32 DLL with old fashioned C styled Entrypoints, and, well, I kinda like working in VB.net these days.

Gone Hunting

Eventually, curiousity got the better of me, and I started looking for ways to expose standard DLL entry points from a .net assembly. I ended up finded Sevin’s CodeProject entry called ExportDLL that allowed just that. Essentially, it works by:

  1. You add a reference in your project to a DLL he created, that only contains a single Attribute for marking the functions you want to export.
  2. Create the functions you want to export as shared functions in a MODULE
  3. You mark those functions with the Attribute
  4. You compile your DLL
  5. You then run ExportDLL against your freshly compiled DLL
  6. ExportDLL then decompiles your DLL into IL, tweaks it, and recompiles the IL code back into a DLL

It sounds complicated but it’s really not.

I set it all up and had things working in about 30 minutes.

Gone South

Unfortunately, all was not quite right. MaLa requires 2 entry points (among a host of them) defined with a single integer argument passed on the stack. Pretty simple stuff. So I coded up:

    <ExportDLL("MaLaOrientationSwitch", CallingConvention.Cdecl)> _
    Public Shared Sub EntryPoint_MaLaOrientationSwitch(ByVal Orientation As Integer)

But when I ran the DLL within MaLa, it crashed immediately after calling this function, even with NO CODE in the function itself.

What this meant is that something about the export process was trashing the stack. I spent a solid day hunting for clues as to what might be failing. I did find that eliminating the argument from the exposed entrypoint allowed MaLa to work properly AND call my entrypoint, but, being unable to get the passed Orientation value, the call was basically useless.

Gone Around Again

In digging through it all, I happened to notice a comment on the CodeProject page for Sevin’s article pointing to a similar library by Robert Giesecke. I’m not sure if the two were developed independently or not, but Robert’s is certainly a more polished set of deliverables. He even went so far as to put together a C# project template that makes it ridiculously easy to kick off a project using his technique.

It turns out, not only is Robert’s approach cleaner, it actually properly exports the MaLaOrientationSwitch function above with no problems. MaLa can call it, pass in the argument and all is good.

Gone Fishing

One big difference between the two techniques is the Robert actually defines an MSBuild targets file to patch his DLL directy into the Visual Studio build process. Very cool! But, his build step happens AFTER the PostBuildEvent target, and it was in that target that I’d setup some commands to copy the DLL into a file called *.MPLUGIN, which is what MaLa specifically looks for. Hooking that process into the build itself makes debugging things quite natural, but, Mr. Giesecke’s target wasn’t allowing for that.

Here’s Robert’s targets file:

<Project
  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <UsingTask TaskName="RGiesecke.DllExport.MSBuild.DllExportTask"
             AssemblyFile="RGiesecke.DllExport.MSBuild.dll"/>
  <Target Name="AfterBuild"
          DependsOnTargets="GetFrameworkPaths"
          >
      <DllExportTask Platform="$(Platform)"
                   PlatformTarget="$(PlatformTarget)"
                   CpuType="$(CpuType)"
                   EmitDebugSymbols="$(DebugSymbols)"
                   DllExportAttributeAssemblyName="$(DllExportAttributeAssemblyName)"
                   DllExportAttributeFullName="$(DllExportAttributeFullName)"
                   Timeout="$(DllExportTimeout)"
                   KeyContainer="$(KeyContainerName)$(AssemblyKeyContainerName)"
                   KeyFile="$(KeyOriginatorFile)"
                   ProjectDirectory="$(MSBuildProjectDirectory)"
                   InputFileName="$(TargetPath)"
                   FrameworkPath="$(TargetedFrameworkDir);$(TargetFrameworkDirectory)"
                   LibToolPath="$(DevEnvDir)\..\..\VC\bin"
                   LibToolDllPath="$(DevEnvDir)"
                   SdkPath="$(FrameworkSDKDir)"/>
  </Target>
</Project>

I’d worked with MSBuild scripts before, so I knew what it was capable of, I just couldn’t remember the exact syntax. A few google searches jogged my memory, and I ended up here at a great post describing exactly how you can precisely inject your own targets before or after certain other predefined targets.

I modified Robert’s targets file and came up with this:

<Project
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <UsingTask TaskName="RGiesecke.DllExport.MSBuild.DllExportTask"
             AssemblyFile="RGiesecke.DllExport.MSBuild.dll"/>

  <!-- Add to the PostBuildEventDependsOn group to force the ExportDLLPoints
       target to run BEFORE any post build steps (cause it really should) -->
  <PropertyGroup>
    <PostBuildEventDependsOn>
      $(PostBuildEventDependsOn);
      ExportDLLPoints
    </PostBuildEventDependsOn>
  </PropertyGroup>

  
  <Target Name="ExportDLLPoints"
          DependsOnTargets="GetFrameworkPaths"
          >
    <DllExportTask Platform="$(Platform)"
                   PlatformTarget="$(PlatformTarget)"
                   CpuType="$(CpuType)"
                   EmitDebugSymbols="$(DebugSymbols)"
                   DllExportAttributeAssemblyName="$(DllExportAttributeAssemblyName)"
                   DllExportAttributeFullName="$(DllExportAttributeFullName)"
                   Timeout="$(DllExportTimeout)"
                   KeyContainer="$(KeyContainerName)$(AssemblyKeyContainerName)"
                   KeyFile="$(KeyOriginatorFile)"
                   ProjectDirectory="$(MSBuildProjectDirectory)"
                   InputFileName="$(TargetPath)"
                   FrameworkPath="$(TargetedFrameworkDir);$(TargetFrameworkDirectory)"
                   LibToolPath="$(DevEnvDir)\..\..\VC\bin"
                   LibToolDllPath="$(DevEnvDir)"
                   SdkPath="$(FrameworkSDKDir)"/>
  </Target>
</Project>

Now, I can perform the compile, and execute my postbuild event to copy the DLL over to the MaLa Plugins folder and give it the requisite MPLUGIN name, all completely automatically.

And, the icing on the cake is that I can build a MaLa plugin completely in VB.net, with no C or C# forwarding wrapper layer and with a fantastic XCOPY-able single DLL application footprint (save for the .net runtime, of course<g>).

It’s a wonderful thing.

Word’s Compatibility Options

28
Filed under .NET, Code Garage, Office, Word

One element you’ll eventually run up against when dealing with Word documents is "compatibility”.

image

You can see one small indicator of compatibility in the above screenshot. When you open any old format DOC file in Word 2007 or 2010, it’ll open in compatibility mode.

But what does that mean, really?

Compatibility in a Nutshell

Word’s Compatibility mode actually encompasses a fairly significant number of tweaks to how Word renders a document. You can see those options at the bottom of the Advanced tab on Word’s Options dialog.

image

a small sampling of compatibility options available

Word sets those options in a number of different combinations depending on the source of the original document. You can select the source document manually via the below dropdown, but most of the time, Word will choose an appropriate selection automatically when it opens the original  document.

image

The problem is, many of those options can cause Word to render a document in very strange, unpredictable ways. In fact, most Word experts advise to manually turn OFF all compatibility options (and so force Word to layout the document using it’s most recent rules, either those set for Word 2007 or for Word 2010).

Controlling Compatibility Programmatically

Manipulating those settings manually via the Options dialog is fine, but if you’ve got thousands of documents to deal with, that may not be your best approach.

Why not automate it with a bit of .net code?

    Private Sub ForceCompatibility(ByVal Doc As Word.Document)
        Doc.Convert()

        Doc.Application.Options.DisableFeaturesbyDefault = False
        For Each e As Word.WdCompatibility In [Enum].GetValues(GetType(Word.WdCompatibility))
            Dim res As Boolean = False
            Select Case e
                Case Word.WdCompatibility.wdDontULTrailSpace
                    res = True
                Case Word.WdCompatibility.wdDontAdjustLineHeightInTable
                    res = True
                Case Word.WdCompatibility.wdNoSpaceForUL
                    res = True
                Case Word.WdCompatibility.wdExpandShiftReturn
                    res = False
                Case Word.WdCompatibility.wdLeaveBackslashAlone
                    res = True
                Case Word.WdCompatibility.wdDontBalanceSingleByteDoubleByteWidth
                    res = True
            End Select
            Doc.Compatibility(e) = res
        Next
    End Sub

So, what’s going on here?

First, I pass in a Document variable to the function. This variable contains a reference to the Document object you need to fix compatibility on. You can easily obtain teh Active document object with the Application.ActiveDocument property.

The function first calls the Doc.Convert method. This converts the document to the latest format available to the version of Word you’re running and enables all new features. This conversion happens in memory. Nothing is saved to disk at this point. Also, you’d think that this would be enough to turn off all compatibility tweaks, but alas, Word leaves many of them still turned of after this conversion.

Next, it uses the DisableFeaturesbyDefault property to enable all available features.

Then, it enumerates all the wdCompability options to clear or set them as necessary. This handy bit of trickery can come in handy in a number of situations. Essentially, it uses a little reflection here:

[Enum].GetValues(GetType(Word.WdCompatibility))

to retrieve an array of all the possible values of the wdCompatibility enumeration.

Then, the For loop simply iterates through all the values in that array.

The SELECT CASE then matches up a few specific enumeration values that don’t work quite like you might expect, and handles them with special cases.

For instance, the wdNoSpaceForUL option is equivalent to the “Add Space for Underlines” option in the Word Options Dialog. However, the logic is reversed.

Leave it to a word processing program to make use of double negatives like this!

Odd Man Out

The wdExpandShiftReturn option is the one exception. When cleared, this option prevents Word from expanding spaces on lines that end with a soft Return (a Shift-Return). Many Word experts indicate that this is preferable to Word’s default behavior of expanding those spaces, so I’ve set it here accordingly. Your mileage may vary.

And finally, be sure the SAVE the document in xml format, using the Save method like this:

Doc.SaveAs FileName:="doc.xml", FileFormat:=wdFormatXML

So there you have it. A quick and easy way to force a document into the latest Word file format and turn off any errant compatibility options in the process.

When Debug.Print Doesn’t Work Anymore

5
Filed under .NET, Troubleshooting, VB Feng Shui

This is one of those “back to basics” posts that, none-the-less, tripped me up for a few minutes, just because it’d been so long since I’d even looking at the setting involved.

I’d been working on a project for a while, when, one day a few weeks back, debug.print just stopped working. Even weirder, when I’d debug, the debugging would completely skip over the Debug.print statement.

When it first happened, I was right in the middle of working through some other problem and didn’t want to get sidetracked. But it hit me again a few weeks later, and I decided to start looking around.

It didn’t take long before I realized this setting was amiss.

cap1

It’s checked in the image above, but in my project, somehow it’d become UNCHECKED, and in the Debug project configuration!?

Still not sure how that happened, other than probably got a little click happy one day with the mouse and didn’t realize it.

Amazing how the little things can still get ya’ sometimes…

(and nobody say anything about my dll base address <g>! )

Visual Studio Styles Made Easy

0
Filed under .NET

Luke Sampson’s put up a nice little site that’s all about custom color styles for Visual Studio (looks like most schemes support VS2005/2008 AND 2010!)

For example, the high rated scheme right now is WekeRoad:

image

Pick one and you can download the scheme right there. Very easy to get a custom scheme (or a good base for your own scheme) going quickly.

I tend to prefer something with a few less colors (I’m not keen on the circus look, no matter how muted), but some of these schemes look quite nice.

Finally, check out my post about programming fonts here for a good font comparison.

Calling C Object Methods from VB.Net

0
Filed under .NET, amBX, Games, Hardware, VB Feng Shui

image I’ve been playing recently with the amBX ambient effects library and devices.

Essentially, it’s an effects platform that allows you to easily create light, wind and rumble effects to coordinate with what’s going on on-screen, in a game, in media players, or what-have-you. The lighting effects are nothing short of fantastic. The rumble and fan effects…. meh. They’re interesting, but I’m not sure where that’ll go.

Regardless, the API for amBX is all C style objects, which means essentially an array of function pointers to the methods of the object; not really an API that VB.net likes to consume. Be sure to grab the amBX developer kit here. You’ll also need to core amBX software available from the main website. Finally, play around with the “Virtual amBX Test Tool”. It’ll allow you to experiment with all the amBX features and functions without having to buy anything at all. Of course, eventually you’ll want to get at least the starter kit, with the lights. But it’s not necessary to begin experimenting.

Hats off to Philips for making this possible!

image

Here’s an example of the structure definition from the amBX.h header file that comes with the API (I’ve clipped out comments and other bits):

struct IamBX {
    amBX_RESULT (*release) (struct IamBX * pThis);
    amBX_RESULT (*createLight) (struct IamBX * pThis,
                                amBX_u32 loc,
                                amBX_u32 height,
                                struct IamBX_Light** ppLight);
....

As you can see, each element in the structure is made up of a pointer to a function. The various functions all take, as their first argument, a pointer back to this structure. Under the covers, this is how virtually all object oriented languages function, it’s just the the compiler usually hides all this nasty plumbing so you don’t have to deal with it regularly.

But this presents a problem. VB.net is “managed” code, and as such, it likes things to be wrapped up in nice “managed” bits. There are plenty of good reasons for this, but these function pointers are decidedly not nice and tidy managed bits! So, what to do?

One solution is the approach Robert Grazz took here. It’s a solid solution, no doubt, and I learned a lot from looking at his approach, but, this being VBFengShui, I wanted that same functionality in native VB.net with no additional dll files hanging around!

Delegates to the Rescue!

A delegate in .net is essentially a managed function pointer. In VB.net, they’re most commonly used to handle events, but you wouldn’t really know it, because VB’s compiler does a good job of hiding all that plumbing from you. However, unlike VB6 and earlier, in VB.net, all the plumbing can, if you’re willing, be “brought into the daylight” and used however you want.

There are many, many discussions about delegates for VB.net out on the web. A really good Introduction to the concepts by Malli_S is on codeproject, so I won’t rehash the basics here.

The problem is, delegates in VB.net tend to be generated by using the AddressOf operator, and I already had the function addresses (they’re in that C structure). I just needed to get a delegate that would allow me to call it.

Some Googling turned up several good posts that provided pointers, including this one on StackOverflow. But it wasn’t exactly all the steps necessary.

Getting the C Structure

The first step toward getting something working with amBX is to retrieve the main amBX object. You do this through a standard Windows DLL call.

<DllImport("ambxrt.dll", ExactSpelling:=True, CharSet:=CharSet.Auto)> _
        Public Shared Function amBXCreateInterface(ByRef IamBXPtr As IntPtr, ByVal Major As UInt32, ByVal Minor As UInt32, ByVal AppName As String, ByVal AppVer As String, ByVal Memptr As Integer, ByVal UsingThreads As Boolean) As Integer
        End Function

Assuming you have the ambxrt.dll file somewhere on your path or in the current dir, the call will succeed, but what exactly does that mean?

Here’s an example of a call to it in C:

    if (amBXCreateInterface(
            &pEngineHandle, 
            majorVersion, minorVersion, 
            (amBX_char*)cAppName.ToPointer(), (amBX_char*)cAppName.ToPointer(),
            nullptr, false)
        != amBX_OK)

Essentially, you pass in the Major and minor version numbers of the Version of amBX you need, and two strings indicating the name of your app and the version of your app. No problems with any of that. But that &EngineHandle is the trick.

It means that this call will return a 4 byte pointer to a block of memory that contains the amBX object structure, which is, itself, an array of 4 byte function pointers to the various methods of the amBX object. Therefore, in VB.net, that argument is declared ByRef IamBXPtr as IntPtr.

Now, we need a place to store that “structure of pointers.” Going through the ambx.h file, I ended up with a structure that looks like this:

        <StructLayout(LayoutKind.Sequential)> _
        Private Structure IamBX
            Public ReleasePtr As IntPtr
            Public CreateLightPtr As IntPtr
            Public CreateFanPtr As IntPtr
            Public CreateRumblePtr As IntPtr
            Public CreateMoviePtr As IntPtr
            Public CreateEventPtr As IntPtr
            Public SetAllEnabledPtr As IntPtr
            Public UpdatePtr As IntPtr
            Public GetVersionInfoPtr As IntPtr
            Public RunThreadPtr As IntPtr
            Public StopThreadPtr As IntPtr
        End Structure

That StructLayout attribute is particularly important. It tells the compiler that the structure should be layed out in memory JUST AS it’s declared in source code. Otherwise, the compiler could possibly rearrange elements on us. With Managed Code, that’d be no problem, but when working with unmanaged C functions, that would not be a good thing!

And finally, we need a way to retrieve that function pointer array and move it into the structure above, so that it’s easier to work with from VB.net. That’s where the System.Runtime.InteropServices.Marshal.PtrToStructure function comes in. This routine will copy a block of unmanaged memory directly into a managed structure.

Private _IamBX As IamBX
Private _IamBXPtr As IntPtr
...

amBXCreateInterface(_IamBXPtr, 1, 0, “MyAppName”, “1.0”, 0, False)

_IamBX = Marshal.PtrToStructure(_IamBXPtr, GetType(IamBX))

And presto, you should now have the _IamBX structure filled in with the function pointers of all the methods of this C “Object”.

Calling the C Function Pointer

At this point, we’ve got everything necessary to call the function pointer. Take the CreateLight function. The C prototype for this function is shown at the top of this page. As arguments, it takes a pointer back to the amBX structure, 2 32bit integers describing the location and height of the light source, and it returns are pointer to another structure, in this case, an amBX_Light structure, which contains another set of function pointers, just like the amBX structure described above.

First, we need to declare a delegate that matches the calling signature of the CreateLight C function we’ll be calling:

<UnmanagedFunctionPointer(CallingConvention.Cdecl)> _
Private Delegate Function CreateLightDelegate(
         ByVal IamBXPtr As IntPtr, _
         ByVal Location As Locations, _
         ByVal Height As Heights, _
         ByRef IamBXLightPtr As IntPtr) As amBX_RESULT

The key points here are:

  1. Make sure you have the CallingConvention attribute set right. Most C libraries will be CDECL, but some libraries are STDCALL.
  2. Make sure your parameter types match, especially in their sizes. Not doing this will lead to corrupted called or system crashes.

Now, create a variable for the delegate and use the Marshal.GetDelegateFromFunctionPointer function to create a new instance of the delegate, based on the applicable function pointer. Since the function pointer for the CreateLight function is stored in the CreateLightPtr field of the _IamBX structure, we pass that in as the pointer argument.

IMPORTANT NOTE: There are 2 overloads for the Marshal.GetDelegateFromFunctionPointer  function. Be sure to use the one what requires a second argument of the TYPE of the delegate to create. Using the other one will fail at runtime because it won’t be able to dynamically determine the type of delegate to create.

Next, call the function via the delegate, just as if it was a function itself.

Finally, use Marshal.PtrToStructure again to copy the array of function pointers returned into another structure, this one formatted to contain the function pointers of the Light object that just got created.

Dim d As CreateLightDelegate = Marshal.GetDelegateForFunctionPointer(_IamBX.CreateLightPtr, GetType(CreateLightDelegate))
Dim r = d(_IamBXPtr, Location, Height, _IamBXLightPtr)
_IamBXLight = Marshal.PtrToStructure(_IamBXLightPtr, GetType(IamBX_Light))

The amBX library is much, much larger than just this little bit I’ve shown here. Once I get the entire thing coded up, I’ll be presenting it here as well.

But in the meantime, if you have a need to interface with C style function pointer objects, don’t let anyone tell you it can’t be done in VB.net

Final Note

As you may or may not have guessed, amBX is a 32bit library and its interfaces, functions and arguments all live in 32bit land. If you’re working with VS2008, BE SURE to set your project to the x86 platform, and NOT “Any CPU” or “x64”! The default, for whatever reason is “Any CPU”, which means things will work properly when run under 32bit windows, but things won’t work well at all if run under a 64bit OS.