Deploying Interop UserControls with RegFree-COM

Deploying Interop UserControls with RegFree-COM

Rate This
  • Comments 26

One of the features of the latest Interop Forms Toolkit is the ability to develop UserControls in addition to Windows Forms. In a previous post, I showed how to create a simple Interop UserControl. I also have a video here on creating them, and one here on deploying a hybrid application using the standard Setup and Deployment project in Visual Studio 2005.

The benefit of creating Interop UserControl libraries is that you can deploy them using what's called RegFree-COM. This means that if you're deploying your VB6 applications on XP or higher OSs then you don't have to manually register the assemblies as COM components. Instead the operating system will "register" them for you on-the-fly at runtime. The COM component registry keys aren't physically created in the system's registry, keeping the system clean and allowing you to deploy COM components in a side-by-side fashion. (On your development machine the UserControls are still physically registered when you build the assemblies so that you can develop in Visual Basic 6.) This may be the way to go if you have a current setup program that you use for your VB6 application that was written with the Setup and Deployment Wizard.

Using RegFree-COM also means that you can take advantage of ClickOnce Deployment (since ClickOnce will not register COM components). The benefit of using ClickOnce deployment with your VB6 applications is that you can take advantage of a modern deployment architecture which includes automatic updates and deploying from a central web server.

What the toolkit does to enable RegFree-COM is that it gets you started with a private assembly manifest for the UserControls. When you select the Interop User Control Library template when creating a new project in Visual Studio, a InteropUserControl.manifest file is created for you along with the rest of the files. Inside this private assembly manifest is XML describing the controls inside your library. By default, the name of the UserControl that is created when you first create your library is InteropUserControl with a generated class id. This information is described in the <clrClass> node. 

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- You don't need to worry about anything in this file unless you're
     using registration-free COM.
     There should be an appropriate <clrclass> section for every InteropUserControl
     defined in the project -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
  manifestVersion="1.0">
<assemblyIdentity
            type="win32"
            name="InteropUserControlLibrary1"
            version="1.0.0.0" />
<clrClass
            clsid="{7395b9d9-da47-4262-80e7-b4eed8768d09}"
            progid="InteropUserControlLibrary1.InteropUserControl"
            threadingModel="Both"
            name="InteropUserControlLibrary1.InteropUserControl" >
</clrClass>

</assembly>

When you change the name of InteropUserControl or the assembly name you need to also update the contents of this file as well. If you add more UserControls to your library you'll need to create a new <clrClass> node with that control's information. You can find the class ID by looking in the Interop UserControl's VB6 Interop Code Region and then in the COM Registration Region:

<ComClass(InteropUserControl.ClassId, InteropUserControl.InterfaceId, InteropUserControl.EventsId)> _

Public Class InteropUserControl

 

#Region "VB6 Interop Code"

 

#If COM_INTEROP_ENABLED Then

 

#Region "COM Registration"

 

    ' These  GUIDs provide the COM identity for this class

    ' and its COM interfaces. If you change them, existing

    ' clients will no longer be able to access the class.

 

    Public Const ClassId As String = "7395b9d9-da47-4262-80e7-b4eed8768d09"

    Public Const InterfaceId As String = "739b2e94-6bdf-4417-beff-25a457e6df8f"

    Public Const EventsId As String = "65029223-ea4e-4cb0-9462-27edbbf985fa"

 

    'These routines perform the additional COM registration needed by ActiveX controls

    <EditorBrowsable(EditorBrowsableState.Never)> _

    <ComRegisterFunction()> _

    Private Shared Sub Register(ByVal t As Type)

        ComRegistration.RegisterControl(t)

    End Sub

 

    <EditorBrowsable(EditorBrowsableState.Never)> _

    <ComUnregisterFunction()> _

    Private Shared Sub Unregister(ByVal t As Type)

        ComRegistration.UnregisterControl(t)

    End Sub

 

#End Region

As an example, I created an Interop UserControl library called ARegFreeComLibrary. In this library I created two UserControls, one called CustomerDetails and one called OrderDetails so my manifest looks like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- You don't need to worry about anything in this file unless you're
     using registration-free COM.
     There should be an appropriate <clrclass> section for every InteropUserControl
     defined in the project -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
  manifestVersion="1.0">
<assemblyIdentity
            type="win32"
            name="ARegFreeComLibrary"
            version="1.0.0.0" />
<clrClass
            clsid="{7395b9d9-da47-4262-80e7-b4eed8768d09}"
            progid="ARegFreeComLibrary.CustomerDetails"
            threadingModel="Both"
            name="ARegFreeComLibrary.CustomerDetails" >
</clrClass>
  <clrClass
            clsid="{bb58ec27-8668-49e0-90cf-3542075654a9}"
            progid="ARegFreeComLibrary.OrderDetails"
            threadingModel="Both"
            name="ARegFreeComLibrary.OrderDetails" >
  </clrClass>
</assembly>

The other manifest file you need to have for RegFree-COM to work is called a client manifest file and this needs to be manually created and then placed in the application's directory. This would be where your VB6 application is also deployed. The contents of this manifest include the name and version of the VB6 application and then the Interop UserControl assembly information:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity type="win32" name="MyVB6App" version="1.0.0.0" processorArchitecture="x86" />
        <dependency>
            <dependentAssembly>
                 <assemblyIdentity type="win32" name="ARegFreeComLibrary" version="1.0.0.0" />
            </dependentAssembly>
        </dependency>
</assembly>

Place this into a file named after your VB6 application with an extension of .manifest, in my case, MyVB6App.exe.manifest, and pop it into the same folder as the exe. It's important that you name the client manifest file the same as your VB6 application + exe.manifest extension otherwise RegFree-COM will not work. To manage the file easier, from the Project menu in Visual Studio I selected Add New Item and selected Text File to create the manifest. In the properties window I then set the "Build Action" to Content and "Copy to Output Directory" to Copy Always. I find it easier to keep track of it this way.  

Next thing to do is copy your VB6 app into the release folder under \bin\Release\ and any supporting files. In my example I am using an Access mdb, but I've added this file to the library I created as a local data file so it'll get built into the Release folder as well. Note, when working with local data files you'll need to also set the Copy to Output Directory appropriately like I explain in this post. Now what the client is going to need in order to run all this is:

1) The .NET Framework 2.0
2) The VB runtime (comes with XP and up OS's) and any OCX's or other referenced components/data you use in your VB6 application
4) Your Interop UserControl assembly and any .config files and the client .exe.manifest
3) The Microsoft.InteropFormTools assembly

When creating Interop UserControls you can remove the reference to the Microsoft.InteropFormTools assembly if you aren't using it -- just remove the reference and then comment out the code at the top of the ActiveXControlHelpers.vb file. However, if you are using it then it's easy to get ClickOnce to install this as a prerequisite (just like the Framework 2.0) because the toolkit now comes with a redistributable package. (You'll see this in a minute.)

You can also add your VB6 application to the project which, in my example, includes the MyVB6App.exe and the Msdatgrd.ocx (the VB6 DataGrid I'm using). Adding them as content files and marking them to always copy to output directory will put them into the \bin\Release folder every time you build the UserControl project. You can also specify the class library project location when you make your VB6 EXE, that way all the files you need to deploy come out in one place, the \bin\Release. If you're deploying this to a machine that already has the VB6 Runtime and the .NET 2.0 Framework then you can just xcopy deploy the Release to the client machine and run.

Using ClickOnce Deployment is optional but for this example we'll set it up this way. Since you can't use ClickOnce to deploy a class library project, instead of adding the VB6 application files to the class library project, we'll add them to a new Windows Forms application instead. So I just added a simple Windows Application to my solution called InteropAppLauncher. Once you have this project created you can then add a reference to your Interop UserControl Assembly and select "Add Existing Item" on the VB6 application files as well as the client manifest file (MyVB6App.exe.manifest). In my case, since I'm using an Access.mdb file I moved this file into the launcher application as well so it can be deployed.

Next thing to do is to write a couple lines of code in the launcher's form so that it will launch your VB6 application right away and close.

Public Class Form1

 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Process.Start("MyVB6App.exe")

        Me.Close()

    End Sub

End Class

Now we're ready to publish with ClickOnce. Select My Project and go to the Publish Tab and enter the deployment location. I just set up a local file share, but you can easily publish to a web server as well. Select the Prerequisites button and you'll see the redistributable packages available. You'll definitely need .NET Framework 2.0 but you can decide whether you need the Interop Forms Toolkit 2.0 package depending on if you left the reference to Microsoft.InteropFormTools assembly. If you did, then you'll need to include this package.

Once you've set all that up you can click the Publish Now button or select Publish from the build menu. Now you have a ClickOnce setup that will launch your VB6 application which uses RegFree-COM in order to create a friction free deployment for your Interop User Controls. I've included the sample I built for your reference. To try out RegFree-COM, just compile the solution and then run the InteropAppLauncher.exe in the \ARegFreeComLibrary\InteropAppLauncher\bin\Release\ folder. For more info on setting up ClickOnce to deploy Visual Basic 6 applications, check out Scott's article on MSDN and this LabCast to try it out yourself right now. By the way, you can use ClickOnce for deploying Visual FoxPro applications as well. 

Anyone developing Visual Basic 6 (or Visual FoxPro) applications should consider taking advantage of the Interop Forms Toolkit 2.0, ClickOnce Deployment, and RegFree-COM to bring .NET's modern capabilities to your users in an easy-to-manage way.

In the next interop post I'll talk about setting up debugging across Visual Studio and VB6. (UPDATE: Here's how to debug.)

Attachment: ARegFreeComLibrary.zip
Leave a Comment
  • Please add 2 and 6 and type the answer here:
  • Post
  • Excellent article!   Additionally, users might want to check out this post which explains in more detail some other aspects of deployment (like how to get any prereqs installed and what to do if you cannot deploy your app with Clickonce, etc...)

    http://blogs.msdn.com/vbteam/archive/2007/06/04/deploying-applications-with-the-interopforms-2-0-toolkit.aspx

    It's very cool to have the ability to deploy VB6 apps using ClickOnce though!

  • great article.  

  • The article seems great, and works on my development machine. However upon deploying to clients I receive an automation error "overlapping i/o" when attempting to show the .NET control. The program then crashes.

    I've tried manually registering the control but this doesn't help. How can this automation error be fixed?

  • Hi Miles,

    I've never seen this error before, but here's a few things you can try:

    1. Ensure you're running all components of the application locally, not off a network share

    2. Ensure your user account has full permissions to access the directory

    3. Ensure none of the files are readonly.

    I'd also recommend trying out the following tool which can be useful for debugging RegFree COM issues: http://blogs.msdn.com/junfeng/archive/2007/06/12/diagnose-sidebyside-failures-in-windows-xp-windows-server-2003.aspx

    I don't know much about Overlapping I/O, but my understanding is it's how the Win32 API handles asynchronous file operations.  Are you doing any sort of long-running operation in your Control's constructor or in your VB Form's Initialize event?

    What happens if you create a new VB6 app + new Interop UserControl and deploy that RegFree?

    Hope that helps,

    Jonathan Aneja

    Program Manager, VB Team

  • Hi

    This article is very useful.

    Srinivas

  • Hi

    I am creating a InteropUserControl and withing the project am accessing a Service via netMSMQ. The usercontrol is throwing an exception stating that it cant find the config information. I am not sure if the App.Config file needs to go to a different location for this kind of applications. Any help will be apprecicated.

    Thanks

  • Hi Injuninus,

    To get the WCF settings to be read properly all you need to do is to rename the .dll.config file that is generated for your UserControl library to the same name as your VB6 application and deploy it in the same folder. For instance

    MyVb6App.exe

    MyVb6App.exe.config  <--- rename to this from MyLibrary.dll.config and place in same directory

    I'll be writing a blog post on this as well as how to read the My.Settings so keep an eye out.

    HTH,

    -B

  • Last week I had the privilege of speaking in Lisbon, Portugal &amp; Birmingham, England at launch events

  • Is it possible to deploy Interop UserControls with RegFree-COM using the same method being applied for VB6 apps with Visual FoxPro? I've followed the steps listed in your article, but get the following error message when launching my VFP 9 app: "The application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem." The client manifest file is causing this error display.

  • Hi Edward,

    I've never tried it with Fox but I believe it should work the same. The manifest is REALLY picky. Make sure you spelled the name of your assembly, user control and classID all match up perfectly and you do NOT already have a COM component in the registry by that name registered already.

    Here's a good interview with Todd Apley where he walks through deploying with RegFree-COM.

    http://channel9.msdn.com/Showpost.aspx?postid=388101

    HTH,

    -B

  • I am in very big trouble. I have created a one application which using a COM component without registering by setting the property Isolated = true. I am very surprising it is debugging and working fine in VS2005. But the same application when i upgraded to VS2008, it is throwing an exception like "Retrieving the com class factory for component with CLSID {} Failed with the following error 80040154." I saw all the manifest, everything is proper. One more interesting thing is that, when i double click on the .exe it woking fine.

    Can you please provide resolution on this?

  • I am getting a "reference in the manifest does not match the identity of the downloaded assembly" error at deployment.

    So, I took your sample code and published.

    And, I'm getting the same error.

    Any idea what I'm missing?

  • I tested VB6 application launcher for ClickOnce deployment. It works with VB6 and C++ MFC based ocx and dll. Manifest files were automatically created by VS 2005. But I could not  make it work if VB6 application has dependency C++ ATL based dll.

    If there something in manifest file that I need to change manually? Any aideas?

    Thanks

  • Hi,

    I have created a number of vb.net 2008 Interop user controls. The controls work on the development machine but I can not get them to work on the client machines. I followed the steps mentioned in "How to: deploy hybrid application" tutorial by Beth Massi, but it does not create the project.msi file.  It does create a setup.exe file but when I try to run it complains about the .msi file missing. I am posting here because I did not get any answers from the forums.

    Please help me I am desperate,

    regards

    Nasir

  • 先週、 ポルトガルのリスボン と イギリスのバーミンガム での Visual Studio 2008 の発表イベントで講演する機会がありました。どちらも熱狂的な雰囲気に包まれていたのは、今回の Visual

Page 1 of 2 (26 items) 12