Friday, July 03, 2009

New "My Downloads" Section

First, thanks to everyone who downloaded the workspaces that I had uploaded to this blog (using http://www.box.net). I hope you found them useful.

Previously you could only find the uploaded workspaces by going to the individual posts. After noticing that these workspaces were being downloaded many times a week, I wanted to make it simpler for you, my readers, to find and download these workspaces.

I have added a "My Downloads" section, on the left sidebar (at the time of this posting, just below the "Older posts of mine" section) that links the relevant downloads. This will be a permanent fixture on each blog post page.

If you notice, these workspaces are being hosted on Google Code at http://ossandcad.googlecode.com which is my new repository for storing and sharing my CAD-API-based plugins and applications.

At the time of writing this post the following workspaces are made available on http://ossandcad.googlecode.com:

  1. Pro/Toolkit + Visual Studio 2005 Workspace (http://ossandcad.googlecode.com/files/ProToolkitVisualCpp.zip)
  2. SolidWorks Batch mode using SolidWorks API+COM (http://ossandcad.googlecode.com/files/swbatch.zip)
  3. SWX+CEEFIT Integrated Test Workspace (http://ossandcad.googlecode.com/files/swxbatch_ceefit_6_16_2009.zip)
Comments, suggestions most welcome.

Thursday, July 02, 2009

New Google Code project to accompany this blog

Thanks to all of you who have downloaded the various zips from my blog. I was using www.box.net to store and share my files. While box.net was sufficient, it was getting difficult to track usage and download rate, since I was only using the free version.

To solve that problem and to find a simpler method to share my code, using a source code repository I have created a Google Code project. You can find my project at http://ossandcad.googlecode.com. I have added an introduction and some Wiki pages and some files for download.

The following files are available for download:

  1. http://ossandcad.googlecode.com/files/swbatch.zip
  2. http://ossandcad.googlecode.com/files/ProToolkitVisualCpp.zip
  3. http://ossandcad.googlecode.com/files/swxbatch_ceefit_6_16_2009.zip -If you wondering what this is, then you have two options - wait for my blog post detailing how to use CEEFIT with SolidWorks API to run IntegratedTests - or - you could download and start working with the source code right away.
The following Wiki pages are also available (but mostly duplicating content originally posted on this blog)
  1. http://code.google.com/p/ossandcad/wiki/SwxBatch
The biggest advantage of this for users is that you could download/browse my source code directly from SVN from http://code.google.com/p/ossandcad/source/browse/#svn/trunk.  For me the biggest advantage is the ability to track usage using Google Analytics.

Comments/suggestions most welcome.

Tuesday, May 19, 2009

Unlocking Pro/TK Applications - Blog Referral

In one of previous posts titled "License needed to run my Pro/Toolkit add-ins" I received a comment requesting help using protk_unclock.exe to unlock the Pro/TK application provided in the same post. (For sake of convenience the following is the zip of the source for Pro/TK application)



As an answer to the question posed in that comment, I refer you to a post by my colleague, Amar Junankar, on his blog at http://cadinterface.blogspot.com/2009/05/unlocking-protoolkit-application.html. Amar has posted solutions for both developers and non-developers.

Welcome to the blogging world Amar.

Tuesday, April 07, 2009

MbUnit + AutoCAD = Unit testing for CAD Plugins

If you follow my blog, you know that I develop CAD plug-ins in both .NET and C++. And in various posts of mine I have written about the difficulty of writing unit tests for these CAD plug-ins. The following are some of my more relevant posts regarding this topic.

My usual solution was to avoid unit testing these CAD plugins and simply write integrated tests for them. The last post mentioned above (Writing CEEFIT class like a regular C++ class) specifically shows a sample CEEFIT (Framework for Integrated Test for C/C++) class that enables integrated testing using SWX (I will post the complete workspace to do this soon).

But imagine my surprise when I read the following post about the release of MbUnit v3.0.5 - http://weblogs.asp.net/astopford/archive/2009/04/02/mbunit-3-rtm.aspx. The below text is an excerpt from that post (bold and italics are my addition):
Gallio provides MbUnit with the runner infrastructure and the list of supported runners is amazing, like MbUnit v2 you can still run MbUnit v3 in MSBuild, NAnt, TD.Net, CruiseControl, commandline (much more ehanched in v3) and GUI (also vastly enhanced in v3) but now tools such as TeamCity, VSTS, Resharper, Powershell, NCover, TypeMock and even AutoCAD.
That last word really caught my attention. What is this? Unit test support for CAD system plug-ins? That is so awesome it is beyond belief. A Google search for "AutoCAD MbUnit" gave more information via http://blog.bits-in-motion.com/2008/11/announcing-gallio-and-mbunit-v305.html. An excerpt:

AutoCAD Integration

Mike Sandberg has added support for testing AutoCAD plugins.
It turns out that AutoCAD has a managed extensibility model so you can create your own plugins using .Net and the ObjectARX toolkit.  Unfortunately it is somewhat difficult to write unit tests for plugins becuase they must run within the main UI thread of AutoCAD.
The AutoCAD integration for Gallio works by loading a shim into the AutoCAD application from which it can launch tests.  To enable this integration, specify the "AutoCAD" runner type to the Echo, Icarus, MSBuild, NAnt or PowerShell runners.
For example:

    Gallio.Echo.exe MyTestAssembly.dll /r:AutoCAD [other options...]

AutoCAD integration is not yet available from within the IDE.  We will be working to improve this use case in the future.
OK. This definitely is promising. The post provides usage scenario, and although low on details on how this is achieved beyond saying "loading a shim", it is exactly what we CAD developers need.

To learn more on how MbUnit developers solved this problem, I turned to the source code available at http://mb-unit.googlecode.com/svn/trunk/v3/src/Extensions/AutoCAD. From first glances it looks as though the shim can connect or load (via the "acad.exe" file) AutoCAD. The shim finds the path to "acad.exe" via the registry key
"HKEY_CURRENT_USER\Software\Autodesk\DWGCommon\shellex\Apps\{F29F85E0-4FF9-1068-AB91-08002B27B3D9}:AutoCAD". 
It then determines if your plugin is loaded and if yes, sends commands to it using a TestDriver (AcadTestDriver).

What I found even more intriguing was the description of the problem that MbUnit developers intended to solve i.e. "difficulty of running unit tests as they run in the main UI thread of AutoCAD ". As I have contended, this is an universal problem for CAD developers. Replace AutoCAD with SolidWorks and the posts that I list above were intended to solve this very problem, although with a hack of a solution, but still following the same lines of thought. The CEEFIT workspace that I work with, loads SolidWorks in the background and using COM, connects to the running instance and then executes SWX-API-based tests. I let CEEFIT be the TestDriver and validate my output. The MbUnit framework has packaged idea this in beautiful .NET code.

This brings up the possibility that since SolidWorks plugins can also be .NET based, would replacing AutoCAD connection commands with SolidWorks connection commands in MbUnit's framework, allow loading the shim into SolidWorks and run unit tests against SolidWorks. I will be exploring this possiblity in the coming weeks/months, as time permits.

Do you develop AutoCAD plugins? Is this new functionality of MbUnit useful to you? Comments welcome.

Monday, March 02, 2009

SolidWorks API - In-process or Global methods - Which to use?

Two SWX API to rule them (or is it 'Two SWX API to confuse us'?)
Did you know that SolidWorks (SWX) provides two distinct (yet confusingly similar) interfaces to 'get' or 'set' arrays through its API? Well it does. I recently installed SWX 2009 SP 2.0 (I know, I know - this release has been out for a while, but I never needed the newer features) - but I upgraded from SWX 2007 SP 0.0 when I ran into some vexing problem with the SWX API and hoping that it was an SWX bug, decided to try their newest version. Turns out the problem were me and my limited knowledge of these two API interfaces.

The one advantage of installing SWX 2009 was the updated API documentation. The 2007 API documentation did not contain a page titled "In-process methods", which the 2009 version does. The following is an excerpt from that SWX 2009 API page (apihelp.chm) (italics are my addition) (note to lawyers: if it is not legal to publish portions of the SWX help documentation, please leave a comment and I will remove the appropriate sections)

In-process Methods
The SolidWorks API provides two types of methods for interfaces that get or set arrays:
  • in-process
  • global
For example, IView contains these methods:
  • IView::IGetCThreads (in-process)
  • IView::GetCThreads  (global)
Both types of methods perform the same work, but each is more or less appropriate for a given language and application.
In-process methods typically begin with the letter I and get or set pointers to arrays that only unmanaged C++ applications can handle. The in-process companion methods (i.e., similarly named methods that do not begin with the letter I) are more globally useful both inside a process and across processes and return predictable results for all of the SolidWorks supported languages.
In VBA, VB6, VB.NET, C#, and C++/CLI (also called managed C++), global methods typically get or set a VARIANT or object that the programmer can iterate as an array. In unmanaged C++, these methods get or set a pointer to a Dispatch object that should be cast as a SafeDISPATCHArray. (SafeDISPATCHArray is a VARIANT helper class defined in a template class, which is available on the API Support website.)
Q. To chose or not to chose
So how do you decide which interface to use? Does it even matter?
A. The answer to the 2nd question 'does it even matter' is - simply - YES IT DOES MATTER.

To answer the 1st question 'how do you decide which interface to use' - consider the following:
  • If 
    1. you are building a DLL Add-in to SWX,

      AND 


    2. you plan to only load that DLL through SWX

      THEN

       
    3. you can comfortably use the "in-process method".
  • But if
    1. you are building an EXE that loads SWX through COM

      AND
       
    2. loads your SWX Add-in DLL (i.e. instantiates classes from the Add-in DLL in the EXE), allowing calls from the Add-in DLL to go to SWX

      THEN
       
    3. you need to use the "global method" in

      BOTH
       
    4. the COM+EXE and Add-in DLL.

      AND

    5. LUCKILY YOU CAN STILL LOAD THE DLL ADD-IN DIRECTLY INTO SWX (doesn't that sound ideal?)
So how do you work this "global method"?
If you are like me and have little experience with COM, DISPATCH and VARIANTS then fear not because SolidWorks is gracious enough to provide us with a C++ template to simplify our lives. The files you need are hosted at http://files.solidworks.com/API/Examples/00000/0100s/0126/Example.htm. Simply download the zip file and include the "smartvars.h" file in your solution. The zip file also contains a sample in the file "usage.cpp", but for the sake of completness let me provide you with an example of my own:
VARIANT vxform;
LPSKETCH pSketch;
...
... // code to InsertSketch() so that pSketch is a valid pointer
...
pSketch->get_ModelToSketchXform(&vxform);
SafeDoubleArray varDimArr(vxform);
wofstream wfs;
wfs.open(L"dimension_data_swx3dexpextrusion.txt");
for( int i = 0 ; i < 13 ; i ++ ) {
     wfs << "\nXFormData at\t" << i << "\t=\t" << varDimArr[i];
}
wfs.close();
CONCLUSION
SolidWorks API while easy to work with have a few surprises - though in this case the missing documentation would have spoiled the surprise for me in the 2007 version. So all in all, I am able to run batch-mode integration test using the combination of CEEFIT and "global methods" to access array data from SolidWorks.