Hi all,
I'm trying to automate importing Microstation files into AutoCad (and then doing interesting things with them). I'm stuck on the import, as it keeps throwing an "Invalid Argument Exception".
I've beaten my head against this one... for the filename, I've thrown empty strings, "hello world" strings, ensured that the string points to a valid file, ensured that the string points to a vaild Microstation file... for the scale factor, I've thrown constants, symbolic constants, variable doubles... and where I think the error lies, the insertion point, I've thrown Points, Point2d's, Point3d's, arrays of integers, arrays of doubles, and AcadPoints, and all of the above even cast as objects.
Supposedly, the signature for import is:
object IAcadDocument.Import(string FileName, object InsertionPoint, double ScaleFactor)
but the <object InsertionPoint> is throwing me... what kind of object is wanted? I'm assuming an AcadPoint but how do I know?
The following is a complete working program; you'll just have to add the two autocad references.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
namespace Snippet
{
class Program
{
static void Main(string[] args)
{
const string DEFAULTACADDWG = "c:\\users\\greg.mathews\\0.dwg";
string fullname = "c:\\users\\greg.mathews\\0.dgn";
const string strProgId = "AutoCAD.Application.18";
double[] zerozero = { 0.0, 0.0, 0.0 };
double SCALEFACTORONE = 1.0;
AcadApplication acAppComObj = (AcadApplication)Marshal.GetActiveObject(strProgId);
AcadDocument newdoc = acAppComObj.Documents.Open(DEFAULTACADDWG);
AcadDatabase db = newdoc.Database;
AcadPoint insertPoint = db.ModelSpace.AddPoint(zerozero);
Console.WriteLine("Importing: " + fullname);
try
{
newdoc.Import(fullname, insertPoint, SCALEFACTORONE); //<<< Exception thrown here >>>
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
and the exception detail
System.ArgumentException was unhandled
HelpLink=C:\Program Files\AutoCAD Map 3D 2010\HELP\OLE_ERR.CHM#-2145320901
Message=Invalid argument
Source=AutoCAD
StackTrace:
at Autodesk.AutoCAD.Interop.AcadDocumentClass.Import(String FileName, Object InsertionPoint, Double ScaleFactor)
at Snippet.Program.Main(String[] args) in c:\users\greg.mathews\documents\visual studio 2010\Projects\Snippet\Snippet\Program.cs:line 32
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
Versions I'm using:
Microsoft Visual Studio 10
Target Framework is .Net 3.5
AutoCAD Map3D 2010
c:\users\greg.mathews\0.dwg is a valid, empty, autocad 2010 drawing
c:\users\greg.mathews\0.dgn is a valid 168 kb Microstation file
(Obviously the intent is not to use hard coded filenames, these are for debug purposes. I'm also running as a Windows project rather than a Console project, but the exception is the same.)
Anyway. Thanks in advance for taking time to read.
Ah, "ArgumentException", isn't it obvious enough: you passed wrong type of data into one of the argumnets of the AcadDocumkent.Import() method.
Look at the method's signature carefully: Import(string FileName, object InsertionPoint, double ScaleFactore).
The second argument is the equivalent of "Variant" in VBA, representing a 3-element array of doubles, NOT an AcadPoint object as you did!
Norman Yuan
Sounds reasonable.
Next (dumb) question... what's the C# equivalent of a VBA variant? I've already tried casting it as an object, i.e.
newdoc.Import(fullname, (object)insertPoint, SCALEFACTORONE);
or, just passing an array of doubles
newdoc.Import(fullname, zerozero, SCALEFACTORONE);
or, a typecast array of doubles
newdoc.Import(fullname, (object)zerozero, SCALEFACTORONE);
I always hope I'm not being obtuse or stubborn... even if I really am!
-Greg
I've made some progress, but it's not yet solved.
If I cast a two-dimensional array to an object, like so...
double[] zerozero = {0.0, 0.0};
newdoc.Import(fullname, (object)zerozero, SCALEFACTORONE);
I get a different error... no longer "InvalidArgument"; I'm now gettnig "Incorrect number of elements in SafeArray". Which means I'm getting further; but if it pukes on three elements, and pukes differently on two elements... it's still puking, and I'm still stuck.
-GM
System.Runtime.InteropServices.COMException was unhandled
HelpLink=C:\Program Files\AutoCAD Map 3D 2010\HELP\OLE_ERR.CHM#-2145320944
Message=Incorrect number of elements in SafeArray
Source=AutoCAD.Application
ErrorCode=-2145320944
StackTrace:
at Autodesk.AutoCAD.Interop.Common.AcadModelSpaceClass.AddPoint(Object Point)
at MS___Acad_Import.FormMain.CadImport() in C:\Users\greg.mathews\Documents\Visual Studio 2010\Projects\MS - Acad Import\MS - Acad Import\FormMain.cs:line 203
at MS___Acad_Import.FormMain.buttonRun_Click(Object sender, EventArgs e) in C:\Users\greg.mathews\Documents\Visual Studio 2010\Projects\MS - Acad Import\MS - Acad Import\FormMain.cs:line 45
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at MS___Acad_Import.Program.Main() in c:\users\greg.mathews\documents\visual studio 2010\Projects\MS - Acad Import\MS - Acad Import\MS - Acad Import.cs:line 21
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.Runtime.Hosting.ManifestRunner.Run(Boolean checkAptModel)
at System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly()
at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext, String[] activationCustomData)
at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext)
at System.Activator.CreateInstance(ActivationContext activationContext)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
From norman.yuan reply and your error it would seem it wants 3 elements
double[] zerozero = {0.0, 0.0, 0.0};
Yeah. That makes sense. Except that's not the case.
double[] zerozero = {0.0, 0.0, 0.0}; // gives me Invalid Argument
double[] zerozero = {0.0, 0.0}; // gives me Incorrect number of elements in SafeArray
Using anything as the second argument gives me the Invalid Argument array. The only thing that gives me the Incorrect Number error is a a two dimensional array of doubles, cast to an object.
Thanks for your continued effort, though!
The insertion point should be an double array of 3 elements.
The sample code (a console app that automate AutoCAD and does the importing) work OK with my Acad 2009. Since I do not have *.dgn file, I used *.wmf, which should not matter, in term of inserting error you have gotten.
using System; using System.IO; using Autodesk.AutoCAD.Interop; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { AcadApplication app =null; try { app = new AcadApplicationClass(); app.Visible = true; } catch(Exception ex) { Console.WriteLine("Canot start AutoCAD: " + ex.Message ); return; } string file = "E:\\Temp\\test.wmf"; if (!File.Exists(file)) { Console.WriteLine("Cannot find file: " + file); return; } Console.WriteLine("Press any key to start importing..."); Console.ReadLine(); double[] pt = new double[] { 0.0, 0.0, 0.0 }; AcadDocument doc = null; if (app.Documents.Count > 1) { doc = app.ActiveDocument; } else { doc = app.Documents.Add("acad.dwt"); } if (doc == null) { Console.WriteLine("No drawing is open"); return; } try { doc.Import(file, (object)pt, 1.0); } catch (Exception ex) { Console.WriteLine("Importing failed: " + ex.Message); Console.ReadLine(); return; } Console.WriteLine("Importing done..."); Console.ReadLine(); } } }
Norman Yuan
Sadly even your code is still failing for me, on versions 9,10, and 11. The only line I've changed is the filename that is being imported. I'm using Visual Studio 2010, if that makes a difference. I've tried using a target framework of both .NET 3.5 and .NET 4.0
This code is from Kerry Brown at http://www.theswamp.org/index.php?topic=34982.0 with a litle a change so thank him.
[CommandMethod("ImportDXF")] public void ImportDXF() { Document doc = Application.DocumentManager.MdiActiveDocument; AcadDocument comDoc = (Autodesk.AutoCAD.Interop.AcadDocument)doc.AcadDocument; double myScale = 1; Point3d p1 = Point3d.Origin; double[] ptArray = p1.ToArray(); comDoc.Import(@"C:\Users\Jeff\My Documents\XrefTest.dxf", (object)ptArray, myScale); }
So, clearly, I'm being troublesome. Rather than
Point3d p1 = Point3d.Origin;
I'm trying to use
AcadPoint InsertionPoint = db.ModelSpace.AddPoint(zerozero);
But I'll try to get the Point3d to work
I have a crazy question. Can you duplicate the Invalid Argument Exception or am I the only one seeing that?
Have you really read my first reply?
You CANNOT pass an AcadPoint (e.g. the variable "insertPoint" in your code) to the Import() method's second argument! AcadPoint is an AcadEntity (a visual presentation of a point), not a geometric point (an array of 3 double element).
Also, since you do out-process Acad automation, you CANNOT use Point3d as the other post suggest: his code sample is run inside AutoCAD (NETLOADED).
When you said the code I showed is "sadly" not working, I can hardly believe it. Have you done debugging to locate the offending code line? What error did you get? Can you show your EXACTcode that simliar to mine, but not working?
Norman Yuan
norman.yuan routine works for A2011 & VS2010 for me.
Thanks for the post Norman
Norman - thanks for your help.
using System;
using System.IO;
using Autodesk.AutoCAD.Interop;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
AcadApplication app = null;
try
{
app = new AcadApplicationClass();
app.Visible = true;
}
catch (Exception ex)
{
Console.WriteLine("Canot start AutoCAD: " + ex.Message);
return;
}
//string file = "E:\\Temp\\test.wmf";
string file = "c:\\users\\greg.mathews\\documents\\1.dgn";
if (!File.Exists(file))
{
Console.WriteLine("Cannot find file: " + file);
return;
}
Console.WriteLine("Press any key to start importing...");
Console.ReadLine();
double[] pt = new double[] { 0.0, 0.0, 0.0 };
AcadDocument doc = null;
if (app.Documents.Count > 1)
{
doc = app.ActiveDocument;
}
else
{
doc = app.Documents.Add("acad.dwt");
}
if (doc == null)
{
Console.WriteLine("No drawing is open");
return;
}
try
{
doc.Import(file, (object)pt, 1.0);
}
catch (Exception ex)
{
Console.WriteLine("Importing failed: " + ex);
Console.ReadLine();
return;
}
Console.WriteLine("Importing done...");
Console.ReadLine();
}
}
}
And, my error:
Importing failed: System.ArgumentException: Invalid argument at Autodesk.AutoCAD.Interop.AcadDocumentClass.Import(String FileName, Object InsertionPoint, Double ScaleFactor) at ConsoleApplication1.Program.Main(String[] args) in C:\Users\greg.mathews\Documents\Visual Studio 2010\Projects\Snippet2\Snippet2\Program.cs:line 60
Jeffrey - thank you so much, that's it.
Which of course means import() is useless. I can manually import a .dgn, but I can't do it through COM.
/shakes fist.
(This entire time, the insertion point wasn't the problem. It was the filename.)
Hmm, that is interesting. The code is the same as mine that proves working (with my Acad2009 and Jeff's Acad2011).
So, what could it be then?
Can you export a *.wmf file from your AutoCAD and then import it manually and then by the code exactly as mine, to just prove that the code, even works for me and Jeff, but still not for you?
Or, are you using 64-bit Acad? No that I know that would be the cause as I know, just try to find out what difference between the your Acad and mine (and Jeff's).
Norman Yuan
Why do it as intended, when brute force works.
newdoc.SendCommand("Import " + fullname + "\n\n\n\n");
Works just fine. I still consider that this forum thread indicates a defect, but WorkAround.Exists = true. You know, it also might just be something spiteful between Autodesk and Bentley.
Thanks everyone for your time.
i get a fatal error, when i try to import a dgn file this way
works fine with dxf