Tuesday, May 16, 2006

Net 2.0 COM Visibilty Part II

Net 2.0 COM Visibilty Part I - The Idea

Net 2.0 COM Visibilty Part II - The Project

Net 2.0 COM Visibilty Part III - Hooking it all up (docs and stuff)

Net 2.0 COM Visibilty Part IV - Deploying

The Project

Here is a picture of the nearly final test harness to give you an idea of what we need to accomplish. Firast a little background.

I felt it was necessary to build a complete and user friendly test harness. This would allow users in teh "scripting" community to test and learn the use of a new object with a visual interface and at the same time give me a means to test this COM control in it's many forms. As long as I have to write the test code then why not make it part of teh deliverable. Scripters are, in most cases, not programmers. We shouldn't make them guess at how or utilities work. To accomplish this we need to provide good documentation and example coed that will work with no modifications. For this project this is quite easy to do. For projects that operate against a domain this can become more complicated than the utility itself.
Test Harness
TestHarness.JPG
The test harness has two initial buttons that let us do something to see if the COM control is registered properly. Then we have the ususal. A funny icon that performs an unknown function; our get me out-of-here "Quit" button and som "Help" A normal Windows Forms Application.


To drive the various flavors of 'Box" functions I have chosen to use a Tab control. This helps to arrange things in a highly visible fashion and eliminates the need for a menu. Each tab has controls for filling in the argument list for the function along with ReeadOnly controls for displaying the results.


<more to come>

Technorati : , , ,

Net 2.0 COM Visibilty Part I

(This entry is a work in progress and will change in the next few days. Code will be available by 5/17.)

The Idea

NET 2.0 greatly simplifies all aspects of COM deployment. In this discussion I will show how easy it is to build and deploy a COM callable class using Visual Studio 2005. I will also explain how to make this callable from scripting languages like VBScript, JScript, VBA and ASP. Before I am done with this series you will have the code and a working COM callable NET 2.0 class library along with a companion setup project that is able to install and register this NET library with only a few mouse clicks.


The idea for this project started when numerous posters to the SriptingAnswers Forum, a web site built and run by Don Jones, an author, scripter and Microsoft MVP, asked if there was a way to have the "MessageBox" and "InputBox" Windows Script Host objects timeout if no input was entered. This is one oversight by the Microsoft designers of administrative scripting tools and is a potentially useful item.

Don Jones had created a replacement for these functions that can also be used to create simple dialogs from scripting languages. His "SuperInpuBox, available at http://www.ScriptingAnswers.com has also left out the timeout function. I originally though I would just go into Don's code and add a timeout but that turned out to be more complex than I thought it would be. SuperInputBox was written in VB6. Mostly VB6 projects will convert painlessly to VB.NET using the Visual Studio Migration Wizard. Not so for this code. VB.NET had issues with the Scripting Dictionary object. Rather than spend the time solving this puzzle I decided it would be faster and easier to create a separate VB.NET DLL with InputBox, MessageBox and PasswordBox functions. Here is a sample of Step 1 of the invention.


Inputbox1.JPG

The image at the left shows the InputBox functionality. In it's final form I want it to very closely copy the normal behavior of the VB InpuBox dialog. I have given the user a caption, a prompt and an optional set of buttons to use for terminating the dialog. Here is the call method that creates this dialog.


return = oUtils.InputBox( "My Prompt", "My Caption", ,vbYesNoCancel, 30 )
response - oUtils.Answer

The return value will be set to the values VB uses for the MessageBox function plus a value of 99 to indicate that the InputBox has timed out. The call template looks like this:

retVal = InputBox ( [prompt As String],[caption As String],[default As String],[vbMBType As Integer],[seconds As Integer]).

All of the arguments should be optional. This will prevent exceptions when the scripter forgets something. The InputBox will display some text that will make it clear that the argument has not been satisfied. The defaults will be no timeout progress bar and no timeout, An OK button, a default caption and a default prompt. It will look very much like the standard VB MessageBox function.

The other Box types; PasswordBox and MessageBox, will be preset variations on the InputBox delivered as separate functions for convenience.

The power that NET 2.0 provides us makes extending and modifying this library a cinch. One thing we will be able to easily do is to add encryption to the PasswordBox function. This will allow the user to grab the encrypted password to save to a file. We could also extend the PasswordBox function to accept Windows credentials and return them as a Windows Credentials object for passing to other objects like WMI. The possibles seem limitless.

WSHUtilities can be downloaded here.

The Code

Building this in Visual Studio 2005 was trivial except for my dislike of VB as a language. To my surprise I found VB.NET 3005 to be very nice to code in. All those little things that C programmers like to do are mostly available. Putting parens on subs and functions is now possible so I can type the way I am used to. Here is the project step by step.

  1. Start by creating a project for a class library. I called in DotNetUtils but name it how you like. Add to the project a Windows Form. Go into the project properties and set the library to be COM Visible. Rename the default class in the class module to something useful; in my case I called it WSHUtils. Rename the class file and form if you like. Preface the class name with "<ComClass()> on the same line in front of the Class declaration. That's it. You now have a COM callable class library. Build the project to be sure you have not broken anything before we begin to add the code.
  2. Now add a Public function to the class named InpuBox and give it the following argument list:
    <past here>

    Place a call to the system MessageBox inside of the function. We are just going to use this for a simple "hook-up" test.
    Build the project again to look for errors.
  3. Now add a new Windows Forms project to the solution and call it InputBoxTest. This will be our simple test harness.. Add a reference to the previously created class library to this project. Add a button to the default form and double click it to get to the event code. In the event code add the following:

    System.Windows.Forms.MessageBox.Show( "Hello World!")
  4. Build and run the project. Push the button. You should see a system messagebox with our "Hello World" message.

In the next installment I Will step through the coding rerquired to implement the described functionality and build the setup project. This will get us to a Script callable COM library setup file that can be installed on any Windows XP or later system. To make this work on Windows 2000 we will have to add some registry hacks to teh setup file before we are done.

Technorati : , , ,


Friday, May 12, 2006

Support for Office Document Creation Under IIS 6.

This question has come up over-and-over for years. See David Wang's blog here of why this can't be made to work well if at all. David is an MSDN blogger and IIS a member development team. His answer should be the final word on this issue. My additions follow: ( so much for the final of anything) For years web developers have tried to automate MS Office from web applications. In my first web project it was the first thing I tried to do with ASP. After all, we can instantiate a Word session from a C or VB application so why not do it in a web session. Seems like a no-brainer for extending Office to the web. So then why don't we see every web site generating Word, Excel and Powerpoint documents for us? First of all I don't believe MS Office is licensed for this kind of use. Secondly see Davids blog for why this is not technically feasible. There are third party objects that can create and edit Office documents without an Interactive Session. This is a fairly large after market for ISVs. I am absolutely not sure but I believe that VSTO also allows for a certain amount of document creation and management without an Interactive session. SQL Server Report Server can generate Excel and Word documents on an IIS application instance. In a user group, N3UG, this question was posed to Peter Laudati (MSDE) as regards PowerPoint support in VSTO. The answer returned (via Miguel Castro MVP) was that there are no plans for PP support in VSTO in this or the next release. I guess we are stuck with third party solutions. If Office 12, which will have support for XML everything, supplies a DTD with PP then we should be able to use this to create and modify PP to some degree. My guess is that PP will not have complete XML support.

Thursday, May 11, 2006

Good NET 1.1 to 2.0 Conversion Resources

NET 1.1 to .NET 2.0 Migration From Peter Laudati's blog (Microsoft Developer Evangelist) on MSDN. Peter's research at Microsoft as a result of questions posed at he N3UG Meeting on 5/9/2006

Monday, May 08, 2006

How to use a script library with VBScript - Part III

[[[note: This is a work in progress. I will update it as I have pieces completed. It is made visible in case the information is useful to anyone.]]]

Using an external source for script functions is a useful and time saving device for scripters. I though I might take some time to share a couple of methods for accomplishing this.

There area basically four different ways to include scripts at runtime.

  1. Injecting a script into the memory of the currently executing script.
  2. WSF file using <script src="pathname"> tag
  3. WSF file using included global <script> section and injecting it into the memory of the executing job.
  4. Creating a WSC (Windows Script Component) that contains the function library.

I will describe each of these and provide a simple example along with any known caveats.

III. WSF File using <script> tag.

One of the advantages of using a WSF file to hold your scripts is that it can also contain a common script library or libraries which can be written in multiple scripting languages. This will allow things like calling jscript functiosn from vbscript and the reverse. A WSF file is XMLfile containing as a set of "JOB" sections that can be run independently from a switch "//Job:<jobname>". The WSF file can contain multiple "<script> blocks.

Let's look at the script tag more closely.

<script id="myscript" language="vbscript">

Function MyFunc1( arg1, arg2 ) End Function

Function MyFunc2( argx, argy, argz ) End Function

</script>

As you can see we can define a "language" attribute which can be set to any scripting language available on you machine. Normally we will use either "vbscript" or "jscript" These are the two default scripting languages installed on Windows.

This is basically the same as declaring a script block in an HTML page. To make it useful in a WSF file we also have to add a way to find the script block. This is done by addin an "ID" attribute. Here we have set the ID to "myscript"

To load this script library into memory we need to use a helper function which can read code from a file and load it into memory in an executable fashion. We will do this with the following function.

Function LoadThisLibrary(strXPATHQuery) Dim xml,fso,strXML

' open file and read it inot a stream Setfso = CreateObject("Scripting.FileSystemObject") Setfs = fso.OpenTextFile(WScript.ScriptFullName) strXML = fs.ReadAll

' create XML DOM and load stream then query for library script Setxml = CreateObject("MSXML2.DOMDocument") xml.loadXML strXML xml.setProperty "SelectionLanguage", "XPath" strScript = xml.selectNodes(strXPATHQuery).item(0).nodeTypedValue

' execute string to load it into memory ExecuteGlobal strScript

End Function

This function takes as an argument an "XPATH" query and uses it to retrieve a specific node in an XML document. Since our WSF file is an XML document we can use this XPATH query to retrieve the contents of our <script> section by using it's ID. The XPATH will look something like this:

child::package/job/script[attribute::id='myscript'

This says that we want to find the "child" of the guy whose ID at the specified path is 'myscript'. The child of the attribute is the contents of the script tag which is our script library.

We do this by loading the current file into a file system object stream using the WScript.ScriptFullName value which is the full pathname of the current WSF file. After loading the stream object we create an XMLDomDocument object and load the stream into the XMLDOM. From here we can select the script by using the XPATHQuery above. Once we have the script loaded into a string "strScript" we can use WScripts "ExecuteGlobal" method to compile this script into memory. Now all of the functions in the script will be callable from the current JOB.

In the next installment I will cover the other structures of the WSF file format that will help to guarantee that this will work reliably. Be patient. When I am done it will be much easier to use this but we need to be sure that you understand how and where it can break. A few more steps will make this clear and yo will be able to quickly wrap related groups of your functions in a WSF <script> wrapper and make them callable from any JOB in the WSF file.