Autodesk Community Tips- ADNオープン
Autodesk Community Tipsではちょっとしたコツ、やり方、ショートカット、アドバイスやヒントを共有しています。
ソート順:
質問 .NET 8移行 の外部アプリケーションから、以下のように Microsoft.VisualBasic.Interaction.GetObject を使用して起動中の AutoCAD の COM オブジェクトを取得しようとすると、Nothing が返されます。 Dim progId As String = "AutoCAD.Application.25.0" Dim acadApp As AcadApplication acadApp = CType(Interaction.GetObject(, progId), AcadApplication)   一方、Interaction.CreateObject を使用して AutoCAD を新規に起動することはできます。   .NET 以降の外部アプリケーションから、起動中の AutoCAD の COM オブジェクトを取得する方法はありますか?   回答 .NET では、Microsoft.VisualBasic.Interaction.GetObject を使用して、従来の .NET Framework と同様に起動中の COM オブジェクトを取得できない場合があります。 この場合、Windows API の GetActiveObject を P/Invoke で呼び出し、Running Object Table(ROT)に登録されている AutoCAD の COM オブジェクトを取得する方法を使用できます。 以下は VB.NET の例です。 Imports System.Runtime.InteropServices Imports Autodesk.AutoCAD.Interop <DllImport("ole32.dll", CharSet:=CharSet.Unicode, PreserveSig:=True)> Private Shared Function CLSIDFromProgIDEx( <MarshalAs(UnmanagedType.LPWStr)> progId As String, ByRef clsid As Guid) As Integer End Function <DllImport("oleaut32.dll", EntryPoint:="GetActiveObject", PreserveSig:=True)> Private Shared Function NativeGetActiveObject( ByRef clsid As Guid, reserved As IntPtr, <MarshalAs(UnmanagedType.IUnknown)> ByRef obj As Object) As Integer End Function Private Shared Function GetActiveObject(progId As String) As Object Dim clsid As Guid Dim hr As Integer = CLSIDFromProgIDEx(progId, clsid) If hr < 0 Then Marshal.ThrowExceptionForHR(hr) End If Dim obj As Object = Nothing hr = NativeGetActiveObject(clsid, IntPtr.Zero, obj) If hr < 0 Then Marshal.ThrowExceptionForHR(hr) End If Return obj End Function   起動中の AutoCAD を取得する場合は、次のように呼び出します。 Dim acadApp As AcadApplication acadApp = CType( GetActiveObject("AutoCAD.Application.25.0"), AcadApplication) 上記の AutoCAD.Application.25.0 は AutoCAD 2025 の ProgID です。使用する AutoCAD のバージョンに応じて ProgID を変更してください。   なお、AutoCAD 2025 から .NET 8 が採用されているため、AutoCAD 2025 以降の外部 .NET アプリケーションで、この違いが表面化するケースがあります。 Autodesk Developer Blog でも、.NET 8 から起動中の AutoCAD COM オブジェクトを取得する方法として、Windows API の GetActiveObject を使用する方法が紹介されています。   参考   Autodesk Developer Blog: AutoCAD 2025 : Marshal.GetActiveObject .NET Core Microsoft: Interaction.GetObject Method  
記事全体を表示
Issue AutoCAD .NET API でスイープ ソリッドとスイープ サーフェスを作成する方法を教えてください。   Solution スイープ ソリッドは Solid3d.CreateSweptSolid メソッドで、スイープ サーフェスは LoftedSurface.CreateSweptSurface メソッドで、それぞれ作図することが出来ます。CreateSweptSolid メソッドを使ったサンプルコードは次のようになります。スイープ サーフェスの場合には、CreateSweptSolid メソッドをCreateSweptSurface メソッドに置き換えてください。   実行時には、プロンプトに従って、断面とパスになるオブジェクトを選択してみてください。   C# コード Database db = HostApplicationServices.WorkingDatabase; Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; PromptEntityOptions peo1 = new PromptEntityOptions("\nスイープする円を選択:"); peo1.SetRejectMessage("\nスイープする円を選択してください"); peo1.AddAllowedClass(typeof(Circle), true); PromptEntityResult pent1 = ed.GetEntity(peo1); if (pent1.Status != PromptStatus.OK) { return; } PromptEntityOptions peo2 = new PromptEntityOptions("\nスイープのパスとなる3Dポリラインかスプラインを選択:"); peo2.SetRejectMessage("\nスイープのパスとなる3Dポリラインかスプラインを選択してください"); peo2.AddAllowedClass(typeof(Polyline3d), true); peo2.AddAllowedClass(typeof(Spline), true); PromptEntityResult pent2 = ed.GetEntity(peo2); if (pent2.Status != PromptStatus.OK) { return; } try { using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent1 = (Entity)tr.GetObject(pent1.ObjectId, OpenMode.ForRead); Entity ent2 = (Entity)tr.GetObject(pent2.ObjectId, OpenMode.ForRead); Curve pathCurve = (Curve)ent2; Circle profileCircle = (Circle)ent1; double distToStart = profileCircle.Center.DistanceTo(pathCurve.StartPoint); double distToEnd = profileCircle.Center.DistanceTo(pathCurve.EndPoint); Solid3d acSweep = new Solid3d(); SweepOptionsBuilder acSwOption = new SweepOptionsBuilder(); acSweep.RecordHistory = true; acSwOption.Bank = false; acSwOption.Align = SweepOptionsAlignOption.AlignSweepEntityToPath; acSwOption.AlignAngle = 0.0; acSwOption.AlignStart = distToStart <= distToEnd; acSweep.CreateSweptSolid(ent1, ent2, acSwOption.ToSweepOptions()); BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); ms.AppendEntity(acSweep); tr.AddNewlyCreatedDBObject(acSweep, true); tr.Commit(); } } catch (Autodesk.AutoCAD.Runtime.Exception ex) { ed.WriteMessage("\nERROR : {0}", ex.Message); }    
記事全体を表示
Issue 3D ソリッド オブジェクトを作成して API でブール演算すると、次のようなエラーメッセージを表示して処理に失敗してしまいます。 ソリッドまたはサーフェス ボディのブール演算に失敗しました。 モデリング操作エラー: Error Code Number is xxxxxxx (xxxxxxx は数字) ブール演算を成功させる方法はありますか?   Solution モデリング操作エラーや、その要因となっているソリッドやサーフェスモデルの破損は、AutoCAD を含むオートデスク製品全般で共用している ACIS 由来のソリッド カーネル Autodesk Shape Manager の精度上の制限が原因となっているのが一般的です。このため、ObjectARX、.NET API、AutoLISP、ActiveX オートメーション(COM API)など、API の種類に関わらず発生することがあります。同様に、AutoCAD の UNION[和] コマンドや SUBTRACT[差] コマンドでも発生するはずです。また、複雑なソリッドやサーフェスモデルの作成時にも発生する場合があります。   AutoCAD 2027 以降のバージョンであれば、Autodesk Assistant がヒントを与えてくれる場合があります。Error Code Number is xxxxxxx ののエラー数字とともに確認することも出来ますので、念のため、確認してみてください。     ソリッドやサーフェスモデルが破損しているか否かは、SOLIDEDIT[ソリッド編集] コマンドの B オプション >> C オプション([ボディ(B)]: [チェック(C)])で確認することが出来ます。まずは、ソリッドやサーフェスモデルが健全かどうかを確認してみてください。 すべてのケースで問題を回避出来る訳ではありませんが、一般に、ソリッドやサーフェスモデル内部情報の破損の可能性を低減する、または、ブール演算時のエラーを低減するには、次のような構造をアドイン アプリケーション内で実装が推奨されています。   ソリッドモデル / サーフェスモデル、素材となるオブジェクトの境界ボックス座標 X、Y、Z 値の最大値が 10,000 以上(最小値の場合、-10,000)になる場合、 最大座標が 10,000 未満(あるいは、-10,000 未満)になるようにソリッド モデルを一時的に原点付近置くか、最大座標が 10,000 未満になるように縮小する。 原点付近、かつ、最大座標が 10,000 未満になる状態でソリッド モデルの編集、ブール演算をおこなう。 ソリッドモデル / サーフェスモデルを縮小した場合、または、縮尺した状態で結果を得た場合には、元の尺度に拡大処理して、元の配置位置に移動する(戻す)。   次の C# コードは、3D 処理前後で原点を基準に 1/100 に縮尺➔処理➔100 倍に拡大(元の大きさ復元)する参考例です。   ... using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent1 = (Entity)tr.GetObject(pent1.ObjectId, OpenMode.ForRead); Entity ent2 = (Entity)tr.GetObject(pent2.ObjectId, OpenMode.ForRead); // 原点(0,0,0)を基準に 1/100 へ縮尺するマトリックス Matrix3d scaleDownMat = Matrix3d.Scaling(1.0 / 100.0, Point3d.Origin); // 原点(0,0,0)を基準に 100 倍へ拡大するマトリックス Matrix3d scaleUpMat = Matrix3d.Scaling(100.0, Point3d.Origin); // 元オブジェクトは変更しないよう、複製してから縮尺 using (Entity ent1Scaled = (Entity)ent1.Clone()) using (Entity ent2Scaled = (Entity)ent2.Clone()) { ent1Scaled.TransformBy(scaleDownMat); ent2Scaled.TransformBy(scaleDownMat); // 1/100 に縮尺したオブジェクトで 3D 処理(ブール演算・3D オブジェクト作成 // 作成した結果(オブジェクト)を、同じ原点(0,0,0)基準で 100 倍に戻す entresult.TransformBy(scaleUpMat); BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); ms.AppendEntity(entresult); tr.AddNewlyCreatedDBObject(entresult, true); } tr.Commit(); } ...  
記事全体を表示
Issue AutoCAD .NET API でロフト ソリッドとロフト サーフェスを作成する方法を教えてください。   Solution ロフト ソリッドは Solid3d.CreateLoftedSolid メソッドで、ロフト サーフェスは LoftedSurface.CreateLoftedSurface メソッドで、それぞれ作図することが出来ます。サンプルコードは次のようになります。断面になるオブジェクトを選択してみてください。   Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; Database db = HostApplicationServices.WorkingDatabase; PromptEntityOptions peo1 = new PromptEntityOptions("\n最初のロフト断面を選択:"); PromptEntityResult pent1 = ed.GetEntity(peo1); if (pent1.Status != PromptStatus.OK) { return; } PromptEntityOptions peo2 = new PromptEntityOptions("\n2番目のロフト断面を選択:"); PromptEntityResult pent2 = ed.GetEntity(peo2); if (pent2.Status != PromptStatus.OK) { return; } using (Transaction tr = db.TransactionManager.StartTransaction()) { Entity ent1 = (Entity)tr.GetObject(pent1.ObjectId, OpenMode.ForRead); Entity ent2 = (Entity)tr.GetObject(pent2.ObjectId, OpenMode.ForRead); Solid3d sld = new Solid3d(); LoftOptions options = new LoftOptions(); Entity[] sections = new Entity[] { ent1, ent2 }; Entity[] guide = new Entity[] { }; sld.CreateLoftedSolid(sections, guide, null, options); BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); ms.AppendEntity(sld); tr.AddNewlyCreatedDBObject(sld, true); tr.Commit(); }    
記事全体を表示
Issue AutoCAD .NET API でパスに沿って押し出すソリッドの作成方法を教えてください。   Solution Solid3d.ExtrudeAlongPath メソッドで、パスに沿って押し出すソリッドを作図することが出来ます。   C# コード Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; Database db = HostApplicationServices.WorkingDatabase; PromptEntityOptions peo1 = new PromptEntityOptions("\nパスに沿って追し出す円を選択:"); peo1.SetRejectMessage("\nパスに沿って追し出す円を選択してください"); peo1.AddAllowedClass(typeof(Circle), true); PromptEntityResult pent1 = ed.GetEntity(peo1); if (pent1.Status != PromptStatus.OK) { return; } PromptEntityOptions peo2 = new PromptEntityOptions("\nパスとなる 3D ポリラインを選択:"); peo2.SetRejectMessage("\nパスとなる 3D ポリラインを選択してください"); peo2.AddAllowedClass(typeof(Polyline3d), true); PromptEntityResult pent2 = ed.GetEntity(peo2); if (pent2.Status != PromptStatus.OK) { return; } using (Transaction tr = db.TransactionManager.StartTransaction()) { Circle acCirc = (Circle)tr.GetObject(pent1.ObjectId, OpenMode.ForRead); Polyline3d acPline3d = (Polyline3d)tr.GetObject(pent2.ObjectId, OpenMode.ForRead); DBObjectCollection acDBObjColl = new DBObjectCollection(); acDBObjColl.Add(acCirc); DBObjectCollection myRegionColl = new DBObjectCollection(); myRegionColl = Autodesk.AutoCAD.DatabaseServices.Region.CreateFromCurves(acDBObjColl); using (Autodesk.AutoCAD.DatabaseServices.Region? acRegion = myRegionColl[0] as Autodesk.AutoCAD.DatabaseServices.Region) { Solid3d acSolid = new Solid3d(); acSolid.ExtrudeAlongPath(acRegion, acPline3d, 0.0); acSolid.RecordHistory = true; BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); ms.AppendEntity(acSolid); tr.AddNewlyCreatedDBObject(acSolid, true); } tr.Commit(); }  
記事全体を表示
Issue AutoLISP の (entlast) 関数や ObjectARX の、 acdbEntLast() 関数のように、図面内の削除されていない最後の主エンティティ(グラフィカル オブジェクト)を取得する方法が AutoCAD .NET API にありますか?   Solution 図面の最後に追加されたグラフィカル オブジェクトを取得するには Autodesk.AutoCAD.Internal.Utils.EntLast メソッドを利用することが出来ます。   Autodesk.AutoCAD.Internal 名前空間以下のメソッドやプロパティは、公式にサポートされたものではないため、ドキュメント化されていません。予告なく、変更される場合がありますので、ご注意ください。  [CommandMethod("GetLast", CommandFlags.Modal)] public void GetLast() // This method can have any name { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; ObjectIdCollection ids = new ObjectIdCollection(); ids.Add(Autodesk.AutoCAD.Internal.Utils.EntLast()); ObjectId[] idArray = new ObjectId[ids.Count]; ids.CopyTo(idArray, 0); ed.SetImpliedSelection(idArray); }   
記事全体を表示
ファミリを他のファミリにネストして、結合したファミリ ジオメトリを含んだ新しいファミリ(サードファミリ)を作成することができます。   たとえば、スクラッチから電球ファミリを含む照明器具をモデリングするのではなく、電球を照明器具ファミリにロードすることで、複合照明ファミリを作成することができます。   下記のヘルパーメソッドは、次の3つのステップを通じて、ドキュメント上に外部のRFAファイルを読み込んで、ファミリインスタンス を生成するサンプルコードです。 ドキュメントにファミリをロードします。 ファミリシンボルを取得します。 新しいファミリインスタンスを作成します。   StructuralType _non_rst = StructuralType.NonStructural; FamilyInstance InsertFamilySymbolFromRfa( string filename, Document doc ) { FamilyInstance fi = null; // // load family file: // Family f; if( doc.LoadFamily( filename, out f ) ) { // // retrieve family symbol: // FamilySymbol symbol = null; foreach( FamilySymbol s in f.Symbols ) { symbol = s; break; } // // create family instance: // if( null != symbol ) { if( doc.IsFamilyDocument ) { fi = doc.FamilyCreate.NewFamilyInstance( XYZ.Zero, symbol, _non_rst ); } else { fi = doc.Create.NewFamilyInstance( XYZ.Zero, symbol, _non_rst ); } } } return fi; } public IExternalCommand.Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements ) { Application app = commandData.Application; Document doc = app.ActiveDocument; FamilyInstance a = InsertFamilySymbolFromRfa( "C:/tmp/column.rfa", doc ); FamilyInstance b = InsertFamilySymbolFromRfa( "C:/tmp/shelf.rfa", doc ); return IExternalCommand.Result.Succeeded; }   実装の際の注意点として、ファミリのタイプまたはパラメータにアクセスするための FamilyManager クラスは、ターゲットとなるファミリのファミリドキュメントをロードしなければ利用できません。パラメータを設定する際には、ドキュメントロードの処理時間も考慮して設計する必要があります。   またファミリをネストしてサードファミリを作成する前には、そのネストするファミリのパラメータの共有設定(有効/無効)を事前に考慮しなければなりません。   この共有設定により、サードファミリをロードして要素を配置した際のジオメトリの動作が異なります。 ネストするファミリが共有設定されていない場合、そのネストしたファミリによって作成したコンポーネントは、他の要素とともに単一ユニットとして動作します。コンポーネントを別々に選択(編集)したり、タグ付けや集計することができません。 ネストするファミリが共有設定されている場合、コンポーネントを別々に選択、タグ付け、および集計できます。 以下のリンクは、複数のファミリをネストしてサードファミリを作成する手法に関する解説です。Revit APIを利用して実装する際にも役立ちますのでご参照ください。 ロード可能なファミリのネスト、共有について コンポーネントがネストされたファミリを作成する コンポーネントがネストおよび共有されたファミリを作成する 交換可能なコンポーネントでネストされたファミリを作成する
記事全体を表示
ファミリを新規に作成するのではなく、ジオメトリ要素をドキュメント上で直接作成するための DirectShape クラスを利用することができます。   DirectShape クラスは、Revit 2015から追加されたAPIで、これは外部で作成されたジオメトリ要素をストアするためのクラスです。 主な使用方法は、IFCなどの他のデータフォーマットからジオメトリをインポートすることですが、ジオメトリ要素を保存する入れ物として利用できます。また作成したDirectShape オブジェクトは、カテゴリを割り当てることができます。 DirectShape オブジェクトにストアできるジオメトリ要素は、IListを引数としてとり、TessellatedShapeBuilder クラスを使用して作成することができます。   TessellatedShapeBuilder は、TessellatedFace オブジェクトで作成された複数の平面からソリッド、ポリメッシュを作成するためのビルダークラスです。   下記にサンプルコードを記載いたします。   using (Transaction tx = new Transaction(doc)) { tx.Start("Create DirectShape"); double length = 1; try { do { length = length + 1; Debug.Print( "Creating DirectShape tetrahedron with side length {0}...", length); List args = new List(3); TessellatedShapeBuilder builder = new TessellatedShapeBuilder(); builder.OpenConnectedFaceSet(false); args.Add(XYZ.Zero); args.Add(length * XYZ.BasisX); args.Add(length * XYZ.BasisY); builder.AddFace(new TessellatedFace(args, ElementId.InvalidElementId)); args.Clear(); args.Add(XYZ.Zero); args.Add(length * XYZ.BasisX); args.Add(length * XYZ.BasisZ); builder.AddFace(new TessellatedFace(args, ElementId.InvalidElementId)); args.Clear(); args.Add(XYZ.Zero); args.Add(length * XYZ.BasisY); args.Add(length * XYZ.BasisZ); builder.AddFace(new TessellatedFace(args, ElementId.InvalidElementId)); args.Clear(); args.Add(length * XYZ.BasisX); args.Add(length * XYZ.BasisY); args.Add(length * XYZ.BasisZ); builder.AddFace(new TessellatedFace(args, ElementId.InvalidElementId)); builder.CloseConnectedFaceSet(); TessellatedShapeBuilderResult result = builder.Build( TessellatedShapeBuilderTarget.Solid, TessellatedShapeBuilderFallback.Abort, graphicsStyleId); ElementId categoryId = new ElementId( BuiltInCategory.OST_GenericModel); DirectShape ds = DirectShape.CreateElement( doc, categoryId, "A", "B"); ds.SetShape(result.GetGeometricalObjects()); ds.Name = "Test"; } while (Iterate_until_crash && length < 100); } catch (Exception e) { Debug.Print( "Creating DirectShape tetrahedron with side length {0} " + "threw exception '{1}'", length, e.Message); message = e.Message; return Result.Failed; } tx.Commit(); }   詳細は Revit API 開発者用ガイドの下記ページをご参照ください。 Revit API 開発者用ガイド - DirectShape
記事全体を表示
窓、ドア、開口部などを含んだ壁のプロファイルを取得するためのメソッドは用意されていませんが、壁の側面を取得して、その面のエッジループを取得することができます。外側と内側のエッジループを識別することができます。   以下にサンプルコードを記載いたします。   このコードでは壁の外側の面を HostObjectUtils.GetSideFaces メソッドで取得し、壁のジオメトリを形成するエッジループを CurveLoop として取得しています。そして IFC 関連のアドイン用に用意されたExporterIFCUtilsクラスのSortCurveLoopsメソッドを使用しています。   このメソッドは CurveLoop に含まれる曲線ループをソートして、外側のエッジループである曲線ループを配列の最初に配置します。そして、窓、ドア、開口部などによる内側のループをその後に配置しています。 ExporterIFCUtilsクラス は IFC 関連のアドインでなくとも RevitAPIIFC.dll を参照追加することで利用できます。   そして、次に IsCounterclockwise メソッドを使用して各ループの方向が時計回りまたは反時計回りかを判定しています。外側のループは常に反時計回りとなります。 従って、SortCurveLoops メソッドでソートをしなくとも IsCounterclockwise メソッドで判定することで外側のループを見つけることができます。   このサンプルでは見つけた各エッジのループに対してモデル線分を作成しています。そして外側のループのモデル線分の色を赤に上書き設定しています。   Reference r = uidoc.Selection.PickObject(ObjectType.Element, "Select a wall"); Element e = uidoc.Document.GetElement(r); Wall wall = e as Wall; using (Transaction tx = new Transaction(doc)) { tx.Start("Wall Profile"); // Get the exteranl wall face for the profile IList<Reference> sideFaces = HostObjectUtils.GetSideFaces(wall, ShellLayerType.Exterior); Element e2 = doc.GetElement(sideFaces[0]); Face face = e2.GetGeometryObjectFromReference(sideFaces[0]) as Face; XYZ normal = face.ComputeNormal(new UV(0, 0)); // the normal of the wall external face Color color = new Color(255, 0, 0); // RED // Get edge loops as curve loops IList<CurveLoop> curveLoops = face.GetEdgesAsCurveLoops(); // ExporterIFCUtils class can be used for none IFC poupose. // SortCurveLoops method sorts curve loops (edge loops) so that outer loops come first IList<IList<CurveLoop>> curveLoopLoop = ExporterIFCUtils.SortCurveLoops(curveLoops); foreach (IList<CurveLoop> curveLoops2 in curveLoopLoop) { foreach (CurveLoop curveLoop2 in curveLoops) { // check if curve loop (edge loop) is counter clockwise bool isCCW = curveLoop2.IsCounterclockwise(normal); CurveArray curves = doc.Application.Create.NewCurveArray(); foreach (Curve curve in curveLoop2) { curves.Append(curve); } // Create model lines for an cureve loop SketchPlane sketchPlane = SketchPlane.Create(doc, doc.Application.Create.NewPlane(curves)); ModelCurveArray curveElements = doc.Create.NewModelCurveArray(curves, sketchPlane); // if the curve loop direction is counter clockwise, change the color to RED if (isCCW) { foreach (ModelCurve mcurve in curveElements) { OverrideGraphicSettings overrides = doc.ActiveView.GetElementOverrides(mcurve.Id); overrides.SetProjectionLineColor(color); doc.ActiveView.SetElementOverrides(mcurve.Id, overrides); } } } } tx.Commit(); }      
記事全体を表示
Revit APIのアイドルリング・イベントを使用してアドインにバッチ処理を実装することができます。   下記の記事ではRevit プロジェクトをPDFファイルに書き出すバッチ処理を例にして、バッチ処理の実装方法をご紹介しています。 サンプルプロジェクトがダウンロードで入手できますのでどうぞそちらをご覧ください。 https://jeremytammik.github.io/tbc/a/0957_auto_pdf_print.htm   この例ではWindowsタスクスケジューラで作成したスタンドアロンアプリケーションの実行を管理しています。このスタンドアロンアプリケーションはRevitを起動します。   Revitがアイドル状態になるとRevitアドインが予め指定されたフォルダ内のプロジェクトファイルを開いてPDFファイルとして書き出します。これをフォルダ内のすべてのファイルに行います。   Revit SDKには以下のアイドリング・イベントのサンプルが含まています。 Revit SDK\Samples\ModelessDialog\ModelessForm_IdlingEvent
記事全体を表示
質問 Visual Studioで「InventorViewCtrl.ocxの自己登録に失敗しました」エラーが発生して、Inventor ViewコントロールをWindowsフォームへ追加することが出来ない。   回答 Inventor View 2021では、64bit版のOCXのみが提供されておりますが、Visual Studioが32bit版のアプリケーションのため、Inventor Viewコントロールをツールボックスへ追加することや、Visual StudioのGUIからのWindows フォームへの配置を行うことができません。 このため、WindowsフォームでInventor Viewコントロールを使用するためには、プログラムから動的にInventor Viewコントロールを追加をする必要があります。 以下に、Visual Studioで、InventorViewCtl.ocxを使用する際の、環境設定及びWindows Form(C#)のサンプルプロジェクトの作成の手順を示します。 Step 1. Aximp.exe(Windows フォーム ActiveX コントロール インポーター) を用いて、InventorViewCtl.ocxの相互運用アセンブリを作成 1.管理者権限でコマンドプロンプトを起動2.Inventor View 2021インストールディレクトリ(デフォルトではC:\Program Files\Autodesk\Inventor View 2021\Bin)へ移動。 >cd C:\Program Files\Autodesk\Inventor View 2021\Bin 3.InventorViewCtrl.ocxをレジストリ登録 >regsvr32 InventorViewCtrl.ocx 4.64bit版のAximp.exeを用いて相互運用アセンブリを作成。 >"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\x64\aximp.exe" InventorViewCtrl.ocx ※ご利用の環境でインストールされているWindows SDKで64bit版のaximp.exeを探し、aximp.exeのパスを置き換えて実行。 正しく実行されれば以下のようなメッセージが出力され、相互運用アセンブリInventorApprentice.dll、InventorViewControlLib.dll、AxInventorViewControlLib.dllが出力されます。 生成されたアセンブリです: C:\Program Files\Autodesk\Inventor View 2021\Bin\InventorApprentice.dll 生成されたアセンブリです: C:\Program Files\Autodesk\Inventor View 2021\Bin\InventorViewControlLib.dll 生成されたアセンブリです: C:\Program Files\Autodesk\Inventor View 2021\Bin\AxInventorViewControlLib.dll Step2. Path システム環境変数に、C:\Program Files\Autodesk\Inventor View 2021\Binを追加   Step3. 相互運用アセンブリを、Visual Studioのプロジェクトに追加 1.Visual Studioで、新規Windows Form アプリケーション(C#)を作成 2.Visual Studioのソリューションエクスプローラから、「参照」を選択し右クリック「参照の追加」を選択。 3.参照マネージャダイアログで「参照」ボタンをクリックし、C:\Program Files\Autodesk\Inventor View 2021\Bin配下「AxInventorViewControlLib.dll」、「InventorViewControlLib.dll」を選択して「追加」を押下。ソリューションエクスプローラの「参照」配下に「AxInventorViewControlLib」、「InventorViewControlLib」が追加される。 4.ソリューションエクスプローラの「参照」-「InventorViewControlLib」を選択して右クリックメニューから「プロパティ」を選択 5.「InventorViewControlLib」のプロパティで、相互運用方の埋め込みを「False」に変更し、「ローカルにコピー」がTrueとなっていることを確認   6.ソリューションエクスプローラで、プロジェクトを選択し、右クリックメニューから「プロパティ」を選択し、ビルドのプラットフォームターゲットをx64に変更   7.Windows Formに、InventorViewのインスタンスを格納する変数および、初期化処理をFormのLoadイベントに追加 ※サンプルコードでは、フォームの(7, 7)の位置に、大きさ(500, 400)でInventorViewCtrl.ocxを張り付け、FileNameプロパティに指定したInventorファイルを表示。 public partial class Form1 : Form { private AxInventorViewControlLib.AxInventorViewControl inventerViewCtl; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { inventerViewCtl = new AxInventorViewControlLib.AxInventorViewControl(); inventerViewCtl.Location = new System.Drawing.Point(7, 7); inventerViewCtl.Size = new System.Drawing.Size(500, 400); inventerViewCtl.Visible = true; this.Controls.Add(inventerViewCtl); inventerViewCtl.FileName = "<ロードするInventorファイルへのパス>"; } }   8.ソリューションをビルドして、出力されたexeを実行   実行時にエラーが発生した場合、Step2の環境変数設定が反映されていない可能性があるため、Windowsの再起動等を行い、環境変数が反映されている状態で再度exeを実行確認してください。  
記事全体を表示
質問 Vaultクライアントで表示されているファイル名と、Vault APIのFileAssoc.ExpectedVaultPathで取得した値が異なっている場合がある。 回答 プロパティ名のExpected(=期待する)が表すように、その値はVault内でのパスを表すことが期待されるものですが、Vaultクライアントでのファイル名を返さない場合があります。 例えば、Inventorのアセンブリファイルなど親子関係の構成を持つファイルの子ファイルの名前を、Vaultクライアントの名前変更で名前を変更した場合にVaultクライアントでのファイル名とFileAssoc.ExpectedVaultPathの値に差異が生じます。 この場合、Vaultクライアントで名前変更をしても、そのファイルを参照している、親のファイル内のデータは書き換えられていないため、Inventorで対象の親ファイルを開く際に、このExpectedVaultPathの値を用いて名前変更が行われたことを検知して、変更後の名前を用いて子ファイルの参照を解決します。 FileAssoc.ExpectedVaultPathはこのような用途で用いられるため、Vaultクライアントでのファイル名を返さない場合があることにご留意ください。
記事全体を表示
質問 Vault APIを使用して作成したカスタムアプリケーションからVaultにログインをするとFailed to acquire a license.ダイアログが表示されログインができない。 APIからではなくVault アプリケーションからは、正常にログインができる。   回答 Valut製品インストールフォルダ配下にある、AdskLicensingSDK_3.dllを、カスタムアプリケーションの実行モジュール(.exe)と同一ディレクトリにコピーをすることで、ログインダイアログ以降に進むことが可能です。  
記事全体を表示
質問 Managed .Net API でレイアウト空間のビューポート表示範囲のオブジェクトを取得する方法はありますか?   回答 AutoCADでの、レイアウトのビューポートは、モデル空間への覗き窓となり、ビューポートに表示されている図形の実態はレイアウト空間には存在しません。 また、ビューポートは、モデル空間とは異なる座標系を持つため、ビューポートに表示されている図形を取得するためには、ビューポートの表示領域の対角点座標をモデル空間上の座標に変換した後に、変換後の座標でモデル空間上の図形を選択する必要があります。 次のコードは、ビューポートに表示されている図形の選択を行うサンプルコードです。 Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; Database db = doc.Database; ed.SwitchToPaperSpace(); //ビューポートを選択 var peo = new PromptEntityOptions("\nSelect viewport: "); peo.SetRejectMessage("\nRequires a Viewport"); peo.AddAllowedClass(typeof(Viewport), false); PromptEntityResult result = ed.GetEntity(peo); if (result.Status != PromptStatus.OK) return; using (var tr = new OpenCloseTransaction()) { Viewport viewport = (Viewport)tr.GetObject(result.ObjectId, OpenMode.ForRead); /// ビューポート設定から、変換マトリクスを取得 Point2d viewCenter = viewport.ViewCenter; double x = viewCenter.X; viewCenter = viewport.ViewCenter; Point3d center = new Point3d(x, viewCenter.Y, 0.0); Point3d vpcenter = viewport.CenterPoint; Matrix3d tfmatrix = (Matrix3d.Displacement(new Vector3d(vpcenter.X - center.X, vpcenter.Y - center.Y, 0.0)) * Matrix3d.Scaling(viewport.CustomScale, center) * Matrix3d.Rotation(viewport.TwistAngle, Vector3d.ZAxis, Point3d.Origin) * Matrix3d.WorldToPlane(new Plane(viewport.ViewTarget, viewport.ViewDirection))).Inverse(); ///ビューポートのMin/Max座標を変換マトリクスでモデル座標に変換 Extents3d extents = viewport.GeometricExtents; Point3d msMinPoint = extents.MinPoint.TransformBy(tfmatrix); Point3d msMaxPoint = extents.MaxPoint.TransformBy(tfmatrix); tr.Commit(); ed.SwitchToModelSpace(); //取得したMin、Maxポイントを用いて図形を選択 var psr = ed.SelectWindow(msMinPoint, msMaxPoint); }  
記事全体を表示
質問 InventorのPack And Goを、VBAから実行する場合は参照設定には、どのモジュールを追加すればよいですか?   回答 .net 系の言語からPack And Goを利用する場合は、COM相互運用モジュールのAutodesk.PackAndGo.Interop.dllを参照設定しますが、VBAからPackAndGoを行う場合、Autodesk.PackAndGo.Interop.dllではなく、<Inventorインストールフォルダ>\bin\DTInterop.dllを参照設定をする必要があります。
記事全体を表示
Inventor で他のドキュメントへの参照が含まれるドキュメントを開くときには、参照先ドキュメントのパスを決定する必要があります。このプロセスは「ファイル解決」と呼ばれ、InventorのFileAccessEvents.OnFileResolutionイベントを使用することで、 Inventor の標準ファイル解決をオーバーライドして、ユーザ自身で解決を実行することができます。   このオーバライドは、FileAccessEvents.OnFileResolutionイベントのFullFileName引数に、ファイルのフルパスを指定することによって行われますが、FullFileNameに正しくファイルのパスを指定したにもかかわらず、Inventorが指定したファイルを読み込まないことがあります。   解決方法 Visual Studio 2010 .Net Framework 4.0以降に導入された「相互運用型の埋め込み」の不具合により、イベント処理が正しく行われていない可能性があります。 以下の手順にて、Autodesk.Inventor.Interropの「相互運用型の埋め込み」を行わないようにすることで不具合を回避することが可能です。 1.Visual Studioのプロジェクトエスプローラより、「参照」-「Autodesk.Inventor.Interrop」を選択し、右クリックメニューより「プロパティを選択」して、アセンブリのプロパティを表示 2.プロパティリストの、「相互運用型の埋め込み」の値をTrueからFalseに変更 3.プロジェクトをリビルド  
記事全体を表示
質問 InventorのAPIで図面のシートをコピーすることは出来ますか?   回答 InventorのSheet.CopyTo()メソッドを利用することでシートのコピーをすることが出来ます。 なお、Inventor 2021.2より前のバージョンの場合、同一ドキュメント内でシートを直接コピーすることが出来ず、ダミーのドキュメントを作成しダミーのドキュメントにシートを一旦コピーしてから、元のドキュメントにコピーを作成する必要があります。 Inventor 2021.2以降のバージョンでは、同一ドキュメント内でのコピーが可能です。   Inventor 2021.1より前 Dim doc As DrawingDocument = g_inventorApplication.ActiveDocument 'コピー用にダミーのドキュメントを作成 Dim dummyDoc As DrawingDocument = g_inventorApplication.Documents.Add(DocumentTypeEnum.kDrawingDocumentObject, , False) 'ダミーのドキュメントにシートをコピー Dim orgSheet As Sheet = doc.Sheets(1) Dim cpSheet As Sheet = orgSheet.CopyTo(dummyDoc) ’コピーしたシートを元のドキュメントにコピー Dim tgSheet As Sheet = cpSheet.CopyTo(doc)   Inventor 2021.2以降 Dim doc As DrawingDocument = g_inventorApplication.ActiveDocument Dim orgSheet As Sheet = doc.Sheets(1) Dim tgSheet = orgSheet.CopyTo(doc)
記事全体を表示
質問 InventorのAPIで、IDWファイルをバージョンを指定してDXFに変換する方法はありますか?   回答 DWG Translator Addinを用いることでidwをバージョンを指定してdxfに出力することが可能です。 Dim oDWGAddIn As TranslatorAddIn oDWGAddIn = ThisApplication.ApplicationAddIns.ItemById("{C24E3AC2-122E-11D5-8E91-0010B541CD80}") If oDWGAddIn Is Nothing Then MessageBox.Show("DWG アドインが見つかりません") Return End If If Not oDWGAddIn.Activated Then oDWGAddIn.Activate End If Dim oNameValueMap As NameValueMap oNameValueMap = ThisApplication.TransientObjects.CreateNameValueMap Dim strIniFile As String = "" oNameValueMap.Add("Export_Acad_IniFile", strIniFile) Dim oContext As TranslationContext oContext = ThisApplication.TransientObjects.CreateTranslationContext oContext.Type = kFileBrowseIOMechanism Dim oOutputFile As DataMedium oOutputFile = ThisApplication.TransientObjects.CreateDataMedium oOutputFile.FileName = "" oDWGAddIn.SaveCopyAs(ThisApplication.ActiveDocument, oContext, oNameValueMap, oOutputFile)   コード中の 出力設定Iniファイルのパスを、使用する出力設定Iniファイルのパスに置き換えてください。 出力設定のIniファイルは、InventorのGUIから「コピーを名前を付けて保存」でdxfファイルをを出力する際に「オプションダイアログ」を起動しダイアログ内の「設定を保存」ボタンから作成が可能です。   このIniファイルには、ダイアログで指定した出力対象のdxfのバージョン指定が保存されます。 出力対象のDxfのバージョン毎に出力設定Iniファイルを作成することで、バージョンを指定しての出力が可能となります。
記事全体を表示
質問 Inventorの2D図面に配置したView内の各コンポーネントを、AutoCAD図面のブロックにする方法はありますか?   回答 次のStepでInventorとAutoCADのAPIを用いてInventorの2D図面を加工することで、2D図面に配置したView内の各コンポーネントをAutoCADのブロック化することが可能です。 ただし、2D図面でViewとして配置したアセンブリの直下のコンポーネントの単位でのみブロック化が可能です。サブアセンブリ配下のコンポーネントについては個別のブロックとすることは出来ません。 Step 1.Inventor 2D図面を構成する図形(CurveやFaceやEdge 等)を、図形の元となるコンポーネント毎に層を作成して分類 Step 2.1で加工した図面をInventorの出力機能を用いてAutoCAD図面として出力 Step 3.2で出力したAutoCAD図面で、各層の図形をブロック化して配置 Step 1.Inventor 2D図面を構成する図形(CurveやFaceやEdge 等)を、図形の元となるコンポーネント毎に層を作成して分類 InventorのAPIで、DrawingView.DrawingCurves( [ModelObject] As Variant ) As DrawingCurvesEnumerator プロパティを利用してInventor 2D図面を構成する図形(CurveやFaceやEdge 等)を、図形の元となるコンポーネント毎に層を作成して分類します。 以下は、この処理を行うVBAのコードです。実行にはVBAエディタから「ツール」-「参照設定」にて「Microsoft Scripting Runtime」の参照設定が必要です。 Option Explicit Sub ClassifyDrawingCurvesToOccurenceLayer() ThisApplication.ScreenUpdating = False If ThisApplication.ActiveDocumentType <> kDrawingDocumentObject Then MsgBox "This macro is for drawing document." Exit Sub End If Dim oDoc As DrawingDocument Set oDoc = ThisApplication.ActiveDocument Dim oTO As TransientObjects Set oTO = ThisApplication.TransientObjects Dim oSheet As Sheet Dim oDrawingView As DrawingView Dim layerNameObjDic As Scripting.Dictionary Set layerNameObjDic = New Scripting.Dictionary Dim oTrans As Transaction Set oTrans = ThisApplication.TransactionManager.StartTransaction(ThisApplication.ActiveDocument, "AssignOccurencesToLayer") For Each oSheet In oDoc.Sheets For Each oDrawingView In oSheet.DrawingViews Dim refAssyDef As ComponentDefinition If oDrawingView.ReferencedDocumentDescriptor.ReferencedDocumentType = kPresentationDocumentObject Then Set refAssyDef = oDrawingView.ReferencedDocumentDescriptor.ReferencedDocument.ReferencedDocuments(1).ComponentDefinition ElseIf oDrawingView.ReferencedFile.DocumentType = kAssemblyDocumentObject Then Set refAssyDef = oDrawingView.ReferencedFile.DocumentDescriptor.ReferencedDocument.ComponentDefinition End If Dim oComponentOccurence As ComponentOccurrence For Each oComponentOccurence In refAssyDef.Occurrences Dim oDrawingCurve As DrawingCurve For Each oDrawingCurve In oDrawingView.DrawingCurves(oComponentOccurence) Dim oLayer As Layer Dim LayerName As String Set oLayer = Nothing Dim oSeg As DrawingCurveSegment For Each oSeg In oDrawingCurve.Segments Dim ComponentOccurenceName As String ComponentOccurenceName = oComponentOccurence.Name ComponentOccurenceName = Replace(ComponentOccurenceName, ":", "#") LayerName = "Occurence:" & ComponentOccurenceName If oLayer Is Nothing Then Set oLayer = GetOrCreateLayer(LayerName, oSeg.Layer, oDoc) End If Dim objColl As ObjectCollection If Not layerNameObjDic.Exists(LayerName) Then Set objColl = oTO.CreateObjectCollection layerNameObjDic.Add LayerName, objColl Else Set objColl = layerNameObjDic.Item(LayerName) End If objColl.Add oSeg Next Next Next Dim key As Variant For Each key In layerNameObjDic.Keys Set objColl = layerNameObjDic.Item(key) Set oLayer = oDoc.StylesManager.Layers.Item(key) Call oDrawingView.Parent.ChangeLayer(objColl, oLayer) objColl.Clear Next layerNameObjDic.RemoveAll Next Next oTrans.End ThisApplication.ScreenUpdating = True End Sub Function GetOrCreateLayer(LayerName As String, sourceLayer As Layer, oDoc As DrawingDocument) Set GetOrCreateLayer = Nothing Dim oNewLayer As Layer On Error Resume Next Set oNewLayer = oDoc.StylesManager.Layers.Item(LayerName) On Error GoTo 0 If oNewLayer Is Nothing Then Set oNewLayer = sourceLayer.Copy(LayerName) End If Set GetOrCreateLayer = oNewLayer End Function   Step 2.Step 1で加工した図面をInventorの出力機能を用いてAutoCAD図面として出力 InventorのDWG Translator Addinを用いてAutoCAD図面を出力します。 以下のVBAのサンプルコードの実行には、 <Path to ini file>を使用する出力設定Iniファイルに、<Path to output dwg file>を出力するDWGファイルのパス(拡張子.dwg付き)に置き換えが必要です。 なお、出力設定のIniファイルは、InventoのGUIから、「ファイル」-「コピーを名前を付けて保存」で、「コピーを名前を付けて保存」ダイアログで、「保存先のファイルの種類」として「AutoCAD DWGファイル(*.dwg)」を選択して、「オプション」ボタンを押下して「DWG図面ファイルのエクスポートオプション」ダイアログを起動し、ダイアログ内の「設定を保存」ボタンから作成が可能です。 Public Sub DWGOutUsingTranslatorAddIn() Dim oDWGAddIn As TranslatorAddIn Set oDWGAddIn = ThisApplication.ApplicationAddIns.ItemById("{C24E3AC2-122E-11D5-8E91-0010B541CD80}") If oDWGAddIn Is Nothing Then MsgBox "The DWG add-in could not be found." Exit Sub End If If Not oDWGAddIn.Activated Then oDWGAddIn.Activate End If Dim oNameValueMap As NameValueMap Set oNameValueMap = ThisApplication.TransientObjects.CreateNameValueMap Dim strIniFile As String strIniFile = "Path to output dwg file" Call oNameValueMap.Add("Export_Acad_IniFile", strIniFile) Dim oContext As TranslationContext Set oContext = ThisApplication.TransientObjects.CreateTranslationContext oContext.Type = kFileBrowseIOMechanism Dim oOutputFile As DataMedium Set oOutputFile = ThisApplication.TransientObjects.CreateDataMedium oOutputFile.FileName = "Path to output dwg file" Call oDWGAddIn.SaveCopyAs(ThisApplication.ActiveDocument, oContext, oNameValueMap, oOutputFile) End Sub   Step 3.2で出力したAutoCAD図面で、各層の図形をブロック化して配置 Step 2で出力したAutoCAD図面で、名前がOccurenceで始まる各層にある図形をブロック化してブロックインスタンスを配置、元図形を削除します。 [CommandMethod("Convert2Block")] public void Convert2Block() { Document activeDoc = Application.DocumentManager.MdiActiveDocument; Database db = activeDoc.Database; Editor ed = activeDoc.Editor; ed.Command("._Zoom", "A"); using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable; BlockTableRecord modelSpaceBTR = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; SymbolTable symTable = (SymbolTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead); foreach (ObjectId id in symTable) { LayerTableRecord symbol = tr.GetObject(id, OpenMode.ForRead) as LayerTableRecord; if (!symbol.Name.StartsWith("Occurence")) { continue; } String name = symbol.Name; name = name.Replace("#", @"`#"); // Create a TypedValue array to define the filter criteria TypedValue[] acTypValAr = new TypedValue[1]; acTypValAr.SetValue(new TypedValue((int)DxfCode.LayerName, name), 0); // Assign the filter criteria to a SelectionFilter object SelectionFilter acSelFtr = new SelectionFilter(acTypValAr); // Request for objects to be selected in the drawing area PromptSelectionResult acSSPrompt; acSSPrompt = ed.SelectCrossingWindow(db.Extmin, db.Extmax, acSelFtr); // If the prompt status is OK, objects were selected if (acSSPrompt.Status != PromptStatus.OK) { continue; } SelectionSet acSSet = acSSPrompt.Value; ed.WriteMessage("\nNumber of objects in {0} selected: {1}", symbol.Name, acSSet.Count.ToString()); ObjectId[] ids = acSSet.GetObjectIds(); //add a block table record with name if (!bt.Has(symbol.Name)) { //create new BlockTableRecord record = new BlockTableRecord(); record.Name = symbol.Name; bt.Add(record); tr.AddNewlyCreatedDBObject(record, true); } else { continue; } ObjectId blockId = bt[symbol.Name]; //copy the select entities to block by using deepclone. ObjectIdCollection collection = new ObjectIdCollection(ids); IdMapping mapping = new IdMapping(); db.DeepCloneObjects(collection, blockId, mapping, false); //erase select entities foreach(ObjectId entid in ids) { Entity ent = tr.GetObject(entid, OpenMode.ForWrite) as Entity; if (ent != null) { ent.Erase(true); } } // create a new block reference using (var br = new BlockReference(new Point3d(0,0,0), bt[symbol.Name])) { modelSpaceBTR.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); } } ed.Regen(); tr.Commit(); } }  
記事全体を表示
現象 Inventor ApprenticeServerComponent.Openメソッドを実行すると、「エラー -21474672258(80004005) Openメソッドは失敗しました」が発生します。   診断 利用しているApprenticeServerのバージョンが、OpenしようとしているInventorファイルより古いために、Openに失敗している可能性があります。   解決策 ApprenticeServerComponent.SoftwareVersion.DisplayVersionプロパティを参照して、利用されているApprenticeServerのバージョンを確認して、対象のInventorファイルより下位バージョンのApprenticeServerが利用されていないかを確認してください。   もし、端末に、複数バージョンのInventor(またはInventorViewer)をインストールしている状態で、古いバージョンのApprenticeServerがロードされてしまっている場合は、以下の方法で、対象のInventorファイルを読み込むことのできるバージョンのApprenticeServerを登録しなおしてください。   1.利用したいバージョンの、InventorApperenticeの実行モジュールがあるフォルダ(InventorViewerの場合は、<InventorViewerのインストールフォルダ>\Bin 配下、Inventorの場合は<InventorViewerのインストールフォルダ>\Bin 配下)を開く 2.1のフォルダ配下にある、ApprenticeRegSvr.exeを管理者権限にて実行する
記事全体を表示