Wednesday 19 August 2015

C# integration

As many of you know DOORS has a COM interface. Some use it via VBS, other via Java.
Today I will show you how to make a very simple application with C#.

VBS example

Let's see very simple VBS example:

Set DOORSObj = CreateObject("DOORS.Application")

DOORSObj.runStr ("ack ""hello""")


It's so simple to call a DXL script from VBS!

C# Example

Well C# is little bit more complex than VBS. But once all steps are done it is very easy to use it.

CLR Assembly

First you need to create a .NET common language runtime (CLR) assembly. I used TlbImp.exe. This converts type definitions found in COM type library into equivalent definitions in CLR assembly.
You can find DOORS type library in DOORS bin folder:

C:\>"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\x64\TlbImp.exe" "c:\Program Files\IBM\Rational\DOORS\9.6\bin\doors.tlb"

Above created a DOORSCOMLib.dll in c:\.

Once you have this dll you can simply add it to your C# project.
  1. Select References
  2. Add Referece...
  3. Browse to the location where is your DOORSCOMLib.dll.
  4. Once imported right-click on DOORSCOMLib and see its properties
  5. Set "Embed Interop Types" to false.

Embed Interop Types set to false
Embed Interop Types set to false

Now you can use this library in your code.

DOORSCOMLib interface

DOORSCOMLib has a following interfaces:


IDoorsDXL lets you run DXL:
  • void runDXL(string)
  • void runFile(string) 
  • string restult()
IDoorsStatus enables checking DOORS session status:
  • string clientVersion
  • string clientStatus (1 user logged in, 0 DOORS started but user not logged)

Usage

Usage of DOORSCOMLib is very simple; simply declare a required interface and use it.
IDoorsStatus doorsStatus = Activator.CreateInstance(typeof(DOORSClass)) as IDoorsStatus;

IDoorsDXL doorsDXL = Activator.CreateInstance(typeof(DOORSClass)) as IDoorsDXL;

Here is a simple "Hello Word" application illustrating how to use those interfaces:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DOORSCOMLib;

namespace HelloCOM
{
    class Program
    {
        static void Main(string[] args)
        {
            IDoorsStatus doorsStatus = null;
            doorsStatus = Activator.CreateInstance(typeof(DOORSClass)) as IDoorsStatus;
            if (doorsStatus == null) {
                Console.WriteLine("Null instance");
                return;
            }

            // the session is up, but user might not be logged in
            int trycount = 0;
            while (doorsStatus.clientState != 1 && trycount < 30)
            {
                Console.WriteLine("DOORS not logged in yet");
                System.Threading.Thread.Sleep(2000);
                ++trycount;
            }

            // we have a session
            Console.WriteLine("DOORS version " + doorsStatus.clientVersion);

            IDoorsDXL doors = Activator.CreateInstance(typeof(DOORSCOMLib.DOORSClass)) as IDoorsDXL;

            if (doors != null) {
                doors.runStr("ack \"hello from C# !\"");
            }
        }
    }
}

This should start a DOORS session (if not already started) and display a "hello from C# !" message.

Update

In Visual Studio 2010 or 2013 you can simply added doors.tlb to the references and you can skip creating CLR Assembly.

8 comments:

  1. Hello, I'm trying to integrate an own php software with Doors 9.2 to be able to import and update Doors' requeriments in our own software. The best way i figured out to do it is to call a myfile.exe developed in c# (which will be similar to your post) from php, which would executate a dxl file in doors and get the response of the .exe (or not, if no response is necessary).
    But in Doors 9.2 i can't find this DOORSCOM.Lib you're mentioning, i only find the static library dxlapi.lib, but it doesn't work as expected when i try to run my .c project because the functions of the .lib don't appear as defined.
    Could you give me some advice?

    Thanks a lot

    ReplyDelete
  2. Hi Clea,
    If you are using C# you can simply add doors.tlb or (doorsdxl.tlb) into your references.
    But please be aware doorsdxl.tlb doesn't have IDoorsStatus interface (thus it doesn't have clientVersion nor clienStatus).

    DOORS 9.2 is out of support so I cannot confirm it was shipped with doors.tlb.

    ReplyDelete
  3. Still not running. I get this error:
    (extern symbol not solved, in english)

    dxlips.obj : error LNK2001: símbolo externo _apiFinishLibrary@0 sin resolver
    1>dxlips.obj : error LNK2001: símbolo externo _apiGetErrorState@0 sin resolver
    1>dxlips.obj : error LNK2001: símbolo externo _apiInitLibrary@12 sin resolver
    1>dxlips.obj : error LNK2001: símbolo externo _apiSend sin resolver
    1>dxlips.obj : error LNK2001: símbolo externo _apiConnectSockV2@8 sin resolver
    1>dxlips.obj : error LNK2001: símbolo externo _apiError sin resolver
    1>dxlips.obj : error LNK2001: símbolo externo _apiConnectSock@8 sin resolver

    ReplyDelete
  4. But I decided to use c because the api was in c. Is there an easier way to integrate Doors in a php software? Any advice or help would be great, I'm quite new on developing this kind of things and i'm quite lost

    ReplyDelete
  5. The idea would be to be able to manage DOORS requirements from a php project management application. I don't know if the best idea is by using batch mode, or OLEObjects or the C Api included in the Doors instalation.

    ReplyDelete
  6. hmm like I said 9.2 so is out of support so I cannot even test it...
    but why you need using .NET in between DOORS and php?

    I'm not a php developer but below seams promising:
    http://php.net/manual/en/class.com.php
    $obj = new COM("DOORS.Application")

    ReplyDelete
  7. How can we check DOORS application already opened?
    I don't want to application restarted if user already login to DOORS with his/her account.

    ReplyDelete
    Replies
    1. hi,

      Activator.CreateInstance method will not start new DOORS session if the DOORS application is already running. It will reuse object from existing session.
      And using clientStatus you can check if user is already logged in.

      Delete

Note: only a member of this blog may post a comment.