The Artima Developer Community
Sponsored Link

.NET Buzz Forum
Turn a .NET winforms application into a (COM) automation server

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Peter van Ooijen

Posts: 284
Nickname: petergekko
Registered: Sep, 2003

Peter van Ooijen is a .NET devloper/architect for Gekko Software
Turn a .NET winforms application into a (COM) automation server Posted: Jun 3, 2005 4:13 AM
Reply to this message Reply

This post originated from an RSS feed registered with .NET Buzz by Peter van Ooijen.
Original Post: Turn a .NET winforms application into a (COM) automation server
Feed Title: Peter's Gekko
Feed URL: /error.htm?aspxerrorpath=/blogs/peter.van.ooijen/rss.aspx
Feed Description: My weblog cotains tips tricks and opinions on ASP.NET, tablet PC's and tech in general.
Latest .NET Buzz Posts
Latest .NET Buzz Posts by Peter van Ooijen
Latest Posts From Peter's Gekko

Advertisement

As a start to the next 2 years of blogging I want to look back on an "ancient" technology : COM, which is still the glue between software parts created with a great diversity of tools. COM brought me to .NET, exploring the world of COM in Delphi I discovered the .NET 1.0 betas. Never to leave again.

COM support in .NET is good. You can make your .NET code accessible to any COM client (for instance VBscript) by setting the "Register for COM Interop" property in a project.

Having done that all the public classes in your assembly are available as COM server classes. Public methods and properties are exposed as COM callable methods and props. You can finetune this by setting the ComVisible attribute on a class or method

using System;
using System.Runtime.InteropServices;

namespace MyAutomationLibrary
{

   [ClassInterface(ClassInterfaceType.AutoDual)]
   [ProgId("MyComClass.Test")]
   public class MyComClass
   {

      [ComVisible(false)]
      public void MyNonComMethod()
      {

This makes building COM servers with .NET a snap.

But there is one huge drawback: you can register only a dll for COM interop. And not an exe like a WinForms application. Making a Winforms application (COM) automatable requires a little work on the architecture of your app.

  • Creat a windows forms application
  • Add a class library to the solution
  • Add System.Windows.Forms to the references of the lib
  • Add a form to the class library
  • Add the classlibrary to the references of the winforms app
  • Delete the main form of the windows app
  • Add a new class to the winform application

Your solution should now look like this

By deleting the mainform from the windows app we have also removed the entry point of the application. By default on startup a .net executable searches for a static main method. VS generates this method for you in the mainform. The new entry point will now be in the MainClass.

using System;
using System.Windows.Forms;

namespace MyAutomatableWinformApp
{

   public class MainClass
   {

       [STAThread]
       static void Main()
      {
         Application.Run(new MyWinFormClassLibrary.MainForm());
      }

   }
}

It does exactly the same as the original main method, but it creates a form which is housed in the class library instead of the exe itself. Now you still have your winform app and have moved all “real” code into a class library.

The next step is to make the application automatable. Add a new class libary to the solution and register it for COM interop. The library references the windows form class library and System.Windows.Forms. The Show method of the COM class will fire up the mainform found in the MyWinFormClassLibrary. Just creating the form and running it, like the Main method did, has one problem: the method will not return to the calling COM client untill the application has stopped running the mainform. That is when the winform app has terminated. To circumvent this the form has to be started in a separate thread. Given the great threading support in .NET this no big deal either.

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

…

[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("MyWinComServer.Test")]
public class MyComClass
{

   private void formThread()
   {
      Application.Run(new MyWinFormClassLibrary.MainForm());
   }

   public void Show()
   {
      Thread t = new Thread(new ThreadStart(formThread));
      t.ApartmentState = ApartmentState.STA;
      t.Start();
   }

}

The actual code to run the mainform is in the private formThread method. Which is wrapped up in a ThreadStart delegate. A more detailed article on threading in winforms is here.

This snippet of VBscript will test your code

set o = CreateObject("MyWinComServer.Test")
o.Show()
msgBox("Click to stop")

It creates the mainform. You can toy around with that until you click the script-messagebox. Which will terminate your main app.

As the thread in the server interacts with the UI you have to set the thread’s appartmentstate to STA. Another thing to watch out for is when you want to access the form from other methods in your COM class. You will cross a thread boundary and have to Invoke methods and properties on the form. More details are in this article.

That should do the trick. Of a very great value was this blogpost by Rick Strahl on automating winforms in general. This result is just a couple of lines code but .NET is doing some very powerfull things here. More than enough to get you into trouble, so feel free to chime in.

 

Read: Turn a .NET winforms application into a (COM) automation server

Topic: .NET Framework 1.1 SP1 Previous Topic   Next Topic Topic: Enterprise Library and .NET 2.0: What's the deal?

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use