Monthly Archives: October 2010

Get Out The Vote!

0
Filed under Rants

image Or rather, Get out AND vote!

I’m not going to get up on any soapboxes here about politics. That’s not what this blog is all about. But whatever your inclinations are, at least get down to the polls this Tuesday and put your vote in!

Now, back to hacking at a generic interception framework!

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.

Old School Advice That Still Rings True

0
Filed under Rants

Earlier today, I was reading an excerpt from an interview with Dan Bricklin (the guy that invented the spreadsheet, for those that might not know).

He was asked about his approach to building programs back in the day (the mid 80’s, all legwarmers and The A Team).

His response was quite interesting, very “agile” when agile only meant an adjective to describe gymnasts.

One thing I’ve always done, for many years — I know Bob Frankston did, too — you have to figure out a path through the whole thing and implement that first. And then you go back to add more. Getting the path through is like building a scaffold. A lot more is put on [the application] before it’s a real product, but you have the critical path in place. It’s always building off something that’s working.

I thought that was fantastic. Yet another example of how programming seems to be a lot of doing the same thing over and over, just with each generation coming up with trendy new names for it all in the process.

Word’s Compatibility Options

224
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.

WindowsXP periodically disconnects from Windows7

5
Filed under Networking, Troubleshooting, Windows 7

Very strange, and utterly frustrating issue recently.

After I got hit by lightning, I ended up replacing an Iomega NAS storage server with a simple Win7 box running 2 raided 2TB harddrives. It was a quick build and was a little cheaper than an equivalent 4TB Iomega unit, plus it’s running real Windows, so I can do more stuff with it.

But, I’ve got several XP Virtual Machines (under VMWare Workstation), that would, very consistently, disconnect from the Win7 “server”.

I googled for days, and tried at least a dozen different suggestions but none worked.

Essentially, if I rebooted the Win7 machine, the XP machines could connect to and work with the server for a while. But eventually, the WinXP machines would loose connection to the Win7 machine and the ONLY way to get them connected again was to reboot the Win7 machine.

The main problem was that the failure was very generic: something along the lines of “The server does not have enough resources to complete the request”.

Not much to go on.

On a whim, I happened to check in the event log at one point and came across this:

Source: srv
Event ID: 2017
Level: Error
The server was unable to allocate from the system nonpaged pool because the server reached the configured limit for nonpaged pool allocations.

Googling “srv error 2017” turned up a number of new suggestions I hadn’t seen before, but one in particular on Alan LaMielle’s blog looked very promising, though he was talking about connected via SAMBA.

The Bottom Line

In a nutshell, the problem is that if you use a “normal” version of Windows more like a server (lots a machines connecting to it for files), normal Windows installs aren’t configured for that.

You need to change 2 registry entries (on the SERVER machine, in my case the Win7 machine):

HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\LargeSystemCache

should be set to ‘1’, and:

HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters\Size

should be set to ‘3’.

Then, either reboot, or use the Services control panel to restart the ‘SERVER’ service.

Since I’ve done that, I’ve connected several XP systems up, and run full backups overnight without a single hiccup.