hexagon logo

PC-Dmis Automation C#

So I retired as of last July, but had all this stuff about PC-Dmis Automation which I've finally got around to uploading. Don't know it it is of any interest, but here it is.

The zip file has to Visual Studio project folders, both written in C#. One folder is a Class Library which has all the code for connecting with and dynamically interacting with PC-Dmis. The second folder is a C# application with uses the Class Library to connect and interact with PC-Dmis.

I also included two documents one explains how to setup the two Projects the other is about the application program.

Rather than trying to anticipate every possible question, the provided documents should be sufficient for someone familiar with visual studio and C#. Otherwise, I'll watch for questions to show up here. I can't promise to answer every question, given the complexity of what the answer might require. But I have taken phone calls and zoom opens up the possibility to demo live.

Good Luck

https://drive.google.com/drive/folders/1EDMe0GvN6TC_0Fcr_7Zt7_UqH-EV_8o2?usp=sharing
Parents
  • Being retired with a little time on my hands at the moment, I thought I would add here a little tutorial on the PC-Dmis library I made available on Google Drive (see my initial comment that started this thread).

    The Google drive has a zip file containing two C# project folders. Folder 'PcdmisLib' is the C# project which is a library of C# objects which enable the connection to PC-Dmis by your C# application. The second folder 'DmisMenu' is an example of a user C# application which uses the library. If you're new to Visual Studio and C# Setting up project folders and a Library and connecting it to your C# application can seem to be complicated, if you are having trouble with this PM me and we can set up a zoom where I can demo live the process. Plan on the demo taking about an hour.

    In this tutorial, I'm just going to walk through how to start PC-Dmis in it's own thread space and enable communication to and from the running PC-Dmis

    Here we go...

    In the application 'DmisMenu' there is a C# sourcefile called PcdmisMain.cs which is actually an extention of the application 'Mainform' class. C# allows the source code for a class to be broken up between multiple files. I purposely created the 'PcdmisMain' file to separate methods related to PC-Dmis from the rest of 'Mainform' class code. You can consider all the code in 'PcdmisMain' to be a part of the 'Mainform' class.

    On startup of the 'DmisMenu' application the 'Mainform' constructor is executed (see the Mainform method in file Mainform.cs).

            public Mainform()
            {
                InitializeComponent();
    
                // Turn off the menu strip till PC-Dmis has started.
                DmisMenuStrip.Enabled = false;
    
                HomeDir = Application.StartupPath;
                xmlFile = HomeDir + @"\DmisMenuData.xml";
    
                // Display the Main Form Title
                this.Text = "Project Action Mananger  Version " + Settings.Default.Version;
    
                // Start Pcdmis
                InitializePcdmis();
    
                // DataSet
                ReadData();
                UpDateProgramList();
                UpdateToolMenu();
            }
    


    The connection with PC-Dmis begins with the call to 'InitializePcdmis()' method, which is found in the PcdmisMain.cs source file. This method connecting to PC-Dmis is done in two parts. First, an instance of the 'PcdmisHelper' class which is in the PcdmisLib library is created. This class will be the object by which all interactions between your C# application and PC-Dmis will take place. This class is sometimes called a 'wrapper' class as it is made to wrap around PC-Dmis and hide the details of communicating with PC-Dmis from your C# application. From the point of view of your C# application the class PcdmisHelper is the running copy of PC-Dmis. Second, after we have an instance of 'PcdmisHelper' class we use this instance to connect to PC-Dmis

    The following two blocks of code from the InitializePcdmis method in the PcdmisMain source file shows how your C# application creates an instance of the PcdmisHelper class, then connects to PC-Dmis.

     1            string PcdmisVersion = Settings.Default.PcdmisVersion;
     2            try
     3            {
     4                CMMsession = new PcdmisHelper(ExternalToInternalVersion(PcdmisVersion));
     5            }
     6            catch (Exception e)
     7            {
     8                String message = e.Message;
     9                MessageBox.Show("Incorrect Version of PCDMIS or PCDMIS not found.",
    10                    "PCDMIS not Found", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    11                return;
    12            }
    


    Line 1: The version of PC-Dmis used by this application is set in the application configuration file. If you happen to have multiple versions of PC-Dmis installed on your PC, the PcdmisHelper class will ensure the connection the connection to correct version of PC-Dmis.

    Line 4: Create an instance of the class PcdmisHelper. As CMMsession is defined as a global variable, in may used anywhere in the Mainform method of your application to interact with the live PC-Dmis session. The ExternalToInternalVersion method is needed because for some reason the version used by external Hexagon documentation is not the same as the version used in the registery when PC-Dmis is installed. To activate PC-Dmis by version number it must be by using internal version number used by the registery. A call to the ExternalToInternalVersion method fixes this and passes to PcdmisHelper the correct version number.

    Now that we have an instance of the PcdmisHelper class, we can now start PC-Dmis and make a connection to the PC-Dmis session. Later in the InitializePcdmis method we use CMMsession to start this process.

     1            try // to startup and connect with PC-Dmis
     2            {
     3                CMMsession.ConnectPCDLRN();
     4            }
     5            catch (NoRegistryException e)
     6            {
     7                String message = e.Message;
     8                MessageBox.Show(message, "Connection Error - Check Help->PCDLRN Info",
     9                MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    10                return;
    11            }
    


    Line 3: A call is made to the ConnectPCDLRN method in the PcdmisHelper class. (remember CMMsession is an instance of the PcdmisHelp class).

    Lines 5-11: There are a number of reason for which the startup and connection to PC-Dmis may fail. PcdmisHelper helper tries to capture and document the various errors encountered in a text variable the contents of which the C# application, in this case DmisMenu, can display.

    We now move to the PcdmisHelper.cs source file in the Library to follow the process of starting and connecting to PC-Dmis.

     1        /// <summary>
     2        /// This method starts the PCDMIS/PCDLRN CMM session in the background and
     3        /// establishes a connection with the running PCDLRN session. The session is
     4        /// running on a thread separate from the user DotNet application.
     5        /// </summary>
     6        public void ConnectPCDLRN()
     7        {
     8            if (!IsSessionActive)
     9            {
    10                Func<Boolean> method = Connect;
    11                method.BeginInvoke(ConnectionDone, method);
    12            }
    13            else
    14            {
    15                .
    16                . Code removed for brevity.
    17                .
    18            }
    19        }
    


    Line 8: A global boolean variable is used to track whether or not we have already started PC-Dmis.

    Line 10: Define a function variable that points to method called 'Connect' that returns a boolean value (we'll look at method 'Connect' next).

    Line 11: Use the system method to invoke a new thread, execute the 'method' function (which points to the method 'Connect'), then execute the method ConnectionDone. By using the BeginInvoke method our application doesn't 'lockup' when PC-Dmis is busy doing something. Both the C# application and PC-Dmis are running in their own thread and appear to be active and running at the same time.

    After the new thread is created by the system method, the 'Connect' method is executed as follows.

     1        /* execute this method to make connection to the PCDLRN. */
     2        private Boolean Connect()
     3        {
     4            Type comType;
     5            Object comObj;
    
     6            try
     7            {
     8                pcdSession = null;
     9                // Make sure the PCDLRN process is not already running.
    10                Process[] PCDLRN_List = Process.GetProcessesByName("PCDLRN");
    11                foreach (Process exe in PCDLRN_List)
    12                {
    13                    exe.Kill();
    14                }
    
    15                //PCDMIS_CLSID = getCLSID_RegisterValue();
    16                comType = Type.GetTypeFromCLSID(Guid.Parse(PCDMIS_CLSID), true);
    17                comObj = Activator.CreateInstance(comType);
    18                pcdSession = comObj as PCDLRN.Application;
    19                return IsSessionActive;
    20            }
    21            catch (Exception e)
    22            {
    23                ExceptionMessages = ExceptionMessages + "Problems starting PCDLRN CLSID " +
    24                PCDMIS_CLSID + "\n" + e.Message;
    25            }
    26            return false;
    27        }
    


    Lines 9-14: Make sure any existing running PC-Dmis processes are killed.

    Lines 16-18: This is the proper way of launching a windows program using the registry.

    Line 16: From the registry we get the 'comType' for a perticular version of PC-Dmis from the registry.

    Line 17: This the line that actually causes PC-Dmis to startup, when this happens the operator will see PC-Dmis screen momentarily appear on the monitor then disappear into the background. The Activator method returns the activated PC-Dmis session as an 'object'.

    Line 18: To use the 'object' return in Line 17, we need to recast the object as a PCDLRN.Application object. From here on the PcdmisHelper class can use pcdSession as a live PC-Dmis session.

    Recap

    After the above executed code, we have a C# application with the global variable 'CMMsession' which represents an instance of the wrapper class PcdmisHelper. The application will use this wrapper for all interactions with a live session of PC-Dmis. Within the wrapper we have the global variable 'pcdSession' which represents the PC-Dmis class PCDLRN.Application. The wrapper class will use this variable for all direct interactions with the live session of PC-Dmis.
Reply
  • Being retired with a little time on my hands at the moment, I thought I would add here a little tutorial on the PC-Dmis library I made available on Google Drive (see my initial comment that started this thread).

    The Google drive has a zip file containing two C# project folders. Folder 'PcdmisLib' is the C# project which is a library of C# objects which enable the connection to PC-Dmis by your C# application. The second folder 'DmisMenu' is an example of a user C# application which uses the library. If you're new to Visual Studio and C# Setting up project folders and a Library and connecting it to your C# application can seem to be complicated, if you are having trouble with this PM me and we can set up a zoom where I can demo live the process. Plan on the demo taking about an hour.

    In this tutorial, I'm just going to walk through how to start PC-Dmis in it's own thread space and enable communication to and from the running PC-Dmis

    Here we go...

    In the application 'DmisMenu' there is a C# sourcefile called PcdmisMain.cs which is actually an extention of the application 'Mainform' class. C# allows the source code for a class to be broken up between multiple files. I purposely created the 'PcdmisMain' file to separate methods related to PC-Dmis from the rest of 'Mainform' class code. You can consider all the code in 'PcdmisMain' to be a part of the 'Mainform' class.

    On startup of the 'DmisMenu' application the 'Mainform' constructor is executed (see the Mainform method in file Mainform.cs).

            public Mainform()
            {
                InitializeComponent();
    
                // Turn off the menu strip till PC-Dmis has started.
                DmisMenuStrip.Enabled = false;
    
                HomeDir = Application.StartupPath;
                xmlFile = HomeDir + @"\DmisMenuData.xml";
    
                // Display the Main Form Title
                this.Text = "Project Action Mananger  Version " + Settings.Default.Version;
    
                // Start Pcdmis
                InitializePcdmis();
    
                // DataSet
                ReadData();
                UpDateProgramList();
                UpdateToolMenu();
            }
    


    The connection with PC-Dmis begins with the call to 'InitializePcdmis()' method, which is found in the PcdmisMain.cs source file. This method connecting to PC-Dmis is done in two parts. First, an instance of the 'PcdmisHelper' class which is in the PcdmisLib library is created. This class will be the object by which all interactions between your C# application and PC-Dmis will take place. This class is sometimes called a 'wrapper' class as it is made to wrap around PC-Dmis and hide the details of communicating with PC-Dmis from your C# application. From the point of view of your C# application the class PcdmisHelper is the running copy of PC-Dmis. Second, after we have an instance of 'PcdmisHelper' class we use this instance to connect to PC-Dmis

    The following two blocks of code from the InitializePcdmis method in the PcdmisMain source file shows how your C# application creates an instance of the PcdmisHelper class, then connects to PC-Dmis.

     1            string PcdmisVersion = Settings.Default.PcdmisVersion;
     2            try
     3            {
     4                CMMsession = new PcdmisHelper(ExternalToInternalVersion(PcdmisVersion));
     5            }
     6            catch (Exception e)
     7            {
     8                String message = e.Message;
     9                MessageBox.Show("Incorrect Version of PCDMIS or PCDMIS not found.",
    10                    "PCDMIS not Found", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    11                return;
    12            }
    


    Line 1: The version of PC-Dmis used by this application is set in the application configuration file. If you happen to have multiple versions of PC-Dmis installed on your PC, the PcdmisHelper class will ensure the connection the connection to correct version of PC-Dmis.

    Line 4: Create an instance of the class PcdmisHelper. As CMMsession is defined as a global variable, in may used anywhere in the Mainform method of your application to interact with the live PC-Dmis session. The ExternalToInternalVersion method is needed because for some reason the version used by external Hexagon documentation is not the same as the version used in the registery when PC-Dmis is installed. To activate PC-Dmis by version number it must be by using internal version number used by the registery. A call to the ExternalToInternalVersion method fixes this and passes to PcdmisHelper the correct version number.

    Now that we have an instance of the PcdmisHelper class, we can now start PC-Dmis and make a connection to the PC-Dmis session. Later in the InitializePcdmis method we use CMMsession to start this process.

     1            try // to startup and connect with PC-Dmis
     2            {
     3                CMMsession.ConnectPCDLRN();
     4            }
     5            catch (NoRegistryException e)
     6            {
     7                String message = e.Message;
     8                MessageBox.Show(message, "Connection Error - Check Help->PCDLRN Info",
     9                MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    10                return;
    11            }
    


    Line 3: A call is made to the ConnectPCDLRN method in the PcdmisHelper class. (remember CMMsession is an instance of the PcdmisHelp class).

    Lines 5-11: There are a number of reason for which the startup and connection to PC-Dmis may fail. PcdmisHelper helper tries to capture and document the various errors encountered in a text variable the contents of which the C# application, in this case DmisMenu, can display.

    We now move to the PcdmisHelper.cs source file in the Library to follow the process of starting and connecting to PC-Dmis.

     1        /// <summary>
     2        /// This method starts the PCDMIS/PCDLRN CMM session in the background and
     3        /// establishes a connection with the running PCDLRN session. The session is
     4        /// running on a thread separate from the user DotNet application.
     5        /// </summary>
     6        public void ConnectPCDLRN()
     7        {
     8            if (!IsSessionActive)
     9            {
    10                Func<Boolean> method = Connect;
    11                method.BeginInvoke(ConnectionDone, method);
    12            }
    13            else
    14            {
    15                .
    16                . Code removed for brevity.
    17                .
    18            }
    19        }
    


    Line 8: A global boolean variable is used to track whether or not we have already started PC-Dmis.

    Line 10: Define a function variable that points to method called 'Connect' that returns a boolean value (we'll look at method 'Connect' next).

    Line 11: Use the system method to invoke a new thread, execute the 'method' function (which points to the method 'Connect'), then execute the method ConnectionDone. By using the BeginInvoke method our application doesn't 'lockup' when PC-Dmis is busy doing something. Both the C# application and PC-Dmis are running in their own thread and appear to be active and running at the same time.

    After the new thread is created by the system method, the 'Connect' method is executed as follows.

     1        /* execute this method to make connection to the PCDLRN. */
     2        private Boolean Connect()
     3        {
     4            Type comType;
     5            Object comObj;
    
     6            try
     7            {
     8                pcdSession = null;
     9                // Make sure the PCDLRN process is not already running.
    10                Process[] PCDLRN_List = Process.GetProcessesByName("PCDLRN");
    11                foreach (Process exe in PCDLRN_List)
    12                {
    13                    exe.Kill();
    14                }
    
    15                //PCDMIS_CLSID = getCLSID_RegisterValue();
    16                comType = Type.GetTypeFromCLSID(Guid.Parse(PCDMIS_CLSID), true);
    17                comObj = Activator.CreateInstance(comType);
    18                pcdSession = comObj as PCDLRN.Application;
    19                return IsSessionActive;
    20            }
    21            catch (Exception e)
    22            {
    23                ExceptionMessages = ExceptionMessages + "Problems starting PCDLRN CLSID " +
    24                PCDMIS_CLSID + "\n" + e.Message;
    25            }
    26            return false;
    27        }
    


    Lines 9-14: Make sure any existing running PC-Dmis processes are killed.

    Lines 16-18: This is the proper way of launching a windows program using the registry.

    Line 16: From the registry we get the 'comType' for a perticular version of PC-Dmis from the registry.

    Line 17: This the line that actually causes PC-Dmis to startup, when this happens the operator will see PC-Dmis screen momentarily appear on the monitor then disappear into the background. The Activator method returns the activated PC-Dmis session as an 'object'.

    Line 18: To use the 'object' return in Line 17, we need to recast the object as a PCDLRN.Application object. From here on the PcdmisHelper class can use pcdSession as a live PC-Dmis session.

    Recap

    After the above executed code, we have a C# application with the global variable 'CMMsession' which represents an instance of the wrapper class PcdmisHelper. The application will use this wrapper for all interactions with a live session of PC-Dmis. Within the wrapper we have the global variable 'pcdSession' which represents the PC-Dmis class PCDLRN.Application. The wrapper class will use this variable for all direct interactions with the live session of PC-Dmis.
Children
No Data