Visual Basic 和 Visual C# 扩展性疑难解答

更新:2007 年 11 月

以下技巧用于解决开发 Visual Basic 或 Visual C# 项目的扩展性应用程序时可能遇到的某些较为常见的扩展性问题。

如果此列表中未列出您遇到的特定问题,请参见位于 https://support.microsoft.com/default.aspx?ln=zh-cn 的 MSDN 联机支持以了解更多信息。

CodeModel 中的 Add 和 Remove 方法不工作。

Visual Basic 项目不支持 CodeModel2 对象的各种类的 Add 和 Remove 方法。如果您调用了其中某一方法,您将会获得“未实现”错误。不受支持的方法包括:

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 对象的属性的值,请更改源文件中代码元素的定义。可以采取两种方式进行这一更改:

对 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 方法采用两个参数。第一个参数是向导文件(.vsz 文件)的名称。第二个参数是在向导运行时传递给该向导的值的数组。通过将该数组的第七个元素设置为 true,可以强制这些错误引发可在 Try...Catch 结构中捕获的异常。新建 Windows 应用程序向导要求数组中具有以下值:

数组索引

0

WizardType,指示向导类型的 GUID。对于新项目向导,GUID 为“{0F90E1D0-4999-11D1-B6D1-00A0C90F2744}”。

1

ProjectName,新项目名称的字符串。

2

本地目录,包含将在其中创建新项目的文件夹的完整路径的字符串。

3

安装目录,为一个字符串,它包含 Visual Studio 安装到的文件夹。

4

独占,指示是否应关闭任何现有打开的解决方案的 Boolean 值。

5

解决方案名称,解决方案文件的字符串名称,无路径或扩展名。

6

无提示,指示向导是否应无提示运行的 Boolean 值。

下面的宏显示如何在调用向导时使用无提示标志。如果您运行一次此宏,只要目录和项目尚不存在,它将无错误运行。如果您第二次运行此宏,将会引发错误。由于无声标志被设置为 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

请参见

概念

项目扩展性介绍