Showing posts with label NX Dev.. Show all posts
Showing posts with label NX Dev.. Show all posts

2011-03-03

The mechanism of UG/NX Load .net dll

Now we talk about how UG/NX load a .net plugin dll.

As far as we know, NX run without .net framework, i.e., no need setup .net framework on the PC to use NX.

But, why NX can also load .net dll. (Of cource, who use .net plugin should setup .net framework by selves).

As I known, a native C/C++ program to load a .net program could use CLI, COM, and API methods. Others are between processes.

Obviously, NX didn't use CLI nor COM, because of both methods should prepare .net framework on PC.

API is the short of CLR Hodting APIs, some COM components to load .net program.

API is different with .net versions, especially .net4 having in process side by side which let it be reprogram. (The usage of .net API is not the businee of this post and I would post another article latter).

Conclusion, NX load the customer .net dll with ManagedLoader.dll by .net hosing API.

 

ManagedLoader.dll is a key component.

Let us have a look for it.

image

From the Fig., we see a interface and a class which is a implementation of the former.

image

The interface realiezed how to load a .net dll, and run their methods.

 

We pay attension to Load(string), for it is take charge for loading the customer dll. So, let's look:

   1:  public string Load(string assemblyName)
   2:  {
   3:      string str = null;
   4:      this.myAssemblyName = assemblyName;
   5:      Trace.WriteLine(string.Concat(new object[] { "ManagedLoader.Load: ", assemblyName, " ", AppDomain.CurrentDomain }));
   6:      Trace.WriteLine("AppBase: " + AppDomain.CurrentDomain.BaseDirectory);
   7:      try
   8:      {
   9:          AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(this.AssemblyResolveHandler);
  10:          AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(this.AssemblyLoadHandler);
  11:          this.myAssembly = Assembly.LoadFrom(assemblyName);
  12:      }
  13:      catch (Exception exception)
  14:      {
  15:          Trace.WriteLine(exception.ToString());
  16:          str = exception.ToString();
  17:      }
  18:      return str;
  19:  }
  20:   
  21:   




Line 9, mainly correspond to loading dll successfully event. There is nothing, only Trace information for debugging.


Line 10, deal with loading the dependent dlls, very importantly, details latter.


Line 11, load customer .net dll. Note, it use LoadForm, not LoadFile, there is differen between them.


In addition, reflection have some variation in .net4, you could look for MSDN.


 


What are dependent dlls?


Different from native dlls which could be found form the Path directory. .net dll only could put donw in exe path or GAC.


That's the problem. The main process of UG/NX is ugraf.exe, at program files/UGS… . It could not ask put all customer dlls in there, so there must be some place for users.


Except the path of the customer dll, NX allows the path speciafied by the system variable  UGII_MANAGED_DLL_PATH to put down.


 


The Event AssemblyResolve deal with searching these dependent dlls, you can look:http://msdn.microsoft.com/zh-cn/library/system.appdomain.assemblyresolve(v=vs.80).aspx


Now, let's see the implementation of above line 10 function.


   1:  private Assembly AssemblyResolveHandler(object sender, ResolveEventArgs args)
   2:  {
   3:      Trace.WriteLine("Resolve failed: " + args.Name);
   4:      int index = args.Name.IndexOf(',');
   5:      string str = args.Name.Substring(0, index);
   6:      if ((!(str == "NXOpen") && !(str == "NXOpen.Utilities")) && (!(str == "NXOpenUI") && !(str == "NXOpen.UF")))
   7:      {
   8:          return null;
   9:      }
  10:      str = str + ".dll";
  11:      string str2 = TranslateVariable("UGII_MANAGED_DLL_PATH");
  12:      string path = null;
  13:      if (str2 != null)
  14:      {
  15:          foreach (string str4 in str2.Split(new char[] { Path.PathSeparator }))
  16:          {
  17:              path = Path.Combine(str4, str);
  18:              if (File.Exists(path))
  19:              {
  20:                  break;
  21:              }
  22:              path = null;
  23:          }
  24:      }
  25:      if (path == null)
  26:      {
  27:          str2 = TranslateVariable("UGII_ROOT_DIR");
  28:          if (str2 != null)
  29:          {
  30:              path = Path.Combine(Path.Combine(str2, "managed"), str);
  31:          }
  32:      }
  33:      Assembly assembly = Assembly.LoadFrom(path);
  34:      if (assembly == null)
  35:      {
  36:          Trace.WriteLine("Failed to load: " + str);
  37:          return assembly;
  38:      }
  39:      Trace.WriteLine("Loaded: : " + assembly.GetName(false).ToString());
  40:      return assembly;
  41:  }



4-5, acquire the name of a dependent dll.


6-9, exclude 4 dlls laoding automatically with ManagedLoader.dll.


10-24, search them in the path speciafied by UGII_MANAGED_DLL_PATH.


25-32, search them in the path specialfied by UGII_ROOR_DIR which is the root of UG/NX.


Line 33, load the dependent dll.


34-38, deal with errors.


Ohters are searched form the path of the customer plugin, which is automatically realized by reflection of .net.


 


OK, that's all.


About .net API usage, we talk about latter.


 


All rights 白途思(Beck)


2011-03-01

......

[Read More]

2011-02-10

Application of a UG CAM API: UF_SETUP_generate_program

Application of a UG CAM API: UF_SETUP_generate_program

Beck (BAI Tusi)

Email/MSN:begtostudy@gmail.com

Defined in: uf_setup.h

Overview

This function generates the NC program for all the operations contained in the specified group of the specified setup. It will use the Post (i.e., the Definition File and Event Handler) specified by 'post_name'. It will write the generated NC Program to a file with name 'output_filename'. If 'output_filename' exists the output will be appended to the existing file. If the behavior wanted is to overwrite the exsiting file, then the user has to delete the file before calling this function.

See the Note in the File Description regarding the relationship between the 'post_name' and the CAM resource files.

Environment

Internal and External

History

Originally released in V16.0

Required License(s)

cam_base

int UF_SETUP_generate_program

(

tag_t setup,

tag_t group,

const char * post_name,

const char * output_filename,

UF_SETUP_output_units_t output_units

)

tag_t

setup

Input

- the setup object to process

tag_t

group

Input

- the program group to process

const char *

post_name

Input

- the name (as found in a resource file) of the post instructions to use. This name specifies the Definition File and Event Handler file to use

const char *

output_filename

Input

- the name of the file to write the output to

UF_SETUP_output_units_t

output_units

Input

- the output units for the Post to use

Before using this function, we must setup something as follows:

Firstly, we should find the folder from the NX setup folder as shown in Figure 1: \UGS\NX 6.0\MACH\resource\postprocessor

And then, copy three post-process files into this folder, as shown in Figure 3:

clip_image002

图 1

Open template_post.dat in Figure 1 by notepad (Figure 2).

Append a line in the file:

begtostudy,${UGII_CAM_POST_DIR}begtostudy.tcl,${UGII_CAM_POST_DIR}begtostudy.def

It specifies the name, tcl file and def file, divided by ‘;’ respectively.

${UGII_CAM_POST_DIR} is the special the folder, of course, you could use a full path name.

clip_image004

图 2

After restarted UG, it would display the configuration in the post-processor dialog (Figure 3).

clip_image005

图 3

At last, we could use the api, UF_SETUP_generate_program, in our program:

UF_CALL(UF_SETUP_generate_program(setup_tag,pro_tag/*Program group*/,”begtostudy”,filename/*output the NC file*/, UF_SETUP_OUTPUT_UNITS_INCH ));

Note: You must ensure you can generate nc file by hand in NX.

End.

......

[Read More]

2011-01-11

Open APIs and NXOpen Class Library of UG/NX Secondary Development

(I am not native speaker, so sorry for my English. If you find some mistakes, please tell me in the following comments or email to me: begtostudy@gmail.com)
There are two open application interface system, i.e., Open APIs and NXOpen class library. Open, also named UFun, is based on C-Langrage at the start and later supported C++, which is good at geometry functions. After purchased by Siemens (or extended to PLM business), UG/NX have another one, NXOpen class library. It concludes almost the functions of NX software and is entirely object-oriented. However NX didn’t give up the Open APIs, with NXOpen.UF namespace, we can use them by encapsulation technology. Maybe for the short history, NXOpen have less help data than Open. And the same reason, before NX6, there are so many bugs in NXOpen. We give some comparisons in Table 1.
Table 1. Comparisons

Language Open API/UFun NXOpen
C procedure-oriented
good at geometry functions, especially efficiency
Not support
C++ (Open C++)
Partly object-oriented
Partly support NX functions
Almost support NX functions
(native code)
.net/java NXOpen.UF namespace by encapsulation technology Almost support NX functions
(managed code)
In conclusion, if using C/C++, you could use Open C and Open C++ directly, and if using .net, you primary use NXOpen and API by NXOpen.UF, i.e., you could use both systems separately.
Following, I would take some examples to illustrate their difference. For .net, I only picked C#, and others, e.g. VB, are the same. Sorry for java, I know little about it.

I. Open C

1. Find each body in the work part

#include <uf_object_types.h>
#include <uf_part.h>
#include <uf_obj.h>
#include <uf_modl.h>
#include <string>
#include <sstream>
using std::string;
using std::stringstream;
//code segments as follow
UgSession session( true );
try
    {
/* TODO: Add your application code here */
uf_list_p_t lpObj;
UF_MODL_create_list(&lpObj);
tag_t prt = UF_PART_ask_display_part();
tag_t Next_tag=NULL_TAG;
do
         {
UF_OBJ_cycle_objs_in_part(prt,UF_solid_type,&Next_tag);
if(Next_tag==NULL_TAG) break;
int t,subtype;
UF_OBJ_ask_type_and_subtype(Next_tag,&t,&subtype);
if(subtype==UF_solid_body_subtype)
UF_MODL_put_list_item(lpObj,Next_tag);
         } while(1);
logical is_open;
UF_UI_is_listing_window_open(&is_open);
if(!is_open) UF_UI_open_listing_window();
int sum;
UF_MODL_ask_list_count(lpObj,&sum);
for (int i=0;i<sum;i++)
         {
tag_t t;
UF_MODL_ask_list_item(lpObj,i,&t);
stringstream s;
s<<(int)t;
string str;
str = s.str();
UF_UI_write_listing_window(str.c_str());
UF_UI_write_listing_window("\n");
         }
//       UF_UI_exit_listing_window();
UF_MODL_delete_list(&lpObj);
    }
/* Handle errors */
catch ( const UgException &exception )
    {
processException( exception );
}

2. Create a block

#include <uf.h>
#include <uf_ui.h>
#include <uf_exit.h>
#include <uf_modl.h>
//code segments as follow
/* Initialize the API environment */
if( UF_CALL(UF_initialize()) )
    {
/* Failed to initialize */
return;
    }
/* TODO: Add your application code here */
double corner[3] ={0,0,0};
char* edge[3] = {"10","5","20"};
tag_t tag;
UF_MODL_create_block(UF_NULLSIGN,NULL_TAG,corner,edge,&tag);
/* Terminate the API environment */
UF_CALL(UF_terminate());

II. Open C++

1. Find each body in the work part

#include <ug_typed.hxx>
#include <ug_part.hxx>
#include <ug_body.hxx>
#include <ug_string.hxx>
using std::string;
// code segments as follow
UgSession session( true );
try
{
/* TODO: Add your application code here */
UgPart *pWorkPart = UgSession::getWorkPart();
UgTypedObject *pObj;
ostrstream buffer;
for ( pObj = pWorkPart->iterateFirst ( );
pObj;
pObj = pWorkPart->iterateNext ( pObj ) )
{
std::string name = pObj->getName ( );
UgBody *pBody = dynamic_cast<UgBody*>(pObj);
if (pBody)
{
buffer<<(int)pBody->getTag()<<"\n";
}
}
UgInfoWindow::open();
UgInfoWindow::write(string(buffer.str()));
delete buffer.str();
}
/* Handle errors */
catch ( const UgException &exception )
{
processException( exception );
}

2. serching

#include <ug_body.hxx>
#include <ug_iterator.hxx>
#include <ug_string.hxx>
// code segments as follow
UgSession session( true );
try
{
/* TODO: Add your application code here */
ostrstream buffer;
// Construct an iterator for NX face objects
UgIterator < UgBody > pObj;//workpart 可以通过其他方式指定
//UgIterator < UgFace *> curFace;
//// Loop through all faces
//while ( !curFace.isFinished ( ) )
//{
//   // Get the name of the current face
//   std::string faceName = (*(*curFace))->getName ( );
//   curFace.findNext ( );
//}
// Loop through all faces
while ( !pObj.isFinished ( ) )
{
// Get the name of the current face
std::string faceName = (*pObj)->getName ( );
buffer<<(int)(*pObj)->getTag()<<endl;
pObj.findNext ( );
}
UgInfoWindow::open();
UgInfoWindow::write( std::string( buffer.str() ));
delete buffer.str();
}
/* Handle errors */
catch ( const UgException &exception )
{
processException( exception );
}

III. NXOpen C++

1. Create a block

#include <NXOpen/Session.hxx>
#include <NXOpen/Part.hxx>
#include <NXOpen/Features_BlockFeatureBuilder.hxx>
#include <NXOpen/Features_Block.hxx>
#include <NXOpen/PartCollection.hxx>
#include <NXOpen/Features_FeatureCollection.hxx>
#include <NXOpen/UI.hxx>
#include <NXOpen/NXMessageBox.hxx>
using namespace NXOpen;
// code segments as follow
NXOpen::Session *theSession = NXOpen::Session::GetSession();
try
    {
/* TODO: Add your application code here */
Part* thePart = theSession->Parts()->Work();
NXOpen::Features::Feature* block = NULL;
NXOpen::Features::BlockFeatureBuilder* theBuilder = thePart->Features()->CreateBlockFeatureBuilder(block);
NXOpen::Point3d basePoint(100, 100, 100);
theBuilder->SetOriginAndLengths(basePoint, "100", "200", "300");
//              NXOpen.Body theBody = null;
//              theBuilder.SetBooleanOperationAndTarget(NXOpen.Features.Feature.BooleanType.Create, theBody);
theBuilder->Commit();
//theBuilder->CommitFeature();
NXOpen::UI::GetUI()->NXMessageBox()->Show("", NXMessageBox::DialogType::DialogTypeInformation, "OK!");
//   UI->GetUI()->NXMessageBox.Show("", NXMessageBox.DialogType.Information, "OK!");
    }
/* Handle errors */
catch ( const UgException &exception )
    {
processException( exception );
}

2. Find each Feature in the work part

#include <NXOpen/Session.hxx>
#include <NXOpen/Part.hxx>
#include <NXOpen/Features_BlockFeatureBuilder.hxx>
#include <NXOpen/Features_Block.hxx>
#include <NXOpen/PartCollection.hxx>
#include <NXOpen/Features_FeatureCollection.hxx>
#include <NXOpen/UI.hxx>
#include <NXOpen/NXMessageBox.hxx>
#include <NXOpen/ListingWindow.hxx>
using namespace NXOpen;
// code segments as follow
NXOpen::Session *theSession = NXOpen::Session::GetSession();
try
     {
/* TODO: Add your application code here */
Part* thePart = theSession->Parts()->Work();
theSession->ListingWindow()->Open();
NXOpen::Features::FeatureCollection::iterator i;
for (i=thePart->Features()->begin();i!=thePart->Features()->end();i++)
         {
theSession->ListingWindow()->WriteLine((*i)->Name()+"--"+(*i)->GetJournalIdentifier());
         }
NXOpen::UI::GetUI()->NXMessageBox()->Show("", NXMessageBox::DialogType::DialogTypeInformation, "OK!");
//   UI->GetUI()->NXMessageBox.Show("", NXMessageBox.DialogType.Information, "OK!");
     }
/* Handle errors */
catch ( const UgException &exception )
    {
processException( exception );
}

IV. NXOpen C#

1. Create a block

using NXOpen;
using NXOpen.Utilities;
using NXOpen.UF;
using NXOpenUI;
// code segments as follow
Session theSession = Session.GetSession();
try
            {
Part thePart = theSession.Parts.Work;
NXOpen.Features.Feature block = null;
NXOpen.Features.BlockFeatureBuilder theBuilder = thePart.Features.CreateBlockFeatureBuilder(block);
NXOpen.Point3d basePoint = new Point3d(100f, 100f, 100f);
theBuilder.SetOriginAndLengths(basePoint, "100", "200", "300");
theBuilder.Commit();
//theBuilder.CommitFeature();
UI.GetUI().NXMessageBox.Show("", NXMessageBox.DialogType.Information, "OK!");
            }
catch(NXException ex)
            {
UI.GetUI().NXMessageBox.Show("error!", NXMessageBox.DialogType.Error, ex.Message);
            }

2. Find each Feature in the work part

using NXOpen;
using NXOpen.Utilities;
using NXOpen.UF;
using NXOpenUI;
// code segments as follow
Session theSession = Session.GetSession();
theSession.ListingWindow.Open();
try
            {
Part thePart = theSession.Parts.Work;
foreach (NXOpen.Features.Feature c in thePart.Features)
                {
//NXOpen.Features.Block t = c as NXOpen.Features.Block;
//if(t!=null)
//{
//    theSession.ListingWindow.WriteLine(t.ToString());
//}
theSession.ListingWindow.WriteLine(c.Name+"--"+c.ToString());
                }
UI.GetUI().NXMessageBox.Show("", NXMessageBox.DialogType.Information, "OK!");
            }
catch (NXException ex)
            {
UI.GetUI().NXMessageBox.Show("error!", NXMessageBox.DialogType.Error, ex.Message);
            }

V. NXOpen.UF

1. analogy of Case I.1 for Open C

using NXOpen;
using NXOpen.Utilities;
using NXOpen.UF;
using NXOpenUI;
NXOpen.UF.UFSession theUFSession = NXOpen.UF.UFSession.GetUFSession();
try
            {
double[] corner ={ 0, 0, 0 };
string[] edge = { "10", "5", "20" };
Tag tag;
theUFSession.Modl.CreateBlock1(FeatureSigns.Nullsign, corner, edge, out tag);
            }
catch (NXException ex)
            {
UI.GetUI().NXMessageBox.Show("error!", NXMessageBox.DialogType.Error, ex.Message);
            }

1. analogy of Case I.1 for Open C

using NXOpen;
using NXOpen.Utilities;
using NXOpen.UF;
using NXOpenUI;
NXOpen.UF.UFSession theUFSession = NXOpen.UF.UFSession.GetUFSession();
try
            {
Tag[] list=null;
Tag thePart = theUFSession.Part.AskDisplayPart();
theUFSession.Modl.CreateList(out list);
Tag Next_tag=Tag.Null;
do
                {
theUFSession.Obj.CycleObjsInPart(thePart,70/* UF_solid_type*/,ref Next_tag);
if (Next_tag == Tag.Null) break;
int t, subType;
theUFSession.Obj.AskTypeAndSubtype(Next_tag,out t, out subType);
if (subType == 0/*UF_solid_body_subtype*/)
theUFSession.Modl.PutListItem(list, Next_tag);
                } while (true);
bool isOpen;
theUFSession.Ui.IsListingWindowOpen(out isOpen);
if (!isOpen) theUFSession.Ui.OpenListingWindow();
int sum;
theUFSession.Modl.AskListCount(list,out sum);
for (int i = 0; i < sum;i++ )
                {
Tag t;
theUFSession.Modl.AskListItem(list, i, out t);
theUFSession.Ui.WriteListingWindow(t.ToString());
                }
/*Treat all the arguments with the"Output to be freed " annotation as an output parameter.
                 * The system takes care of freeing memory.*/
            }
catch (NXException ex)
            {
UI.GetUI().NXMessageBox.Show("error!", NXMessageBox.DialogType.Error, ex.Message);
            }

......

[Read More]

2011-01-10

Build a NX Open .NET application

 

A basic setup to build a NX Open .NET application using Visual Studio (IDE)

Interactive Application: .NET authoring license is required

Start Visual Studio 2003 (7.1)

Create class library project

  • File -> New -> Project -> Visual C# Projects (project types) -> Class Library

Add references

  • Project -> Add Reference…

Browse to UGII_BASE_DIR\UGII\managed\
Add the following files

  • NXOpen.dll
  • NXOpen.Utilities.dll
  • NXOpen.UF.dll
  • NXOpenUI.dll (only needed if you build an user interface for your application)

Add Main() function to the class

    public static void Main()
    {

    }

Compile and build the application

Test Appilcation:

Launch NX

Run your sample application

  • File -> Execute -> NX/Open… (browse to your sample application \bin\Debug\ location, select your application.dll)

Sign Application:
In order to release an application and have non programers use this (someone without a .NET authoring license) you need to sign your application.

Add resource file NXSigningResource.res to your Visual Studio project

  • File -> Add Existing Item -> browse to UGII_BASE_DIR\UGOPEN\NXSigningResource.res

Set the NXSigningResource.res file Build Action to Embedded Resource

  • Properties on the NXSigningResource.res file that’s attached to your Visual Studio project

Sign the application, at a command prompt:

  • UGII_BASE_DIR\UGII\SignLibrary.exe yourSampleApplicationLocation\sampleApplication.dll

If you don’t sign your application when you release it to your end users, they will be required to have a “.NET authoring license”. This is very costly and unnecesary.

Set your Project Configuration Build to Release
This will change the build arguments and remove the unnecessary debug statements for the released application

  • Build -> Configuration Manager
  • Set “Active Solution Configuration” to Release

Compile, Build, and test

Summary
This application does not do anything but it does set up the foundation needed to get an application built using the Visual Studio IDE and have it signed for release.

Original post:http://plmexchange.net/build-a-nx-open-net-application/

......

[Read More]