Autodesk Community Tips- ADNオープン
Autodesk Community Tipsではちょっとしたコツ、やり方、ショートカット、アドバイスやヒントを共有しています。
ソート順:
質問 Inventor APIでiPropertyの質量を取得すると値がグラムで取得されます。 Inventor APIで取得する値の単位は何でしょうか。 回答 Inventorでは各ドキュメントの表示単位を設定可能ですが、内部データべースの単位は、常に同じ単位を利用しております。 InventorのAPIはこのデータベース単位を利用いたしますので(表示単位の設定にかかわらず)、データベース単位での値が取得されます。   Inventorの表示単位や内部データベースの単位の詳細については、APIリファレンスの「Inventor APIのユーザマニュアル」-「一般的なコンセプト」-「計測単位」にまとめられています。 以下は、APIリファレンスに記載のデータベース単位の表となります。   ただし、以下のコードでiPropertyの質量を取得すると、値がデータベース単位のキログラムではなく、グラムで取得されるため注意が必要です。 ThisApplication.ActiveDocument.PropertySets.Item("Design Tracking Properties").Item("Mass").Value   質量をデータベース単位のキログラムで取得する場合は、以下のようにMassPropertesのmassプロパティから取得が可能です。 ThisApplication.ActiveDocument.ComponentDefinition.MassProperties.mass  
記事全体を表示
質問 APIでInventorを起動する際にバージョン指定する方法はありますか。 回答 AutoCAD等でGetTypeFromProgID()の引数に、"AutoCAD.Application.xx” (xxはバーンジョンを表す数値)等を渡すことでバージョンを指定して起動することが出来るため、Inventorも同様の方法で起動する方法を探している状況かと思います。   残念ながら、InventorではAutoCADとはCOMのレジストリ登録の仕組みが異なっており、CreateInstance()でバージョンを指定して起動することが出来ません。   プログラムから指定のバージョンのInventorを起動する場合、以下の2通り方法があります。 1.カスタムプログラムからexeを起動する 2.カスタムプログラムから、CreateInstance()関数の実行時に、CreateInstance()関数が参照するInventorのExeのパスが記述されている、レジストリ情報を対象バージョンのInventor.exeのパスで上書きしたのちに、GetTypeFromProgID()⇒CreateInstance()を行う。 ただし、2の方法はCLASSES_ROOT配下のレジストリ情報の書き換えを行うため、adminまたはCLASSES_ROOTの書き換えに必要なユーザ権限が必要となりるため、通常は1の方法をとることになるかと思いますので、ここでは1の方法を記載します。   以下は、1の方法でInventorを起動するヘルパークラスです。 class AdnInventorLoader { public enum Version { Inventor_2020, Inventor_2021, Inventor_2022, Inventor_2023, }; public static Inventor.Application CreateInstanceFromProcess(Version version) { try { string exePath = GetExePath(version); if (exePath != string.Empty) { CleanUpRegistry(); System.Diagnostics.Process process = System.Diagnostics.Process.Start(exePath); if (process != null) { //Wait for 5 Mins if (process.WaitForInputIdle(300000)) { while (true) { try { Inventor.Application app = Marshal.GetActiveObject("Inventor.Application") as Inventor.Application; return app; } catch (Exception ex) { if (!ex.Message.Contains("MK_E_UNAVAILABLE")) break; System.Threading.Thread.Sleep(1000); } } } } } return null; } catch { return null; } } // Clean up registry to prevent // "Re-registration" dialog // http://tinyurl.com/dx4tsnu private static bool CleanUpRegistry() { try { using (RegistryKey inventorKey =Registry.CurrentUser.OpenSubKey("Software").OpenSubKey("Autodesk").OpenSubKey("Inventor").OpenSubKey("Current Version",true)) { if (inventorKey == null) return false; inventorKey.DeleteValue("Executable"); inventorKey.DeleteValue("LastVersionRun"); inventorKey.DeleteValue("Registered"); inventorKey.DeleteValue("RegistryVersion"); inventorKey.DeleteValue("SilentMode"); inventorKey.DeleteValue("UBI"); inventorKey.Close(); return true; } } catch { return false; } } // Retrieve Inventor.exe fullpath based on version private static string GetExePath(Version version) { try { string key = string.Empty; switch (version) { case Version.Inventor_2020: key = "RegistryVersion24.0"; break; case Version.Inventor_2021: key = "RegistryVersion25.0"; break; case Version.Inventor_2022: key = "RegistryVersion26.0"; break; case Version.Inventor_2023: key = "RegistryVersion27.0"; break; default: return string.Empty; } using (RegistryKey inventorKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64). OpenSubKey("SOFTWARE"). OpenSubKey("Autodesk"). OpenSubKey("Inventor"). OpenSubKey(key)) { if (inventorKey == null) return string.Empty; string path = inventorKey.GetValue("InventorLocation") as string; inventorKey.Close(); path += "Inventor.exe"; return (System.IO.File.Exists(path) ?path : string.Empty); } } catch { return string.Empty; } } } }    利用側からは以下のように、起動するInventorのバージョンを指定する列挙値を指定して起動します。 Inventor.Application app = AdnInventorLoader.CreateInstanceFromProcess(AdnInventorLoader.Version.Inventor_2023); if (app != null) app.Visible = true;   ※この記事はブログ記事「Running programmatically a specific version of Inventor」を元に、必要な部分を抽出し、加筆修正と日本語化を行ったものとなります。
記事全体を表示
質問 Vaultのカスタムプログラムの開発のために、Vault Exploror(Vaultクライアント)のコマンドが利用しているVault APIを知りたい。 回答 Vaultのカスタムプログラムを開発する際に、Vault Exploror(Vaultクライアント)のコマンド(またはその一部)と同様の処理を実現したい場合に、どのようなAPIを利用すればよいかを知りたい場合が多くあります。   Vault Exploror(Vaultクライアント)はコマンドの実行時に、Vault サーバのWebサービスAPIを実行してその機能を実現しているため、その通信内容をパケットキャプチャツール等で確認することで、どのWebサービスAPIが実行されているかを確認することが出来ます。   ここでは、パケットキャプチャツールのFiddler ClassicとVaultの通信内容をFiddler Classicで見やすくするエクステンションツールのvapiTraceを利用した方法を紹介します。   なお、以下手順の環境としてはVaultサーバとVaultクライアントが同一のマシン上にインストールされているテスト環境を前提としています。原理的には、別端末にインストールされている場合でも、Vaultクライアントがインストールされている環境で実行することで通信内容を確認できるはずですが、追加のFiddlerの設定が必要となる可能性があります。   手順   1.以下URLからFiddler Classicをダウンロードしてインストールします。 https://www.telerik.com/fiddler/fiddler-classic   2.以下GitHubリポジトリのリリースから、vapiTraceFiddlerExtension.zipをダウンロードし、zpiファイル解凍して、C:\Users\<ログインユーザ名>\AppData\Local\Programs\Fiddler\Inspectors 配下に配置します。 https://github.com/coolOrangeLabs/vapiTrace   3.Fiddlerを起動し[Tool]-[Option]メニューからCapture HTTPS Connections設定を有効にする。    4.Fiddlerを再起動して、Vaultクライアントを起動します。  Fiddlerの画面の左側には、キャプチャされた通信内容が時系列にリストで表示されます。URLが/AutodeskDMで始まる通信がVaultサーバとの通信となります。   リストからアイテムを選択し、右側の上下のペインでvapiTraceタブを選択すると、以下のスクリーンショットのように、上側のペインに呼び出したVault API(とその引数)、下側のペインにはAPIのレスポンスが表示され、実行されたAPIを確認することが出来ます。     リストの内容は、リストアイテムを選択して、右クリックメニュー[Remove]-[All Sessions]からクリアできるので、調査したいVaultエクスプローラのコマンドを実行前にリストをクリアし、Vaultのコマンドを実行後に[File]-[Capture Traffic]のチェックを外してキャプチャを停止することで、コマンドが実行しているAPIを効率的に調査することが出来るかと思います。   また、Vaultクライアントはコマンドの実行後にGUIを最新の情報に更新するために、情報を取得するAPIの呼び出しを行っています。カスタムプログラムの開発時には、要件に合わせてどのAPIが必要なのかの判断が必要となりますので、各APIの詳細をVault SDKのAPIリファレンスを参照して確認ください。   なお、Vaultクライアントからサーバにログインする際にVaultサーバにlocalhostを指定するとFiddlerで通信をキャプチャすることが出来ません。Vaultサーバにはマシン名を指定してください。
記事全体を表示
質問 AutoCADの.net APIで雲マーク(REVCLOUD)を取得する方法はありますか。   回答 AutoCADの雲マーク(RevCloudコマンドで作成される図形)は、拡張データ領域にアプリケーション名”RevcloudProps”のデータを持つLWPolylineとなっております。   このため、net APIで図形を選択する際のフィルタ条件に、図形がLWPolylineでかつアプリケーション名が”RevcloudProps”の拡張データを持つ図形指定することで雲マーク図形を取得することが可能です。   Dim dc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = dc.Database Dim ed As Editor = dc.Editor Dim tvs(1) As TypedValue tvs.SetValue(New TypedValue(DxfCode.Start, "LWPOLYLINE"), 0) tvs.SetValue(New TypedValue(DxfCode.ExtendedDataRegAppName, "RevcloudProps"), 1) Dim sf As SelectionFilter = New SelectionFilter(tvs) Dim psr As PromptSelectionResult psr = ed.SelectAll(sf) If psr.Status<> PromptStatus.OK Then Exit Sub End If Using tx As Transaction = db.TransactionManager.StartTransaction() Try For Each id As ObjectId In psr.Value.GetObjectIds() Dim lwp As Polyline = tx.GetObject(id, OpenMode.ForWrite) Next tx.Commit() Catch e As System.Exception tx.Abort() ed.WriteMessage(e.Message) End Try End Using    
記事全体を表示
質問 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が公開されている必要があります)。  
記事全体を表示
質問 AutoCADのVBAで、以下のサンプルコードの様にコレクションの要素を取得し存在しない場合は要素を追加する処理がありますが、同様の処理をAutoLispで行う場合はどのように記述したらよいでしょうか。 Dim sset As AcadSelectionSet On Error Resume Next Set sset = ThisDrawing.SelectionSets.Item("Test") On Error GoTo 0 If sset Is Nothing Then Set sset = ThisDrawing.SelectionSets.Add("Test") End If 回答 AutoLispのvl-catch-all-applyを使用することで、コレクションに存在しないアイテムを取得する際に発生するエラーをハンドルすることが可能です。 vl-catch-all-applyには引数のリストを指定された関数に渡し、すべての例外をトラップします。   上述のVBAと同様の処理を実現する場合は以下のサンプルコードのようにlambda式を作成して処理を実行、結果の値を確認する形となります。 (setq acadObject (vlax-get-acad-object)) (setq activeDocument (vla-get-activedocument acadObject)) (setq selectionSets (vla-get-selectionsets activeDocument)) (vl-catch-all-apply '(lambda() (setq sset (vla-Item selectionSets "test")) ) ) (if (= nil sset) (progn (setq sset (vla-add selectionSets "test")) ) )    
記事全体を表示
現象 Windows 11環境では、AutoCAD(AutoCAD 2022、2023、2024)のWindowにGDIを使用したカスタムグラフィック描画がされない。Windows 10環境では、同じプログラムでカスタムグラフィックが描画される。   診断 AutoCAD 2022以降のバージョンでは、DirextX12をサポートしております。このためWindows 11環境ではGDIを用いたカスタムグラフィックの描画が行われません。 解決策 この問題の解決のためには、カスタムグラフィックの描画にGDIではなくDirectX 12を使用するよう、プログラムの修正を行うことを推奨します。   プログラムの修正が困難な場合、ハードウェアアクセラレーションをオフに設定する、またはシステム変数GFXDX12の設定値を0に設定することで、この現象を回避することが可能です。  
記事全体を表示
現象 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 Excel VBA から Excel シート上のテーブル値に応じた作図が出来ますか?   Solution AutoCAD の ActiveX オートメーションは、Windows の COM 機構を利用します。AutoCAD のカスタマイズを手助けする AutoCAD API のとおり、Microsoft Office 製品は、自身の機能を COM サーバー として公開、内部の VBA を COM クライアントとして公開しているので、AutoCAD VBA から Excel を操作したり、Excel VBA から AutoCAD を操作することが出来ます。     Excel VBA から AutoCAD の ActiveX オートメーション インタフェースを利用するには、Excel VBA からAutoCAD オブジェクト情報を公開している AutoCAD タイプライブラリ(AutoCAD Type Library)を参照設定するだけです。    次のコードは、Excel の「精密テーブル」タブのテーブル上のカーソル列の値を読み取って、AutoCAD 図面のモデル空間に「精密滑車」ブロックを挿入するものです。   Option Explicit Public Sub CommandButton1_Click() On Error Resume Next Dim oApp As AcadApplication Set oApp = GetObject(, "AutoCAD.Application.25") If Err Then Debug.Print "AutoCAD が起動されていません..." Set oApp = CreateObject("AutoCAD.Application.25") End If oApp.Visible = True If oApp.Documents.Count = 0 Then MsgBox "アクティブな図面がありません..." Exit Sub End If Dim oDoc As AcadDocument Set oDoc = oApp.ActiveDocument oDoc.SetVariable "DIMASZ", 0.1 oDoc.SetVariable "DIMEXE", 0.2 oDoc.SetVariable "DIMEXO", 0.1 oDoc.SetVariable "DIMGAP", 0.02 oDoc.SetVariable "DIMTXT", 0.1 Call oDoc.ActiveDimStyle.CopyFrom(oDoc) Dim oModel As AcadModelSpace Set oModel = oDoc.ModelSpace Dim oEntity As AcadEntity For Each oEntity In oModel If oEntity.ObjectName = "AcDbBlockReference" Then Dim oBlockRef As AcadBlockReference Set oBlockRef = oEntity If oBlockRef.Name = "精密滑車" Then oBlockRef.Delete End If End If Next Err.Clear oDoc.Regen (acActiveViewport) Dim ptBase As Variant ptBase(0) = 0#: ptBase(1) = 0# Dim oBlock As AcadBlock Set oBlock = Nothing Set oBlock = oDoc.Blocks.Item("精密滑車") If oBlock Is Nothing Then Set oBlock = oDoc.Blocks.Add(ptBase, "精密滑車") Else For Each oEntity In oBlock oEntity.Delete Next End If Dim SelectedRange As Range Set SelectedRange = Application.ActiveCell Dim SelectedRow As Long SelectedRow = SelectedRange.Row Dim OD As Double Dim Bore As Double Dim A As Double Dim B As Double OD = Sheets("滑車テーブル").Cells(SelectedRow, 2) Bore = Sheets("滑車テーブル").Cells(SelectedRow, 3) A = Sheets("滑車テーブル").Cells(SelectedRow, 4) B = Sheets("滑車テーブル").Cells(SelectedRow, 5) Dim ptVertexs(0 To 17) As Double ptVertexs(0) = 0#: ptVertexs(1) = Bore * -0.5 ptVertexs(2) = ptVertexs(0): ptVertexs(3) = A * -0.5 ptVertexs(4) = B: ptVertexs(5) = ptVertexs(3) ptVertexs(6) = ptVertexs(4): ptVertexs(7) = ptVertexs(3) - (OD - A) * 0.5 ptVertexs(8) = ptVertexs(6) + 0.05: ptVertexs(9) = ptVertexs(7) ptVertexs(10) = ptVertexs(8) + 0.15: ptVertexs(11) = ptVertexs(9) ptVertexs(12) = ptVertexs(10) + 0.05: ptVertexs(13) = ptVertexs(9) ptVertexs(14) = ptVertexs(12): ptVertexs(15) = ptVertexs(1) ptVertexs(16) = ptVertexs(0): ptVertexs(17) = ptVertexs(1) Dim oPLine As AcadLWPolyline Set oPLine = oBlock.AddLightWeightPolyline(ptVertexs) oPLine.SetBulge 4, -0.5 Dim oLoop1(0 To 0) As AcadEntity Set oLoop1(0) = oPLine Dim pt1(0 To 2) As Double Dim pt2(0 To 2) As Double pt1(0) = 0#: pt1(1) = 0#: pt1(2) = 0# pt2(0) = ptVertexs(14): pt2(1) = 0#: pt2(2) = 0# Dim oColor As AcadAcCmColor Set oColor = AcadApplication.GetInterfaceObject("AutoCAD.AcCmColor.25") Call oColor.SetRGB(255, 0, 0) Dim oHatch1 As AcadHatch Set oHatch1 = oBlock.AddHatch(acHatchPatternTypePreDefined, "ANSI31", True, acHatchObject) oHatch1.AppendOuterLoop (oLoop1) oHatch1.PatternScale = 0.01 oHatch1.TrueColor = oColor oHatch1.Evaluate Dim oLoop2(0 To 0) As AcadEntity Set oLoop2(0) = oLoop1(0).Mirror(pt1, pt2) Dim oHatch2 As AcadHatch Set oHatch2 = oBlock.AddHatch(acHatchPatternTypePreDefined, "ANSI31", True, acHatchObject) oHatch2.AppendOuterLoop (oLoop2) oHatch2.PatternScale = 0.01 oHatch2.TrueColor = oColor oHatch2.Evaluate pt1(0) = 0#: pt1(1) = Bore * -0.5: pt1(2) = 0# pt2(0) = 0#: pt2(1) = pt1(1) + Bore: pt2(2) = 0# Call oBlock.AddLine(pt1, pt2) pt1(0) = ptVertexs(12) pt2(0) = ptVertexs(12) Call oBlock.AddLine(pt1, pt2) Dim oDimAligned As AcadDimAligned Dim ptLoc(0 To 2) As Double pt1(0) = ptVertexs(12): pt1(1) = ptVertexs(11) pt2(0) = ptVertexs(12): pt2(1) = pt1(1) + OD ptLoc(0) = pt1(0) + 1.2: ptLoc(1) = Abs(pt1(1) - pt2(1)) * 0.5: ptLoc(2) = 0# Set oDimAligned = oBlock.AddDimAligned(pt1, pt2, ptLoc) pt1(0) = ptVertexs(0): pt1(1) = ptVertexs(7) + A + (OD - A) pt2(0) = ptVertexs(0) + B: pt2(1) = ptVertexs(7) + A + (OD - A) ptLoc(0) = Abs(pt1(0) - pt2(0)) * 0.5: ptLoc(1) = pt1(1) + 1# Set oDimAligned = oBlock.AddDimAligned(pt1, pt2, ptLoc) pt1(0) = ptVertexs(0): pt1(1) = ptVertexs(3) pt2(0) = ptVertexs(0): pt2(1) = pt1(1) + A ptLoc(0) = pt1(0) - 1.2: ptLoc(1) = Abs(pt1(1) - pt2(1)) * 0.5 Set oDimAligned = oBlock.AddDimAligned(pt1, pt2, ptLoc) pt1(0) = ptVertexs(0): pt1(1) = ptVertexs(3) + (A - Bore) * 0.5 pt2(0) = ptVertexs(0): pt2(1) = pt1(1) + Bore ptLoc(0) = pt1(0) - 0.75: ptLoc(1) = Abs(pt1(1) - pt2(1)) * 0.5 Set oDimAligned = oBlock.AddDimAligned(pt1, pt2, ptLoc) '挿入基点を指定する場合 'Dim ptInsert As Variant 'oDoc.Utility.InitializeUserInput 1 'ptInsert = oDoc.Utility.GetPoint(, vbCrLf & "挿入点を指定:") '挿入基点を原点で固定する場合 Dim ptInsert(0 To 2) As Double ptInsert(0) = 0#: ptInsert(1) = 0# Call oModel.InsertBlock(ptInsert, "精密滑車", 1#, 1#, 1#, 0#) oApp.ZoomExtents End Sub
記事全体を表示
Issue VBA で拡張エンティティ データを付加・参照・削除するには、それぞれ、どのようなマクロを作成すればいいでしょうか?   Solution 拡張エンティティ データは、AutoCAD 図面内の任意のオブジェクトに任意のカスタム データの付加、参照する手法です。   AutoCAD の標準コマンドは、付加された拡張エンティティ データを認識しないので、標準ユーザー インタフェースに値が表示されることはありませんが、逆に、ユーザから付加された固有データを隠蔽することが可能です。また、プログラムを介在させない限り、拡張エンティティ データを削除したり、値を変更したりすることができないので、ユーザーによる改変を防止することもできます。    次のコードは、拡張エンティティ データを付加する SetXData マクロ、参照する GetXData マクロ、削除する RemoveXData マクロの例です。 Public Sub GetXData() 'オブジェクト選択 Dim ptPick As Variant Dim oEnt As Object Dim oUtil As AcadUtility Set oUtil = ThisDrawing.Utility oUtil.GetEntity oEnt, ptPick, "拡張オブジェクトデータを参照する図形を選択:" '拡張オブジェクトデータ取得 Dim vXDataType As Variant Dim vXDataValue As Variant oEnt.GetXData "MYDATA", vXDataType, vXDataValue If VarType(vXDataType) = vbEmpty Then oUtil.Prompt (vbCrLf & "拡張オブジェクトデータ 'MYDATA' が付加されていません...") Else 'データ表示 oUtil.Prompt (vbCrLf & "年齢は " & CInt(vXDataValue(2))) oUtil.Prompt (vbCrLf & "身長は " & CDbl(vXDataValue(3))) oUtil.Prompt (vbCrLf & "体重は " & CDbl(vXDataValue(4))) oUtil.Prompt (vbCrLf & "人相は " & CStr(vXDataValue(5))) End If End Sub Public Sub SetXData() 'オブジェクト選択 Dim ptPick As Variant Dim oEnt As Object Dim oUtil As AcadUtility Set oUtil = ThisDrawing.Utility oUtil.GetEntity oEnt, ptPick, "拡張オブジェクトデータを付加する図形を選択:" '拡張オブジェクトデータ取得 Dim vXDataType As Variant Dim vXDataValue As Variant oEnt.GetXData "MYDATA", vXDataType, vXDataValue If VarType(vXDataType) <> vbEmpty Then oUtil.Prompt (vbCrLf & "既に拡張オブジェクトデータ 'MYDATA' が付加されています...") Else '入力 Dim nAge As Integer oUtil.InitializeUserInput (7) nAge = oUtil.GetInteger(vbCrLf & "年齢を入力(整数):") Dim dHeight As Double oUtil.InitializeUserInput (7) dHeight = oUtil.GetReal(vbCrLf & "身長を入力(実数):") Dim dWeight As Double oUtil.InitializeUserInput (7) dWeight = oUtil.GetReal(vbCrLf & "体重を入力(実数):") Dim strLooks As String strLooks = oUtil.GetString(True, vbCrLf & "人相を入力(文字):") 'データ付加 Dim nDataType(0 To 6) As Integer Dim vDataValue(0 To 6) As Variant nDataType(0) = 1001 'アプリケーション名 vDataValue(0) = "MYDATA" 'アプリケーション名 nDataType(1) = 1002 'コントロール文字 vDataValue(1) = "{" 'コントロール文字 nDataType(2) = 1070 '年齢(整数) vDataValue(2) = nAge '年齢(整数) nDataType(3) = 1040 '身長(実数) vDataValue(3) = dHeight '身長(実数) nDataType(4) = 1040 '体重(実数) vDataValue(4) = dWeight '体重(実数) nDataType(5) = 1000 '人相(文字) vDataValue(5) = strLooks '人相(文字) nDataType(6) = 1002 'コントロール文字 vDataValue(6) = "}" 'コントロール文字 oEnt.SetXData nDataType, vDataValue End If End Sub Public Sub RemoveXData() 'オブジェクト選択 Dim ptPick As Variant Dim oEnt As Object Dim oUtil As AcadUtility Set oUtil = ThisDrawing.Utility oUtil.GetEntity oEnt, ptPick, "拡張オブジェクトデータを削除する図形を選択:" '拡張オブジェクトデータ取得 Dim vXDataType As Variant Dim vXDataValue As Variant oEnt.GetXData "MYDATA", vXDataType, vXDataValue If VarType(vXDataType) <> vbEmpty Then 'データ付加 Dim nDataType(0) As Integer Dim vDataValue(0) As Variant nDataType(0) = 1001 'アプリケーション名 vDataValue(0) = "MYDATA" 'アプリケーション名 oEnt.SetXData nDataType, vDataValue Else oUtil.Prompt (vbCrLf & "拡張オブジェクトデータ 'MYDATA' が付加されていません...") End If End Sub 1 オブジェクトへの付加サイズ総量が 16 キロバイトまでに制限されています。 削除したい拡張エンティティ データのアプリケーション名を SetXData メソッドで上書きすると、同じアプリケーション名の拡張エンティティ データを削除することが出来ます。 付加されている拡張エンティティ データは、Express Tools の XDLIST コマンドで参照することが出来ます。
記事全体を表示
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"); } } } }  
記事全体を表示
Issue 図面ファイルを開いた際に、その図面ファイルの DWG ファイル形式が表示されます。 この情報を AutoCAD .NET API で取得することは出来ますか?    Solution 図面ファイル形式は、Database.OriginalFileVersion プロパティで返される DwgVersion 値で取得することが出来ます。    次のコードは、その C# 使用例です。   [CommandMethod("MyCommand", CommandFlags.Modal)] public void MyCommand() { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; Database db = Application.DocumentManager.MdiActiveDocument.Database; ed.WriteMessage("\nSaved DWG format:{0}", GetDwgFormat(db.OriginalFileVersion)); } private string GetDwgFormat(DwgVersion ver) { string dwgFormat = string.Empty; switch (ver) { case DwgVersion.AC1002: dwgFormat = "AutoCAD 2.5 形式"; break; case DwgVersion.AC1003: dwgFormat = "AutoCAD 2.6 形式"; break; case DwgVersion.AC1004: dwgFormat = "AutoCAD R9 形式"; break; case DwgVersion.AC1006: dwgFormat = "AutoCAD R10 形式"; break; case DwgVersion.AC1009: dwgFormat = "AutoCAD R11/R12 形式"; break; case DwgVersion.AC1012: dwgFormat = "AutoCAD R13 形式"; break; case DwgVersion.AC1014: dwgFormat = "AutoCAD R14 形式"; break; case DwgVersion.AC1015: dwgFormat = "AutoCAD 2000 形式"; break; case DwgVersion.AC1021: dwgFormat = "AutoCAD 2007 形式"; break; case DwgVersion.AC1024: dwgFormat = "AutoCAD 2010 形式"; break; case DwgVersion.AC1027: dwgFormat = "AutoCAD 2013 形式"; break; case DwgVersion.AC1032: dwgFormat = "AutoCAD 2018 形式"; break; case DwgVersion.AC1800: case DwgVersion.AC1800a: dwgFormat = "AutoCAD 2004 形式"; break; default: dwgFormat = "Unknown 形式"; break; } return dwgFormat; }    
記事全体を表示