2 Replies Latest reply: May 15, 2014 9:59 AM by BrianAllOver _ RSS

    Monarch and C# .NET

    BrianAllOver _

      I am converting Access VBA code that automates Monarch into C# .NET, but I'm getting this error:

       

      QueryInterface for interface MONARCHLib._DMonarch failed.

       

      I've added a reference to MONARCHLib to my project, and instantiate successfully with this statement:

      MONARCHLib.MonarchClass     lMonarch = new MONARCHLib.MonarchClass();

       

      Any statement I've tried on my lMonarch object subsequent to that generates the above error. I've looked around at other posts in this forum, and no one mention C#. They do mention using CreateObject in VB.NET, but this doesn't seem to be an option in C#.

       

      So how's it done? Does Monarch support automation via C# .NET?

       

      Brian Schwartz

      Programmer/Consultant

      HCA Physician Services

        • Monarch and C# .NET
          BrianAllOver _

          A follow-up for others who might have a similar problem:

           

          Google searches for the generic part of the error message in my original post (without the Monarch library name) reveal some slightly interesting information along these lines. It appears that Monarch 7 does not correctly register itself. Searching my registry, I find entries for v4, the one I used to have, but nothing for v7. I tried to manually register the Monarch.tlb with regsvr32, but it returns an error. On a whim, I tried the type-library creation tools I have with .NET and with VB6, but neither worked.

           

          I called Monarch's tech support phone number. Here I am disappointed with this company. They do not support their COM interface. The immediate reply I received was "we don't help with writing code." I explained that this was not a code writing problem, but appears to be a problem with the type library and Monarch's registry entries, but the gentleman, while kind, was of zero help.

           

          Our solution has been to create a separate DLL (a "class library") in VB.NET which uses CreateObject, and then reference this DLL in our C# project. Not ideal, but it works. For each Monarch function we want to use in C#, we create a wrapper function in the VB class. The VB code goes something like this:

           

          Public Class Monarch

           

              Private mMonarch As Object = CreateObject("Monarch32")

           

              Public Sub CloseAllDocuments()

                  mMonarch.CloseAllDocuments()

              End Sub

           

              'Can't use just "Exit" because it is a VB keyword

              Public Sub ExitMonarch()   

                  mMonarch.Exit()

              End Sub

           

              Public Function JetExportTable(ByVal vDestDBFilespec As String, ByVal vDestTable As String, ByVal vAddFlag As Byte) As Boolean

                  Dim success As Boolean = False

           

                  If Not vDestDBFilespec Is Nothing And Not vDestTable Is Nothing _

                  AndAlso vDestDBFilespec <> "" And vDestTable <> "" _

                  Then

                      Try

                          success = mMonarch.JetExportTable(vDestDBFilespec, vDestTable, vAddFlag)

                          If (Not success) Then

                              'Report an error

                              '    "Export failed for " & vDestTable & " to " & vDestDBFilespec & "."

                          End If

                      Catch ex As Exception

                          'Report an error

                      End Try

                  Else

                      'Report an error

                      '    File not specifed

                  End If

           

                  Return success

           

              End Function

           

              Public Function SetProjectFile(ByVal vFilespec As String) As Boolean

                  Dim success As Boolean = False

           

                  If Not vFilespec Is Nothing AndAlso vFilespec <> "" Then

                      Try

                          success = mMonarch.SetProjectFile(vFilespec)

                          If (Not success) Then

                              'Report an error

                              '    "Could not open Monarch project file " & vFilespec & ". Open the project in Monarch for more information."

                          End If

                      Catch ex As Exception

                          'Report an error

                      End Try

                  Else

                      'Report an error

                      '    File not specifed

                  End If

           

                  Return success

           

              End Function

           

          End Class

          • Monarch and C# .NET
            BrianAllOver _

            FYI for all.

             

            Working on another project I learned how to access a COM object with late-binding in C#. I don't have Monarch code, but these hints from my use of the Cognos Impromptu object model may get you started (some of this needs to be at the class level, some inside a procedure):

             

            //----


            System.Type     typImp;     //The Impromptu type object

            object          objImp;     //The Impromptu instance object, created from the Impromptu type object

             

            //Get Impromptu instance

            typImp = System.Type.GetTypeFromProgID("CognosImpromptu.Application");

            objImp = System.Activator.CreateInstance(typImp);

             

            private const System.Reflection.BindingFlags     flagsMethod = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.InvokeMethod;

            private const System.Reflection.BindingFlags     flagsGetProp = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.GetProperty;

            private const System.Reflection.BindingFlags     flagsSetProp = System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.SetProperty;

             

            private object Invoke(object target, string member, System.Reflection.BindingFlags flags, params object[] args)

            {

                 return typImp.InvokeMember(member, flags, null, target, args);

            }

            //----


             

            After all that setup, you can call Invoke like this:

             

            Invoke(objImp, "Quit", flagsMethod, null);

             

            Hope that helps someone,

            Brian