Visual Basic および Visual C# の機能拡張のトラブルシューティング
更新 : 2007 年 11 月
Visual Basic プロジェクトまたは Visual C# プロジェクトの機能拡張アプリケーションの開発時に発生する可能性のある、機能拡張に関する一般的な問題を修正する方法を次に示します。
ここに記載されていない特定の問題の詳細については、MSDN オンライン サポート (https://support.microsoft.com) を参照してください。
CodeModel の Add メソッドおよび Remove メソッドが動作しない
CodeModel2 オブジェクトのさまざまなクラスの Add メソッドおよび Remove メソッドは、Visual Basic プロジェクトではサポートされていません。これらのメソッドのいずれかを呼び出すと "実装されていません" というエラーが表示されます。サポートされていないメソッドを次に示します。
AddAttribute |
AddBase |
AddClass |
AddDelegate |
AddEnum |
AddFunction |
AddImplementedInterface |
AddInterface |
AddNameSpace |
AddParameter |
AddProperty |
AddStruct |
AddVariable |
RemoveInterface |
RemoveMember |
RemoveMethod |
RemoveParameter |
|
マクロを使用してコード要素をアプリケーションに追加するには、機能拡張モデルのテキスト編集機能を使用します。詳細については、「方法 : Visual Basic または C# のコード エディタでマクロを使用してテキストを追加する」を参照してください。このトピックには、コードをソース ファイルに追加する方法の例が記載されています。Visual Studio の汎用機能拡張モデルには、ソース コードの参照および変更に役立つオブジェクトが複数含まれています。このようなオブジェクトには、Document、TextDocument、EditPoint、TextPoint、VirtualPoint などがあります。
CodeModel オブジェクトのプロパティを変更できない
CodeModel2 のほとんどのプロパティは、Visual Basic プロジェクトの読み取り専用のフィールドとして実装されます。プロパティを実行時に設定しようとすると "実装されていません" というエラーが表示されます。読み取り専用のプロパティを次に示します。
Access |
CanOverride |
Comment |
DocComment |
Getter |
InitExpression |
IsAbstract |
IsConstant |
IsShared |
MustImplement |
Setter |
|
CodeModel2 オブジェクトのプロパティの値を変更するには、ソース ファイル内のコード要素の定義を変更します。これは次の 2 つの方法で実行できます。
コード エディタを使用して手動で行います。
機能拡張モデルのテキスト編集機能を使用してプログラムで行います。詳細については、「方法 : Visual Basic または C# のコード エディタでマクロを使用してテキストを追加する」を参照してください。このトピックには、コードをソース ファイルに追加する方法の例が記載されています。Visual Studio の汎用機能拡張モデルには、ソース コードの参照および変更に役立つオブジェクトが複数含まれています。このようなオブジェクトには、Document、TextDocument、EditPoint2、TextPoint、VirtualPoint などがあります。
CodeElement オブジェクトの呼び出しに失敗する
CodeModel2 への参照を作成した後でプロジェクトが変更されると、CodeModel2 オブジェクトの呼び出しは失敗します。たとえば、開発環境で実行中の機能拡張アプリケーションが存在する場合を考えます。このアプリケーションが、プロジェクトで定義されたクラスのいずれかについて CodeModel2 インスタンスを取得したとします。その後、ユーザーが開発環境でこのクラスを削除したとします。プロジェクトにクラスがなくなるため、その後、そのクラスの CodeModel2 の呼び出しは失敗します。
参照が有効かどうかをテストして調べるためのプロパティはありません。これらの問題は信頼性の高いプログラミング手法によって回避できます。
マクロ コードをテキスト エディタで編集する
マクロ ファイルをテキスト エディタで編集する場合があります。プレーンテキストのマクロ ファイルを保存するには、[ファイル] メニューの [エクスポート] コマンドをクリックします。[ファイルのエクスポート] ダイアログ ボックスが表示されたら、作成するエクスポート ファイルの名前を入力します。このファイルは、.vb 拡張子の付いた Visual Basic ソース ファイルとして保存されます。
[ファイル] メニューの [既存項目の追加] コマンドを使用することにより、Visual Basic ソース ファイルをマクロ プロジェクトに追加できます。
詳細については、「方法 : マクロを管理する」を参照してください。
使用できない項目についてのメッセージが表示される
コードがいずれかの機能拡張オブジェクトへの参照を保持する間に、プロジェクト構造が変更されると、各種のエラー メッセージが表示されます。これは、次の場合に発生します。
開発環境でプロジェクトを閉じた場合。この場合、このプロジェクトへの Project 参照は無効になります。このプロジェクトに含まれるすべてのオブジェクトについても同様に無効になります。プロジェクトにファイルを追加する場合など、その Project 参照を使用すると、このメソッドは失敗します。たとえば、次のマクロで proj.Name にアクセスしようとすると、"プロジェクトを使用できません。" が返されます。
' Macro editor Public Sub AccessAClosedProject() Dim proj As Project = DTE.Solution.Projects.Item(1) DTE.Solution.Close() MsgBox(proj.Name) End Sub
ファイルをプロジェクトから削除した場合。たとえば、次のマクロで projItem.Name にアクセスしようとすると、"プロジェクト アイテムを使用できません。" が返されます。
' Macro editor Public Sub AccessADeletedFile() Dim proj As Project = DTE.Solution.Projects.Item(1) Dim projItem As ProjectItem = proj.ProjectItems.Item(1) proj.ProjectItems.Item(1).Delete() MsgBox(projItem.Name) End Sub
参照をプロジェクトから削除した場合。たとえば、次のマクロで ref.Name にアクセスしようとすると、"サーバーによって例外が返されました。" が返されます。
' Macro editor Public Sub AccessARemovedReference() Dim vsproj As VSProject = _ CType(DTE.Solution.Projects.Item(1).Object, VSProject) Dim ref As Reference = vsproj.References.Item(1) vsproj.References.Item(1).Remove() MsgBox(ref.Name) End Sub
ソース管理の変更によりプロジェクトが再読み込みされた場合。この場合、古いオブジェクトは無効になります。たとえば、プロジェクト ファイルをチェックアウトし、ソース管理データベースに新しいバージョンが存在する場合に再読み込みが発生します。別の例としては、プロジェクト ファイルをチェックインするとき、それをソース管理のファイルとマージする必要がある場合に再読み込みが発生します。
プロジェクト項目が [名前を付けて保存] コマンドを使用して保存された場合。これにより、ファイルの新しい ProjectItem オブジェクトが作成されます。元のオブジェクトは無効になります。
なんらかの原因によりプロジェクトの再読み込みが発生した場合。
プロジェクトまたはプロジェクト項目への参照が有効かどうかをテストして調べるためのプロパティはありません。オブジェクトの一部のプロパティおよびメソッドから返される当該のエラーは、オブジェクトが既に無効であることを示します。これらの問題は信頼性の高いプログラミング手法によって回避できます。
新しいプロジェクトの作成でエラー メッセージが表示されないようにする
AddFromFile メソッドを使用すると、プロジェクトの作成中にエラーが発生した場合、さまざまなダイアログ ボックスが表示されます。LaunchWizard メソッドを使用すると、新しいプロジェクトを作成したり、ユーザー インターフェイスへの画面出力を中止したりできます。LaunchWizard を呼び出し、機能拡張プロジェクトから新しいプロジェクトを作成する場合、既定の動作では、メッセージ ボックスにエラーが表示されます。
LaunchWizard メソッドは、プロジェクトの新規作成ウィザードの実行時に 2 つの引数を受け取ります。1 つ目の引数は、ウィザード ファイルの名前です (.vsz file)。2 つ目の引数は、実行時にウィザードに渡される配列の値です。この配列の 7 番目の要素を true に設定すると、対象のエラーに Try...Catch 構造体でキャッチされる例外を強制的にスローさせることができます。新しい Windows アプリケーション ウィザードでは、配列に次の値を格納できます。
配列のインデックス |
値 |
---|---|
0 |
ウィザード タイプ (ウィザードの種類を示します GUID)。プロジェクトの新規作成ウィザードの場合、GUID は "{0F90E1D0-4999-11D1-B6D1-00A0C90F2744}" です。 |
1 |
プロジェクト名 (新しいプロジェクトの名前を示す文字列)。 |
2 |
ローカル ディレクトリ (新しいプロジェクトの作成場所となるフォルダへの完全パスを含む文字列)。 |
3 |
インストール ディレクトリ (Visual Studio がインストールされているフォルダを含む文字列)。 |
4 |
排他 (既存の開かれているソリューションを閉じるかどうかを指定するブール値)。 |
5 |
ソリューション名 (パスおよび拡張子を含まないソリューション ファイルの文字列名)。 |
6 |
サイレント (ウィザードをサイレント モードで実行するかどうかを指定するブール値)。 |
ウィザードを呼び出すときに Silent フラグを使用する方法を次のマクロに示します。このマクロを 1 回実行した後は、ディレクトリおよびプロジェクトが存在していない場合でもエラーにならずに実行できます。このマクロを 2 回実行すると、エラーを発生させるようになります。サイレント フラグが true に設定されているため、例外は Try...Catch ブロックでキャッチされます。
' Macro editor
Sub RunLaunchWizard()
Dim params() As Object = New Object() { _
"{0F90E1D0-4999-11D1-B6D1-00A0C90F2744}", _
"NewProjectName", _
"NewProjectPath", _
"", _
False, _
"", _
True} ' --> This is the "Silent" flag ... TRUE=No UI, FALSE=UI
Dim res As EnvDTE.wizardResult
Dim s As String = _
DTE.Solution.TemplatePath(VSLangProj.PrjKind.prjKindVBProject)
Try
res = DTE.LaunchWizard(s & "WindowsApplication.vsz", params)
Catch e1 As System.Exception
MsgBox("Cannot create new project.")
End Try
End Sub
HRESULT: 0x80047E2C が発生する
このエラーは、Visual Basic ソース ファイルの CodeModel2 オブジェクトを操作した場合に発生することがあります。
CodeElement2 オブジェクトへの参照を保持するコードを記述する場合は、参照を保持している間に基になるソース コードが変更される可能性があることに注意してください。コード要素が削除されたり、名前が変更されたり、コンパイラ エラーの原因となったりする場合があります。そのような場合は、CodeElement2 オブジェクトを呼び出すと、"HRESULT からの例外です : 0x80047E2C。" というエラー メッセージが表示されます。
いったんこのように無効になった参照は、復元できません。この問題を修正するには、ソース コード内のエラーを修正し、CodeModel2 オブジェクトから新しい参照を取得する必要があります。
このエラーがどのようにして起こるかを次のマクロに示します。LostClass という名前のクラスをプロジェクトに追加します。このクラスを、名前空間またはほかのクラスの内部ではなく、トップレベル クラスにします。SetElement マクロを実行し、クラスを削除してから、GetElement マクロを実行します。GetElement を実行すると、クラスが既に存在しないため、lostClass 参照は無効であり、エラーを返します。
Public Module CreateLostClass
Dim lostClass As CodeElement
Sub SetElement()
Dim proj As Project = DTE.Solution.Projects.Item(1)
lostClass = proj.CodeModel.CodeElements.Item("LostClass")
MsgBox(lostClass.Name)
End Sub
Sub GetElement()
MsgBox(lostClass.Name)
End Sub
End Module