Author Topic: Assembly Test Request  (Read 7730 times)

0 Members and 1 Guest are viewing this topic.

TR

  • Guest
Assembly Test Request
« on: January 22, 2007, 08:04:01 PM »
Can anyone with .NET 2.0 Runtime and a version of AutoCAD greater than 2005 installed test an assembly for me? I compiling against the 2005 versions of the managed dll files and am wondering if anyone else can use them, mainly since the method of writing to the command line has changed between 2005 and future versions.

To Run:

* netload the PyAcadDotNet.dll
* issue the pyfile command
* browse to the folder you unziped to and select print.py

If you see a bunch of text strings dumped onto the commandline then it worked. If not please let me know. I'm doing some trickery to automatically add the AutoCAD managed dlls as references in python so that may be screwing things up.

Here is the source code for the dll if anyone is interested.
Code: [Select]
/*
PyAcadDotNet.cs
Copyright (c) 2005, Tim Riley (riltim@gmail.com)
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:

- Redistributions of source code must retain the above copyright notice, this list
  of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above copyright notice, this list
  of conditions and the following disclaimer in the documentation and/or other materials
  provided with the distribution.

- Neither the name Tim Riley nor the names of its contributors may be used to
  endorse or promote products derived from this software without specific prior written
  permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &AS IS& AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


using System;
using System.Collections;
using System.Windows.Forms;
using System.IO;
using System.Text;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;

using IronPython.Hosting;

namespace PyAcadDotNet
{
   public class AcadInterface : IExtensionApplication
   {   
       public Autodesk.AutoCAD.ApplicationServices.Application AcadApplication;
       
        public void Initialize()
       {
            CommandLinePrompts.Message("\nPyAcad.NET Loaded Successfully....");
            CommandLinePrompts.Message("\ntype 'pyhelp' for commands....");
       }
       
        public void Terminate()
        {
        //nothing to see here.
        }     
        delegate void AddReference(object assembly);

       [CommandMethod("pyfile", CommandFlags.Session)]
       public void pythonfile()
       {
        // Create a new instance of PythonEngine and set variables.
        PythonEngine engine = new PythonEngine();
        engine.AddToPath(Environment.CurrentDirectory);
        // Send Stdout and Stderr to the AutoCAD command line.
        engine.SetStandardOutput(new AcadCommandLine());
        engine.Import("clr");
       
       
        //lets load some AutoCAD assemblies.
        AddReference adr = engine.CreateMethod<AddReference>("clr.AddReference(assembly)");
        adr(typeof(BlockTableRecord).Assembly);
        adr(typeof(Editor).Assembly);
       
        // Display an OpenFileDialog and run the script.
    OpenFileDialog ofd = new OpenFileDialog();
    ofd.Filter = "Python files (*.py)|*.py|All files (*.*)|*.*" ;
    ofd.ShowDialog();
   
    // Run the file selected by the open file dialog box.
    //engine.ExecuteFile(ofd.FileName);
    CompiledCode cc = engine.CompileFile(ofd.FileName);
    cc.Execute();
   
       }
   }
   class AcadCommandLine : Stream
    //Modified version of a class coded by Mike Stall.
    {
        #region unsupported Read + Seek members
        public override bool CanRead
        {
            get { return false; }
        }

        public override bool CanSeek
        {
            get { return false; }
        }

        public override bool CanWrite
        {
            get { return true; }
        }

        public override void Flush()
        {
            // nop
        }

        public override long Length
        {
            get { throw new NotSupportedException("Seek not supported"); } // can't seek
        }

        public override long Position
        {
            get
            {
                throw new NotSupportedException("Seek not supported");  // can't seek
            }
            set
            {
                throw new NotSupportedException("Seek not supported");  // can't seek
            }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {           
            throw new NotSupportedException("Reed not supported"); // can't read
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotSupportedException("Seek not supported"); // can't seek
        }

        public override void SetLength(long value)
        {
            throw new NotSupportedException("Seek not supported"); // can't seek
        }
        #endregion

        public override void Write(byte[] buffer, int offset, int count)
        {
            // Very bad hack: Ignore single newline char. This is because we expect the newline is following
            // previous content and we already placed a newline on that.
            if (count == 1 && buffer[offset] == '\n')
                return;

            StringBuilder sb = new StringBuilder();
            while (count > 0)
            {
                char ch = (char) buffer[offset];
                if (ch == '\n')
                {
                    CommandLinePrompts.Message(sb.ToString() + "\n");
                    sb.Length = 0; // reset.
                }
                else if(ch != '\r')
                {
                    sb.Append(ch);
                }
 
                offset++;
                count--;               
            }
          if (sb.Length > 0)
                CommandLinePrompts.Message(sb.ToString()+ "\n");
        }
   }
}

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Assembly Test Request
« Reply #1 on: January 22, 2007, 08:28:01 PM »
Command: NETLOAD
Command: pyfile
Unknown command "PYFILE".  Press F1 for help.

in AC2007.

.. and your Initialize method did not execute.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

MickD

  • King Gator
  • Posts: 3637
  • (x-in)->[process]->(y-out) ... simples!
Re: Assembly Test Request
« Reply #2 on: January 22, 2007, 08:31:44 PM »
I tried it in 2006 with no luck, it was looking for the earlier version of the acad assemblies which was no suprise (attached output). All things being ok it should work in 2005 though (which I don't have installed sorry).
Good Luck.
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Assembly Test Request
« Reply #3 on: January 22, 2007, 08:36:48 PM »
Can anyone with .NET 2.0 Runtime and a version of AutoCAD greater than 2005 installed test an assembly for me?

not in AC2007 or AC2006

but works in AC2005 ..

Quote
Command: netload

PyAcad.NET Loaded Successfully....
type 'pyhelp' for commands....
Command: pyhelp
Unknown command "PYHELP".  Press F1 for help.

Command: pyfile

Command: pyfile
This is a test

This is also a test

4

Word

387420489

4.5
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8722
  • AKA Daniel
Re: Assembly Test Request
« Reply #4 on: January 22, 2007, 08:49:19 PM »
Got this in 2007 with vs 2005


Code: [Select]
This is a test
This is also a test
4
Word
387420489
4.5

attached the solution

« Last Edit: January 22, 2007, 08:51:32 PM by Danielm103 »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Assembly Test Request
« Reply #5 on: January 22, 2007, 08:55:57 PM »
hey ! .. that's cheating !! :lol:

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8722
  • AKA Daniel
Re: Assembly Test Request
« Reply #6 on: January 22, 2007, 08:57:54 PM »
 I only added your code  :-D

Code: [Select]
using AcEd = Autodesk.AutoCAD.EditorInput;

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Assembly Test Request
« Reply #7 on: January 22, 2007, 09:23:13 PM »
.. ;-) and a small recompile using the AC2007 references I 'spose ?
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8722
  • AKA Daniel
Re: Assembly Test Request
« Reply #8 on: January 22, 2007, 10:05:41 PM »
Busted,  :oops:
Sorry Tim, I didn’t mean to cheat, I just wanted to play with your python stuff.

Dan

TR

  • Guest
Re: Assembly Test Request
« Reply #9 on: January 22, 2007, 11:48:16 PM »
Thanks for all the testing guys. I am really looking to get this project back on it's feet and I would appreciate any help I can get. My main problem is I'm stuck with 2005 and I'd like to get this running with the newer versions of AutoCAD.

TR

  • Guest
Re: Assembly Test Request
« Reply #10 on: January 23, 2007, 12:51:01 AM »
So is it possible for me to create an assembly that can be compiled against any version of AutoCAD's managed dlls? Perhaps something similiar to C's ifdef statement or something?

MickD

  • King Gator
  • Posts: 3637
  • (x-in)->[process]->(y-out) ... simples!
Re: Assembly Test Request
« Reply #11 on: January 23, 2007, 12:56:42 AM »
That would be a feat! You may be able to do it by using ifdef's but you will still need to write different code for the different acad versions anyway and you would need to call in the references in your code instead of just importing them into your project which 'may' be easy enough.
I haven't looked at the 2007 api yet but I don't think there are too many changes from 2006 except for using .net 2 perhaps but 2005 should never have been released as a 'dependable' api, it did change considerably on the face of it once you start looking, teething problems I expect :)
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

TR

  • Guest
Re: Assembly Test Request
« Reply #12 on: January 23, 2007, 01:15:10 AM »
I'm doing very little interaction with the AutoCAD environment, mainly just mapping between the two. Which requires very little calls to the AutoCAD api.

If anyone is interested in hacking on this project I have created a svn repository. You can access it via:
Code: [Select]
svn checkout http://pyacaddotnet.googlecode.com/svn/trunk/ pyacaddotnet. If you have a google account I will give you commit access.

Project page is: http://code.google.com/p/pyacaddotnet/

Note: I'm using SharpDevelop so I'm not sure how this will interact with VS.
« Last Edit: January 23, 2007, 01:19:28 AM by Tim Riley »

TR

  • Guest
Re: Assembly Test Request
« Reply #13 on: January 23, 2007, 01:23:29 PM »
If anyone would be so kind as to run the following files through PyAcadDotNet for me it would be greatly appriciated. Note, you can open these with notepad to see that there is nothing harmful going on in them.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8722
  • AKA Daniel
Re: Assembly Test Request
« Reply #14 on: January 23, 2007, 01:43:01 PM »
here's what I had with the solution built for 2007

Dan

« Last Edit: January 23, 2007, 01:46:42 PM by Danielm103 »

TR

  • Guest
Re: Assembly Test Request
« Reply #15 on: January 23, 2007, 01:50:23 PM »
Thanks a lot Dan. It's somewhat comforting that the code is working with newer versions of AutoCAD (with only a slight modification and recompile by you). The first file you ran is supposed to dump all the layer names to the command line, I assume you were on a new drawing and that's why it only dumped '0'. Also I assume you saw a windows form when running winforms.py.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8722
  • AKA Daniel
Re: Assembly Test Request
« Reply #16 on: January 23, 2007, 01:55:01 PM »
Yes sir you got it. Pretty interesting project.
Dan

TR

  • Guest
Re: Assembly Test Request
« Reply #17 on: January 23, 2007, 02:11:19 PM »
Thanks. The goal is to give AutoCAD programmers the ability to use AutoCAD's .NET API with any .NET library and/or almost any Python library (as long as it wasn't written in C). The real advantage is the ability to quickly hack up and test code without bothering with building, launching AutoCAD and testing. Instead we can just test, fix, test, fix, test, fix, etc. in a single session of AutoCAD.

The current stage is more of a proof of concept than anything but hopefully it can reach a point when it's production ready. However if you find the project interesting you are more than welcome to hack on it if you want.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8722
  • AKA Daniel
Re: Assembly Test Request
« Reply #18 on: January 23, 2007, 02:12:51 PM »
I just noticed an error when I closed the drawing though. I will run each one to see if I can’t find the culprit


FATAL ERROR:  Unhandled Access Violation Reading 0xf0000000 Exception at 136b23ch

01/23/2007 at 12:10:20.666  Drawing:
-------------

TR

  • Guest
Re: Assembly Test Request
« Reply #19 on: January 23, 2007, 07:58:17 PM »
You can probably attribute that error to sloppy translations of C# to python for the examples on my part. I did them rather quickly.

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8722
  • AKA Daniel
Re: Assembly Test Request
« Reply #20 on: January 24, 2007, 02:22:16 AM »
I did find the error, it was in layer.py not disposing the transaction manager.

I also made a few mods to your code just for fun(for 2007). I added using() to PythonEngine and AcadCommandLine because they are both disposable


Code: [Select]
/*
PyAcadDotNet.cs
Copyright (c) 2005, Tim Riley (riltim@gmail.com)
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:

- Redistributions of source code must retain the above copyright notice, this list
  of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above copyright notice, this list
  of conditions and the following disclaimer in the documentation and/or other materials
  provided with the distribution.

- Neither the name Tim Riley nor the names of its contributors may be used to
  endorse or promote products derived from this software without specific prior written
  permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &AS IS& AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Windows.Forms;
using System.IO;
using System.Text;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
using Autodesk.AutoCAD.EditorInput;

using AcEd = Autodesk.AutoCAD.EditorInput;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;

using IronPython.Hosting;

namespace PyAcadDotNet
{
  public class AcadInterface : IExtensionApplication
  {
    static internal AcEd.Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;

    public void Initialize()
    {
      ed.WriteMessage("\nPyAcad.NET Loaded Successfully....");
      ed.WriteMessage("\ntype 'pyhelp' for commands....");
    }

    public void Terminate()
    {
      this.Terminate();
    }

    internal delegate void AddReference(object assembly);

    [CommandMethod("pyfile", CommandFlags.Session)]
    static public void pythonfile()
    {
      using (PythonEngine engine = new PythonEngine())
      {
        using (AcadCommandLine myCommandLine = new AcadCommandLine())
        {
          try
          {
            // Create a new instance of PythonEngine and set variables.
            engine.AddToPath(Environment.CurrentDirectory);
            // Send Stdout and Stderr to the AutoCAD command line.
            engine.SetStandardOutput(myCommandLine);
            engine.Import("clr");

            //lets load some AutoCAD assemblies.
            AddReference adr = engine.CreateMethod<AddReference>("clr.AddReference(assembly)");
            adr(typeof(BlockTableRecord).Assembly);
            adr(typeof(Editor).Assembly);

            // Display an OpenFileDialog and run the script.
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "Python files (*.py)|*.py|All files (*.*)|*.*";
            ofd.ShowDialog();

            // Run the file selected by the open file dialog box.
            //engine.ExecuteFile(ofd.FileName);
            CompiledCode cc = engine.CompileFile(ofd.FileName);
            cc.Execute();
          }
          catch (System.Exception e)
          {
            ed.WriteMessage(e.ToString());
          }
        }
      }
    }
  }

  //
  public class AcadCommandLine : Stream
  //Modified version of a class coded by Mike Stall.
  {
    public AcadCommandLine()
    {
      //constructor
    }

    #region unsupported Read + Seek members
    public override bool CanRead
    {
      get { return false; }
    }

    public override bool CanSeek
    {
      get { return false; }
    }

    public override bool CanWrite
    {
      get { return true; }
    }

    public override void Flush()
    {
      //
    }

    public override long Length
    {
      get { throw new NotSupportedException("Seek not supported"); } // can't seek
    }

    public override long Position
    {
      get
      {
        throw new NotSupportedException("Seek not supported");  // can't seek
      }
      set
      {
        throw new NotSupportedException("Seek not supported");  // can't seek
      }
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
      throw new NotSupportedException("Reed not supported"); // can't read
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
      throw new NotSupportedException("Seek not supported"); // can't seek
    }

    public override void SetLength(long value)
    {
      throw new NotSupportedException("Seek not supported"); // can't seek
    }
    #endregion

    public override void Write(byte[] buffer, int offset, int count)
    {
      try
      {
        // Very bad hack: Ignore single newline char. This is because we expect the newline is following
        // previous content and we already placed a newline on that.
        AcEd.Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;

        if (count == 1 && buffer[offset] == '\n')
          return;

        StringBuilder sb = new StringBuilder();
        while (count > 0)
        {
          char ch = (char)buffer[offset];
          if (ch == '\n')
          {
            ed.WriteMessage(sb.ToString() + "\n");
            sb.Length = 0; // reset.
          }
          else if (ch != '\r')
          {
            sb.Append(ch);
          }

          offset++;
          count--;
        }
        if (sb.Length > 0)
          ed.WriteMessage(sb.ToString() + "\n");
      }
      catch (System.Exception e)
      {
        throw e;
      }
    }
  }
}


TR

  • Guest
Re: Assembly Test Request
« Reply #21 on: January 24, 2007, 10:58:24 AM »
Dan:

That looks really good. I'm really not too good with C# so thanks for fixing those few problems.

Seeing that that only thing that's stopping this code file from being compiled for both AutoCAD 2005 and 2006/2007 is the way it interacts with AutoCAD's command line. Is there any way to check what versions of acmgd.dll we're compiling against and issue the correct interface to the command line that way. This way we would could keep everyone working on a single project instead of forking it to run on 2007. I'm not sure if my compiler will complain though about missing assemblies.

MickD

  • King Gator
  • Posts: 3637
  • (x-in)->[process]->(y-out) ... simples!
Re: Assembly Test Request
« Reply #22 on: January 24, 2007, 03:49:38 PM »
The problem is Tim that when acad loads the assembly it will look into the metadata in your dll to find the dependencies which means it will only work with a certain version of the assembly it was compiled with (it will look for the same version that version of acad uses). This is to avoid the dll hell of the past and means you can have various versions of the same assembly in the GAC without conflicts, it looks at each to find the correct version using reflection/metadata or similar.
So, the short answer is you will either need a separate project for each version or you will need some funky pre-processor code to 'switch' which versions you wish to compile to use the appropriate code, either way you will need the assemblies for each version of acad and produce a separate dll for each version. You will need them as you are 'using' them in your C# code.
hth
« Last Edit: January 24, 2007, 03:50:56 PM by MickD »
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

Draftek

  • Guest
Re: Assembly Test Request
« Reply #23 on: January 24, 2007, 04:39:03 PM »
Yeah, The only other option I could think of is late binding but I wouldn't recommend it for much interaction. I have an example posted somewhere here....

I have a detail library program in which the only autocad function is to insert a drawing. I used late binding in c# and it works with v2000 - v2007.

TR

  • Guest
Re: Assembly Test Request
« Reply #24 on: January 24, 2007, 05:29:31 PM »
Mick:

I'm not looking for a single .dll to run across all across all versions of AutoCAD but instead a project that will compile against newer versions of the .NET managed assemblies. I'm fine distributing a seperate dll for each version of AutoCAD. So far the only conflict I'm having in the project is it's interaction with AutoCAD's command line. In fact the C# project will be doing very minimal interaction with AutoCAD's managed libraries. The python files will but that's beyond the scope of the C# project.

In the python world we can do tricks like:
Code: [Select]
try:
    import LatestAndGreatestLib
except importerror:
   import OlderAndLessGreatLib
   'some code that will make it somewhat compatible with the new lib

This allows you to use the newer version of the library if it's available but fall back upon an older lib if necessary.

Can we do something like this?:
Code: [Select]
try
{
    using AcEd = Autodesk.AutoCAD.EditorInput;
}
catch (System.Exception e)
{
    //some code here to make it compatible.
}
« Last Edit: January 24, 2007, 05:30:32 PM by Tim Riley »