QDV Interface for external clients

Unlike macros, the external clients are standalone applications, e.g. EXE. They link to the InterfaceQDV.dll which provides the access to the API. The clients then can use the QDV functionality without need to open a QDV application.

The external application needs to add a reference to the InterfaceQDV.dll which is a part of the QDV installation. This will add the access to the Qdv.QdvInterface namespace which contains the Qdv class.

Once you have the Qdv class, you can initialize it and get the QdvManager object from it.

Important

An external client must call the QDV API from a Single Thread Apartment (STA) mode! If called from a Multi Thread Apartment (MTA) mode, an exception may occur during execution of some API methods. You must ensure that your Main function has STAThreadAttribute marked on it.

This is sometimes not possible. For example, Windows services are executed by the windows service hosting system, which runs using MTA threads. You can't control this. You have to create a new thread and set its ApartmentState to STA, and do your work on this thread. See examples below.

The default mode differs in C# and VB. In C# it is MTA while in VB it is STA. The following will explain how to solve the problem for various types of applications.

Console application

Simply put the STAThreadAttribute on top of Main method. This is only necessary in C# because in VB it is already set as default. But it doesn't hurt if you explicitly define STA also in VB. You can see the code in the example below.

Windows Forms Application

There's nothing special to do. The Windows Forms Application template for C# automatically adds the STAThreadAttribute attribute to C# projects. Because the single-threaded apartment model is the default for Visual Basic, there is no need for the attribute.

You can see a comprehensive Windows Forms example in \SDK\Sample VB.NET\Test_QDV_Interface.vbproj project. Among many other things, it allows you to select STA or MTA at startup to demonstrate how it works or fails.

Windows Service

Windows services are executed by the windows service hosting system, which runs using MTA threads. You cannot control this. You have to create a new thread, set its ApartmentState to STA and do your work on this thread.

using System.Threading;
 Thread t = new Thread(new ThreadStart(MyMainMethod));
 // Make sure to set the apartment state BEFORE starting the thread.
 t.ApartmentState = ApartmentState.STA;
 t.Start();					
This language is not supported or no code example is available.
Imports System.Threading
 Dim t As Thread = new Thread(AddressOf MyMainMethod)
 ' Make sure to set the apartment state BEFORE starting the thread.
 t.ApartmentState = ApartmentState.STA
 t.Start() 					
This language is not supported or no code example is available.

ASP .NET application

Old WebForms ASP.NET applications should set the ASPCompat attribute of the @ Page directive to true to force the page to be serviced by the STA thread pool.

<%@ Page AspCompat="true" ... %>					

This approach is illustrated in \SDK\Sample ASP.NET\ sample.

Unfortunately all other ASP.NET technologies built on top of the core ASP.NET engine do not support STA natively. So if you want to use QDV API in MVC or with class ASMX Web Services, there's no automatic way like the ASPCOMPAT keyword available. See the Creating STA COM compatible ASP.NET Applications article for the solution.

Example
 

Here's an example of how to create a QDV session and open an estimate from a console application. You get an IEstimate instance which can be manipulated with the API.

using System;
 using Qdv.QdvInterface;
 using Qdv.UserApi;
 
 class Test
 {
 
  [STAThread]
  public void Main()
  {
   //Get the reference to the QDV Interface component (and tell the application that QDV is installed in another folder).
   string qdvInstallPath = "C:\\Program Files (x86)\\Qdv";
   Qdv.QdvInterface.Qdv qdvConnector;
   qdvConnector = new Qdv.QdvInterface.Qdv(qdvInstallPath);
 
   //Then initialize the component.
   bool silentMode = true;
   //Set silent mode to true so that you have no message in case of error, update of estimate and so on.
   string licenseCode = "";
   qdvConnector.Initialize(silentMode, licenseCode);
   if (!qdvConnector.IsInitialized) {
    throw new Exception("Cannot initialize QDV interface! Please make sure the component is properly installed.");
   }
 
   // Now, we can use the standard API from Qdv.UserApi namespace.
   // Start with the qdvConnector.QdvUserApiManager property to get a Qdv.UserApi.QdvManager instance.
   // Create the estimate, which will be used for performing of all operations.
   string estimateFile = "c:\\MyEstimate.qdv";
   IEstimate estimate;
   estimate = qdvConnector.QdvUserApiManager.EstimateFactory.GetEstimate(estimateFile, false);
   // Do what you want with the estimate object...
  }
 
 }					
This language is not supported or no code example is available.
Imports Qdv.QdvInterface
 Imports Qdv.UserApi
 
 Class Test
 
     <STAThread>
     Public Sub Main()
         'Get the reference to the QDV Interface component (and tell the application that QDV is installed in another folder).
         Dim qdvInstallPath As String = "C:\Program Files (x86)\Qdv"
         Dim qdvConnector As Qdv.QdvInterface.Qdv
         qdvConnector = New Qdv.QdvInterface.Qdv(qdvInstallPath)
 
         'Then initialize the component
         Dim silentMode As Boolean = True 'set silent mode to true so that you have no message in case of error, update of estimate and so on
         Dim licenseCode As String = ""
         qdvConnector.Initialize(silentMode, licenseCode)
         If Not qdvConnector.IsInitialized Then
             Throw New Exception("Cannot initialize QDV interface! Please make sure the component is properly installed.")
         End If
 
         ' Now, we can use the standard API from Qdv.UserApi namespace.
         ' Start with the qdvConnector.QdvUserApiManager property to get a Qdv.UserApi.QdvManager instance.
         ' Create the estimate, which will be used for performing of all operations.
         Dim estimateFile As String = "c:\MyEstimate.qdv"
         Dim estimate As IEstimate
         estimate = qdvConnector.QdvUserApiManager.EstimateFactory.GetEstimate(estimateFile, False)
         ' Do what you want with the estimate object...
     End Sub
 
 End Class					
This language is not supported or no code example is available.

In this article

Definition