Troubleshooting Visual Basic and Visual C# Extensibility

Here are techniques for remedying some of the more common extensibility problems you might encounter when developing an extensibility application for a Visual Basic or Visual C# project.

If your specific problem does not appear in this list, see MSDN Online Support at https://support.microsoft.com for more information.

The Add and Remove Methods in the CodeModel Do Not Work.

The Add and Remove methods of the various classes of the CodeModel2 object are not supported in Visual Basic projects. If you call one of these methods, you will get a "Not implemented" error. The unsupported methods are:

AddAttribute

AddBase

AddClass

AddDelegate

AddEnum

AddFunction

AddImplementedInterface

AddInterface

AddNameSpace

AddParameter

AddProperty

AddStruct

AddVariable

RemoveInterface

RemoveMember

RemoveMethod

RemoveParameter

 

To add code elements to your application through a macro, use the text-editing features of the extensibility model. For details, see How to: Use a Macro to Add Text in a Visual Basic or C# Code Editor, which contains an example of how to add code to a source file. The Visual Studio general extensibility model contains several objects that are useful for reading and modifying source code. They include the Document object, the TextDocument object, the EditPoint object, the TextPoint object, and the VirtualPoint object.

I Cannot Change the Properties of the CodeModel Objects.

Most of the properties in the CodeModel2 are implemented as read-only fields for Visual Basic projects. If you attempt to set a property at run time, you get a "Not implemented" error. The read-only properties include:

Access

CanOverride

Comment

DocComment

Getter

InitExpression

IsAbstract

IsConstant

IsShared

MustImplement

Setter

 

To change the value of a CodeModel2 object's property, change the definition of the code element in the source file. You can do this in two ways:

Calls to a CodeElement Object Are Failing.

Calls to a CodeModel2 object fail if the project changes after you create a reference to the CodeModel2. For example, you may have an extensibility application running in the development environment. That application may have retrieved a CodeModel2 instance for one of the classes defined in the project. A user might then, in the development environment, delete the class. Subsequent calls to the CodeModel2 for that class fail, because the class no longer exists in the project.

There is no property that you can test to determine whether a reference is still valid. You can avoid these problems by employing robust programming methods.

I Want to Edit My Macro Code in a Text Editor.

There may be occasions when you need to edit your macro file in a text editor. To save your macro file in plain text, on the File menu, click the Export command. When the Export File dialog box appears, type the name of the export file you want to create. The file will be saved as a Visual Basic source file with the .vb extension.

The Add Existing Item command on the File menu allows you to add a Visual Basic source file to your macro project.

For more information, see How to: Manage Macros.

I am Getting Messages About Unavailable Items.

An object may display an assortment of error messages if the structure of the project changes while your code is holding a reference to one of the extensibility objects. This may happen when:

  • A project is closed in the development environment. In this case, the Project reference to it becomes invalid, as will any objects contained in the project. If you use that Project reference, perhaps to add a file to the project, the method fails. For example, the following macro returns "Project unavailable" when trying to access proj.Name:

    ' Macro editor
    Public Sub AccessAClosedProject()
       Dim proj As Project = DTE.Solution.Projects.Item(1)
       DTE.Solution.Close()
       MsgBox(proj.Name)
    End Sub
    
  • A file is deleted from the project. For example, the following macro returns "Projectitem unavailable" when trying to access 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
    
  • A reference is deleted from the project. For example, the following macro returns "The server threw an exception" when trying to access 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
    
  • Source control changes cause a reload of the project. In this case, the old objects become invalid. For example, a reload occurs if you check out the project file and a new version exists in the source control database. As another example, a reload occurs when you check in the project file and it must be merged with the files in source control.

  • A project item is saved using the Save As command. This creates a new ProjectItem object for the file. The original object becomes invalid.

  • Anything happens that causes the project to be reloaded.

There is no property that you can test to determine whether a reference to a project or project item is still valid. Relevant errors returned by some properties and methods of an object indicate that it is no longer valid. You can avoid these problems by employing robust programming methods.

I Want To Create a New Project, and I Do Not Want Any Error Messages To Appear.

When using the AddFromFile method, various dialog boxes appear when errors occur while creating the project. The LaunchWizard method can be used to create new projects and suppress the user interface. When calling LaunchWizard to create a new project from an extensibility project, the default behavior is that errors are displayed in message boxes.

The LaunchWizard method takes two arguments when running a new project wizard. The first argument is the name of the wizard file (.vsz file). The second argument is an array of values that is passed to the wizard when it runs. By setting the seventh element of the array to true, you can force the errors to throw exceptions which may be caught in a Try...Catch structure. The New Windows Application wizard expects the following values in the array:

Array index

Value

0

WizardType, a GUID indicating the type of wizard. For a new project wizard, the GUID is "{0F90E1D0-4999-11D1-B6D1-00A0C90F2744}".

1

ProjectName, a string for the name of the new project.

2

Local directory, a string containing the full path to the folder where the new project will be created.

3

Installation directory, a string containing the folder where Visual Studio is installed.

4

Exclusive, a Boolean value indicating whether any existing open solution should be closed.

5

Solution name, a string name for the solution file, without path or extension.

6

Silent, a Boolean indicating whether the wizard should run silently.

The following macro shows how to use the Silent flag when calling the wizard. If you ran this macro once, it would run without error, providing the directory and project did not already exist. If you ran this macro a second time, an error would be raised. Since the Silent flag is set to true, an exception is caught by the Try...Catch block.

' 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

What is HRESULT: 0x80047E2C?

This error can occur when you manipulate the CodeModel2 objects of Visual Basic source files.

When you are writing code that maintains references to CodeElement2 objects, you should be aware that the underlying source code can change while you are holding the reference. The code element may be deleted, renamed, or involved in a compiler error. When this happens, any calls to the CodeElement2 object return the error message, "Exception from HRESULT: 0x80047E2C."

Once a reference becomes invalid in this way, it cannot be recovered. To fix this problem, you must fix errors in the source code and retrieve a new reference from the CodeModel2 object.

The following macros demonstrate how this error might occur. Add a class named LostClass to your project. Make this a top-level class, not inside a namespace or class. Run the SetElement macro, delete the class, and then run the GetElement macro. When you run GetElement, the class no longer exists, and the lostClass reference is invalid and returns the error.

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

See Also

Concepts

Introduction to Project Extensibility