Autodesk Community Tips- ADNオープン
Autodesk Community Tipsではちょっとしたコツ、やり方、ショートカット、アドバイスやヒントを共有しています。
ソート順:
質問 AutoCAD Plant3D .net API でデータマネージャで表示されているガスケットのプロパティ情報を取得したい。 回答 ガスケット(≒ コネクタ)の場合、Connector.AllSubPartsからサブパーツ数を取得し、DataLinksManager.MakeAcPpObjectId()をsubIndexを指定してrowIdを取得後にDataLinksManager.GetAllProperties()を実行することでプロパティを取得することが可能となります。   以下は、選択したガスケットのプロパティ情報を取得するC#のサンプルコードとなります。 [CommandMethod("GetPipingProperties")] public void GetPipingProperties() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; PromptEntityResult res = ed.GetEntity("Pick Object obtain properties : "); if (res.Status == PromptStatus.OK) { ObjectId objectId = res.ObjectId; PlantProject currentProj = PlantApplication.CurrentProject; PipingProject pipingProj = (PipingProject)currentProj.ProjectParts["Piping"]; DataLinksManager dlm = pipingProj.DataLinksManager; int rowId = dlm.FindAcPpRowId(res.ObjectId); List<KeyValuePair<string, string>> properties; properties = dlm.GetAllProperties(rowId, true); for (int i = 0; i < properties.Count; i++) ed.WriteMessage("\nProperty name:" + properties[i].Key + " = " + properties[i].Value); Database trDatabase = objectId.Database; using (Transaction tr = trDatabase.TransactionManager.StartTransaction()) { Connector connector = tr.GetObject(objectId, OpenMode.ForRead, false, true) as Connector; if (connector != null) { SubPartCollection subPartCollection = connector.AllSubParts; int index = 1; foreach (object connectorSubPart in subPartCollection) { int acPcRowId = dlm.FindAcPpRowId(dlm.MakeAcPpObjectId(objectId, index)); List<KeyValuePair<string, string>> subProps = dlm.GetAllProperties(acPcRowId, true); if (subProps != null) { foreach(var subProp in subProps) ed.WriteMessage("\nProperty name:" + subProp.Key + " = " + subProp.Value); } index++; } } } } }
記事全体を表示
Issue AutoCAD .NET API:ダウンロードしたアセンブリが NETLOAD 出来ない - Autodesk Community の内容に沿ってブロック解除したアドイン アプリ アセンブリがロード出来ません。  なぜでしょうか?     Solution アセンブリ ファイルのブロックを解除しても改善が見られないようでしたら、SECURITYOPTIONS コマンドで [セキュリティ オプション] ダイアログの信頼できるパスにアセンブリ ファイルの配置パスをに追加してみてください。     セキュリティ オプションを変更したら、AutoCAD を再起動して、再度、NETLOAD してみてください。   ご参考: AutoCAD 2016 のセキュリティとアドインのデジタル署名 - Technology Perspective from Japan (typepad.com) アドイン ロード時の警告ダイアログ抑止 - Technology Perspective from Japan (typepad.com)
記事全体を表示
Question 以下のサンプルコードの様に、AutoCAD .net APIで作成した球体のソリッドで、GUIのプロパティ表示「ジオメトリ」に中心座標や半径が表示されない。 「ジオメトリ」が表示されるようにするにはどうしたらよいでしょうか。 Document dc = Application.DocumentManager.MdiActiveDocument; Database db = dc.Database; Editor ed = dc.Editor; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable acBlkTbl; acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord acBlkTblRec; acBlkTblRec = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; double rd, x, y, z; string sLayer; short lyColor; rd = 1.0; x = 0.0; y = 0.0; z = 0.0; using (Solid3d sphere = new Solid3d()) { sphere.CreateSphere(rd); Point3d location = new Point3d(x, y, z); sphere.TransformBy(Matrix3d.Displacement(location - Point3d.Origin)); acBlkTblRec.AppendEntity(sphere); tr.AddNewlyCreatedDBObject(sphere, true); } tr.Commit(); }   Answer   APIから作成した球の場合には、タイププロパティ(GUIではAutoCADのコマンドから作成した球のプロパティを参照するとジオメトリの項目に表示されるソリッドタイプ)が設定されていないことが、GUIにジオメトリの項目が表示されない原因です。   このタイププロパティはAutoCADのコマンドから球や円柱等のプリミティブなソリッド形状を作成した場合にのみ設定され、Object ARX .net、ActiveX 等のAPIから3Dソリッドを作成した場合にはこのプロパティは設定されません。   回避方法としては、以下のサンプルコードの様に.netのコードからEditor.Command()メソッドを用いて、Shpereコマンドを実行する方法となります。   Document dc = Application.DocumentManager.MdiActiveDocument; Database db = dc.Database; Editor ed = dc.Editor; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable acBlkTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord acBlkTblRec = tr.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; acLyrTbl = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable; double rd, x, y, z; rd = 1.0; x = 0.0; y = 0.0; z = 0.0; Point3d location = new Point3d(locX, locY, locZ); ed.Command("_.sphere", location, rd, ""); Solid3d sphere = tr.GetObject(ed.SelectLast().Value.GetObjectIds()[0], OpenMode.ForWrite) as Solid3d; tr.Commit(); }    
記事全体を表示
Issue AutoCAD .NET API で SURFEXTEND[延長サーフェス] コマンド と同じような処理は出来ますか?   Solution サーフェス エッジの延長は、Surface.ExtendEdges メソッド で実装することが出来ます。   次の C# コードは、選択した1つのサーフェス エッジを 100 ポイント延長するものです。 SURFEXTEND[延長サーフェス] コマンド と同様に、エッジの延長でサーフェスに自己交差すると延長に失敗する場合があります。   var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; var db = doc.Database; var ed = doc.Editor; try { PromptSelectionOptions pso = new PromptSelectionOptions(); pso.MessageForAdding = "\n延長するサーフェス エッジを選択:"; pso.SingleOnly = true; pso.SinglePickInSpace = true; pso.ForceSubSelections = true; PromptSelectionResult psr = ed.GetSelection(pso); if (psr.Status != PromptStatus.OK) return; SelectionSet ss = psr.Value; SelectedObject surfedge = ss[0]; ObjectId surfId = ss.GetObjectIds()[0]; if (!surfId.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(Autodesk.AutoCAD.DatabaseServices.Surface)))) { ed.WriteMessage("\nサーフェス エッジを選択を選択してください ..."); return; } using (var tr = db.TransactionManager.StartTransaction()) { var surf = tr.GetObject(surfId, OpenMode.ForWrite) as Autodesk.AutoCAD.DatabaseServices.Surface; if (surf != null) { if (surfedge.GetSubentities()[0].FullSubentityPath.SubentId.Type != SubentityType.Edge) { ed.WriteMessage("\n{0} が選択されました ...\nサーフェス エッジを選択を選択してください ...", surfedge.GetSubentities()[0].FullSubentityPath.SubentId.Type); tr.Abort(); return; } FullSubentityPath[] edges = { surfedge.GetSubentities()[0].FullSubentityPath }; surf.ExtendEdges(edges, 100.0, Autodesk.AutoCAD.DatabaseServices.Surface.EdgeExtensionType.ExtendEdge, true); } tr.Commit(); } } catch (Autodesk.AutoCAD.BoundaryRepresentation.Exception ex) { ed.WriteMessage("\nエラー: {0}\r\n at {1}", ex.Message, ex.StackTrace); }   なお、SURFEXTEND[延長サーフェス] コマンド によるサーフェス延長とは異なり、Surface.ExtendEdges メソッド  による延長では、延長されたサーフェス部分は、無条件に元のサーフェスに結合された状態になります。 SURFEXTEND[延長サーフェス] コマンド では、延長されたサーフェスを元のサーフェスと結合(合成)するか、別のサーフェスとして追加するか(既定値)をコマンド プションで指定することが出来ます。  
記事全体を表示
Issue 寸法を分解すると寸法値にあたる文字が MText オブジェクトとして分解されます。 この MText オブジェクトについて、MText.Contents プロパティから寸法値の文字を取得すると、寸法値にないコードが返される場合があります。   例:\A1;57,{\H0.7x;\S66^;}   このコードはどのようなものでしょうか?   Solution このコードは、マルチテキストの整形するために用意された「書式コード」と呼ばれるコードで、AutoCAD のオンラインヘルプ ページで内容を確認することが出来ます。 AutoCAD 2024 ヘルプ | 他のテキスト エディタの書式コード リファレンス | Autodesk AutoCAD .NET API で MText オブジェクトの文字列の内容を確認する場合には、Contents プロパティが書式コード付きの内容を、Text プロパティが書式コードを削除した内容を返すので、用途に応じてプロパティを使い分けることが出来ます。   Database db = HostApplicationServices.WorkingDatabase; Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; PromptEntityOptions peo = new PromptEntityOptions("\nMText オブジェクトを選択:"); peo.SetRejectMessage("\nMText オブジェクトではありません."); peo.AddAllowedClass(typeof(MText), true); PromptEntityResult pent = ed.GetEntity(peo); if (pent.Status != PromptStatus.OK) { return; } using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent = tr.GetObject(pent.ObjectId, OpenMode.ForRead) as Entity; ed.WriteMessage("\nObject Type : " + ent.GetType().ToString()); MText mtext = (MText)ent; ed.WriteMessage("\n\tMText Text : {0}", mtext.Text); ed.WriteMessage("\n\tMText Contents : {0}", mtext.Contents); tr.Commit(); }   寸法オブジェクトを分解せずに、AutoCAD .NET API :分解せずに寸法文字の情報を取得するには? (autodesk.co.jp) の方法も利用することが可能です。 
記事全体を表示
現象 Autocad 2022のVBAでCreateObject("VL.Application.16")を実行すると「実行エラー-2147220999(800701f9): オートメーション エラーです。DLLでエラーが発生しました」となってします。 同じ処理は、旧バージョンのAutoCADでは問題なく動作をしていました。   解決策 AutoCAD 2022以降のバージョンでは、CreateObject()で"VL.Application.16"を取得できないように変更がされております。VBAのプログラムから、AutoCADのActiveX APIで直接オブジェクトを取得するAPIが存在しないAutoCADのCOMモデル内のオブジェクトを取得する場合には、CreateObject()ではなくAutoCAD ApplicationオブジェクトのGetInterfaceObject メソッド(ActiveX) を利用することを推奨いたします。   今回の場合、以下のサンプルコードの様に変更することで対応が可能です。 なお、以下サンプルコードの変数appはAutoCADのActiveX APIでのApplicationオブジェクトが格納された変数となります。   Set VL = app.GetInterfaceObject("VL.Application.16")  
記事全体を表示
Issue オブジェクト イベント ハンドラを使わずに、特定のオブジェクト タイプの編集を抑止することは出来ますか?   Solution 特定のオブジェクト タイプ(クラス)の編集を抑止する目的では、ObjectARX と .NET API で利用することが出来るオーバールール(Overrule)プロトコルを使用して、既定の振る舞いを変更することが可能です。   次の C# コードは、Open メソッドをオーバールール プロトコルでオーバライドし、書き込みモードのオブジェクト オープン時に例外を発生させることで、円弧(ARC)の編集を抑止する例となります。MyCommand コマンドの実行でオーバールールを有効化したり、無効化したりしています。  using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.GraphicsInterface; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using System; using System.Windows.Controls; [assembly: CommandClass(typeof(AutoCAD_CSharp_plug_in1.MyCommands))] namespace AutoCAD_CSharp_plug_in1 { public class MyCommands { public class OpenOverrule : ObjectOverrule { public override void Open(DBObject dbObject, OpenMode mode) { if (mode == OpenMode.ForWrite) { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; ed.WriteMessage("\nModifying ARC is not allowed..."); base.Open(dbObject, mode); ed.Regen(); throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NotApplicable); } } } static OpenOverrule _overrule = null; [CommandMethod("MyCommand")] static public void MyCommand() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; if (_overrule == null) { _overrule = new OpenOverrule(); ObjectOverrule.AddOverrule(RXObject.GetClass(typeof(Arc)), _overrule, false); ObjectOverrule.Overruling = true; ed.WriteMessage("\nBegin modifying ARC overrule"); } else { ObjectOverrule.RemoveOverrule(RXObject.GetClass(typeof(Arc)), _overrule); _overrule.Dispose(); _overrule = null; ed.WriteMessage("\nEnd modifying ARC overrule"); } } } }  
記事全体を表示
Question Vault APIで、Vaultエクスプローラの「コピーデザイン」コマンドでコピーされたファイルに対してプロパティの追加等の特定の処理を行いたい。 Answer Vault APIを用いて、Vault エクスプローラのカスタムエクステンションを作成することにより、Vaultエクスプローラでのコマンドの実行とコマンドの終了をイベントとして受け取ることが出来ます。   また、Vault APIのWebサービスコマンドイベントを利用することでVaultへのファイルの追加や削除などのVault操作が行われたことをイベントとして受け取ることが可能です。   一見、これらのイベントを組み合わせることで、「コピーデザイン」コマンドの実行開始前~終了の間に、追加されたファイルをWebサービスコマンドイベントのファイル追加イベントに検出することで「コピーデザイン」コマンドにて、コピーされたファイルに対して特定の操作を行うことが可能なように思われます。   ただ、残念ながら、Vault 2021以降「コピーデザイン」機能の拡張が行われ、「コピーデザイン」コマンドは「コピーデザイン」を行う対象を選択するモードレスイアログを起動するコマンドとなり、実際のコピー処理はモードレスアログ上で操作で行われる形となったため、「コピーデザイン」コマンドの開始~終了により追加されたファイルを判定するという方法が取れなくなっています。   この要望を完全に満たすカスタマイズを行うことが出来ませんが、以下のサンプルコードの様に   1.IExplorerExtensionを実装したVault Explororのエクステンションを作成 2.OnStartupにてコマンドの開始(CommandBegin)およびCopy Designダイアログのクローズ(CopyDesignDialogClosed)のイベントハンドラを設定 3.CommandBeginイベントハンドラにて対象のコマンドがCopyDesignの場合、AddFileEventsハンドラを設定 4.設定したAddFileEventsイベントハンドラにて追加がされたファイルの情報を収集 5.CopyDesignDialogClosedイベントハンドラにて、収集したファイルの情報(追加されたファイル)に対して処理を行う   といった形で、コピーデザインダイアログのダイアログが表示されている間にVaultに追加されたファイル情報を収集して処理を行うことは可能です。 ただし、コピーデザインダイアログがモードレスダイアログであり、ダイアログ表示中にもVaultエクスプローラや別の画面も操作可能であるためコピーデザインダイアログの外でVaultに追加されたファイルの情報も収集してしまいます。   このため、コピーデザインダイアログを表示後、デザインをコピーする際にはダイアログ外での操作を行わないといった制限を、運用で制御できる状況であれば利用可能な方法となる点に注意が必要です。 public class HelloWorldCommandExtension : IExplorerExtension { private List<Tuple<long, string>> m_addedFiles = null; private static string COPY_DESING_COMMAND_ID = "CopyDesign"; public void OnStartup(IApplication application) { application.CommandBegin += new EventHandler<CommandBeginEventArgs>(application_CommandBegin); Autodesk.DataManagement.Client.Framework.Vault.Forms.Library.CopyDesignDialogClosed += new EventHandler(CopyDesignDialogClosed); } void application_CommandBegin(object sender, CommandBeginEventArgs e) { if (e.CommandId == COPY_DESING_COMMAND_ID) { m_addedFiles = new List<Tuple<long, string>>(); DocumentService.AddFileEvents.GetRestrictions += new EventHandler<AddFileCommandEventArgs>(AddFileEvents_GetRestrictions); } } void CopyDesignDialogClosed(object sender, EventArgs e) { DocumentService.AddFileEvents.GetRestrictions -= new EventHandler<AddFileCommandEventArgs>(AddFileEvents_GetRestrictions); //Update properties for added files. m_addedFiles.ForEach((item) =>{ }); m_addedFiles.Clear(); m_addedFiles = null; } void AddFileEvents_GetRestrictions(object sender, AddFileCommandEventArgs e) { m_addedFiles.Add(Tuple.Create(e.FolderId, e.FileName)); }  
記事全体を表示
質問 .Net で、Inventor API AutoCADBlock.GetPromptTextValues()でブロックの属性値が取得できない。 VBAからはAutoCADBlock.GetPromptTextValues()で値が取得できているため、データの問題ではありません。.Netからは、AutoCADBlock.GetPromptTextValues()を利用できないのでしょうか? 回答 .Net言語からAutoCADBlock.GetPromptTextValues()を利用する場合、outパラメータの引数をメソッド実行前にstring配列で初期化する必要があります。   以下はC#の場合のサンプルとなります。 object tags = new string[] { }; object attrs = new string[] { }; oAcadBlock.GetPromptTextValues(out tags, out attrs);
記事全体を表示
Issue サーフェスの外形エッジやパス形状をオブジェクトとして再作成することは出来ますか?   Solution サーフェスの外形エッジやパス形状はサーフェスのサブエンティティ(FullSubentityPath)から形状を模倣して再作成することが出来ます。  Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; PromptEntityOptions peo = new PromptEntityOptions("\nサーフェスを選択:"); peo.SetRejectMessage("\nサーフェスを選択してください..."); peo.AddAllowedClass(typeof(Autodesk.AutoCAD.DatabaseServices.Surface), false); PromptEntityResult per = ed.GetEntity(peo); if (per.Status != PromptStatus.OK) return; using (Transaction tr = db.TransactionManager.StartTransaction()) { ObjectId objId = per.ObjectId; Entity ent = tr.GetObject(objId, OpenMode.ForWrite) as Entity; ObjectId[] entId = new ObjectId[] { ent.ObjectId }; IntPtr pSubentityIdPE = ent.QueryX(AssocPersSubentityIdPE.GetClass(typeof(AssocPersSubentityIdPE))); if (pSubentityIdPE == IntPtr.Zero) return; AssocPersSubentityIdPE subentityIdPE = AssocPersSubentityIdPE.Create(pSubentityIdPE, false) as AssocPersSubentityIdPE; SubentityId[] edgeIds = subentityIdPE.GetAllSubentities(ent, SubentityType.Edge); objId = SymbolUtilityServices.GetBlockModelSpaceId(db); BlockTableRecord btr = tr.GetObject(objId, OpenMode.ForWrite) as BlockTableRecord; foreach (SubentityId subentId in edgeIds) { FullSubentityPath path = new FullSubentityPath(entId, subentId); Entity edge = ent.GetSubentity(path); if (edge != null) { edge.ColorIndex = 3; edge.LineWeight = LineWeight.LineWeight100; btr.AppendEntity(edge); tr.AddNewlyCreatedDBObject(edge, true); } } tr.Commit(); }  
記事全体を表示
Issue AutoCAD .NET API を利用してサーフェス同士を結合することは出来ますか?   Solution AutoCAD .NET API には、サーフェス同士を結合する ObjectARX の AcDbSurface::booleanUnion() メンバ関数ラッパーである サーフェス同士を結合する Surface.BooleanUnion メソッドが用意されています。   次の C# 例は、Surface.BooleanUnion メソッドでサーフェス同士を結合するものです。   [CommandMethod("MyCommand", CommandFlags.Modal)] public void MyCommand() // This method can have any name { Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; PromptEntityOptions peo = new PromptEntityOptions("\n結合するサーフェスを選択:"); peo.SetRejectMessage("\nサーフェスを選択してください..."); peo.AddAllowedClass(typeof(Autodesk.AutoCAD.DatabaseServices.Surface), false); PromptEntityResult per = ed.GetEntity(peo); if (per.Status != PromptStatus.OK) return; ObjectId objId1 = per.ObjectId; peo = new PromptEntityOptions("\n結合させたいサーフェスを選択:"); peo.SetRejectMessage("\nサーフェスを選択してください..."); peo.AddAllowedClass(typeof(Autodesk.AutoCAD.DatabaseServices.Surface), false); per = ed.GetEntity(peo); if (per.Status != PromptStatus.OK) return; ObjectId objId2 = per.ObjectId; try { using (Transaction tr = db.TransactionManager.StartTransaction()) { Autodesk.AutoCAD.DatabaseServices.Surface surf1 = tr.GetObject(objId1, OpenMode.ForWrite) as Autodesk.AutoCAD.DatabaseServices.Surface; Autodesk.AutoCAD.DatabaseServices.Surface surf2 = tr.GetObject(objId2, OpenMode.ForWrite) as Autodesk.AutoCAD.DatabaseServices.Surface; Autodesk.AutoCAD.DatabaseServices.Surface surf = surf1.BooleanUnion(surf2); if (surf == null) { if (surf1 != null) { surf1.ColorIndex = 5; surf1.LineWeight = LineWeight.LineWeight100; } if (surf2 != null) { surf2.Erase(); } } else { surf1.Erase(); surf2.Erase(); ObjectId objId = SymbolUtilityServices.GetBlockModelSpaceId(db); BlockTableRecord btr = tr.GetObject(objId, OpenMode.ForWrite) as BlockTableRecord; surf.ColorIndex = 5; surf.LineWeight = LineWeight.LineWeight100; btr.AppendEntity(surf); tr.AddNewlyCreatedDBObject(surf, true); } tr.Commit(); } } catch(Autodesk.AutoCAD.Runtime.Exception ex) { ed.WriteMessage("\n" + ex.Message); } }  
記事全体を表示
質問 InventorのAPIを使って、Inventorのコマンドを実行する方法はありますか。   回答 Inventorの各コマンド(カスタムコマンドを含む)はCommandManagerオブジェクトからControlDefinition オブジェクトとして取得することが出来ます。 取得したControlDefinition オブジェクトのExecuteメソッドを実行することで、コマンドを実行することが可能です。   以下は"Vaultステータスを更新"コマンドを実行するサンプルコードとなります。 ' Get the CommandManager object. Dim oCommandMgr As CommandManager = ThisApplication.CommandManager ' Get control definition. Dim oControlDef As ControlDefinition = oCommandMgr.ControlDefinitions.Item("VaultRefresh") ' Execute the command. Call oControlDef.Execute   ControlDefinitions.Itemメソッドに指定する引数は、取得するコマンドの名称となります。   コマンドの名称の取得方法としては、以下の2つの方法があります。   1.以下のサンプルコード(VBA)を実行し、出力されるファイル内から取得する Sub PrintCommandNames() ' Get the CommandManager object. Dim oCommandMgr As CommandManager Set oCommandMgr = ThisApplication.CommandManager ' Get the collection of control definitions. Dim oControlDefs As ControlDefinitions Set oControlDefs = oCommandMgr.ControlDefinitions ' Open the file and print out a header line. Dim oControlDef As ControlDefinition Open "C:\temp\CommandNames.txt" For Output As #1 Print #1, Tab(10); "Command Name"; Tab(75); _ "Description"; vbNewLine ' Iterate through the controls and write out the name. For Each oControlDef In oControlDefs Print #1, oControlDef.InternalName; Tab(55); _ oControlDef.DescriptionText Next ' Close the file. Close #1 End Sub   2.Inventor SDKに付属のEventWatcherを使用し、Inventorでコマンドを実行してコマンド名を取得する   EventWatcherは、Inventorに付属のInventor SDKをインストールすると以下のフォルダにあります。 C:\Program Files\Autodesk\<Inventor Version>\SDK\DeveloperTools\Tools\EventWatcher\bin\Release   EventoWatcherを起動し、左側のリストから「UserInputEvents.OnActivateCommand」をチェックされた状態で、InventorでAPIから実行したいコマンドを実行すると、実行されたコマンド名がウィンドウに表示されます。 取得したコマンド名をControlDefinitions.Itemメソッドの引数に指定することで、対象のコマンドを取得することが出来ます。     なお、コマンド実行時にダイアログが表示されるタイプのコマンド(例:押し出し コマンド)の場合、ダイアログ内で指定するパラメータ(押し出しコマンドの場合、押し出し方向や距離 等)の指定についてはコマンドの機能となり、コマンドを実行するAPIから制御(指定)することが出来ません。   このようなタイプのコマンドの場合、APIからユーザの入力なしに実行したい場合は、InventorのAPIを用いて処理を作成する必要があります(もちろん処理には、希望の処理に対応するInventorのAPIが公開されている必要があります)。  
記事全体を表示
現象 Inventor 2025で、.NET FrameworkをターゲットにしてビルドしたC#アプリケーションからiLogicを実行すると、System.Runtime.InteropServices.COMException HResult=0x80131165 Message=Typelib エクスポート: タイプ ライブラリが登録されていません。 (HRESULT からの例外:0x80131165) Source=mscorlibが発生する。 エラーはiLogicの実行だけではなく、iLogicのAPIを実行すると発生する。   なお、同じソースコードでInventor 2024以下のバージョンではエラーは発生せずにiLogicを実行することが出来る。   以下のサンプルコードの場合、 auto.RunRule(doc, "Rule1");でエラーとなる。 var type = Type.GetTypeFromProgID(ProgId) ?? throw new Exception($"Failed to get type from '{ProgId}'"); var app = (Inventor.Application)Activator.CreateInstance(type); app.Visible = true; var addin = app.ApplicationAddIns.get_ItemById(ILogicAddInClassId); try { if (!addin.Activated) { addin.Activate(); } } catch (Exception ex) { throw new Exception("Failed activating iLogic addin", ex); } var doc = app.Documents.Open(@"<path to ipt file>"); dynamic auto = addin.Automation; auto.RunRule(doc, "Rule1"); 診断 InventorのiLogic APIはActiveX/COM Automationを用いてAPIを公開しています。Inventor 2025の場合Inventor 本体が従来の.NET Frameworkから.NET(.NET 8)を使用するよう更新がされており、iLogic機能を提供するコンポーネントも.NET 8を使用しております。   一方で、.NETでは.NET系の言語からCOM/ActiveX を実行する際の利用されるCOM Callable WrapperにITypeInfoのサポートを削除する変更が加えられています(.NET FrameworkではITypeInfoのサポートされていた)。   このため、.NET FrameworkをターゲットにしてビルドしたC#アプリケーションから、iLogicのAPIを遅延バインディング(dynamicキーワドを用いる形で、iLogic APIを呼び出す)を用いて利用すると、.NET で実装されていないITypeInfo情報を取得する処理(GetITypeInfoFromIDispatch 関数)が実行され、エラーが発生します。 解決策 以下のような方法で、エラーの回避が可能です。   1.対象のカスタムアプリケーションを.NETを使用するようにマイグレーションを行う   2.何らかの事情で、.NET へのマイグレーションが出来ない場合、対象のアプリーションをVB.NETを用いて開発する。VB.NETの場合、上述の問題となっている関数GetITypeInfoFromIDispatchを利用しない形で、遅延バインディングによるAPI実行を行っているため、エラーとなりません。   3.Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateCallを利用する 2のVB.Netでアプリケーションを開発した場合、VB.NETが内部的に利用している、遅延バインディングでのAPI実行を行う、低レベルのAPIを使用することでC#からもiLogic APIの実行が可能となります。   NewLateBinding.LateCall(auto, ((object)auto).GetType(), "RunRule1", new object[] { doc, "Rule" }, null, null, null, false);   4.dynamic 変数をobject型にCastしたのちにGetType().InvokeMember()を行う ((object)auto).GetType().InvokeMember("RunRule", BindingFlags.Public | BindingFlags.InvokeMethod, null, auto, new object[] { doc, "Rule1" });   3及び4の方法は、ソースコードの記述が非常に煩雑でわかりにくくなるため、iLogic APIの利用箇所が少ない場合などの回避としてご利用ください。      
記事全体を表示
現象 Windows 11環境では、AutoCAD(AutoCAD 2022、2023、2024)のWindowにGDIを使用したカスタムグラフィック描画がされない。Windows 10環境では、同じプログラムでカスタムグラフィックが描画される。   診断 AutoCAD 2022以降のバージョンでは、DirextX12をサポートしております。このためWindows 11環境ではGDIを用いたカスタムグラフィックの描画が行われません。 解決策 この問題の解決のためには、カスタムグラフィックの描画にGDIではなくDirectX 12を使用するよう、プログラムの修正を行うことを推奨します。   プログラムの修正が困難な場合、ハードウェアアクセラレーションをオフに設定する、またはシステム変数GFXDX12の設定値を0に設定することで、この現象を回避することが可能です。  
記事全体を表示
質問 AutoCADの.net APIで寸法拘束の拘束フォームを変更する方法はありますか。 回答 残念ながら、AutoCADの.net APIには寸法拘束の拘束フォームを変更するAPIはありません。 一方でObjectARX C++のAPIには対応するAPIが存在するため、.netのプログラムからは、P/Invoke を用いることで.netから寸法拘束の拘束フォームを変更することが可能です。   寸法拘束の拘束フォームの変更には、ObjectARX C++の寸法線の基底クラスAcDbDimensionの、isConstraintDynamic()メソッドおよびsetConstraintDynamic(bool isDynamic)メソッドを使用します。   isConstraintDynamic()メソッドは、その戻り値で現在の拘束フォームの設定状態を確認することが出来ます(true:ダイナミック, false:注釈)。 また、setConstraintDynamic(bool isDynamic)メソッドは、引数に指定した値で拘束フォームの設定状態を変更することが可能です。   以下は、AutoCAD 2023でP/Invokeを用いて.net で作成したAutoCADのカスタムコマンドから、選択した寸法拘束の拘束フォームの設定を変更するサンプルコードとなります。 [CommandMethod("FlipConstraintsForm")] public void FlipConstraintsForm() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; var option = new PromptEntityOptions("\n" + "Select a dimension constraints."); PromptEntityResult result = ed.GetEntity(option); if (result.Status != PromptStatus.OK) return; ObjectId id = result.ObjectId; using (Transaction tx = db.TransactionManager.StartTransaction()) { Dimension dim = tx.GetObject(id, OpenMode.ForWrite) as Dimension; DatabaseExtensions.DatabaseExtensions.Dimension_FlipConstraintsForm(dim); tx.Commit(); } } //DatabaseExtensions.cs namespace DatabaseExtensions { public class DatabaseExtensions { private static class AcDbDimension { [DllImport("acdb24.dll", CallingConvention = CallingConvention.ThisCall, CharSet = CharSet.Unicode, EntryPoint = "?isConstraintDynamic@AcDbDimension@@QEBA_NXZ")] [return: MarshalAs(UnmanagedType.Bool)] public static extern Boolean isConstraintDynamic(IntPtr dimension); [DllImport("acdb24.dll", CallingConvention = CallingConvention.ThisCall, CharSet = CharSet.Unicode, EntryPoint = "?setConstraintDynamic@AcDbDimension@@QEAA?AW4ErrorStatus@Acad@@_N@Z")] public static extern ErrorStatus setConstraintDynamic(IntPtr dimension, [MarshalAs(UnmanagedType.Bool)] Boolean bDynamic); } public static void Dimension_FlipConstraintsForm(Dimension dim) { dim.UpgradeOpen(); bool isDynamic = AcDbDimension.isConstraintDynamic(dim.UnmanagedObject); AcDbDimension.setConstraintDynamic(dim.UnmanagedObject, !isDynamic); } } }   DllImportによりImportするdllファイル名は、対象のAutoCADのバージョンに依存して変わる点にご留意ください。   なお、P/Invokeを用いたAPIの実装方法についてはこちらの記事に開設がありますので、ご参照ください。
記事全体を表示
Question AutoCADのAPIでレイヤーをロックした場合、レイヤー上のエンティティの表示がローライト表示されません。 GUIでレイヤーをロックする場合と同様にレイヤー上のエンティティをローライト表示する方法はありますか。 Answer レイヤーのロックを設定する際に、レイヤーのプロパティを編集し、レイヤに変更がされたことをAutoCADエディタに認識させた後に、Regenを実行することでGUIからロック状態を変更した場合と同様に、ロックしたレイヤー上のエンティティをローライト表示させることが可能です。   以下は、上述の処理をLockという名前のレイヤーに対して実行するサンプルコードです。   C#  [CommandMethod("Layerlack")] static public void Layerlack() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable table = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable; if (table.Has("Lock")) { LayerTableRecord record = tr.GetObject(table["Lock"],OpenMode.ForWrite) as LayerTableRecord; record.IsLocked = true; record.LineWeight = record.LineWeight; } tr.Commit(); } ed.Regen(); }    VBA Sub Example_Lock() Dim layerObj As AcadLayer Set layerObj = ThisDrawing.Layers.Add("Lock") layerObj.Lock = True layerObj.Lineweight = layerObj.Lineweight ThisDrawing.Regen acAllViewports End Sub    
記事全体を表示
質問 AutoCAD .net API でパレットを作成しました。パレットには、テキストボックスを配置したカスタムコントロールを配置しています。パレットを表示しテキストボックスに値を入力している途中で、マウスカーソルをパレットから外すと、フォーカスがテキストボックスから外れ、以後のキー入力はAutoCADのコマンド入力として処理されてしまいます。 パレットからマウスカーソルを外してもフォーカスが外れないようにすることはできますか。   回答 PaletteSetを継承したクラスを作成し、KeepFocusメソッドをオーバライドして、フォーカスを外したくない場合には戻り値falseを戻すように実装することで実現が可能です。   以下は、テキストボックス(textBox1)を配置したユーザコントロール(UserControl1)をパレットに配置し、textBox1にフォーカスがある場合は、コントロールからフォーカスを外さない処理をKeepFocusメソッドに記述したサンプルコードとなります。   public class MyPalettSet : PaletteSet { private UserControl1 uctl1 = new UserControl1(); public MyPalettSet(string name) : base(name) { this.Style = PaletteSetStyles.ShowTabForSingle | PaletteSetStyles.ShowPropertiesMenu | PaletteSetStyles.ShowAutoHideButton | PaletteSetStyles.ShowCloseButton; this.MinimumSize = new System.Drawing.Size(400, 100); this.Add("uctl", uctl1); this.Visible = true; this.Size = new System.Drawing.Size(400, 100); this.DockEnabled = DockSides.None; } public override bool KeepFocus { get { return uctl1.Controls["textBox1"] != null ? uctl1.Controls["textBox1"].Focused : false; } } }
記事全体を表示
Question AutoCADのVBAで、メニューマクロの^C^Cに相当する文字をSendCommandする方法はありますか? Chr(27)や文字コード27をSendCommandしても、エラーが出て動作しない。 Answer AutoCAD 2015で行われたAutoCADの内部的な実装の変更に起因し、以降のバージョンではChr(27)や文字コード27をSendCommandしてもエラーとなります。 残念ながら、現状ではEscを同期的に実行させる方法はありません。   PostCommandメソッド使用した非同期実行により、代替が可能かをご検討ください。 ThisDrawing.PostCommand Chr(27) & Chr(27)  
記事全体を表示
Question Inventorの言語設定に依存せずにInventorのAPIでBOMのソート列を指定する方法はありますか?   Answer InventorのAPIでは、BOMViewをソートする際に列名を指定する必要があります。 指定する列名は、実行中のInventorの言語設定により同じ項目でも名前が変わる(例 日本語名:”項目”、英語名:”Item”)ため、同じ列でソートする場合においても実行中のInventorの言語設定により、APIに指定する項目名を変える必要があります。   このため、複数言語での利用を想定する場合、以下のサンプルコード(日・英でのサンプル)のように、実行環境の言語に合わせてソート項目名を指定する必要があります。 Dim bv As BOMView Set bv = ThisDocument.ComponentDefinition.BOM.BOMViews(2) Select Case ThisApplication.LanguageCode Case "en-US" Call bv.Sort2("Item") Case "ja-JP" Call bv.Sort2("項目") End Select   なお、Inventor2020以前のバージョンの場合、日本語環境のInventorにて保存したデータを、英語環境のInventorで開いた場合には、上述のサンプルコードのCall bv.Sort2("Item")の実行でエラーが発生します。 この挙動については、Inventor 2021で修正対応がされています。  
記事全体を表示
質問 InventorのアドインでVault接続状態を確認し、接続していない場合はログインをしてVaultのConnectionを取得したい。 回答 Vault APIのConnectionManager.Instance.Connectionにより接続中のVaultコネクションオブジェクトを取得することができます。 接続されていない場合は、InventorのVaultログインコマンド(内部名:ContentLoginCmdIntName)を実行することで、ログインダイアログを表示することが可能です。   以下は、上述のAPIを使用したサンプルコードとなります。 using VDF = Autodesk.DataManagement.Client.Framework; using VB = Connectivity.Application.VaultBase; VDF.Vault.Currency.Connections.Connection conn = VB.ConnectionManager.Instance.Connection; if (null == conn) { try { ControlDefinition oCtlDef = m_inventorApplication.CommandManager.ControlDefinitions["ContentLoginCmdIntName"]; oCtlDef.Enabled = true; oCtlDef.Execute(); conn = VB.ConnectionManager.Instance.Connection; } catch (Exception ex) { } } if (null != conn) { MessageBox.Show(String.Format("Vault = {0}, UserID = {1}, User Name = {2}",conn.Vault, conn.UserID, conn.UserName)); }   なお、Visual Stuidoプロジェクトの参照設定で、Vault SDK配下のAutodesk.DataManagement.Client.Framework.dllおよびVaultインストールフォルダ配下のConnectivity.Application.VaultBase.dllファイルの参照の追加が必要となる点にご留意ください。  
記事全体を表示