Getting Requirements from Module with C#

Hi all

I need to get a list of the requirements from a DOORS module with help of C#. Can anybody provide a sample code if there is a possibility?

Thanks in advance
EA2412 - Tue Apr 20 03:03:07 EDT 2010

Re: Getting Requirements from Module with C#
Mathias Mamsch - Tue Apr 20 08:55:22 EDT 2010

Invoking DOORS over C# is easy. Startup a new C# console project, add a reference to the COM library "Telelogic DOORS Type Library". Then insert the following lines in your code:
 

DOORSCOMLib.DOORSClass x = new DOORSCOMLib.DOORSClass();
                x.runStr("print \"Hallo\"; oleSetResult \"Yes\"");
                        Console.Write("Result = " + x.result) ;

 


Start DOORS. Invoke your c# program, which should print "Hallo" in your currently open DOORS session and print "YES" in your c# console To get requirements data you would need to write a DXL script which gathers the data to a string, use the setOleResult function in dxl to pass the string to c# where you can get the result from the 'result' property of the DOORSClass item. Then you would have to parset the string to get the data you want.

Regards, Mathias

 

Re: Getting Requirements from Module with C#
SystemAdmin - Sun May 02 11:46:25 EDT 2010

Mathias Mamsch - Tue Apr 20 08:55:22 EDT 2010

Invoking DOORS over C# is easy. Startup a new C# console project, add a reference to the COM library "Telelogic DOORS Type Library". Then insert the following lines in your code:
 

DOORSCOMLib.DOORSClass x = new DOORSCOMLib.DOORSClass();
                x.runStr("print \"Hallo\"; oleSetResult \"Yes\"");
                        Console.Write("Result = " + x.result) ;

 


Start DOORS. Invoke your c# program, which should print "Hallo" in your currently open DOORS session and print "YES" in your c# console To get requirements data you would need to write a DXL script which gathers the data to a string, use the setOleResult function in dxl to pass the string to c# where you can get the result from the 'result' property of the DOORSClass item. Then you would have to parset the string to get the data you want.

Regards, Mathias

 

I am having a similar issue and its driving me nuts. I do not think IBM have created this comlibrary properly. You cannot cast the DOORS object using the running object table, if DOORS is running it grabs the instance ok, but it closes DOORS afterwards as .net is attempting to clean up after itself, this is more than a tad annoying. You don't notice the issue in visual basic 6 as you have to do your own cleanup, but connecting to an already running DOORS session from a .net environment, doing something and leaving DOORS running seems impossible. Hopefully I am being stupid and missing something. The attached works, but shuts doors which is not what I want, this is not c#'s fault, you should be able to get the running DOORS session, but you can't, DOORS seems to be a singleton so you are ok in vb6 if you always use CreateObject, not in a .net environment though. Think I'll raise a case.
 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DOORSCOMLib;
using System.Security.Permissions;
using System.Runtime.InteropServices;
namespace debugDOORS
{
    class Program
    {
        [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                //Type t = Type.GetTypeFromProgID("DOORS.Application");
                //System.Object obj = Activator.CreateInstance(t);
                //DOORSClass thisApp = obj as DOORSClass;
 
                DOORS thisApp = new DOORS();
                string passedFile = args[0];
                string debugStr = passedFile.Replace("\\","\\\\");
                //IDoorsDXL thisApp = (DOORSClass) Marshal.GetActiveObject("DOORS.Application");
                //DOORSCOMLib.IDoorsDXL
                string DXLStr = "string ThisFile = \"" + debugStr + "\";#include <C:/PROGRA~1/PSPADE~1/RICHAR~1/SENDER~1.DXL>";
                thisApp.runStr(DXLStr);
                
            }
        }
    }
}

Re: Getting Requirements from Module with C#
Mathias Mamsch - Sun May 02 13:52:24 EDT 2010

SystemAdmin - Sun May 02 11:46:25 EDT 2010

I am having a similar issue and its driving me nuts. I do not think IBM have created this comlibrary properly. You cannot cast the DOORS object using the running object table, if DOORS is running it grabs the instance ok, but it closes DOORS afterwards as .net is attempting to clean up after itself, this is more than a tad annoying. You don't notice the issue in visual basic 6 as you have to do your own cleanup, but connecting to an already running DOORS session from a .net environment, doing something and leaving DOORS running seems impossible. Hopefully I am being stupid and missing something. The attached works, but shuts doors which is not what I want, this is not c#'s fault, you should be able to get the running DOORS session, but you can't, DOORS seems to be a singleton so you are ok in vb6 if you always use CreateObject, not in a .net environment though. Think I'll raise a case.
 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DOORSCOMLib;
using System.Security.Permissions;
using System.Runtime.InteropServices;
namespace debugDOORS
{
    class Program
    {
        [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                //Type t = Type.GetTypeFromProgID("DOORS.Application");
                //System.Object obj = Activator.CreateInstance(t);
                //DOORSClass thisApp = obj as DOORSClass;
 
                DOORS thisApp = new DOORS();
                string passedFile = args[0];
                string debugStr = passedFile.Replace("\\","\\\\");
                //IDoorsDXL thisApp = (DOORSClass) Marshal.GetActiveObject("DOORS.Application");
                //DOORSCOMLib.IDoorsDXL
                string DXLStr = "string ThisFile = \"" + debugStr + "\";#include <C:/PROGRA~1/PSPADE~1/RICHAR~1/SENDER~1.DXL>";
                thisApp.runStr(DXLStr);
                
            }
        }
    }
}

This is not what I am experiencing, are you really sure that the problem is not on the DXL side? When I tried and posted the example, DOORS ran happily before and after it. No shutdowns or crashes. Which DOORS version are you using?

What could be the problem: DOORS is not a "Singleton" but an "out-of-process" COM server, meaning only one instance of the OLE server is active, which is shared by all COM clients. When the last reference to the OLE server is cleared (that is the last application using the DOORS server cleaning up its OLE handle), the OLE server will shut down too. This is normal OLE behavior. You should make sure, that this is not causing your problem.

Regards, Mathias


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

Re: Getting Requirements from Module with C#
SystemAdmin - Mon May 03 08:25:19 EDT 2010

Mathias Mamsch - Sun May 02 13:52:24 EDT 2010
This is not what I am experiencing, are you really sure that the problem is not on the DXL side? When I tried and posted the example, DOORS ran happily before and after it. No shutdowns or crashes. Which DOORS version are you using?

What could be the problem: DOORS is not a "Singleton" but an "out-of-process" COM server, meaning only one instance of the OLE server is active, which is shared by all COM clients. When the last reference to the OLE server is cleared (that is the last application using the DOORS server cleaning up its OLE handle), the OLE server will shut down too. This is normal OLE behavior. You should make sure, that this is not causing your problem.

Regards, Mathias


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

Hello Mathias,
Thanks for the reply, I am using DOORS 9.2, haven't tried on any other version.
Probably using all the terminology in the wrong way (a little knowledge is a dangerous thing and that is definately how I would describe my com .net interoperability knowledge!), but I can definately confirm that DOORS was closing down using the previously described technique and a myriad of versions of it (no such issue with vb6).
After slamming my head repeatedly on the desk and going down about 10 blind alleys I came up with the following. A little bit of a hack warranted, but it worked robustly for my purposes.
 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DOORSCOMLib;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Diagnostics;
namespace debugDOORS
{
    //used to close a window (swiped this class from the internet)
    public class Win32
    {
        public const int WM_SYSCOMMAND = 0x0112;
        public const int SC_CLOSE = 0xF060;
        [DllImport("user32.dll")]
        public static extern int FindWindow(
        string lpClassName, // class name
        string lpWindowName // window name
        );
        [DllImport("user32.dll")]
        public static extern int SendMessage(
        int hWnd, // handle to destination window
        uint Msg, // message
        int wParam, // first message parameter
        int lParam // second message parameter
        );
    }
    class Program
    {
        [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        static void Main(string[] args)
        {
            //I am passing DOORS a file to debug, but this technique can be used for other things
            //DOORS writes to a log file which is then read into my text editors log window
            if (args.Length > 0)
            {   
                //late binding is not really done intuitively in .net, hence the use of objects and types
                //the following gets an open DOORS session if it is there, but will also try
                //and open DOORS with no parameters if it isn't (don't want it to do this but can't see how to avoid it)
                //doors won't work for me when passwords, usernames, multiple data servers etc are involved
                Type t = Type.GetTypeFromProgID("DOORS.Application");
                System.Object thisApp = Activator.CreateInstance(t);
                string passedFile = args[0];
                string debugStr = passedFile.Replace("\\","\\\\");
                string DXLStr = "string ThisFile = \"" + debugStr + "\";#include <C:/PROGRA~1/PSPADE~1/RICHAR~1/SENDER~1.DXL>";
                Object[] objArgs = { DXLStr };
 
                try
                {
                    t.InvokeMember("runStr", BindingFlags.InvokeMethod, null, thisApp, objArgs);
                }
                catch (TargetInvocationException e)
                {
                    //we want to capture the event associated with DOORS not firing up and hence not being able
                    //to fire our method 
                    Console.WriteLine("\n***Error***");
                    Console.WriteLine("DOORS did not fire up successfully");
                    Console.WriteLine("Message: {0}", e.Message);
                    Console.WriteLine("Source: {0}", e.Source);
                                       
                    //the following is the default location for DOORS, should use registry to get this really
                    //DOORS now fires up OK, but InvokeMember still attached to wrong process
                    //Determine the handle to the Application window (it will be stuck on the login window) and close it.
                    int iHandle = Win32.FindWindow("DOORSWindow", "Login - DOORS");
                    // Post a message to Application to end its existence.
                    int j = Win32.SendMessage(iHandle, Win32.WM_SYSCOMMAND, Win32.SC_CLOSE, 0);
 
                    //thisApp = null;
                    //fire up with .net equivalent to shell command with various paramaters set
                    Process proc = new Process();
                    proc.EnableRaisingEvents = false;
                    proc.StartInfo.FileName=@"C:\Program Files\IBM\Rational\DOORS\9.2\bin\doors.exe";
                    proc.StartInfo.Arguments= " -u Administrator -d 36677@RichardsPC";
                    proc.Start();
                                        
                    try
                    {
                        //get handle to new window and fire method from that
                        thisApp = Activator.CreateInstance(t);
                        t.InvokeMember("runStr", BindingFlags.InvokeMethod, null, thisApp, objArgs);
                    }
                    catch (Exception ef) {
                        //give up!
                        Console.WriteLine("\n***Error***");
                        Console.WriteLine("DOORS did not fire up successfully using default server failed");
                    }
                }
            }
        }
    }
}

Re: Getting Requirements from Module with C#
SystemAdmin - Mon May 03 08:50:27 EDT 2010

SystemAdmin - Mon May 03 08:25:19 EDT 2010

Hello Mathias,
Thanks for the reply, I am using DOORS 9.2, haven't tried on any other version.
Probably using all the terminology in the wrong way (a little knowledge is a dangerous thing and that is definately how I would describe my com .net interoperability knowledge!), but I can definately confirm that DOORS was closing down using the previously described technique and a myriad of versions of it (no such issue with vb6).
After slamming my head repeatedly on the desk and going down about 10 blind alleys I came up with the following. A little bit of a hack warranted, but it worked robustly for my purposes.
 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DOORSCOMLib;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Diagnostics;
namespace debugDOORS
{
    //used to close a window (swiped this class from the internet)
    public class Win32
    {
        public const int WM_SYSCOMMAND = 0x0112;
        public const int SC_CLOSE = 0xF060;
        [DllImport("user32.dll")]
        public static extern int FindWindow(
        string lpClassName, // class name
        string lpWindowName // window name
        );
        [DllImport("user32.dll")]
        public static extern int SendMessage(
        int hWnd, // handle to destination window
        uint Msg, // message
        int wParam, // first message parameter
        int lParam // second message parameter
        );
    }
    class Program
    {
        [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        static void Main(string[] args)
        {
            //I am passing DOORS a file to debug, but this technique can be used for other things
            //DOORS writes to a log file which is then read into my text editors log window
            if (args.Length > 0)
            {   
                //late binding is not really done intuitively in .net, hence the use of objects and types
                //the following gets an open DOORS session if it is there, but will also try
                //and open DOORS with no parameters if it isn't (don't want it to do this but can't see how to avoid it)
                //doors won't work for me when passwords, usernames, multiple data servers etc are involved
                Type t = Type.GetTypeFromProgID("DOORS.Application");
                System.Object thisApp = Activator.CreateInstance(t);
                string passedFile = args[0];
                string debugStr = passedFile.Replace("\\","\\\\");
                string DXLStr = "string ThisFile = \"" + debugStr + "\";#include <C:/PROGRA~1/PSPADE~1/RICHAR~1/SENDER~1.DXL>";
                Object[] objArgs = { DXLStr };
 
                try
                {
                    t.InvokeMember("runStr", BindingFlags.InvokeMethod, null, thisApp, objArgs);
                }
                catch (TargetInvocationException e)
                {
                    //we want to capture the event associated with DOORS not firing up and hence not being able
                    //to fire our method 
                    Console.WriteLine("\n***Error***");
                    Console.WriteLine("DOORS did not fire up successfully");
                    Console.WriteLine("Message: {0}", e.Message);
                    Console.WriteLine("Source: {0}", e.Source);
                                       
                    //the following is the default location for DOORS, should use registry to get this really
                    //DOORS now fires up OK, but InvokeMember still attached to wrong process
                    //Determine the handle to the Application window (it will be stuck on the login window) and close it.
                    int iHandle = Win32.FindWindow("DOORSWindow", "Login - DOORS");
                    // Post a message to Application to end its existence.
                    int j = Win32.SendMessage(iHandle, Win32.WM_SYSCOMMAND, Win32.SC_CLOSE, 0);
 
                    //thisApp = null;
                    //fire up with .net equivalent to shell command with various paramaters set
                    Process proc = new Process();
                    proc.EnableRaisingEvents = false;
                    proc.StartInfo.FileName=@"C:\Program Files\IBM\Rational\DOORS\9.2\bin\doors.exe";
                    proc.StartInfo.Arguments= " -u Administrator -d 36677@RichardsPC";
                    proc.Start();
                                        
                    try
                    {
                        //get handle to new window and fire method from that
                        thisApp = Activator.CreateInstance(t);
                        t.InvokeMember("runStr", BindingFlags.InvokeMethod, null, thisApp, objArgs);
                    }
                    catch (Exception ef) {
                        //give up!
                        Console.WriteLine("\n***Error***");
                        Console.WriteLine("DOORS did not fire up successfully using default server failed");
                    }
                }
            }
        }
    }
}

Hello Mathias/ Anyone else who is interested
Just out of interest (You say): -

"What could be the problem: DOORS is not a "Singleton" but an "out-of-process" COM server, meaning only one instance of the OLE server is active, which is shared by all COM clients. When the last reference to the OLE server is cleared (that is the last application using the DOORS server cleaning up its OLE handle), the OLE server will shut down too. This is normal OLE behavior. You should make sure, that this is not causing your problem."

When using vb6 I noticed that I could never return an open DOORS session using GetObject, and that CreateObject does not create a new DOORS session if one is already open, hence I termed DOORS a "Singleton" which almost certainly means something else! Did you ever get the GetObject to work? My reading suggest that it is IBM's fault that GetObject doesn't work because they appear to have neglected to register DOORS with the running object table - what do you think?

DOORS control would be a lot cleaner if it were registered, don't think there is any reason you wouldn't want to register with the ROT?

Your statement suggests that you accept that closing your application will close DOORS as I do, or am I missing something? My application is designed to get a handle to doors send it a file, check it for dxl errors then return any errors/ a success message, so under previous conditions it always closed down taking DOORS with it.

Re: Getting Requirements from Module with C#
Mathias Mamsch - Mon May 03 16:30:48 EDT 2010

SystemAdmin - Mon May 03 08:50:27 EDT 2010
Hello Mathias/ Anyone else who is interested
Just out of interest (You say): -

"What could be the problem: DOORS is not a "Singleton" but an "out-of-process" COM server, meaning only one instance of the OLE server is active, which is shared by all COM clients. When the last reference to the OLE server is cleared (that is the last application using the DOORS server cleaning up its OLE handle), the OLE server will shut down too. This is normal OLE behavior. You should make sure, that this is not causing your problem."

When using vb6 I noticed that I could never return an open DOORS session using GetObject, and that CreateObject does not create a new DOORS session if one is already open, hence I termed DOORS a "Singleton" which almost certainly means something else! Did you ever get the GetObject to work? My reading suggest that it is IBM's fault that GetObject doesn't work because they appear to have neglected to register DOORS with the running object table - what do you think?

DOORS control would be a lot cleaner if it were registered, don't think there is any reason you wouldn't want to register with the ROT?

Your statement suggests that you accept that closing your application will close DOORS as I do, or am I missing something? My application is designed to get a handle to doors send it a file, check it for dxl errors then return any errors/ a success message, so under previous conditions it always closed down taking DOORS with it.

Hey Richard,

how could DOORS not register to the ROT? The ROT is part of windows, so every COM object running should be in there. I tested it using the code from here http://dotnet-snippets.de/dns/laufende-com-objekte-abfragen-SID526.aspx ... I can get the DOORS COM object from the ROT using (GUID = "DOORS.Application"):
 

Object y = RunningObjectTable.GetRunningCOMObjectByName("5B833C90-FC9E-11CE-9EFC-524153480001");

 


I am not so sure how GetObject really translates into C# ... What I read from the Internet is that it is at least problematic ... That brings me to the question:

Why bother? Using the "New ()" Syntax and a static linked DOORS COM library you will get the same result as "GetObject" since DOORS is an out of process server, which will spawn only one instance anyway. So you can just start DOORS over the shell, login over the commandline and then use "new (...)" to get a new reference to the COM server. Then you can run any DXL without DOORS quitting. When you want to quit the DOORS instance just execute "quit_()" over DXL and the client will shut down.

The only question that is left, when using new() is, that you need to determine if DOORS is already running. You can use the ROT for that or just the management instrumentation interface.

I would not bother about wrapping the DOORS COM object into an RCW. But I am not a C# expert, so there might be other people who can help you there.

Hope this help, regards, Mathias

 

 

 


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

 

 

Re: Getting Requirements from Module with C#
SystemAdmin - Tue May 04 12:19:09 EDT 2010

Mathias Mamsch - Mon May 03 16:30:48 EDT 2010

Hey Richard,

how could DOORS not register to the ROT? The ROT is part of windows, so every COM object running should be in there. I tested it using the code from here http://dotnet-snippets.de/dns/laufende-com-objekte-abfragen-SID526.aspx ... I can get the DOORS COM object from the ROT using (GUID = "DOORS.Application"):
 

Object y = RunningObjectTable.GetRunningCOMObjectByName("5B833C90-FC9E-11CE-9EFC-524153480001");

 


I am not so sure how GetObject really translates into C# ... What I read from the Internet is that it is at least problematic ... That brings me to the question:

Why bother? Using the "New ()" Syntax and a static linked DOORS COM library you will get the same result as "GetObject" since DOORS is an out of process server, which will spawn only one instance anyway. So you can just start DOORS over the shell, login over the commandline and then use "new (...)" to get a new reference to the COM server. Then you can run any DXL without DOORS quitting. When you want to quit the DOORS instance just execute "quit_()" over DXL and the client will shut down.

The only question that is left, when using new() is, that you need to determine if DOORS is already running. You can use the ROT for that or just the management instrumentation interface.

I would not bother about wrapping the DOORS COM object into an RCW. But I am not a C# expert, so there might be other people who can help you there.

Hope this help, regards, Mathias

 

 

 


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

 

 

Hi Mathias,
Thanks for the help, I would be only to happy to use a simple technique if it avoided shutting DOORS down (as said before the simple technique works perfectly except for the fact that for me it exits DOORS on completion which is unacceptable, can't get this to stop happening! Only to happy to be proved wrong, hopefully there is something simple that I am missing. Are you implying that I have to fire the DOORS process via a shell and then use new to get a proper reference and that will not close DOORS when the C# program exits, wheras just using new will?

The code you referenced from the internet does seem to be a viable way to check if DOORS is running or not (just using GetActiveObject dies a death if DOORS is not running). Just a case of reshuffling what I now know into something a little cleaner.

Positive I'm misunderstanding something. What do you mean by "static linked DOORS COM library". Didn't think you can do this in C# (internet seems to agree with this view)? Can you explain what you mean by this and more importantly how to achieve it.

What I do is simply add a reference to the com library in the C# project and use it, doing this copies the com dll into the C# project area - what should I do instead?
You say: -
"When you want to quit the DOORS instance just execute "quit_()" over DXL and the client will shut down."
Yes that would work if DOORS fired up successfully, but you can't issue any commands when stuck at the login screen, but I could use the snippet you have to avoid the issue, so I should no longer have the issue.

Thought for the day: -
You don't know what you don't know and reading a 2000 page book and more importantly understanding it is not something you really have time to do when you have a task to get on with!

Re: Getting Requirements from Module with C#
Mathias Mamsch - Tue May 04 16:04:59 EDT 2010

SystemAdmin - Tue May 04 12:19:09 EDT 2010
Hi Mathias,
Thanks for the help, I would be only to happy to use a simple technique if it avoided shutting DOORS down (as said before the simple technique works perfectly except for the fact that for me it exits DOORS on completion which is unacceptable, can't get this to stop happening! Only to happy to be proved wrong, hopefully there is something simple that I am missing. Are you implying that I have to fire the DOORS process via a shell and then use new to get a proper reference and that will not close DOORS when the C# program exits, wheras just using new will?

The code you referenced from the internet does seem to be a viable way to check if DOORS is running or not (just using GetActiveObject dies a death if DOORS is not running). Just a case of reshuffling what I now know into something a little cleaner.

Positive I'm misunderstanding something. What do you mean by "static linked DOORS COM library". Didn't think you can do this in C# (internet seems to agree with this view)? Can you explain what you mean by this and more importantly how to achieve it.

What I do is simply add a reference to the com library in the C# project and use it, doing this copies the com dll into the C# project area - what should I do instead?
You say: -
"When you want to quit the DOORS instance just execute "quit_()" over DXL and the client will shut down."
Yes that would work if DOORS fired up successfully, but you can't issue any commands when stuck at the login screen, but I could use the snippet you have to avoid the issue, so I should no longer have the issue.

Thought for the day: -
You don't know what you don't know and reading a 2000 page book and more importantly understanding it is not something you really have time to do when you have a task to get on with!

Hey Richard,

Regarding the "Static linked COM library" you are absolutely right. I meant setting the reference to the DOORS COM library. I am not a .NET or C# expert, so I hope you don't mind. Anyway, I am suspecting that we might not be facing the same bug, because we are using different DOORS versions (I only have DOORS 8.2 to try). Maybe this is a DOORS 9 bug that I cannot reproduce on DOORS 8.

The below code works perfectly for me. It solves the startup problem by starting doors as a process, checks for DOORS already running using getProcessByName and waits for the DOORS startup until the DOORS client enters its main window loop (that is, the gui is ready).

If it does not work for you, chances are that there is a bug in DOORS 9. Hope this help, regards, Mathias
 

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
 
namespace doorsExample
{
    class Program
        {
                public static void Main(string[] args)
                {
                        
                        if (Process.GetProcessesByName("doors").Length == 0) {
                                System.Diagnostics.Process proc = new System.Diagnostics.Process();
                                proc.StartInfo.FileName= "S:\\Programme\\Telelogic\\DOORS_8.2\\bin\\doors.exe";
                                proc.StartInfo.Arguments = "-u Administrator";
                                proc.StartInfo.UseShellExecute = false; 
                                proc.Start();                           
                        
                                // Wait for GUI to fire up ...
                                proc.WaitForInputIdle();                        
                        }
                        
                        DOORSCOMLib.DOORSClass d = new DOORSCOMLib.DOORSClass();                                                
                        d.runStr("print \"Hallo\"");
                        // TODO: Implement Functionality Here
                        
                        Console.Write("Check your DOORS output . . . ");
                        Console.ReadKey(true);
                }
        }
}

 


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

 

Re: Getting Requirements from Module with C#
SystemAdmin - Wed May 05 05:38:57 EDT 2010

Mathias Mamsch - Tue May 04 16:04:59 EDT 2010

Hey Richard,

Regarding the "Static linked COM library" you are absolutely right. I meant setting the reference to the DOORS COM library. I am not a .NET or C# expert, so I hope you don't mind. Anyway, I am suspecting that we might not be facing the same bug, because we are using different DOORS versions (I only have DOORS 8.2 to try). Maybe this is a DOORS 9 bug that I cannot reproduce on DOORS 8.

The below code works perfectly for me. It solves the startup problem by starting doors as a process, checks for DOORS already running using getProcessByName and waits for the DOORS startup until the DOORS client enters its main window loop (that is, the gui is ready).

If it does not work for you, chances are that there is a bug in DOORS 9. Hope this help, regards, Mathias
 

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
 
namespace doorsExample
{
    class Program
        {
                public static void Main(string[] args)
                {
                        
                        if (Process.GetProcessesByName("doors").Length == 0) {
                                System.Diagnostics.Process proc = new System.Diagnostics.Process();
                                proc.StartInfo.FileName= "S:\\Programme\\Telelogic\\DOORS_8.2\\bin\\doors.exe";
                                proc.StartInfo.Arguments = "-u Administrator";
                                proc.StartInfo.UseShellExecute = false; 
                                proc.Start();                           
                        
                                // Wait for GUI to fire up ...
                                proc.WaitForInputIdle();                        
                        }
                        
                        DOORSCOMLib.DOORSClass d = new DOORSCOMLib.DOORSClass();                                                
                        d.runStr("print \"Hallo\"");
                        // TODO: Implement Functionality Here
                        
                        Console.Write("Check your DOORS output . . . ");
                        Console.ReadKey(true);
                }
        }
}

 


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

 

Hello Mathias,
Well done, I owe you a beer, I might even stretch to two! You may not want to come to Stevenage to claim it though (there is always a down side)!
 

if (Process.GetProcessesByName("doors").Length == 0)


Is a useful trick, which I seem to have somehow missed even after much hunting around.

For whatever reason DOORS is now not shutting down, I expected it to shutdown when opening a doors session then running the code and pehaps not when starting from scratch, but it seems to stay there in both situations - which is what I want! My problem might be pc specific, have to try it on the original project on my other pc (maybe there is something in the way I set the project up)
Regards,

Richard

Re: Getting Requirements from Module with C#
SystemAdmin - Fri May 07 11:55:35 EDT 2010

SystemAdmin - Wed May 05 05:38:57 EDT 2010

Hello Mathias,
Well done, I owe you a beer, I might even stretch to two! You may not want to come to Stevenage to claim it though (there is always a down side)!
 

if (Process.GetProcessesByName("doors").Length == 0)


Is a useful trick, which I seem to have somehow missed even after much hunting around.

For whatever reason DOORS is now not shutting down, I expected it to shutdown when opening a doors session then running the code and pehaps not when starting from scratch, but it seems to stay there in both situations - which is what I want! My problem might be pc specific, have to try it on the original project on my other pc (maybe there is something in the way I set the project up)
Regards,

Richard

Just had a chance to check this solution on my other machine, same project, same settings, same access rights as far as I know. I'm getting the same result as before, ie, everything works OK until the application closes taking DOORS with it. Works perfectly on the first machine though - weird.

Two things that I know are differrent: -
1) Visual Studio 2008 on working machine, Visual Express C# on non working one
2) Windows XP on working system, Windows 7 on non working one.

Might have to return to my cack handed way of doing this or look at it through process monitor or something unpleasent, internet doesn't seem to help me on this issue.

Re: Getting Requirements from Module with C#
Mathias Mamsch - Fri May 07 13:47:37 EDT 2010

SystemAdmin - Fri May 07 11:55:35 EDT 2010
Just had a chance to check this solution on my other machine, same project, same settings, same access rights as far as I know. I'm getting the same result as before, ie, everything works OK until the application closes taking DOORS with it. Works perfectly on the first machine though - weird.

Two things that I know are differrent: -
1) Visual Studio 2008 on working machine, Visual Express C# on non working one
2) Windows XP on working system, Windows 7 on non working one.

Might have to return to my cack handed way of doing this or look at it through process monitor or something unpleasent, internet doesn't seem to help me on this issue.

Hmmm ... DOORS is started as a process from the Application ... I see two reasons for it to close with the application

1) The COM issue. When the DOORS COM reference is cleaned up, DOORS closes with it
2) The Process is "cleaned up". Since DOORS is started from the application it is the "parent" process, which will not let its "child process" live.

I would suggest to test the following:

What happens when you explicitly free the DOORSClass variable, before the program exits?
What happens when you explicitly free the Process variable, before the program exits?
What if you do both?

It DOORS closes when the process closes, you can try to launch it as a "daemon" (will live even if the parent lives, no idea how to do it :-). If DOORS closes when the COM reference is cleaned up - well I have no idea what to do in this case.

But its worth a try. Regards, Mathias


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

Re: Getting Requirements from Module with C#
pete.kowalski - Sun May 09 15:13:32 EDT 2010

Mathias Mamsch - Fri May 07 13:47:37 EDT 2010
Hmmm ... DOORS is started as a process from the Application ... I see two reasons for it to close with the application

1) The COM issue. When the DOORS COM reference is cleaned up, DOORS closes with it
2) The Process is "cleaned up". Since DOORS is started from the application it is the "parent" process, which will not let its "child process" live.

I would suggest to test the following:

What happens when you explicitly free the DOORSClass variable, before the program exits?
What happens when you explicitly free the Process variable, before the program exits?
What if you do both?

It DOORS closes when the process closes, you can try to launch it as a "daemon" (will live even if the parent lives, no idea how to do it :-). If DOORS closes when the COM reference is cleaned up - well I have no idea what to do in this case.

But its worth a try. Regards, Mathias


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

Mathias,

Is this something that DOORS provides?

DOORSCOMLib.DOORSClass

If so, what versions? I am unfamilar with this "library"? What does it provide?

Re: Getting Requirements from Module with C#
Mathias Mamsch - Sun May 09 16:27:05 EDT 2010

pete.kowalski - Sun May 09 15:13:32 EDT 2010
Mathias,

Is this something that DOORS provides?

DOORSCOMLib.DOORSClass

If so, what versions? I am unfamilar with this "library"? What does it provide?

This is just the "DOORS COM Type Library" ... It is a COM interface to DOORS - it gives you a possibility to execute DXL scripts in a DOORS client from a remote application. Has been there at least since DOORS 7.1 probably a lot earlier. You can take a look at the DXL help "Automation Support" for details. Regards, Mathias

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

Re: Getting Requirements from Module with C#
pete.kowalski - Sun May 09 17:54:02 EDT 2010

Mathias Mamsch - Sun May 09 16:27:05 EDT 2010
This is just the "DOORS COM Type Library" ... It is a COM interface to DOORS - it gives you a possibility to execute DXL scripts in a DOORS client from a remote application. Has been there at least since DOORS 7.1 probably a lot earlier. You can take a look at the DXL help "Automation Support" for details. Regards, Mathias


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

Thanks a lot. I will check this out. I am suprised I have never came across this. I have been using DOORS since 5.2.

Re: Getting Requirements from Module with C#
EA2412 - Tue Jun 22 06:32:06 EDT 2010

Hi all

thanks a lot for your posts, I´ve another question regarding the proc.StartInfo.Arguments = "-u Administrator"; command. How do I can send the password for the user?
Thanks in advance

Re: Getting Requirements from Module with C#
szczy7 - Tue Dec 21 14:31:30 EST 2010

Mathias Mamsch - Sun May 09 16:27:05 EDT 2010
This is just the "DOORS COM Type Library" ... It is a COM interface to DOORS - it gives you a possibility to execute DXL scripts in a DOORS client from a remote application. Has been there at least since DOORS 7.1 probably a lot earlier. You can take a look at the DXL help "Automation Support" for details. Regards, Mathias


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

Mathis,

What .dll file is used to make the COM interface? dxlapi.dll?
Thanks in advance.
Mike

Re: Getting Requirements from Module with C#
Mathias Mamsch - Tue Dec 28 09:52:00 EST 2010

szczy7 - Tue Dec 21 14:31:30 EST 2010
Mathis,

What .dll file is used to make the COM interface? dxlapi.dll?
Thanks in advance.
Mike

Nope, DXLApi.dll / DXLApi.lib is some useless C++ API, which enables you to write your own DXL interpreter, but without any perms for database access.

DOORS.exe is the COM server, it should be registered on installation as a COM server. I linked that one to the c# program (it is called DOORS Application or DOORS COM Library or something like this).

Regards, Mathias


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

Re: Getting Requirements from Module with C#
celalbaba - Tue Jul 05 10:07:57 EDT 2011

EA2412 - Tue Jun 22 06:32:06 EDT 2010
Hi all

thanks a lot for your posts, I´ve another question regarding the proc.StartInfo.Arguments = "-u Administrator"; command. How do I can send the password for the user?
Thanks in advance

it can be "-P password"

"-P" shall be in uppercase, also.

Re: Getting Requirements from Module with C#
DastanAli - Thu Jul 28 02:08:12 EDT 2016

Mathias Mamsch - Tue Apr 20 08:55:22 EDT 2010

Invoking DOORS over C# is easy. Startup a new C# console project, add a reference to the COM library "Telelogic DOORS Type Library". Then insert the following lines in your code:
 

DOORSCOMLib.DOORSClass x = new DOORSCOMLib.DOORSClass();
                x.runStr("print \"Hallo\"; oleSetResult \"Yes\"");
                        Console.Write("Result = " + x.result) ;

 


Start DOORS. Invoke your c# program, which should print "Hallo" in your currently open DOORS session and print "YES" in your c# console To get requirements data you would need to write a DXL script which gathers the data to a string, use the setOleResult function in dxl to pass the string to c# where you can get the result from the 'result' property of the DOORSClass item. Then you would have to parset the string to get the data you want.

Regards, Mathias

 

Hello Mathias,

Could you please provide sample code to get requirement data from Doors. Also any guidelines if I want to get requirements according to values of some attributes.

I connected to Doors using C# as mentioned in above answer, but I am not aware how to do further operations.

I want to get requirements from Doors using C#, any pointers(steps/guidelines) If I want to complete the task.

 

Thanks in advance

Dastan

Re: Getting Requirements from Module with C#
Mathias Mamsch - Thu Jul 28 18:05:26 EDT 2016

DastanAli - Thu Jul 28 02:08:12 EDT 2016

Hello Mathias,

Could you please provide sample code to get requirement data from Doors. Also any guidelines if I want to get requirements according to values of some attributes.

I connected to Doors using C# as mentioned in above answer, but I am not aware how to do further operations.

I want to get requirements from Doors using C#, any pointers(steps/guidelines) If I want to complete the task.

 

Thanks in advance

Dastan

Once you got connection to DOORS, you can run any DXL script you like. There are lots of examples on the DXL forum regarding exporting data from DOORS. For the DOORS Parallels tutorial I also posted a functional SQL export of the data inside a DOORS module (https://github.com/domoran/DXLParallels/tree/master/examples/SqlExport). You should have enough examples to get started. I would suggest, you pass the name of a file to the DXL script, have the DXL script export the data there. And after the execution of the DXL script read the data back from the file from c#. hope that helps, regards, Mathias

Re: Getting Requirements from Module with C#
DastanAli - Tue Aug 02 02:23:36 EDT 2016

Mathias Mamsch - Thu Jul 28 18:05:26 EDT 2016

Once you got connection to DOORS, you can run any DXL script you like. There are lots of examples on the DXL forum regarding exporting data from DOORS. For the DOORS Parallels tutorial I also posted a functional SQL export of the data inside a DOORS module (https://github.com/domoran/DXLParallels/tree/master/examples/SqlExport). You should have enough examples to get started. I would suggest, you pass the name of a file to the DXL script, have the DXL script export the data there. And after the execution of the DXL script read the data back from the file from c#. hope that helps, regards, Mathias

Hi Mathias,

Thank you for valuable information. I am able to read data from doors using below method

string res;
doors.runFile("F://Doors Material/DXL_Scripts/PrintAllRequirementsOfModule.dxl");
res = doors.result;

It works fine for simple C# console application, however I am developing web service using C# and I am using ASP.NET web site project.

I want to display data stored in 'res' variable as XML to user when user calls a web service. But for web service it is not displaying result as it displays in C# console project.

 

Re: Getting Requirements from Module with C#
Mathias Mamsch - Tue Aug 02 09:59:11 EDT 2016

DastanAli - Tue Aug 02 02:23:36 EDT 2016

Hi Mathias,

Thank you for valuable information. I am able to read data from doors using below method

string res;
doors.runFile("F://Doors Material/DXL_Scripts/PrintAllRequirementsOfModule.dxl");
res = doors.result;

It works fine for simple C# console application, however I am developing web service using C# and I am using ASP.NET web site project.

I want to display data stored in 'res' variable as XML to user when user calls a web service. But for web service it is not displaying result as it displays in C# console project.

 

Do not use doors.result for passing data back from DOORS. It is extremely inefficient. Instead do something like this: 

string res;

string resultFile = "F:\\doorsresults.txt";
doors.runStr("string sResult = \"" + resultFile + "\";\n#include <F://Doors Material/DXL_Scripts/PrintAllRequirementsOfModule.dxl>");

// from the DXL script write the result data to sResult and read it back from c#

Hope this helps, regards, Mathias

Re: Getting Requirements from Module with C#
DastanAli - Wed Aug 03 06:56:32 EDT 2016

Mathias Mamsch - Tue Aug 02 09:59:11 EDT 2016

Do not use doors.result for passing data back from DOORS. It is extremely inefficient. Instead do something like this: 

string res;

string resultFile = "F:\\doorsresults.txt";
doors.runStr("string sResult = \"" + resultFile + "\";\n#include <F://Doors Material/DXL_Scripts/PrintAllRequirementsOfModule.dxl>");

// from the DXL script write the result data to sResult and read it back from c#

Hope this helps, regards, Mathias

Hi Mathias,
I am getting error  'Access denied: DOORS session is not authenticated' when I try to connect to doors via web service.
It works fine when I connect to doors via C# WCF Service project(not via web service).
I referred https://www.ibm.com/developerworks/community/forums/html/topic?id=77777777-0000-0000-0000-000014879461 link.
In the link you mentioned two ways to connect to doors. I am not using batch mode to connect to doors.
if (Process.GetProcessesByName("doors").Length == 0) {
   System.Diagnostics.Process proc = new System.Diagnostics.Process();
   proc.StartInfo.FileName= "S:\\Programme\\Telelogic\\DOORS_8.2\\bin\\doors.exe";
   proc.StartInfo.Arguments = "-u Administrator -P ST1PL2";
   proc.StartInfo.UseShellExecute = false; 
   proc.Start();                        
                        
   // Wait for GUI to fire up ...
   proc.WaitForInputIdle();                     
}
                        
DOORSCOMLib.DOORSClass d = new DOORSCOMLib.DOORSClass();                                                
d.runStr("print \"Hallo\"");
// TODO: Implement Functionality Here
                        
Console.Write("Check your DOORS output . . . ");
Console.ReadKey(true);

for this code snippet, it opens doors and waits until user log in and then proceed further, however in my case user is already logged into doors.
I am directly using 'doors' object as 
 IDoorsDXL doors = Activator.CreateInstance(typeof(DOORSCOMLib.DOORSClass)) as IDoorsDXL;
and running dxl scripts to fetch data.
However it gives me error as  'Access denied: DOORS session is not authenticated', when I call it via web service.

Re: Getting Requirements from Module with C#
Mathias Mamsch - Wed Aug 03 07:09:25 EDT 2016

DastanAli - Wed Aug 03 06:56:32 EDT 2016

Hi Mathias,
I am getting error  'Access denied: DOORS session is not authenticated' when I try to connect to doors via web service.
It works fine when I connect to doors via C# WCF Service project(not via web service).
I referred https://www.ibm.com/developerworks/community/forums/html/topic?id=77777777-0000-0000-0000-000014879461 link.
In the link you mentioned two ways to connect to doors. I am not using batch mode to connect to doors.
if (Process.GetProcessesByName("doors").Length == 0) {
   System.Diagnostics.Process proc = new System.Diagnostics.Process();
   proc.StartInfo.FileName= "S:\\Programme\\Telelogic\\DOORS_8.2\\bin\\doors.exe";
   proc.StartInfo.Arguments = "-u Administrator -P ST1PL2";
   proc.StartInfo.UseShellExecute = false; 
   proc.Start();                        
                        
   // Wait for GUI to fire up ...
   proc.WaitForInputIdle();                     
}
                        
DOORSCOMLib.DOORSClass d = new DOORSCOMLib.DOORSClass();                                                
d.runStr("print \"Hallo\"");
// TODO: Implement Functionality Here
                        
Console.Write("Check your DOORS output . . . ");
Console.ReadKey(true);

for this code snippet, it opens doors and waits until user log in and then proceed further, however in my case user is already logged into doors.
I am directly using 'doors' object as 
 IDoorsDXL doors = Activator.CreateInstance(typeof(DOORSCOMLib.DOORSClass)) as IDoorsDXL;
and running dxl scripts to fetch data.
However it gives me error as  'Access denied: DOORS session is not authenticated', when I call it via web service.

I have no idea, what you are talking about, when you say "webservice". Are you talking about an HTTP Server running your c# code, trying to access DOORS over COM? Regards, Mathias

Re: Getting Requirements from Module with C#
DastanAli - Wed Aug 03 07:15:47 EDT 2016

Mathias Mamsch - Wed Aug 03 07:09:25 EDT 2016

I have no idea, what you are talking about, when you say "webservice". Are you talking about an HTTP Server running your c# code, trying to access DOORS over COM? Regards, Mathias

I developed a web service using C# WCF Service project template and deployed it on IIS 7.5. Everything is done on my personal system running on Windows 7 Professional.

 

Re: Getting Requirements from Module with C#
Mathias Mamsch - Wed Aug 03 07:22:30 EDT 2016

DastanAli - Wed Aug 03 07:15:47 EDT 2016

I developed a web service using C# WCF Service project template and deployed it on IIS 7.5. Everything is done on my personal system running on Windows 7 Professional.

 

The IIS Server runs as a service on your server machine. This service usually uses the System user, not your local user. Therefore you cannot access any open DOORS Session from a web service. If you want to implement a web service running DOORS jobs, then you need to resort to using DOORS batch cmdline jobs. Do not use COM from a webservice. Regards, Mathias

Re: Getting Requirements from Module with C#
DastanAli - Wed Aug 03 07:55:59 EDT 2016

Mathias Mamsch - Wed Aug 03 07:22:30 EDT 2016

The IIS Server runs as a service on your server machine. This service usually uses the System user, not your local user. Therefore you cannot access any open DOORS Session from a web service. If you want to implement a web service running DOORS jobs, then you need to resort to using DOORS batch cmdline jobs. Do not use COM from a webservice. Regards, Mathias

If this is the case, I will have to change my approach and start all over again.

Just for confirmation please tell me,

Is there any way we can do it using COM or Doors batch cmdline is only possible approach to do the task

 

 

Re: Getting Requirements from Module with C#
Mathias Mamsch - Wed Aug 03 08:05:00 EDT 2016

DastanAli - Wed Aug 03 07:55:59 EDT 2016

If this is the case, I will have to change my approach and start all over again.

Just for confirmation please tell me,

Is there any way we can do it using COM or Doors batch cmdline is only possible approach to do the task

 

 

Well first of all you need to get your architecture straight. Accessing a running DOORS process from a web service seems weird. There are ways to do so, which would involve process communication between the webservice and the DOORS client. But on a server you cannot ensure that there is always a running DOORS process, sessions will be killed after some time and such.  I would suggest you open a new post, describe the use case you want to solve and people can give you hints about a suitable architecture. 

If you simply want to execute DOORS commands from a web service you definitely should use batch and you should definitely use Files for reading input to the executed DXL and write output from the executed DXL. Note that you should also expect problems if you execute DOORS batch from a service (web server). Since a service does not have a running session (=logged in user) there a couple of things in DOORS, that will not work properly, e.g. the OLE functionality. So depending on your use case, you need to take that into account. 

Regards, Mathias

Re: Getting Requirements from Module with C#
Angad_Bangare - Wed Oct 11 04:46:49 EDT 2017

Mathias Mamsch - Mon May 03 16:30:48 EDT 2010

Hey Richard,

how could DOORS not register to the ROT? The ROT is part of windows, so every COM object running should be in there. I tested it using the code from here http://dotnet-snippets.de/dns/laufende-com-objekte-abfragen-SID526.aspx ... I can get the DOORS COM object from the ROT using (GUID = "DOORS.Application"):
 

Object y = RunningObjectTable.GetRunningCOMObjectByName("5B833C90-FC9E-11CE-9EFC-524153480001");

 


I am not so sure how GetObject really translates into C# ... What I read from the Internet is that it is at least problematic ... That brings me to the question:

Why bother? Using the "New ()" Syntax and a static linked DOORS COM library you will get the same result as "GetObject" since DOORS is an out of process server, which will spawn only one instance anyway. So you can just start DOORS over the shell, login over the commandline and then use "new (...)" to get a new reference to the COM server. Then you can run any DXL without DOORS quitting. When you want to quit the DOORS instance just execute "quit_()" over DXL and the client will shut down.

The only question that is left, when using new() is, that you need to determine if DOORS is already running. You can use the ROT for that or just the management instrumentation interface.

I would not bother about wrapping the DOORS COM object into an RCW. But I am not a C# expert, so there might be other people who can help you there.

Hope this help, regards, Mathias

 

 

 


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

 

 

How to pass Module Name through C# in dxl script?