1 2 First Previous 22 Replies Latest reply on Aug 15, 2016 6:27 AM by thomasle

    More 7.9.x to VX translations

    andrew_french

      I have a few library oriented scripts that run behind the scenes during off hours that I am having issues getting to work correctly in VX.  For example I have a script that finds parts with missing areas in DMS and then goes and calculates an area estimate based on the placement outline and then finally load the data back into dms.  Yeah it jumps around to different tools.

       

      So in the background I am running things such as the part editor and the cell editor.  In 7.9.x this was not an issue as all my environment variables were set.  I figured this was going to be an easy fix, just run my script through the mgscript.exe terminal.  Well its not working for me.

       

      I am using C#.  I do a simple test at first to verify the passed argument is indeed a valid library.  The library is definitely valid.  the code always fails on the first line in the try statement.  Running outside the mgscript environment I get told I'm missing a registered COM, inside the mgscript environment I get the message that it is not a valid library.  I'm not sure what I am doing wrong here.

       

              /// <summary>

              /// Basic test to see if arguments passed in are valid.  Tests to see if they are actually a recognizeable library

              /// </summary>

              /// <param name="lib">The library cache to test</param>

              /// <returns>

              /// True: library check passed

              /// False: Library check failed

              /// </returns>

              public static bool IsitaLibrary(string lib)

              {

                  try

                  {

                      PartsEditorDlg PedApp = new PartsEditorDlg();

                      PartsDB PedDoc = PedApp.OpenDatabaseEx(lib, true);

                      PedApp.CloseActiveDatabase();

                      PedApp.Quit();

                      PedDoc = null;

                      PedApp = null;

                  }

                  catch

                  {

                      return false;

                  }

                  return true;

              }

        • 1. Re: More 7.9.x to VX translations
          jeremy_parker

          In VX, the environment variables are not in play like the were in 7.X. To run automation scripts (outside of the tools) then you must either:

           

          A) Run programs through the MGC PCB Command Window

          B) Setup a batch script to launch MGLaunch to then run the automation script

          C) Add extra code in place to setup the environment to run (See VB code):

           

          Dim SDDHome As String = System.Environment.GetEnvironmentVariable("SDD_HOME")

          Dim VxVersion As String

          SDDHome = Nothing Then

                      Dim vxEnv As New MGCPCBReleaseEnvironmentLib.MGCPCBReleaseEnvServer

                      vxEnv.SetEnvironment()

                      VxVersion = vxEnv.sddVersion

           

           

                      SDDHome = vxEnv.sddHome

                      Dim idx As Integer = SDDHome.IndexOf("SDD_HOME")

                      SDDHome = SDDHome.Substring(0, idx).Replace("\", "\\") & "SDD_HOME"

                      vxEnv.SetEnvironment(SDDHome)

                  End If

           

          After this code executes, you should be able to run the automation like normal for that instance.

          • 2. Re: More 7.9.x to VX translations
            andrew_french

            I'll give option C a try but I couldn't get the first two to work for me.  mgscript.exe = MGC PCB Command Window.

            • 3. Re: More 7.9.x to VX translations
              jeremy_parker

              MG Launch is a little different than the other. MG Launch is a wrapper around the program where as MGC PCB Command Window is an actual command window. You drag the executable into the window and run it.

               

              Good luck!

              • 4. Re: More 7.9.x to VX translations
                andrew_french

                Sorry I was saying mgscript.exe which is wrong, but I was indeed using the "MGC PCB Command Window VX.1.1"

                 

                Is this a true or false statement?

                I should be able to use the "MGC PCB Command Window VX.1.1" utility to run my script with no modifications other than updating the references to the new dlls.  This script worked fine in the 7.9.4/5 environment.

                • 5. Re: More 7.9.x to VX translations
                  jeremy_parker

                  There should be no code changes other than changing com objects and setting up your project to compile for 32-bit if you are running 32-bit Mentor tools or 64-bit if you are running 64-bit Mentor tools.

                  • 6. Re: More 7.9.x to VX translations
                    andrew_french

                    Man this is frustrating at this point.  I have no clue what I am doing wrong or if its even me that's the problem now.  When are you all going to officially support modern programming languages as opposed to antiquated VBS?

                    • 7. Re: More 7.9.x to VX translations
                      jeremy_parker

                      Even though it is not "officially" supported, what is limiting you from using VB.net or C#?

                      • 8. Re: More 7.9.x to VX translations
                        andrew_french

                        Well I translated your code to C# and I got this

                         

                        string SDD_HOME_env_var = Environment.GetEnvironmentVariable("SDD_HOME");

                                    if (String.IsNullOrEmpty(SDD_HOME_env_var))

                                    {

                                       //MGCPCBReleaseEnvServer vxEnv = new MGCPCBReleaseEnvServer();

                                        var vxEnv = new MGCPCBReleaseEnvironmentLib.MGCPCBReleaseEnvServer();

                                        vxEnv.SetEnvironment();

                         

                         

                                        SDD_HOME_env_var = vxEnv.sddHome;

                                        int idx = SDD_HOME_env_var.IndexOf("SDD_HOME");

                                        SDD_HOME_env_var = SDD_HOME_env_var.Substring(0, idx).Replace(@"\", @"\\") + "SDD_HOME";

                                        vxEnv.SetEnvironment(SDD_HOME_env_var);

                                    }

                         

                        Trying to set the vxEnv variable I always get the error "A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll"

                         

                        I have two lines there for setting the vxEnv variable, first one is currently commented out but should work as well.  I also get the same COMException error here.

                         

                        I have the MGCPCBReleaseEnvironmentLib referenced for this project as well.  Am I missing a reference maybe?

                        • 9. Re: More 7.9.x to VX translations
                          andrew_french

                          I'm assuming you can't get it to work either.

                          • 10. Re: More 7.9.x to VX translations
                            jeremy_parker

                            Actually, I haven't been able to test it because of other commitments :-(

                            • 11. Re: More 7.9.x to VX translations
                              Patrick.Cashman

                              Andrew, here is some information that I think will help.

                               

                              First, forget about the MGCPCBReleaseEnvServer.  It does not work, because there's no COM object for it that I've found. So I don't even know how you'd let your project know it exists. But no matter, because it's not needed. 

                               

                              There are two things you need to get:

                              1. The path to the currently registered version of mglaunch.exe.

                              2. The COM version number of the currently registered installation of the Mentor tools.

                               

                              (an aside: it is possible to have more than one registered version active on a system.  In that case, you'd need some other method of choosing the COM version and the mglaunch version.  I will let the geniuses who decided a complete paradigm shift was necessary to accomplish this illogical scenario put in the time and effort to figure that out.  We plan to keep one version registered at a time, the latest viable release.  Naturally, my tools will be smart enough to figure out what that is, even when we change versions, so that install paths do not need to be hard coded into the software anywhere.)

                               

                              You only need to use mglaunch when you are also using the CreateObject mode of starting an automation hook into one of the Mentor tools. If, on the other hand, you are creating an automation hook into an already running tool, use the GetObject mode, and then mglaunch is not needed. 

                               

                              How to get the mglaunch path before you run your externally compiled automation tool:

                              - Make a .vbs file.  Call it whatever you want.  I'll use Dx_Library_Automation.vbs as an example which will demonstrate how to load the PDBEditor and CellEditor.  Both of these run stand-alone, meaning you will never have an existing session of them already running, and what to hook into it.

                              - The contents of the .vbs file would look something like this:

                               

                              Option explicit

                              run

                               

                              Sub run()

                                 Dim objShell, regkey, mglaunch

                               

                                 Set objShell = CreateObject("WScript.Shell")

                                 regkey = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\mglaunch.exe\"

                                 mglaunch = objShell.RegRead(regkey)

                                 mglaunch = mglaunch & " " & chr(34) & "path_to_your_automation_executable" & chr(34)

                                 objShell.run mglaunch

                                 set objShell = Nothing

                              End sub

                               

                              (I'm not sure if the subroutine is actually needed.  I got that as an example long ago and just kept using it.  vbs experts may know better)

                              So, what's going on here?

                              1. We create the objShell object, an instance of the wscript shell.

                              2. We give it the name of the Windows registry key where the path to mglaunch.exe is stored, and then read that key's value into the mglaunch variable.

                              3. mglaunch becomes a command string, with the path to mglaunch, a space, double quote (in case there is a space in what follows, the automation tool executable path), the automation executable's path, and another double quote.

                              4. We execute the command line string, then kill the shell.

                               

                              This is essentially equivalent to opening a command window and typing the path to mglaunch and the path to the automation executable, which will open the automation tool from inside the mglaunch wrapper.

                               

                              So now your automation tool is running, and doing so under the care and protection of mglaunch.

                               

                              At this point, the only other thing needed is the COM version to be used in the automation tool to start the CreateObject commands. So how is that done?

                               

                              Again, we use the Windows registry. In my vb.net project, I have a module with all of the following in it.

                              1. An imports statement with   

                              Imports Microsoft.Win32

                              This is there so that we can interface with the registry.

                               

                              2. Global variables used to hold the COM version and an error-checking boolean.

                              Public proceed As Boolean

                              Public prog_id As Integer

                               

                              prog_id is the COM version.

                               

                              3. A subroutine that reads the COM version from the registry with error checking and reporting via the proceed boolean variable.

                              Public Sub get_ver()

                                       Dim regkey As RegistryKey

                                       Dim tmp As String

                                      

                                       regkey = Registry.LocalMachine.OpenSubKey("SOFTWARE\Classes\MGCPCB.ExpeditionPCBApplication\CurVer", False)

                                      

                                       If regKey Is Nothing Then

                                           tmp = "Critical registry keys are missing.  This most likely means that the Mentor Graphics "

                                           tmp = tmp & "tools have not been installed properly." & vbCrLf & vbCrLf

                                           tmp = tmp & "Try to correct that then start over. "

                                           MsgBox(tmp)

                                           proceed = false

                                           exit sub

                                       End If

                                      

                                       tmp = regkey.GetValue("")

                                       tmp = tmp.Substring(InStrRev(tmp, "."))

                                       prog_id = CInt(tmp)

                                      

                                       regKey.Close()

                              End Sub

                              4. You see here that the tmp variable is used to get the regkey value.  It is then parsed to get only the part after the last dot in the string.  This number is the COM version, and is stored in the prog_id global variable. I run this subroutine prior to running the routine that includes the CreateObject command, and use the proceed boolean to make sure it all works properly.  Here is an example of how that is done:

                               

                                       proceed = True

                                       get_ver()

                                       if proceed = false then

                                           MsgBox("Unable to find registry keys needed for automation access to EXpedition.")

                                           me.close

                                        end if

                              5. After get_ver has successfully run, we know the COM version. 

                              6. I have a subroutine that starts the Part Editor, or the Cell Editor.  Here is an example of starting the PartEditor

                               

                              Public Sub Get_Part_Editor()

                                       'Creates a handle to the Parts Editor in Library Manager

                                      

                                       Try

                                           part_ed_dlg = CreateObject("MGCPCBLibraries.PartsEditorDlg" & "." & prog_id.ToString)

                                       Catch ex As Exception

                                           Debug.Print("failing to create part editor session with this error: " & ex.Message)

                                           proceed = False

                                           Exit Sub

                                       End Try

                                      

                                       pdb_db = part_ed_dlg.OpenDatabaseEx(job, False)

                                        'job is the path to the central library .lmc file

                                       If part_ed_dlg.LockServer() Then

                                           'do nothing

                                       else

                                           msgbox("Could not lock database for writing")

                                       End If

                              End Sub

                              7. The important line is the one right after the Try command.

                              part_ed_dlg = CreateObject("MGCPCBLibraries.PartsEditorDlg" & "." & prog_id.ToString)

                               

                              You see that it uses the CreateObject function, identifies the tool that it's going to create, then adds the COM version to the end.

                               

                              I have verified that this works successfully in VX.1.  I have not yet tried it in VX.1.1 or VX.1.2, because of other problems with both of those releases.

                               

                              8. For CellEditor, there's a similar subroutine:

                              Public Sub GetCellLib()

                                      'there are some other globally declared variables in here.

                                       Try

                                           celldlg = CreateObject("CellEditorAddin.CellEditorDlg" & "." & prog_id.ToString)

                                       Catch ex As Exception

                                           Debug.Print("failing to create cell editor session with this error: " & ex.Message)

                                           proceed = False

                                           Exit Sub

                                       End Try

                                       celldb = celldlg.OpenDatabase(job, false)

                                        'job is the path to the central library .lmc file

                                       celldlg.visible = False

                                      

                              End Sub

                              Again, I've verified that this works.  I assume you are using the Windows Task Scheduler or some equivalent tool to run your scrips after hours.  I set up a simple task in Task Scheduler to run my library editor tool with the .vbs startup script.  It works, and I can extract data from the PartEditor and the CellEditor. or execute functions on the parts and cells.

                               

                              To start automation hooks into already-running tools, just use GetObject instead of CreateObject, and don't bother with the .vbs script that starts the executable with mglaunch.  However, sometimes it's a mixed bag.  You may be hooking into a running session of Xpedition with the GetObject command, but also running one of the PCB Engines.  PCB Engines require the CreateObject statement, so in that case you would need to use the mglaunch wrapper for the entire executable.

                               

                              Here's an example of starting a hook into Xpedition with GetObject:

                              app = GetObject(, "MGCPCB.ExpeditionPCBApplication" & "." & prog_id.ToString)

                              (note the comma in the above statement right after the opening parentheses.  I forget why it is needed, but it is.  And different than the CreateObject statement, which does not need it)

                               

                               

                              And starting a Mask Engine instance with CreateObject. (mglaunch needed in this case):

                              mskeng = CreateObject("MGCPCBEngines.MaskEngine" & "." & prog_id.ToString)

                               

                              I think this includes everything, but it's late and I may have forgotten something.  Go over it and then get in touch, and we'll hammer out any issues.

                               

                              Best wishes getting it all to work

                              • 12. Re: More 7.9.x to VX translations
                                jeremy_parker

                                The Release environment com object is available and does work.

                                • 13. Re: More 7.9.x to VX translations
                                  Patrick.Cashman

                                  So it is. Thank you for posting that.

                                   

                                  I had looked previously and didn't see it. Maybe back when I was still trying to use VX.1.1 or .1.2, and it wasn't there. Not sure. I don't remember exactly when in the process I looked, but I ended up on the path of using the registry. I like using the registry; simple and dependable.

                                  • 14. Re: More 7.9.x to VX translations
                                    andrew_french

                                    I need to take some time to investigate all this but I think the crux of my problem here is that in C# I do not have a way to specify the COM version.  C# does not use CreateObject.  In C# and 79X life was good all I had to do to start a new instance of the cell editor and open it was to say:

                                     

                                    CellEditorAddinLib.CellEditorDlg cellEd = new CellEditorAddinLib.CellEditorDlg();

                                    CellEditorAddinLib.CellDB cellDB = cellEd.OpenDatabase(lib, false);

                                     

                                    that's far more simple and straight forward than the mess this has become.  Hopefully I can find a C# guru here at work and find an equivalent command to createobject that lets me specify the COM version.

                                    1 2 First Previous