Monthly Archives: November 2009

VBScript in VB.Net

1
Filed under .NET, ActiveX, Languages, VB Feng Shui

A long (long) time ago, if you wanted your users to be able to enhance your product by add coding logic, you pretty much had two choices:

  • Dig into Lex and Yacc or….
  • Roll your own parser and scripting execution engine.

Then, around the time VB 6 was released, Microsoft introduced VBA. It worked, but it was expensive and a god awful complicated mess to integrate with your app, so outside of Microsoft Office (which even as of Office 2010, still supports it!), very few applications actually made use of it.

Around the same time, the Microsoft Scripting Control was released. This was an ActiveX control you could use from any COM compatible language to embed VBScript. Now, of course, this is VBScript, not a “real” language like C or even VB. But, it was free, easy to obtain, and very easy to use.

As the years have rolled by, .NET has steadily grown in capability and while the Windows Scripting Host exe is still shipped with Windows, the old VBScript and JScript scripting has largely been supplanted by either:

  • ASP and more recently ASP.NET
  • Powershell
  • Dynamically compiled .NET code
  • and likely lots more options I’m not familiar with

Now, all these options are good, and each definitely has it’s place, but, for many purposes, good ol’ VBscript still fits the bit quite nicely.

But can you use it from .NET? And if so, how?

The Tempest in the Teapot

Before I continue, I should point out that any time you start talking about allowing users to add their own code into your application, you’re opening up a huge can of worms that you’ll need to deal with. Things like properly catching exceptions from badly written user code (yeah, that never happens), adding watchdog timers to deal with hung and infinitely looping user code, security concerns, and the like all will have to factor into the decision. You have been warned <g>.

So Simple It Hurts

I had a plugin project recently where I wanted to give the user the ability to write some very simple logic to expand the functionality of the application.

Of course, I wanted to build a full plugin API, but I also wanted to provide a lighter-weight option for those users that didn’t want to dive head-first into a full on .NET project. VBScript seemed like the obvious choice.

A few Google searches later and most everything I found was talking about how to dynamically compile .NET code, which is cool indeed, but not what I was really after. Other articles and posts insisted that users should convert their VBScript code to .NET (ok, yeah, but that’s not really the point now is it?).

Then I did a Google Desktop search of my own system and turned up some VB6 code I’d written ages ago to experiment with the Microsoft Scripting Control.

Now, I know that .NET languages support accessing ActiveX Controls and COM objects in general, but this was pretty old stuff. Would it actually still work?

I cobbled up a dirt simple VB.net project:

Public Sub Main()
    Dim Script = New MSScriptControl.ScriptControl
    Script.Language = "VBScript"
    Script.AddCode("sub Main" & vbCrLf & "MsgBox ""This is a Test"" " & vbCrLf & "End Sub")
    Script.Run("Main")
End Sub

Be sure to add a reference in the VB.net project to the COM object “Microsoft Scripting Control”.

Run it, and lo and behold, I get the “This is a Test” message box, straight from VBScript!

Obviously, there’s lots more to making use of the Scripting Control than just this, but, clearly, VBScript is still very much a choice for adding limited programmable logic to your application.

Creating Good ol’ Standard DLLs with VB.NET

0
Filed under .NET

Managed code (VB.net and C#) are great for a lot of things, but unfortunately, even as of VS2008, it’s still missing at least one. Standard DLL exports.

You see, way back in the olden days, virtually every DLL in Windows was written in C or assembler and exported functions via the standard DLL export table.

Then came COM and now .NET, providing much easier, object oriented export capabilities. Old style EXPORTS have been falling by the wayside ever since.

Unfortunately, if you program for Windows, eventually you’ll find yourself needing to either consume or provide exports. There’s just no way around it.

For consuming (ie simply “calling”) exported functions in a DLL, .net makes that almost trivially easy. All of the Windows API can be called in this way, simply by including the proper attributes (for VB) for the function declaration in your application. Here’s an example for the SENDMESSAGE Windows API function.

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
End Function

The Hard Part

However, exporting functions from a .NET DLL in the standard Windows API style is not near as easy.

Why would you need to do this? The main reason is to provide hooks that other applications can call. There are many, many applications out there that require addins or plugins to export standard DLL entry points. Being unable to do this in .net means either having to write a shell in C/C++ around those entry points (doable but cumbersome), or simply not providing that functionality.

The good news is that the .NET compiler designers didn’t completely forget about such down-to-the-metal tidbits as this. The bad news is that they didn’t provide any syntactic sugar to make it straightforward either.

Emilio Reale posted an excellent article on CodeProject that discusses the dirty IL (Intermediate Language in .net speak) mechanics of how to:

  1. compile your .net DLL
  2. disassembly it with ILDASM to IL source code.
  3. find the necessary bits in the disassembled output and what to change them to
  4. reassembly the IL source using ILASM into a DLL with the proper functions exported.

All fine and dandy till you look at what’s required. Needless to say, it’s an amazingly involved process to perform manually.

Fortunately, another CodeProject contributor tackled this problem and posted this article. In it, he presents a small utility and attribute definition dll that allows you to export a function (almost ANY function) from a .NET DLL simply by applying an attribute to it, like so:

<ExportDllAttribute.ExportDll("MyFunction", _
System.Runtime.InteropServices.CallingConvention.Cdecl)> _
Public Shared Sub EntryPoint_MyFunction()
     ...my code goes here....
End Sub

and then running the utility on the compiled DLL, which automates the above tasks.

It takes a little work to get things set up, but in the end, it worked flawlessly for me. Within just a few hours, I’d put together the shell of a plugin for an application that I’d had reservations about writing plugins for, simply because it looked like I’d have to do so in C++.

Now, the whole plugin is done, it’s all in VB.net (my language of preference currently), it’s a single DLL with no dependencies (other than the .net runtime <g>), and it can be deployed by simply copying it into a folder.

Can’t get better than that!

507 Mechanical Movements

0
Filed under Hardware, Misc

   image

Just came across this excellent little book. Originally published in 1868, it’s a compendium of just about every sort of mechanical means of transferring one type of motion to another than you can think of. Lots of illustrations. Makes a great reference, and the best part, it’s available free online in a djvu version. It’s a 75mb download, because the book has just been scanned in (even the text), so it’s not really searchable.

But who cares?

If you’re into steampunk in any way at all, this is a must have reference book.

As a side note, while the DJVU format and viewer is quite nice, I preferred a PDF version.

It took some effort, because, when I tried to convert it (using the PRINT function from DJVU into a PDF printer), I kept getting errors about the Courier font not being found (which it most definitely IS installed on my machine).

After some fiddling, I ended up being able to “print” it to the “Office Document Image Writer” printer driver. I then loaded that file up into the Office Document Image Viewer, and printed to the PDF printer from there.