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
  • In the 'Solution Explorer', right-click on 'Form1.cs' and select 'View Code'.

    The code listing below is all the code needed in 'Form1.cs', for a bare bones connection to PC-Dmis using C#. It's a simple application with a button to connect to PC-Dmis, a textbox that changes from red to green when PC-Dmis is connected. A second button, which is disabled until PC-Dmis is connected, is used to display and hide the PC-Dmis window via the PCDLRN.Application object 'Visible' property. It is provided as a way of demonstrating that both the C# application and PC-Dmis are connected and both running at the same time. It is liberally commented throughout the code.

    Two important notes on working with C# and PC-Dmis via Visual Studio.
    1. After clicking on the Connect PC-Dmis button wait at least a minute or two depending on the speed of your PC. The PC-Dmis window should appear for a moment then disappear into the background. After the status textbox turns green, clicking on the 'View PC-Dmis' button will confirm that PC-Dmis is still active.
    2. You need to be aware that under certain circumstances, when quiting out of the C# program you can leave PC-Dmis still running in the background. Get in the habit of doing a <Ctrl><Alt><Del> to activate the Task Manager to check that a PC-Dmis process is not already running, if so, kill it before running the C# application.

    Form1.cs source Code
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace BareBonesPCdmis
    {
        public partial class Form1 : Form
        {
            //Global variable are declared here
            PCDLRN.Application pcdSession = null; // pcdSession will become the PC-Dmis Application session.
    
            /// <summary>
            /// Define a delegate that points to a method which has as input, a boolean value.
            /// </summary>
            /// <param name="results">Indicates the true or false status of the connection to PCDLRN.
            /// A delegate is similar to a function pointer in C++. Delegates encapsulate both an object
            /// and a method.
            public delegate void ConnectionDelegate(Boolean results);
    
    
            public Form1()
            {
                InitializeComponent();
    
                // Update Pcdmis connection status
                UpdatePcdmisStatus();
            }
    
            /// <summary>
            /// This method handles the click event for the top button.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnConnect_Click(object sender, EventArgs e)
            {
                // Disable the PC-Dmis connect button to prevent multiple clicks
                // while PC-Dmis is trying to start.
                btnConnect.Enabled = false;
    
                if (pcdSession is null)
                {
                    Func<Boolean> method = Connect; // Assign the Connect method to a function delegate called 'method'.
                    method.BeginInvoke(ConnectionDone, method); // Launch PC-Dmis in another thread.
                }
    
                // This method is finished immediately after the above Invoke statement. It does
                // not wait around for PC-Dmis to start. While PC-Dmis is starting up, every part
                // of this application and UI are still active and not 'locked' up.
            }
    
            /// <summary>
            /// This method is executed in a new thread created in the btnConnect_Click method.
            /// It performs the work of starting PC-Dmis.
            /// </summary>
            /// <returns>A connection status of true or false.</returns>
            private Boolean Connect()
            {
                try
                {
                    Type pcdmisType = Type.GetTypeFromProgID("PCDLRN.Application");
                    pcdSession = Activator.CreateInstance(pcdmisType) as PCDLRN.Application;
                    return true;
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message, "Problems starting PC-Dmis", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                return false;
            }
    
            /// <summary>
            /// After PC-Dmis has started, this method is executed in the same thread that started PC-Dmis.
            /// This method exists to provide a convenient way of notifying the user and enabling various
            /// parts of the UI. There may be UI components that you may want disabled till PC-Dmis is
            /// up and running.
            /// </summary>
            /// <param name="cookie"></param>
            private void ConnectionDone(IAsyncResult cookie)
            {
                var target = (Func<Boolean>[emoticon:4191F5EE34E248A29FA0DBE8D975F74A]cookie.AsyncState;
                Boolean connectionResult = target.EndInvoke(cookie);
    
                if (connectionResult) // if connect() returns true
                {
                    // If you want to see what a cross-threading error looks like, uncomment the following line.
                    //UpdatePcdmisStatus();
    
                    // This method is still a part of the new thread PC-Dmis was started in. The user interface
                    // is executing in a different thread, thus, accessing the UI component from here, even
                    // indirectly by calling a method (UpdatePcdmisStatus) is forbidden.
    
                    // However, you can set local variables, or call methods which do not access UI objects.
    
                    // While still in the PC-Dmis thread We need a way to create an action that will
                    // execute in the application thread to update the application UI.
                    // We can get around the cross-threading issue by using a delegate.
    
                    // The next line creates an instance object (cb) of the ConnectionDelegate defined at
                    // the top of this code. It's basically a pointer to the PCdmis_Connected method.
                    ConnectionDelegate cb = new ConnectionDelegate(PCdmis_Connected);
    
                    // In the following statement, 'this' is a reference to this form. Here we invoke the
                    // form thread (which is the same thread that the UI is running) to execute the method
                    // the delegate object (cb) points to, thus avoiding cross-threading issues.
                    // The second parameter in the Invoke statement below is an anonymous object, or
                    // an object without a name. The boolean value, connectionResult, becomes a property of
                    // this new object. This anonymous object will become the required input parameter of
                    // the method the delegate object points to.
                    this.Invoke(cb, new object[] { connectionResult });
                }
            }
    
            /// <summary>
            /// This method calls a method to update the UI.
            /// </summary>
            /// <param name="IsConnected"></param>
            private void PCdmis_Connected(bool IsConnected)
            {
                btnViewPcdmis.Enabled = IsConnected; // Enable this button if PC-Dmis is connected
    
                UpdatePcdmisStatus();
            }
    
            /// <summary>
            /// A method to manage the use of a textbox to display the connection status of
            /// PC-Dmis.
            /// </summary>
            private void UpdatePcdmisStatus()
            {
                if (PcdmisIsConnected)
                {
                    txbStatus.BackColor = Color.Green; // set the status textbox to green
                    btnConnect.Enabled = false;        // disable button to prevent 2nd connection.
                }
                else
                {
                    txbStatus.BackColor = Color.Red;
                    btnConnect.Enabled = true;
                }
            }
    
            /// <summary>
            /// Method to return true or false according to the state of pcdSession variable.
            /// </summary>
            private Boolean PcdmisIsConnected
            {
                get
                {
                    if (pcdSession is null)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
            }
    
            /// <summary>
            /// This method is a listener to the 'View Pcdmis' button click event. When this button
            /// is clicked this method flips between displaying and hiding the PC-Dmis window.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnViewPcdmis_Click(object sender, EventArgs e)
            {
                // Always confirm you have a connected session first
                if (!PcdmisIsConnected) return;
    
                if (pcdSession.Visible)
                {
                    // make it invisible)
                    pcdSession.Visible = false;
                    btnViewPcdmis.Text = "View PC-Dmis Window";
                }
                else
                {
                    // make it visible
                    pcdSession.Visible = true;
                    btnViewPcdmis.Text = "Unview PC-Dmis Window";
                }
            }
    
            /// <summary>
            /// Listener method for the form closing event. Handles the proper closing of the PC-Dmis
            /// session. Without this method PC-Dmis will continue living in the background after this
            /// application is closed and exited.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                // Close the PCDLRN runtime service when this application is shutdown.
                if (pcdSession != null)
                {
                    pcdSession.UserExit = true;
                    pcdSession.Quit();
                    pcdSession = null;
                }
            }
        }
    }
    

Reply
  • In the 'Solution Explorer', right-click on 'Form1.cs' and select 'View Code'.

    The code listing below is all the code needed in 'Form1.cs', for a bare bones connection to PC-Dmis using C#. It's a simple application with a button to connect to PC-Dmis, a textbox that changes from red to green when PC-Dmis is connected. A second button, which is disabled until PC-Dmis is connected, is used to display and hide the PC-Dmis window via the PCDLRN.Application object 'Visible' property. It is provided as a way of demonstrating that both the C# application and PC-Dmis are connected and both running at the same time. It is liberally commented throughout the code.

    Two important notes on working with C# and PC-Dmis via Visual Studio.
    1. After clicking on the Connect PC-Dmis button wait at least a minute or two depending on the speed of your PC. The PC-Dmis window should appear for a moment then disappear into the background. After the status textbox turns green, clicking on the 'View PC-Dmis' button will confirm that PC-Dmis is still active.
    2. You need to be aware that under certain circumstances, when quiting out of the C# program you can leave PC-Dmis still running in the background. Get in the habit of doing a <Ctrl><Alt><Del> to activate the Task Manager to check that a PC-Dmis process is not already running, if so, kill it before running the C# application.

    Form1.cs source Code
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace BareBonesPCdmis
    {
        public partial class Form1 : Form
        {
            //Global variable are declared here
            PCDLRN.Application pcdSession = null; // pcdSession will become the PC-Dmis Application session.
    
            /// <summary>
            /// Define a delegate that points to a method which has as input, a boolean value.
            /// </summary>
            /// <param name="results">Indicates the true or false status of the connection to PCDLRN.
            /// A delegate is similar to a function pointer in C++. Delegates encapsulate both an object
            /// and a method.
            public delegate void ConnectionDelegate(Boolean results);
    
    
            public Form1()
            {
                InitializeComponent();
    
                // Update Pcdmis connection status
                UpdatePcdmisStatus();
            }
    
            /// <summary>
            /// This method handles the click event for the top button.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnConnect_Click(object sender, EventArgs e)
            {
                // Disable the PC-Dmis connect button to prevent multiple clicks
                // while PC-Dmis is trying to start.
                btnConnect.Enabled = false;
    
                if (pcdSession is null)
                {
                    Func<Boolean> method = Connect; // Assign the Connect method to a function delegate called 'method'.
                    method.BeginInvoke(ConnectionDone, method); // Launch PC-Dmis in another thread.
                }
    
                // This method is finished immediately after the above Invoke statement. It does
                // not wait around for PC-Dmis to start. While PC-Dmis is starting up, every part
                // of this application and UI are still active and not 'locked' up.
            }
    
            /// <summary>
            /// This method is executed in a new thread created in the btnConnect_Click method.
            /// It performs the work of starting PC-Dmis.
            /// </summary>
            /// <returns>A connection status of true or false.</returns>
            private Boolean Connect()
            {
                try
                {
                    Type pcdmisType = Type.GetTypeFromProgID("PCDLRN.Application");
                    pcdSession = Activator.CreateInstance(pcdmisType) as PCDLRN.Application;
                    return true;
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message, "Problems starting PC-Dmis", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                return false;
            }
    
            /// <summary>
            /// After PC-Dmis has started, this method is executed in the same thread that started PC-Dmis.
            /// This method exists to provide a convenient way of notifying the user and enabling various
            /// parts of the UI. There may be UI components that you may want disabled till PC-Dmis is
            /// up and running.
            /// </summary>
            /// <param name="cookie"></param>
            private void ConnectionDone(IAsyncResult cookie)
            {
                var target = (Func<Boolean>[emoticon:4191F5EE34E248A29FA0DBE8D975F74A]cookie.AsyncState;
                Boolean connectionResult = target.EndInvoke(cookie);
    
                if (connectionResult) // if connect() returns true
                {
                    // If you want to see what a cross-threading error looks like, uncomment the following line.
                    //UpdatePcdmisStatus();
    
                    // This method is still a part of the new thread PC-Dmis was started in. The user interface
                    // is executing in a different thread, thus, accessing the UI component from here, even
                    // indirectly by calling a method (UpdatePcdmisStatus) is forbidden.
    
                    // However, you can set local variables, or call methods which do not access UI objects.
    
                    // While still in the PC-Dmis thread We need a way to create an action that will
                    // execute in the application thread to update the application UI.
                    // We can get around the cross-threading issue by using a delegate.
    
                    // The next line creates an instance object (cb) of the ConnectionDelegate defined at
                    // the top of this code. It's basically a pointer to the PCdmis_Connected method.
                    ConnectionDelegate cb = new ConnectionDelegate(PCdmis_Connected);
    
                    // In the following statement, 'this' is a reference to this form. Here we invoke the
                    // form thread (which is the same thread that the UI is running) to execute the method
                    // the delegate object (cb) points to, thus avoiding cross-threading issues.
                    // The second parameter in the Invoke statement below is an anonymous object, or
                    // an object without a name. The boolean value, connectionResult, becomes a property of
                    // this new object. This anonymous object will become the required input parameter of
                    // the method the delegate object points to.
                    this.Invoke(cb, new object[] { connectionResult });
                }
            }
    
            /// <summary>
            /// This method calls a method to update the UI.
            /// </summary>
            /// <param name="IsConnected"></param>
            private void PCdmis_Connected(bool IsConnected)
            {
                btnViewPcdmis.Enabled = IsConnected; // Enable this button if PC-Dmis is connected
    
                UpdatePcdmisStatus();
            }
    
            /// <summary>
            /// A method to manage the use of a textbox to display the connection status of
            /// PC-Dmis.
            /// </summary>
            private void UpdatePcdmisStatus()
            {
                if (PcdmisIsConnected)
                {
                    txbStatus.BackColor = Color.Green; // set the status textbox to green
                    btnConnect.Enabled = false;        // disable button to prevent 2nd connection.
                }
                else
                {
                    txbStatus.BackColor = Color.Red;
                    btnConnect.Enabled = true;
                }
            }
    
            /// <summary>
            /// Method to return true or false according to the state of pcdSession variable.
            /// </summary>
            private Boolean PcdmisIsConnected
            {
                get
                {
                    if (pcdSession is null)
                    {
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }
            }
    
            /// <summary>
            /// This method is a listener to the 'View Pcdmis' button click event. When this button
            /// is clicked this method flips between displaying and hiding the PC-Dmis window.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnViewPcdmis_Click(object sender, EventArgs e)
            {
                // Always confirm you have a connected session first
                if (!PcdmisIsConnected) return;
    
                if (pcdSession.Visible)
                {
                    // make it invisible)
                    pcdSession.Visible = false;
                    btnViewPcdmis.Text = "View PC-Dmis Window";
                }
                else
                {
                    // make it visible
                    pcdSession.Visible = true;
                    btnViewPcdmis.Text = "Unview PC-Dmis Window";
                }
            }
    
            /// <summary>
            /// Listener method for the form closing event. Handles the proper closing of the PC-Dmis
            /// session. Without this method PC-Dmis will continue living in the background after this
            /// application is closed and exited.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void Form1_FormClosing(object sender, FormClosingEventArgs e)
            {
                // Close the PCDLRN runtime service when this application is shutdown.
                if (pcdSession != null)
                {
                    pcdSession.UserExit = true;
                    pcdSession.Quit();
                    pcdSession = null;
                }
            }
        }
    }
    

Children
No Data