Friday, February 05, 2010

imageOk, so it’s completely unrelated to VB in every conceivable way \:\-\) .

I just came across a very nifty way to tie your shoes. It’s called the Ian Knot and there’s a very good pictorial writeup (and video) about it here.

I’m not going to repeat his pictures here, but it’s essentially, just:

  1. make a crossover knot, the way you would normally start to tie your shoes.
  2. In the right hand, make a loop exactly like you normally would, with the string going up, over your finger and down.
  3. In the left hand, make the same loop, but with the string starting below your finger and coming up over your finger towards you.
  4. then just push the two loops through each other and tighten.

Check out the site above for pictures. It’s easier to see it than describe it.

But, it IS amazingly fast, and easy.

posted on Friday, February 05, 2010 9:13:17 AM (Central Standard Time, UTC-06:00)   •  # •  Comments [0] • 
Kick it •  Add to del.icio.us •  View blog reactions; 
 Tuesday, February 02, 2010

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.

posted on Tuesday, February 02, 2010 10:37:20 AM (Central Standard Time, UTC-06:00)   •  # •  Comments [1] • 
Kick it •  Add to del.icio.us •  View blog reactions; 
 Thursday, January 28, 2010

At one point a while back (while I was still working for my previous company), we had “support for x64” handled down as a request for an interim version.

I thought, “No sweat”. Grab a few alternative prerequisite MSIs, determine the bitness of the processor you’re on in the install (InstallShield has the functionality built in), and just fire off the appropriate preqs. Our actual application is 32bit, and we had no intention or need to compile as 64bit.

Well. A few clicks later and the install was built and deployed to a test machine.

Crash.

Initial sample database didn’t get deployed properly.

Ok, why not. Well. Long story short, the application couldn’t find a registry key setting. But I hadn’t changed anything about the registry.

Lots of digging through verbose install logs later, and I discovered that the installer was, on a 64bit OS creating registry keys under the key  HKEY_CURRENT_USER\Software\Wow6432Node whereas when my application when to get the registry key, it was looking in the normal HKEY_CURRENT_USER\Software\ key.

Huh?!

First, what the hell was this Wow6332Node? Obviously it’s some kind of “compatibility” bit for running 32bit apps under a 64bit OS. And that’s exactly what it is.

Ok, my Installer is InstallShield, and it’s a 32bit app (even if it can install 64bit packages), so that explains why it was writing the key to that Wow6432Node, but why wasn’t my application reading it from there?

A little digging later, and I found this option buried in the “Advanced Compiler Settings” panel of the “Compile Options” tab of the Project’s properties.

image

See that AnyCPU setting? When set to AnyCPU, the JIT compiler will dynamically compile your .net dll as either a 32bit or 64bit dll, depending on the process that loaded it.

Obviously, on a 32bit OS, all the processes will be 32bit, so everything’s 32bit.

BUT, on a 64bit OS, things get nastier.

If the DLL runs under a native code 32bit process, it’ll get compiled as 32bit x86 code and run under the Wow32 (Windows On Windows) layer. This explains why the DLL that acts as an AddIn to Word worked just fine. Word is a native 32bit process, so the DLL was ending up executing as 32bit too.

However, the little utility app that creates our initial database was a .net application, and it was set to AnyCPU.

That meant that when IT loaded our DLL, the DLL ended up JITed to 64bit code (because the utility app was set to AnyCPU, so it was JITed to 64bit code because it was a base process and was running under a 64bit OS.

Case closed.

Short version of the story. Since tracing all this down, I’ve learned that for VS2008, the .net team decided to change the default of that option from x86 to AnyCPU, and then, in general, that has been regarded as a bad thing to have done.

The default will be changed BACK to x86 in 2010 apparently, but until then, unless you REALLY need to compile code for AnyCPU, be sure to switch this option back to x86!

posted on Thursday, January 28, 2010 2:06:36 PM (Central Standard Time, UTC-06:00)   •  # •  Comments [0] • 
Kick it •  Add to del.icio.us •  View blog reactions; 

I was working on a server issue this morning when I ran into something strange. I could no longer access a server that had been running for quite some time without any problems.

I tried a PING and got back an IP address for the server that made no sense at all. It wasn’t even part of my local IP range!

So I did all the normal stuff:

  1. Checked my HOSTS file
  2. ran IPCONFIG /FLUSHDNS
  3. ran IPCONFIG /REGISTERDNS
  4. ran IPCONFIG /RELEASE
  5. then IPCONFIG /RENEW

No joy. A ping was still returning the same bogus address.

So I checked my server’s DNS service. Not even an hit of that address.

Hmmm. So, where the heck was it coming from? A little googling didn’t turn up much, but eventually, I read a blog post that made an offhand mention of WINS.

Now, I don’t really know all that much about WINS. Just never had a reason to, I suppose. Mostly, I’ve always relied on and stuck with plain DNS. But, Ok, I’ll check it.

Go over to my server, and load up the WINS app (it’s under Admin tools)

image

The left hand window was completely blank. It took a second to realize I had to “query” to retrieve the WINS records, they aren’t automatically just shown.

image

And AHA! There, in the result list of “Active Registrations” was the bogus address for my server. (I’ve already removed it in the image below, but it was in the highlighted column).

image

Case closed. I’m still wondering what changed that suddenly, WINS was being used to resolve the server name when it must have not been before. The only thing I can think of is changing internet providers to Verizon FIOS from Time Warner Cable, and the resulting swap out of the main incoming router.

Granted, for a seasoned network guy, this is likely old hat. But for a software dev who only moonlights as a network guy, it might be some useful information!

posted on Thursday, January 28, 2010 2:04:42 PM (Central Standard Time, UTC-06:00)   •  # •  Comments [0] • 
Kick it •  Add to del.icio.us •  View blog reactions; 
 Sunday, January 24, 2010

I had a need over the weekend to do a little PHP work. Now, I’m no expert in web anything, most of my time has been spent building nice happy fat client apps \:\-\) . But, when I’ve needed to do a little web tinkering, my host (www.ServerGrid.com) pretty much supports everything, so I’ve just uploaded my files and had at it.

However, this time, I wanted to get things running locally, to avoid all the upload/download hassles.

A few google searches turned up the Microsoft Web Platform Installer.

Wow! Something other than Office, VS and SQLServer that Microsoft has done right!

It took a few minutes to run through, and I had to tweak the PHP.INI file a bit (using the instructions here), but, all told, I had a PHP 5.2 installation fully operational under a local IIS7 server in, oh, 10 minutes.

It the Web Platform Installer can install a lot of other stuff too. CMS, SugarCRM, DasBlog, and a bunch more.

Definitely worth the download!

posted on Sunday, January 24, 2010 9:35:44 PM (Central Standard Time, UTC-06:00)   •  # •  Comments [0] • 
Kick it •  Add to del.icio.us •  View blog reactions; 
 Tuesday, January 19, 2010

image Recently, I ran into a need to make use of the Mono.Cecil.dll library from a .net application I was working on. Cecil is a fantastic little project under the Mono project that allows you to interrogate an existing .net assembly (EXE or DLL file) and retrieve all kinds of information about the assembly, from the resources embedded within it to the classes and methods defined, and much more. You can even alter the contents of the assembly and write the new version back out to disk!

The thing is, Cecil comes prebuilt as a C# assembly (a DLL file), and I really did not want to have a second file required for this particular application (it’s just a little command line utility).

My first take was to use Oren Eini’s excellent concept of an assembly locator. My idea here was to embed an assembly as a binary resource, then, when requested, read that resource into a stream, load the assembly from the stream, and resolve references to it via the assembly locator.

I’m still working on that concept, because I think it’s a clever and convenient solution to the problem, but, in researching that, I happened to remember the even easier (as in, no code required at all!) solution of using ILMerge.

ILMerge

If you haven’t already discovered it, ILMerge is a Microsoft research project in the form of a single command line EXE utility, that can “merge” any number of .net assemblies with a “target” assembly, and produce either a .net DLL or EXE output file.

There’s a really good article on CodeProject describing the general use of the program. There’s even a GUI (Gilma) for it.

Automating ILMerge

What the article doesn’t go into is automating the ILMerge process. After all, you won’t want to manually run that command line utility every time you build your application!

The good thing is, it’s trivially easy to automate as long as you take care of one critical step.

  • First, download and install ILMerge from the link above.
  • Once it’s installed be sure to copy the ILMerge.exe utility to somewhere on your path (or add the folder it’s in to your path).
  • Then, grab the Mono.Cecil.dll file (or whatever DLL it is you want to merge into your main project EXE). Put it in the root folder of your project.
  • Go ahead and set a reference to that file, so you still get all the .net intellisense goodness, but be sure to set the Copy Local property for the reference to FALSE (after all, you don’t want to copy this DLL to the output folder along with the application if you don’t actually need it, right?)

    image

  • With that done, you MAY want to mark the DLL you’re embedding as “included in project” from the Solution Explorer.

image If you do this, however, make sure you also set the Copy to Output Folder to “Do not copy” (that’s the default though so it should already be set).

The Tricky Part

One limitation of ILMerge is it that it can’t alter the target assembly “in place”. This means that, for instance, if you want the final resulting executable file name to be called GenerateLineMap (my utility), you can’t have VS compile the assembly to that name. You’ll need to use some other name for the initially compiled assembly.

On the Application tab of the project properties you can change that name, like so:

image

I just added “-Interim” to the Assembly Name.

Now, go to the compile tab of the project properties and click Build Events

image

Insert this as the POST BUILD EVENT

ilmerge /target:winexe /out:"$(TargetDir)$(ProjectName)$(TargetExt)" "$(TargetPath)" "$(ProjectDir)Mono.Cecil.dll"

Notice that the OUT parameter specifies the output file name via the $(ProjectName) variable (which is still “GenerateLineMap”) while the first assembly to merge is specified using the $(TargetPath) variable (which is the full filename of the output assembly, including the “-Interim”).

image

EDIT: Important note: Notice the /target:winexe option. You’ll need to change that as appropriate depending on the type of exe you’re building. In my case, I had a console app where this needed to be set to just /target:exe. Setting it to /target:winexe caused all of the console output functions to just do nothing, which threw me for a bit!

Now, just rebuild the solution and you should see two resulting EXE files in your output folder, one with the “–Interim” (which is the version WITHOUT the embedded Mono.Cecil.DLL file or whatever DLL you’ve chosen) and one WITH the embedded file. As a final cleanup, you may want to add an additional Post build step to remove the “*-Interim” files.

To test, just make sure you DO NOT have the embedded DLL anywhere on the path or in the same folder as the exe and run the exe. If everything went right, your app should work exactly the same as if the embedded DLL was included externally with the app!

Now, your application is back to being a single EXE to distribute, and it was built completely automatically by Visual Studio.

Caveats

You knew there had to be some, right?

The first is that if the dll to embed contains licensing information, it might not work properly after being embedded. I don’t have any DLLs like that to test with, but I’ve read reports about the problem at various sites on the internet. Just something to be aware of.

Second, trying to replace the originally named exe with the newly built one results in VS not being able to debug the exe in the IDE (it throws a message about the assembly manifest being different from what was expected). I haven’t worked that issue out yet. What this means is that you might need to leave any references set to “Copy to Output Folder” while debugging, and not replace the original compiled assembly, just ILMerge it into a new assembly name.

posted on Tuesday, January 19, 2010 12:54:37 PM (Central Standard Time, UTC-06:00)   •  # •  Comments [0] • 
Kick it •  Add to del.icio.us •  View blog reactions; 
 Tuesday, January 05, 2010

If you haven’t already checked it out, definitely head over to Tom’s hardware for their article on setting up “GodMode” in Windows 7 (apparently it works in Vista too, dang, wish I’d known that).

Basically, you create a folder somewhere, then rename it to

GodMode.{ED7BA470-8E54-465E-825C-99712043E01C}

When you do, that folder becomes a “virtual folder” full of (on my system anyway) 278 links to virtually every administrator type function you might ever want to jump to on a Windows Machine. Here’s a sample screenshot:

image

Very, very cool indeed.

posted on Tuesday, January 05, 2010 11:18:15 PM (Central Standard Time, UTC-06:00)   •  # •  Comments [0] • 
Kick it •  Add to del.icio.us •  View blog reactions; 
 Thursday, December 31, 2009

If you haven’t checked it out already, DirectShowLib.net is pretty much THE way to get at direct show functionallity in VB.net (that is unless you want to spend $$$). Thing is, it’s only a paper thin wrapper over the DirectShow COM api stuff, so there ain’t no hand holding here.

I’d mucked with it for a while and with the help of some of the sample code, got video playing in a form in VB.net fairly easily, but, I needed to flip and/or rotate that video under some circumstances.

After many googles, I finally came across the IVMRMixingControl9 interface that the VideoMixingRenderer9 exposes, but, no matter what I did, I could not cast from a VMR9 to the MixingControl, like so:

Dim Mixer = DirectCast(VMR9, IVMRMixerControl9)

I kept getting an “Interface not implemented”. Then I happened across a post about a wholly different problem, but buried within it was a comment about needing to set the VMR into “mixing mode” in order for it to implement that IVMRMixingControl9 interface. Ugh! DirectShow is nothing if not interfaces. And odd dynamically implemented interfaces at that. Oh well.

A little more digging, and it turns out to be quite easy. Just obtain the IVMRFilterConfig9 interface from your VMR9 object, and call SetNumberOfStreams on it (with and argument 1 or more).

The end result is code that looks like this (remember, this is with a reference to DirectShowLib.net):

DIM FGM = New FilterGraph
Dim VMR9 As IBaseFilter = New VideoMixingRenderer9

FGM.AddFilter(VMR9, "Video Mixing Renderer 9")
Dim FC As IVMRFilterConfig9 = VMR9
FC.SetRenderingMode(VMR9Mode.Windowed)
FC.SetNumberOfStreams(1)

Dim Mixer = DirectCast(VMR9, IVMRMixerControl9)
Mixer.SetOutputRect(0, New NormalizedRect(1, 1, 0, 0))
Mixer.SetAlpha(0, 0.2)

Note that in this case, the SetOutputRect is reversing the output rectangle, so the video is going to end up flipped and upsidedown, exactly what I was needing. I’ve also set the alphachannel to .2, meaning the video is somewhat transparent.

Unfortunately, there doesn’t appear to be any way to rotate the video using the MixingControl, so that is my next topic of research.

posted on Thursday, December 31, 2009 12:11:22 PM (Central Standard Time, UTC-06:00)   •  # •  Comments [1] • 
Kick it •  Add to del.icio.us •  View blog reactions; 
 Sunday, December 13, 2009

image Well, I suppose the economic storm finally caught up with me.

The company I was working for just sold. Unfortunately, it was more of a liquidation than a sale, and the buyer already has a pile of developers on staff.

Soooo. I’ll soon be available for other engagements. \:\-\)

If you or your company needs an experienced architect/developer/manager highly skilled in:

  • VB.net
  • Legacy vb to .net conversions (VB1 through 6, even the old DOS Basica and PDS, I’ve done ‘em all!)
  • Code porting to .net (I’ve worked with Cobol and Pascal, but can read just about anything)
  • SQL Server
  • Document Management System Integrations (particularly, DocsOpen, Interwoven, and WorldOX, various versions)
  • Legal and medical field software
  • Office integrations (especially commercial level addin design and development)
  • Low level integrations (serial port, networking, that sort of stuff)
  • Installer building (particularly Wise or InstallShield)
  • Development management
  • Product design/architecture

By all means, leave a comment here or better, drop me a note using this form. I’d love to talk with you.

Thanks for reading!

posted on Sunday, December 13, 2009 5:48:00 PM (Central Standard Time, UTC-06:00)   •  # •  Comments [0] • 
Kick it •  Add to del.icio.us •  View blog reactions;