Autodesk Community Tips- ADNオープン
Autodesk Community Tipsではちょっとしたコツ、やり方、ショートカット、アドバイスやヒントを共有しています。
ソート順:
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(); }  
記事全体を表示
現象 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の利用箇所が少ない場合などの回避としてご利用ください。      
記事全体を表示
Issue AutoCAD のダイナミック ブロックについて、VBA でどの程度操作ができるかわかりません。 モデル空間などに配置されているダイナミック ブロックのパラメータの状態を取得したり、パラメータの値を更新して、形状や表示状態を変更することはできますか?   Solution ダイナミックブロックとして配置されているブロック参照からは、ある程度の情報を取得したり、その値を変化させることができます。ただし、現在のバージョンでは一部制限があるため、すべての情報の制御や、パラメータ間の関連付けを得ることができません。   ブロック参照からダイナミックブロック固有の情報にアクセスするには、AcadBlockReference オブジェクトの GetDynamicBlockProperties メソッドを使用して、パラメータ情報を含むコレクションを取得します。このコレクションには、DynamicBlockReferenceProperty オブジェクトがパラメータ(アクションとの組み合わせ)数分含まれます。   DynamicBlockReferenceProperty オブジェクトを取得した後は、このオブジェクトが持つプロパティを使って、パラメータ別の情報にアクセスできます。つまり、ダイナミック ブロック参照の現在の設定値を得ることが可能です。   なお、パラメータによっては、ルックアップ テーブルや可視テーブルなど、リスト化された情報も存在します。このような場面では、パラメータを表す DynamicBlockReferenceProperty.Value プロパティは配列として返されます。これをチェックすれば、その内容を AllowedValues プロパティから閲覧することもできます。   添付のコードは、ダイナミックブロックの情報を取得する例です。   Dim nDataIndex As Long Dim vDataInfo As Variant Dim oData As AcadDynamicBlockReferenceProperty Dim nListIndex As Long Dim vListInfo As Variant Dim nRound As Integer Dim oEnt As AcadEntity Dim oBlkRef As AcadBlockReference nRound = ThisDrawing.GetVariable("LUPREC") For Each pEnt In ThisDrawing.ModelSpace If pEnt.ObjectName = "AcDbBlockReference" Then Set oBlkRef = pEnt If oBlkRef.IsDynamicBlock Then ThisDrawing.Utility.Prompt vbCrLf & "***** ダイナミックブロック - " ThisDrawing.Utility.Prompt oBlkRef.EffectiveName & " : " & oBlkRef.Name nCtrlIndex = 1 For nDataIndex = LBound(oBlkRef.GetDynamicBlockProperties) To UBound(oBlkRef.GetDynamicBlockProperties) Set oData = oBlkRef.GetDynamicBlockProperties(nDataIndex) If oData.show Then ' パラメータ名ラベル ThisDrawing.Utility.Prompt vbCrLf & oData.PropertyName & " : " ' パラメータが配列か確認 vDataInfo = oData.Value If IsArray(vDataInfo) Then ' 座標データの場合 ThisDrawing.Utility.Prompt Round(vDataInfo(0), nRound) & "," & Round(vDataInfo(1), nRound) & "," & Round(vDataInfo(2), nRound) Else ' リスト要素か確認 vListInfo = oData.AllowedValues If UBound(vListInfo) > 0 Then ' リスト要素の場合 For nListIndex = LBound(vListInfo) To UBound(vListInfo) If VarType(vDataInfo) = vbDouble Then ThisDrawing.Utility.Prompt vbCrLf & vbTab & CStr(Round(vListInfo(nListIndex), nRound)) Else ThisDrawing.Utility.Prompt vbCrLf & vbTab & vListInfo(nListIndex) End If Next nListIndex If VarType(vDataInfo) = vbDouble Then ThisDrawing.Utility.Prompt vbCrLf & vbTab & "現在値 : " & CStr(Round(vDataInfo, nRound)) Else ThisDrawing.Utility.Prompt vbCrLf & vbTab & "現在値 : " & vDataInfo End If Else ' 通常データの場合 If VarType(vDataInfo) = vbDouble Then ThisDrawing.Utility.Prompt Round(vDataInfo, nRound) Else ThisDrawing.Utility.Prompt vDataInfo End If End If End If End If ThisDrawing.Utility.Prompt vbCrLf Next End If End If Next
記事全体を表示
Issue 任意のタイミングで、開いている図面に共通画層があるかどうかチェックして、画層がなかった際に追加したいと考えています。    ... private DocumentCollection docs = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager; public void Initialize() { docs.DocumentActivated += new DocumentCollectionEventHandler(OnDocumentActivated); } public void Terminate() { docs.DocumentActivated -= OnDocumentActivated; } public void OnDocumentActivated(object sender, DocumentCollectionEventArgs e) { if (e.Document != null) { Database db = e.Document.Database; Document doc = e.Document; doc.LockDocument(); using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable? tbl = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable; string name = "Main"; if (!tbl.Has(name)) { LayerTableRecord rec = new LayerTableRecord(); rec.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(ColorMethod.ByAci, 3); rec.Name = name; tr.GetObject(db.LayerTableId, OpenMode.ForWrite); tbl.Add(rec); tr.AddNewlyCreatedDBObject(rec, true); } db.Clayer = tbl[name]; tr.Commit(); } } } ...   この際、ユーザーには上記の図面編集を意識させたくないため、図面に編集を加えなかったときには図面保存ダイアログの表示はさせたくありません。(イベントハンドラーで画層追加すると、図面タブで表示図面を切り替えたりすると、図面保存のダイアログが表示されるようです。)     新規図面が対象ではないので、図面テンプレート(.dwt)が使用出来ません。 何かいい方法はありますか?   Solution 図面の編集有無はシステム変数 DBMOD の値が 0 以外になっているか否かで判定されています。DBMOD は読み取り専用のシステム変数ですが、Document.PushDbmod メソッド と Document.PopDbmod メソッドを利用すると、両メソッド呼び出し間の処理を無効化して DBMOD の値を 0 に復元することが出来ます。   下記は、その使用例を示す C# コードです。   public void OnDocumentActivated(object sender, DocumentCollectionEventArgs e) { if (e.Document != null) { Database db = e.Document.Database; Document doc = e.Document; doc.LockDocument(); doc.PushDbmod(); using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable? tbl = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable; string name = "Main"; if (!tbl.Has(name)) { LayerTableRecord rec = new LayerTableRecord(); rec.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(ColorMethod.ByAci, 3); rec.Name = name; tr.GetObject(db.LayerTableId, OpenMode.ForWrite); tbl.Add(rec); tr.AddNewlyCreatedDBObject(rec, true); } db.Clayer = tbl[name]; tr.Commit(); } doc.PopDbmod(); } }  
記事全体を表示
Issue 比較的時間のかかるカスタム コマンドがあります。内部でループ制御による反復処理をしていますが、ESC キー押下で処理をキャンセルさせる実装にすることは出来ますか?   Solution AutoCAD 2011 以降、HostApplicationServices.UserBreak メソッドで、物理的な ESC キーの押下を検出することが出来るようになっています。ESC キーが押下されると同メソッドが true を返すので、例外を発生させるなどして処理を中断することが可能です。   [CommandMethod("MyCommand", CommandFlags.Modal)] public static void MyCommand() { ProgressMeter pm = new ProgressMeter(); pm.Start("Long process"); pm.SetLimit(100); try { for (int i = 0; i < 1000; i++) { if (HostApplicationServices.Current.UserBreak()) throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.UserBreak, "ESCAPE pressed"); pm.MeterProgress(); System.Threading.Thread.Sleep(100); } } catch (Autodesk.AutoCAD.Runtime.Exception ex) { Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.Message); } finally { pm.Stop(); } }  
記事全体を表示
Issue Editor.GetNestedEntity(PromptNestedEntityOptions) メソッドを利用して作図空間のブロック参照内の要素オブジェクトを直接選択、取得することが出来ますが、取得した要素オブジェクトからブロック名を得ることは出来ますか?   Solution 選択した要素オブジェクトの DBObject.OwnerId プロパティで、同オブジェクトのコンテナ オブジェクト、この場合、ブロック定義(BlockTableRecord)オブジェクトを取得ことが出来ます。その後、SymbolTableRecord.Name プロパティからブロック名を得ることが出来ます。      Database db = HostApplicationServices.WorkingDatabase; Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; PromptNestedEntityOptions peo = new PromptNestedEntityOptions("\nブロック参照を選択:"); PromptEntityResult pent = ed.GetNestedEntity(peo); if (pent.Status != PromptStatus.OK) { return; } using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent = (Entity)tr.GetObject(pent.ObjectId, OpenMode.ForRead); ed.WriteMessage("\nObject Type : " + ent.GetType().ToString()); BlockTableRecord blkDef = (BlockTableRecord)tr.GetObject(ent.OwnerId, OpenMode.ForRead); ed.WriteMessage("\nBlock Name : " + blkDef.Name); tr.Commit(); }
記事全体を表示
Issue REVCLOUD コマンド Object オプションを AutoCAD 上に入力して作成した雲マークには、「円弧の長さ」プロパティが表示されますが、同じ内容を AutoCAD .NET API から呼び出して作成した雲マークには、「円弧の長さ」プロパティが表示されません。     コマンドプロンプトで指定したコマンドは次の内容です。     一方、AutoCAD .NET API から呼び出しは、次のようになります。   Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; PromptEntityResult pent = ed.GetEntity("\nオブジェクトを選択:"); if (pent.Status == PromptStatus.OK) { ed.Command("REVCLOUD", "O", pent.ObjectId, "N"); }   この違いはなぜ生まれるのでしょうか? AutoCAD .NET API から作成した雲マークに同じように「円弧の長さ」プロパティを表示する方法はありますか?   Solution REVCLOUD コマンドは過去に数回機能強化されていて、 AutoCAD 2021で「円弧の長さ」プロパティが追加されています。AutoCAD は、アドインを含む古いスクリプトからの REVCLOUD コマンド呼び出しの互換性を維持する必要するため、コマンドの呼び出し元の環境に応じて、内部でコマンド バージョンを切り替える処理をしています。 今回の場合、ユーザーインターフェース(UI)から呼び出された REVCLOUD コマンドは内部コマンドバージョン 3 で実行されています。一方、アドインから同じコマンドを呼び出すと、内部コマンドバージョン 1 を使用して雲マークを作成します。この違いが、「円弧の長さ」プロパティの表示有無の結果を生んでいます。 アドインから REVCLOUD コマンドを呼び出す場合、次のようにコマンド呼び出しの直前に Editor.InitCommandVersion メソッドを用いて内部コマンドバージョンを切り替えることが出来ます。この処理で「円弧の長さ」プロパティを持つ内部コマンドバージョン 3 を実行することが出来ます。   Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; PromptEntityResult pent = ed.GetEntity("\nオブジェクトを選択:"); if (pent.Status == PromptStatus.OK) { Application.DocumentManager.MdiActiveDocument.Editor.InitCommandVersion(3); ed.Command("REVCLOUD", "O", pent.ObjectId, "N"); }
記事全体を表示
Issue AutoCAD のユーザー インターフェース上に開いている現在のアクティブな図面(MDI 子ウィンドウにフォーカスが当たっている表示中の図面)を Database.SaveAs(string, DwgVersion)  メソッドで保存しようとしても、図面ウィンドウ上の図面タイトルが指定した名前に変化しません。 SAVEAS コマンドと同等の挙動を実現したいのですが、どうすればいいでしょうか?     Solution Database.SaveAs メソッドには、次の3つのオーバロード メソッドが用意されています。 Database.SaveAs(string, Autodesk.AutoCAD.DatabaseServices.SecurityParameters) Database.SaveAs(string, DwgVersion) Method | Autodesk Database.SaveAs(string, [MarshalAs(UnmanagedType.U1)] bool, DwgVersion, Autodesk.AutoCAD.DatabaseServices.SecurityParameters) あいにく、いずれのオーバロード メソッドも SAVEAS コマンドに対応した動作を完全に実現するものではなく、同コマンドの実装の一部分を担う機能しか実装されていない状態です。   図面ウィンドウ上の図面タイトルが指定した名前を反映させる方法として Database.SaveAs(string, [MarshalAs(UnmanagedType.U1)] bool, DwgVersion, Autodesk.AutoCAD.DatabaseServices.SecurityParameters) のオーバーロード バージョンの第2パラメーターを true を指定する方法があります。ただし、この方法も SAVEAS コマンドと同等の動作をするものではありません。   完全に SAVEAS コマンドと同じ挙動を得るには、SAVEAS コマンドをそのまま呼び出す必要があります。   次の例は、Editor.Command メソッドで SAVEAS コマンドを呼び出すものです。   [CommandMethod("MyCommand1", CommandFlags.Modal)] public void MyCommand1() { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; if (doc != null) { string path = @"C:\temp\Test.dwg"; int filedia = System.Convert.ToInt32(Application.GetSystemVariable("FILEDIA")); Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("FILEDIA", 0); if (System.IO.File.Exists(path)) { ed.WriteMessage("\n指定したフォルダに同じ名前の図面ファイルが既に存在しています"); string check_path = Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("DWGPREFIX").ToString(); check_path = check_path + Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("DWGNAME").ToString(); if (path == check_path) { ed.WriteMessage("\n開いている同じ名前の図面ファイルで上書きします..."); ed.Command("SAVEAS", "2018", path); } else { ed.WriteMessage("\n開いている図面で上書きします..."); ed.Command("SAVEAS", "2018", path, "Y"); } } else { ed.WriteMessage("\n指定したフォルダに初めて指定した名前で図面ファイルを保存します..."); ed.Command("SAVEAS", "2018", path); } Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("FILEDIA", filedia); } }   通常の SAVEAS コマンドでは、保存先のパスとファイル名を指定する際にファイル ダイアログが表示されてしまうので、FILEDIA システム変数でその表示を抑止しています。また、保存先のパスに同じファイル名の図面が存在した場合、アクティブな現在の図面の状態によって上書き保存の可否を指定するプロンプト オプションが異なるため注意が必要です。
記事全体を表示
Issue モデル空間やペーパー空間(レイアウト)の作図領域の背景色は、[オプション] ダイアログの [表示] タブからアクセス出来る [作図ウィンドウの色] ダイアログから変更出来ますが、AutoCAD .NET API で同等の処理を実装することは出来ますか?     Solution あいにく、AutoCAD .NET API ネイティブにモデル空間やペーパー空間(レイアウト)の作図領域の背景色を変更する API が用意されていません。   代替として、COM Interop を使って PreferencesDisplay オブジェクト(ActiveX) の  GraphicsWinModelBackgrndColor プロパティ(モデル空間背景色)、 GraphicsWinLayoutBackgrndColor プロパティ(ペーパー空間背景色)を使用、背景色を取得、設定することが出来ます。   この場合、 GraphicsWinModelBackgrndColor プロパティ、 GraphicsWinLayoutBackgrndColor プロパティには AcCmColor オブジェクト が適用出来ないため、インデックスカラーやカラーブックの指定は出来ず、RGB 指定になってしまう点にご注意ください。   次の C# コードは、  GraphicsWinModelBackgrndColor プロパティ を使ってモデル空間の作図領域の背景色を変更するものです。   using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application; ... ... Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor; // ↓ if you face an error at 'var acadApp' below, try 'dynamic acadApp' var acadApp = (AcadApplication)AcadApp.AcadApplication; var modelBk = acadApp.Preferences.Display.GraphicsWinModelBackgrndColor; var color = ColorTranslator.FromOle((int)modelBk); ed.WriteMessage("\nCurrent Color = {0}", color.ToString()); acadApp.Preferences.Display.GraphicsWinModelBackgrndColor = (uint)ColorTranslator.ToOle(System.Drawing.Color.FromArgb(11, 22, 33)); modelBk = acadApp.Preferences.Display.GraphicsWinModelBackgrndColor; color = ColorTranslator.FromOle((int)modelBk); ed.WriteMessage("\nNew Color = {0}", color.ToString()); ...   なお、ObjectARX では、 acedGetCurrentColors() グローバル関数と acedSetCurrentColors() グローバル関数を使って、AcColorSettings 構造体の dwGfxModelBkColor 値、dwGfxLayoutBkColor 値で背景色の取得/設定をおこなうことが出来ます。
記事全体を表示
Issue VPORTS[ビューポート管理] コマンドで作成したモデル空間ビューポート内の表示をすべて再作図したいのですが、.NET API で REGENALL[全再作図] コマンドと同じような実装をすることは可能でしょうか?     Solution AutoCAD .NET API の Editor.Regen メソッドには、表示中のすべてのモデル空間ビューポートの再作図を指定するパラメーターがありません。このため、すべてのモデル空間ビューポートを走査して、ビューポートを識別する ViewportTableRecord.Number プロパティの値を CVPORT システム変数に指定、アクティブなビューポートをを切り替えて Editor.Regen メソッドを呼び出す必要があります。   [CommandMethod("MyCommand", CommandFlags.Modal)] public void MyCommand() { Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; var curVPort = Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("CVPORT"); using (Transaction tr = db.TransactionManager.StartTransaction()) { ViewportTable vpTable = (ViewportTable)tr.GetObject(db.ViewportTableId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead); if (vpTable != null) { ed.WriteMessage(Constants.vbLf + "Model Space Viewports : "); foreach (ObjectId vpId in vpTable) { ViewportTableRecord vptr = (ViewportTableRecord)tr.GetObject(vpId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite); Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("CVPORT", vptr.Number); ed.WriteMessage(vptr.Number.ToString()); ed.Regen(); } } tr.Commit(); } Autodesk.AutoCAD.ApplicationServices.Application.SetSystemVariable("CVPORT", curVPort); }    もちろん、プロジェクトの参照設定に Autodesk.AutoCAD.Interop.Common.dll と Autodesk.AutoCAD.Interop.dll の 2つのアセンブリを追加して、COM Interop(COM 相互運用機能)で ActiveX オートメーション(COM API)を利用、 acAllViewports パラメーターを指定して Regen メソッドを呼び出すことも可能です。   [CommandMethod("MyCommand", CommandFlags.Modal)] public void MyCommand() // This method can have any name { Autodesk.AutoCAD.Interop.AcadApplication COM_App = (Autodesk.AutoCAD.Interop.AcadApplication)Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication; COM_App.ActiveDocument.Regen(Autodesk.AutoCAD.Interop.Common.AcRegenType.acAllViewports); }   
記事全体を表示
現象 Inventor 2025以前のバージョンでは、Inventor 起動時に対応するバージョンのInventor Apprentice Serverのレジストリ登録が行われていました。 一方で、Inventor 2026起動時には、Inventor Apprentice Server 2026のレジストリ登録が行われない。 このため、異なるバージョンのInventorがインストールされている混在環境においては、以下の様な状態となります。   手順 ・Inventor 2025をインストール ・Inventor 2026およびInventor Apprentice Server 2026をインストール ・Inventor 2025を起動。⇒同時に Apprentice Server 2025のレジストリ登録が行われる。 ・Inventor 2025を終了 ・Inventor 2026を起動。 ⇒ Apprentice Server 2026のレジストリ登録は行われないため、レジストリ登録はApprentice Server 2025のままとなる。   診断 Inventor 2025 以前ではInventor Pro のインストーラに Apprentice Server のコピーが含まれており、Inventor Pro のインストール時に併せてインストールがされおり、Inventor起動時に同梱されてるApprentice Serverの情報でレジストリ登録を更新しておりました。   一方、Inventor 2026 以降ではInventor Pro のインストール時に Apprentice Server がインストールされなくなりました(より正確には、Regfee版のApprentice Server がインストールされますが、このRegfree版のApperentice ServerはInventor以外のアプリケーションからは利用できません)。また、Inventor起動時に同時に行っていた、同梱されているApprentice Serverでレジストリ登録情報の更新を行う処理も行われなくなりました。   このため以前のリリースから Inventor 2026 に切り替えてもApprentice Serverのレジストリ登録は更新されません。 解決策 Inventor 2026以降では、スタンドアロン版のApprentice Serverをインストールして、利用するようにしてください。 Inventor 2026以降で以前バージョンのApprentice Server から切り替えるには、スタンドアロン版のApprentice Serverインストールディレクトリ配下で以下のコマンドラインを実行してください。   ApprenticeRegSvr.exe /install  
記事全体を表示
Issue グループやブロック化していない状態の特定オブジェクトを移動や回転する際に、 イベント処理を使用せずに、アプリ内で関係のあるオブジェクトを同じように移動や回転する方法はありますか?   Solution 特定のオブジェクト タイプ(クラス)の移動や回転、縮尺変更など編集は、TransformOverrule オーバールール(Overrule)プロトコルを使用して、既定の振る舞いを変更することが可能です。ただし、イベント ハンドラーでのオブジェクト編集で同一イベントが発生してしまい、無限ループに陥らないような配慮が必要です。   次の C# コードは、MOVE コマンドや ROTATE コマンド、SCALE コマンドで円弧オブジェクト(Arc)を選択すると、青色(インデックスカラー色:5)の線分オブジェクト(Line)に同じマトリックス変換を実施するものです。   public class TransformByOverrule : TransformOverrule { public override void TransformBy(Entity ent, Matrix3d mat) { Database db = HostApplicationServices.WorkingDatabase; Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor; ed.WriteMessage("\nTransformBy.TransformBy Overrule - matrix {0}", mat.ToString()); base.TransformBy(ent, mat); TypedValue[] typeval = new TypedValue[2]; typeval.SetValue(new TypedValue(62, 5), 0); typeval.SetValue(new TypedValue(0, "LINE"), 1); SelectionFilter filter = new SelectionFilter(typeval); PromptSelectionResult psr = ed.SelectAll(filter); ed.WriteMessage("\nGetSelection = {0}", psr.Status.ToString()); if (psr.Status == PromptStatus.OK) { using (Transaction tr = db.TransactionManager.StartTransaction()) { SelectionSet sset = psr.Value; foreach (ObjectId objId in sset.GetObjectIds()) { ed.WriteMessage("\nObjectTd:" + objId.ToString()); Entity slave = (Entity)tr.GetObject(objId, OpenMode.ForWrite); slave.TransformBy(mat); } tr.Commit(); } } } } static TransformByOverrule _toverrule = null; [CommandMethod("MyCommand")] static public void MyCommand() { Editor ed = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor; if (_toverrule == null) { _toverrule = new TransformByOverrule(); ObjectOverrule.AddOverrule(RXObject.GetClass(typeof(Arc)), _toverrule, true); ObjectOverrule.Overruling = true; ed.WriteMessage("\nBegin modifying ARC overrule"); } else { ObjectOverrule.RemoveOverrule(RXObject.GetClass(typeof(Arc)), _toverrule); _toverrule.Dispose(); _toverrule = null; ed.WriteMessage("\nEnd modifying ARC overrule"); } }        
記事全体を表示
Issue 選択したオブジェクトが自動調整配列複写の要素かどうか判定して、自動調整配列複写であった場合に分解する実装するには、どのようなコードを記述すればいいでしょうか?       Solution 自動調整配列複写の対象となっているオブジェクト一式は、匿名ブロック(Anonymous Block)として自動調整フレームワークで管理、維持されています。   自動調整配列複写の判定には、AcDbAssocArrayActionBody::isAssociativeArray() メンバー関数を利用することが出来ます。同様に、分解には AcDbAssocArrayActionBody::explode() メンバー関数 を利用することが出来ます。   次のコードは、選択したオブジェクトが自動調整配列複写の構成要素だった場合に、トップレベルの調整配列複写を分解する例です。   ads_name ename; ads_point pt; int stat = acedEntSel(_T("\nオブジェクトを選択 : "), ename, pt); if (stat != RTNORM) return; AcDbEntity* pEnt; AcDbObjectId objId; acdbGetObjectId(objId, ename); Acad::ErrorStatus err = acdbOpenAcDbEntity(pEnt, objId, AcDb::kForRead); if (err != Acad::eOk) return; if (AcDbAssocArrayActionBody::isAssociativeArray(pEnt)) { acutPrintf(_T("\n自動調整配列です")); AcDbObjectId actId = AcDbAssocArrayActionBody::getControllingActionBody(pEnt, NULL); AcDbAssocArrayActionBody* pAryAct = NULL; err = acdbOpenAcDbObject((AcDbObject*&)pAryAct, actId, AcDb::kForWrite); if (err != Acad::eOk) { pEnt->close(); return; } if (AcDbAssocArrayPathParameters::cast(pAryAct->parameters())) acutPrintf(_T("\n - パス")); if (AcDbAssocArrayPolarParameters::cast(pAryAct->parameters())) acutPrintf(_T("\n - 円形状")); if (AcDbAssocArrayRectangularParameters::cast(pAryAct->parameters())) acutPrintf(_T("\n - 矩形状")); AcDbObjectIdArray newIds; pAryAct->explode(pEnt, newIds); pAryAct->close(); } else acutPrintf(_T("\n自動調整配列ではありません")); pEnt->close(); return;   EXPLODE コマンドで自動調整配列複写を分解する場合には、次のようなコードで AcDbAssocArrayActionBody::explode()  メンバー関数を代替することが出来ます。いずれの場合も、自動調整フレームワークが構成要素オブジェクトを保持しているため、すべてのオブジェクトを指定する必要はありません。   ads_name sset; acedSSAdd(NULL, NULL, sset); acedSSAdd(ename, sset, sset); acedCommandS(RTSTR, _T("EXPLODE"), RTPICKS, sset);      
記事全体を表示
Issue 選択したオブジェクトが自動調整配列複写の要素かどうか判定して、自動調整配列複写であった場合に分解する実装するには、どのようなコードを記述すればいいでしょうか?     Solution 自動調整配列複写の対象となっているオブジェクト一式は、匿名ブロック(Anonymous Block)として自動調整フレームワークで管理、維持されています。   自動調整配列複写の判定には、AssocArray.IsAssociativeArray メソッドを利用することが出来ます。 同様に、分解には AssocArray.Explode メソッドを利用することが出来ます。   次のコードは、選択したオブジェクトが自動調整配列複写の構成要素だった場合に、トップレベルの調整配列複写を分解する C# 例です。   Database db = HostApplicationServices.WorkingDatabase; Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; PromptEntityResult pent = ed.GetEntity("\nオブジェクトを選択:"); if (pent.Status != PromptStatus.OK) { return; } using (Transaction tr = db.TransactionManager.StartTransaction()) { if (AssocArray.IsAssociativeArray(pent.ObjectId)) { ed.WriteMessage("\n自動調整配列です"); AssocArray ary = AssocArray.GetAssociativeArray(pent.ObjectId); var param = ary.GetParameters(); if (param as AssocArrayPathParameters != null) ed.WriteMessage("\n - パス"); if (param as AssocArrayPolarParameters != null) ed.WriteMessage("\n - 円形状"); if (param as AssocArrayRectangularParameters != null) ed.WriteMessage("\n - 矩形状"); AssocArray.Explode(pent.ObjectId); } else ed.WriteMessage("\n自動調整配列ではありません"); tr.Commit(); }   EXPLODE コマンドで自動調整配列複写を分解する場合には、次のようなコードで AssocArray.Explode メソッドを代替することが出来ます。いずれの場合も、自動調整フレームワークが構成要素オブジェクトを保持しているため、すべてのオブジェクトを指定する必要はありません。   var sset = SelectionSet.FromObjectIds(new ObjectId[] { pent.ObjectId }); ed.Command("EXPLODE", sset);    
記事全体を表示
AutoCAD .NET APIリファレンスに記載の様に、PromptSelectionOptions.SingleOnlyは、AutoCAD ObjectARXでのacedSSGet()での”:S”モードの設定に相当します。また、 PromptSelectionOptions.SinglePickInSpaceは、":A"モードに相当します。   ObjectARXでのacedSSGetでは、”:S"モードは、単一のエンティティの選択が許容される状態となりますが、窓選択については有効な状態のままとなります。   また、”:A"モードについては、aecdSSGetのリファレンスでは「This mode option causes acedSSGet() to perform single pick selection in space on entities that implement a subselection filter.」との説明がありますが、これは例えばテーブルの様な、エンティティ内にサブエンティティがあるようなエンティティにおいて、テーブルのセル内の文字のクリックを、テーブル自身の選択とするオプション設定となります。
記事全体を表示
現象 AutoCAD 2025のAccoreconsole.exe でSystem.Data.OleDbを参照するプラグインのカスタムコマンドを実行すると、Accoreconsole.exeが異常終了するAutoCAD 2025のAccoreconsole.exe でSystem.Data.OleDbを参照するプラグインのカスタムコマンドを実行すると、Accoreconsole.exeが異常終了してしまいます。   なお、プラグインはAutoCAD 2025に合わせて.net 8を利用するように移植済みです。 また、System.Data.OleDbはVisual Studio のNugetパッケージマネージャから 9.0.2をプロジェクトにインストールして使用しています。 診断 AutoCAD インストールフォルダ配下のSystem.Data.OleDb.dllのバージョンと、プラグインプロジェクトのNugetでインストールしているSystem.Data.OleDb.dllのバージョンの差異に起因してAccoreconsole.exeが異常終了している状況です。   AutoCAD 2024以前は、.NET FrameworkのAppDomain機能を用いてプラグインは分離された実行空間にロード・実行されていました。AutoCADが利用するアセンブリとは異なるバージョンのアセンブリをプラグインが参照している場合でも問題なく実行することが出来ておりました。 一方で、AutoCAD 2025では、従来の.NET Frameworkから、.NET Core(.NET 8)にサポートプラットフォームが変更されましたが、この.NET CoreではAppDomain機能がサポートされておらず、すべてのプラグインとその参照アセンブリは同じ実行空間にロードされます。このため、AutoCADとプラグイン、または異なるプラグイン間でバージョンの異なる同じアセンブリを参照している場合、競合が発生して異常終了等の予期せぬ事態が発生することがあります(参照アセンブリによっては異常終了せず動作する場合もあります)。   解決策 System.Data.OleDbに特化した解決方法としては、プラグインが参照するSystem.Data.OleDbのライブラリをAutoCADのインストールフォルダ配下の者とすることで、問題を解消することが可能です。 以下、手順となります。 1.VisualStudio のプロジェクトからSystem.Data.OleDbのNugetパッケージを削除する 2.代わりに、VisualStudio のプロジェクトの参照設定で、AutoCADのインストールフォルダ(acad.exeおよびaccoreconsole.exeがあるフォルダ)配下のSystem.Data.OleDb.dllを参照ファイルに追加をする。   また、System.Data.OleDbに特化しない一般的な解決方法としては、.NET Coreが提供するAssemblyLoadContext機能を用いて、カスタム処理を異なる空間で実行することにより、参照するアセンブリのバージョン違いによる干渉を防ぐ方法となります。 AssemblyLoadContext機能については、Microsoft社の提供するマテリアル「System.Runtime.Loader.AssemblyLoadContext について」をご参照ください。
記事全体を表示
質問 InventorのVBA環境で、VBAの「ツール」-「参照設定」から利用するライブラリの参照設定が行えます。 VBAを実行するクライアント端末が複数あり、各端末でライラリファイルの参照設定をすることが手間なので、ライブラリの参照設定を出力して配布することは可能でしょうか? 回答 Inventorの設定ファイルには、VBAでの参照設定を編集する機能はありません。また、InventorのAPI にも直接的に参照設定を編集する機能はありません。   一方で、InventorのAPIで、Microsoft社が提供するVBA開発環境のVBProjectオブジェクトを取得するAPIが公開されているため、VBProjectオブジェクトのReferences.AddFromFile()メソッド等を利用することで、プログラムコードから参照設定を行うことが可能です。   以下は、"Adbe Acrobat 10 Type Library”への参照を追加する場合のサンプルコードとなります。 Dim app As Application Set app = ThisApplication Dim VBProject As Object Set VBProject = app.VBAProjects.Item(1).VBProject Const RefFile As String = "<path to acrobat.tlb file>" VBProject.References.AddFromFile RefFile
記事全体を表示
質問 Vaultクライアントで、プロジェクトエクスプローラ($)配下の、あるフォルダに対してローカル作業フォルダを規定値から別のフォルダに変更するを設定しました。 その後、Vault APIで対象のフォルダのローカル作業フォルダのパスを取得すると、変更したフォルダパスではなく、規定値のフォルダパスが取得されている状況です。 Vault クライアントで変更したフォルダパスを取得する方法はありますか。 回答  Vaultのローカル作業フォルダの設定を規定値から変更した場合、変更した設定は以下のファイルに保存されます(*****部は、実行環境により変化します)。   C:\Users\<Windows ログインユーザ>\AppData\Roaming\Autodesk\VaultCommon\Servers\Services_Security_******\<接続先サーバ名>\Vaults\<ボルト名>\Objects\WorkingFolders.xml     ファイルパスに<Windowsログインユーザ>、<接続先サーバ名>、<ボルト名>が含まれているため、カスタムアプリケーションからVaultに接続する際に、これらのどれかが異なる場合には、異なるローカル作業フォルダの設定が読み込まれます(ファイルが存在しない場合は、既定のパスとなります)。   ローカル作業フォルダの設定を規定値から変更したVaultクライアントアプリケーションと、APIを実行しているアプリケーションで、この値のどれかが異なっている場合Vault クライアントで変更したフォルダパスを取得することが出来ません。これらの値を合わせたうえで、変更後のフォルダパスが取得できるかを確認してください。
記事全体を表示
現象 Inventorを、VBAや.NET FrameworkのCreateObject()等のCOM API経由で起動後、カスタマイズプログラムからQuit()を実行せずに、GUIで終了(xボタン押下当)した場合、バックグラウンドプロセスとしてInventorが残ってしまう。   診断 外部プロセスから、VBAや.NET Framework等のCreateObject()等を用いて外部アプリケーションを起動した場合、対象のアプリケーションはQuit()メソッドにより終了をさせる必要があります。Quit()を実行せずアプリケーションGUI側から終了した場合バックグラウンドにプロセスが残存してしまいます。 この挙動はInventorのみならずExcel等でも同様で、COMオブジェクトを公開するアプリケーションに共通の挙動となります。   解決策 CreateObject()により取得したアプリケーションオブジェクトをQuit()メソッドで終了せず利用したい場合は、CreateObject()ではなくProcess.Start()等によりプロセスを起動し、GetObject()等を用いて起動中のアプリケーションのCOMオブジェクトを取得することで回避が可能です。   「APIでInventorを起動する際にバージョン指定する方法」にProcess.Start()を用いてInventorを起動し起動したInventorアプリケーションのCOMオブジェクトを取得する方法のサンプルコードがありますので、ご参照ください。  
記事全体を表示
Issue AutoCAD .NET API でフォルダ内の DWG ファイルを順に開いて処理していますが、サイズの大きい図面があると相対的に処理時間が長くなってしまいます。高速化するアイデアはありますか?   Solution   AutoCAD 上に図面を開いて表示する際、描画に多く時間がかかってしまいます。 もし、ユーザインターフェース上に図面を表示する必要がないのであれば、Database.ReadDwgFile メソッドを使って、メモリ上に図面を展開する方法を採用することで、描画にかかかる時間を省いて処理全体を高速化させることが出来ます。   次のコードは、フォルダを指定後にフォルダ内の .dwg ファイルを順に Database.ReadDwgFile メソッドでメモリ展開し、モデル空間のオブジェクト タイプを表示するものです。 [CommandMethod("MyCommand", CommandFlags.Modal)] public void MyCommand() { Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; using (FolderBrowserDialog fd = new FolderBrowserDialog()) { if (fd.ShowDialog() == DialogResult.OK) { string folder = fd.SelectedPath; System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(folder); IEnumerable<System.IO.FileInfo> files = di.EnumerateFiles("*.dwg", System.IO.SearchOption.AllDirectories); if (files == null) return; ed.WriteMessage("\n\t{0}", folder); foreach (System.IO.FileInfo f in files) { string file = f.FullName; ed.WriteMessage("\n - {0}", file); try { using (Database db = new Database(false, true)) { db.ReadDwgFile(file, FileOpenMode.OpenForReadAndAllShare, false, null); using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead); foreach (ObjectId id in btr) { Entity ent = (Entity)tr.GetObject(id, OpenMode.ForRead); ed.WriteMessage("\n - {0}", ent.GetType().ToString()); } tr.Commit(); } } } catch (System.Exception ex) { ed.WriteMessage(ex.ToString()); } } } } }   なお、Database.ReadDwgFile メソッドの使用時には、次の点に注意が必要です。   Database.ReadDwgFile メソッドで読み込む Database インスタンスを new ステートメントで用意する必要があります。この際、最低限必要なシンボルテーブルとオーナーシップを持つ Database 構造は、読み込む DWG ファイルに定義されているため、コンストラクタには Database.Database([MarshalAs(UnmanagedType.U1)] bool, [MarshalAs(UnmanagedType.U1)] bool)  オーバーロードを使用して、第1パラメーターの値を false にして、読み込む DWG ファイルの Database 構造との競合を抑止する必要があります。 AutoCAD のユーザインターフェースに表示された Database インスタンスは、同図面を表示している MDI 子ウィンドウを閉じると、AutoCAD が Database 領域をメモリから削除します。ただし、Database.ReadDwgFile メソッドでメモリ上に展開した Database インスタンスの領域は、展開したアドイン アプリがメモリーから削除しなければなりません。削除には上、記コードのように using ステートメントを利用してスコープ内の処理後に削除させるか、using ステートメントでスコープ指定せずに Dispose メソッドを明示的に呼び出すことも出来ます。 Database.ReadDwgFile メソッドで読み込んだ Database インスタンス内の DBText オブジェクトや AttributeReference オブジェクトの位置合わせを変更する場合、Database インスタンスを HostApplicationServices.WorkingDatabase プロパティで設定していないと予期しないズレが発生する場合があります。これは、DBText クラス実装が、位置合わせ時に現在の図面データベース(Database)を参照している関係で発生してしまう現象です。Database インスタンスを HostApplicationServices.WorkingDatabase プロパティで設定して処理した場合、処理後にオリジナル(ユーザーインターフェースに開いている図面の Database インスタンスを HostApplicationServices.WorkingDatabase プロパティで再設定する必要があります。
記事全体を表示