Connect to running DXL server and execute DXL

Hi there,

I am quite despaired because I know it must work but I have not yet found how (having googled for all keywords that should be a hit):

I want to create a convenient way for me to open a specific module. So, I do not want to manually navigate to the module“s folder, and open it. Instead, a hotkey (using autohotkey) shall trigger a script. I thougt I would just somehow connect to Doors by a script and let a DXL script run which will open the module for me.

Precondition: Doors server is available and doors client already opened (regarding the license and the credentials).

I am using the Sodius DXL editor which obviously copes with this situation: it uses my open client to connect to doors in order to execute the DXL scripts in its editor. So, how do they do this?

Environment: WinXP, Doors 9.1

Best regards
Frank
SystemAdmin - Mon Feb 28 04:24:45 EST 2011

Re: Connect to running DXL server and execute DXL
Mathias Mamsch - Mon Feb 28 07:11:22 EST 2011

Hi Frank,

DOORS has a COM API which allows you to execute DXL from a VBS/VBA script. So you can create a VBS script like the following:
 

set doorsApp = createObject ("DOORS.Application")
doorsApp.runStr "read(""/Test/New Module33"", true)"

 


Regards, Mathias

 

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

 

Re: Connect to running DXL server and execute DXL
Mathias Mamsch - Mon Feb 28 07:12:47 EST 2011

Oh by the way, you know of the "Favourites" function of DOORS, do you? So you start DOORS, add the module as a favourite and can open it from the DOORS Database explorer directly. Regards, Mathias


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

Re: Connect to running DXL server and execute DXL
SystemAdmin - Thu Mar 03 11:27:46 EST 2011

Mathias Mamsch - Mon Feb 28 07:12:47 EST 2011
Oh by the way, you know of the "Favourites" function of DOORS, do you? So you start DOORS, add the module as a favourite and can open it from the DOORS Database explorer directly. Regards, Mathias


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

Thank you, Mathias.

(your first post): OK, so this should be the solution. When having searched for my topic, I also searched for COM API but did not find information about it, maybe my search was wrong - so in case you have a link for me I would be glad.

(your second post): Yes, I know. But the idea is to have a little GUI outside Doors where I can quickly (using hotkeys) address a module (and possibly add an object id, too) to then open the module (and navigate to the object). The Doors favourites are really too clumsy for me (I am using Doors every day, every hour and need to navigate fast).

Thanks for your reply!
Frank

Re: Connect to running DXL server and execute DXL
llandale - Thu Mar 03 13:43:47 EST 2011

SystemAdmin - Thu Mar 03 11:27:46 EST 2011
Thank you, Mathias.

(your first post): OK, so this should be the solution. When having searched for my topic, I also searched for COM API but did not find information about it, maybe my search was wrong - so in case you have a link for me I would be glad.

(your second post): Yes, I know. But the idea is to have a little GUI outside Doors where I can quickly (using hotkeys) address a module (and possibly add an object id, too) to then open the module (and navigate to the object). The Doors favourites are really too clumsy for me (I am using Doors every day, every hour and need to navigate fast).

Thanks for your reply!
Frank

Several years ago I made a feeble effort and providing a VBA button that referenced a particular object posted on some Web site, with the notion of opening DOORS, finding the object, and displaying it. Proved the concept but never polished nor deployed it. My VBA and API are extremely weak but that's what you got Mathias for. Here are a couple files from 2005 that perhaps you can make sense out of.

Here is file "HyperLinkTo_SSUP_3.vbs: This file is somehow associated with a hyperlink on some web page.

' If DOORS isn't running you'll get a VBA error
' User can then loginto DOORS and try this again
Set DOORSObj = CreateObject("DOORS.Application")
DOORSObj.runStr ("#include <c:\doors-stuff\VBS-Stuff\HyperlinkToObj.inc>; fHyperLinkToObj(""SSUP_3"", """")")


Here is the referenced Include file.

I see there is a presumed default project, variable "g_NameProj". That concept may not apply to you in which case your VBA may need to explicitely call out the name of the Project.

I see that there is the presumed policy that each module in the project has a unique name, and that the Prefix of the module is the same as the module Name, so that the code presumes that when its requested to display an Object with Identifier "SSUP_3" that it will find the module named "SSUP" and will try to find the object with absolute number "3".

I see the nature of the "include" presumes everybody using the web page indeed has access to the include file via the "addins" variable. That's not a good presumption, but I don't know what to do about that. I wonder if you put the include code in a config file, then opened and ran the contents via eval_.

Yes, this old test code is below my current standards, oh well.

 

// HyperLinkToObj.inc
/*
Include file provides one user function: fHyperLinkToObj.
Finds and displays a particular object in a particular module in a particular project.
The second Project name parameter defaults to 'Ship HME'.
The first parameter is the Module name, followed by a dash or underscore - or _,
   followed by an Absolute Number.  Note that this is consistent with DDX policies
   featuring module Prefixes the same as the module, this the 'ID' is the same
   as the 'Object Identifier' for DDX modules.
   There must be exactly one dash or underscore in this field.
Example: fHyperLinkToObj("MyModule_1234", "MyProject")  will look for object with Absolute
    number "1234" in module 'MyModule' in project 'MyProject'.
The module is opened, the object made current, and then displayed.

Notes:
Will find the first such module in the project.  If there is more than one with the same
   name, than whichever on is found first will be searched, and the second one ignored.
If null, project is defaulted to the "Ship HME" project.
This is a library function.  The user would do something like the following:
    #include <.../HyperLinkToObj.inc>
        fHyperLinkToObj("MyModule_1234", "MyProject).

This CAN be used by Visual basic.  Put the following in a *.vbs file:
        Set DOORSObj = CreateObject("DOORS.Application")
        DOORSObj.runStr ("#include <c:\...s\HyperlinkToObj.inc>; fHyperLinkToObj(""SSHP-13"", """")")
If DOORS isn't yet running then it is started and you can expect the DOORS login screen
    along with a VBA error message.
   If so, cancel the error, Log into doors and try again.
*/
 
/*

----------- Another post from the Internet ----------
here's some VBA which looks for an instance of DOORS... 
Dim appDoors As DoorsDXL 
Private Function connectToDOORS() As Boolean 
On Error GoTo connectHandler 
Dim sErrMsg As String 
Set appDoors = CreateObject("DOORS.Application") 
connectToDOORS = True 
Exit Function 

connectHandler: 
        sErrMsg = "Unable to communicate with DOORS. DOORS has not been started" 
        MsgBox prompt:=sErrMsg, Buttons:=vbCritical 
        connectToDOORS = False 
End Function 

have a look at www.msdn.microsoft.com for examples of CreateObject and GetObject 

there can only ever be one instance of this object and this is registered in the table of running objects in windows.
  Running DOORS for the first time creates this entry in the table.
  Running DOORS for a second time replaces this with a new instance. 

runStr() is what you need for running a snippet of dxl.
   Have a look in the DXL reference help for definitions of this function and the automation interface.
   {DOORSHOME}/bin/doorsdxl.tlb is the COM type library for this interface. 

because this is a COM automation interface you can use VBScript, JavaScript, or anything else which
   implements the windows scripting interfaces. Script, of course, can be embedded in html,
   but VBScript is not the same as VBA. 

"windows 2000 scripting guide" from Microsoft Press is a good book to look at for scripting. 

This is a very crude COM interface. If you wanted anything more sophisticated you might need to use
  the DXL API (dxlapi.dll) and create your own COM interface - which would allow you to do some more
  interesting things with explorer, I.E, or VB. Have a look at the example "C" code in {DOORSHOME}/api. 

----------- End Internet Post ----------

----------- Email from Richard Williams: ------------

I would first check to see what available commands there are within the DOORSObj.  
  There may be one which will allow you to verify that the application has already authenticated.  
  If so there may also be a command which will allow you to handle the authentication programmatically.  
  If not you can use the SendKeys commands to send the key commands to the login prompt.  
  Some of the commands you attempt to execute in the DOORSObj may return a predictable error specifying
   the error state is a result of the not-logged-in state.  The syntax for the Message Box would be:

If IsNull(DOORSObj)  Then
        MsgBox "Login to Doors and click OK"
End If
DOORSObj.runStr (etc...)

If you download the scripting runtime documentation from Microsoft, it may help a great deal.  
  The URL to get more detail is:
http://msdn.microsoft.com/scripting/

-------- End Richard Williams Email Respons -------

*/
 
        // The following two commands will probably be part of the Hyperlink housed OUTSIDE this DXL file:
string  g_ID    = "SSUP_640"
string  g_NameProj      = "Ship HME"
 
//**********************
string  flStripNameMod(string ID)
{     // Get the name of the module from the ID
 
    int OffSet, Len
    string      NameMod = ""
 
    if (findRichText(ID, "_", OffSet, Len, true)      or
        findRichText(ID, "-", OffSet, Len, true))
      NameMod = ID[0:OffSet-1]
    // print "fStripNameMod, ID/NameMod = '" ID "'\t'" NameMod "'\n"
    return(NameMod)
}     // end flStripNameMod()
 
//**********************
bool    flStringToInt(string InString, int &OutInt)
{     // Convert the InString to a valid Integer.  Return whether it worked.
        // Improper or null Strings return False and Zero
    OutInt = 0
    if (null InString)            return(false)
    if (!isValidInt(InString))  return(false)
    OutInt      = intOf(InString)
    return(true)
}     // end fStringToInt()
 
//**********************
int     flStripAbsNo(string ID)
{     // Get the Absolute Number from the specified Identifier
        // Return 0 (zero) if its a bad ID.
    int OffSet, Len
    int AbsNo = 0               // Stays 0 unless its good
    string      AbsNoID
 
    if (findRichText(ID, "_", OffSet, Len, true)      or
        findRichText(ID, "-", OffSet, Len, true))
    { AbsNoID = ID[OffSet+1:]
      if(!flStringToInt(AbsNoID, AbsNo))
       infoBox("HyperLinkToObj:\nPoorly formed Absolute Number '" AbsNoID "'  in the input Identifier '" ID "'")
    }
    // print "fStripNameMod, ID/NameMod = '" ID "'\t'" NameMod "'\n"
    return(AbsNo)
 
}    // end flStripAbsNo()
 
//**********************
string  flFindModule(string NameBase, string NameProj)
{    // Find the module in the Specified project (does NOT start with a slash)
 
    Project     prj     = project("/" NameProj)
    Item        itm
    string      NameItem, NameFound, NameFull
    ModName_    mn
    if (null prj)
    { infoBox("HyperLinkToObj:\nNo such DOORS Project '" NameProj "'")
      return("")
    }
    NameFound = ""
    for itm in prj do
    {
      NameItem = name(itm)
      NameFull = fullName(itm)
      if (NameItem != NameBase) continue
      mn = module(NameFull)
      if (!null mn                      and 
          type(itm) "" == "Formal"  and
          !isDeleted(mn) )
      { NameFound = NameFull
        break
      }
    }        // end for items anywhere in the Project
    if (null NameFound) infoBox("HyperLinkToObj:\nCannot find module '" NameBase "'   in project '" NameProj "'")
    return(NameFound)
}    // end flFindModule()
 
//**********************
void    fHyperLinkToObj(string DesiredID, NameProj)
{
    Module      mod
    Object      obj
    Object      oFound = null, oDisplay
    string      NameBase = flStripNameMod(DesiredID)
    int         DesiredAbsNo    = flStripAbsNo(DesiredID)
    int         ObjAbsNo
    string      NameFull
 
    if (null NameProj)
         NameFull = flFindModule(NameBase, g_NameProj)
    else NameFull = flFindModule(NameBase, NameProj)
    string      Reason = ""
 
    if (null NameFull or DesiredAbsNo == 0)
    {}        // Error already acked
    else
    { mod = read(NameFull, true)
      if (null mod) infoBox("HyperLinkToObj:\nCannot open module '" NameBase "'")
      else
      { for obj in entire mod do
        { ObjAbsNo = obj."Absolute Number"
          if (ObjAbsNo == DesiredAbsNo)
          { current = mod
            current = obj       // Sets to obj IF it is displayed.  Sets it to the nearest object
                                        //   above it if obj is NOT displayed.
            refresh mod
            oFound = obj
            break
          }  // end AbsNo match
        }    // end for all objects in the module
        if (null oFound) infoBox("HyperLinkToObj:\nObject #" DesiredAbsNo "  does not exist in module '" NameBase "'.")
        elseif(!isVisible(oFound))
        { if    ( isDeleted(oFound))                 Reason = " (Is Deleted)"
          elseif(!isFiltered(oFound))           Reason = " (Filtered)"
          elseif(table(oFound) or row(oFound))  Reason = " (Internal DOORS table object)"
          oDisplay = current    // Object actually displayed
          infoBox("HyperLinkToObj:\nObject #" DesiredAbsNo " not displayed " Reason ",\nIts actually just below " identifier(oDisplay))
        }
      }      // module opens OK
    }        // end module is not deleted
}    // end fHyperLinkToObj()
 
//----------------------
void    fHyperLinkToObj(string DesiredID)
{    // Overloaded, presumes the default Project
    fHyperLinkToObj(DesiredID, "")
}    // end Overloaded fHyperLinkToObj()
 
// ack("Hellow from " c_Version)
// fHyperLinkToObj(g_ID, g_NameProj)
//      ---- end file HyperLinkToObj.dxl ----

 

 

  • Louie