Compartir a través de


Tutorial: Crear una extensión de proyecto de SharePoint

En este tutorial se muestra cómo crear una extensión para los proyectos de SharePoint.Puede utilizar una extensión de proyecto para responder a los eventos de nivel de proyecto como cuando se agrega, se elimina, o cambia un proyecto.También puede agregar propiedades personalizadas o responder cuando cambia un valor de propiedad.A diferencia de las extensiones de elemento de proyecto, las extensiones de proyecto no pueden estar asociadas a un tipo de proyecto de SharePoint determinado.Cuando crea una extensión de proyecto, se carga cuando se abre cualquier tipo de proyecto de SharePoint en Visual Studio.

En este tutorial, creará una propiedad booleana personalizada que se agrega a cualquier proyecto de SharePoint creado en Visual Studio.Cuando se establece en True, la nueva propiedad agrega o asigna una carpeta de recursos Images al proyecto.Cuando se establece en False, se quita la carpeta Images, si existe.Para obtener más información, vea Cómo: Agregar y quitar carpetas asignadas.

En este tutorial se muestran las siguientes tareas:

  • Crear una extensión Visual Studio para los proyectos SharePoint que hace lo siguiente:

    • Agrega una propiedad de proyecto personalizada a la ventana Propiedades.La propiedad se aplica a cualquier proyecto de SharePoint.

    • Utiliza el modelo de objetos de proyecto de SharePoint para agregar una carpeta asignada a un proyecto.

    • Usa el modelo de objetos de automatización (DTE) de Visual Studio para eliminar una carpeta asignada del proyecto.

  • Compilar un paquete de extensión (VSIX) de Visual Studio para implementar el ensamblado de la extensión de propiedad de proyecto.

  • Depurar y probar la propiedad de proyecto.

Requisitos previos

Necesitará los componentes siguientes en el equipo de desarrollo para completar este tutorial:

Crear los proyectos

Para completar este tutorial, debe crear dos proyectos:

  • Un proyecto VSIX para crear el paquete VSIX e implementar la extensión de proyecto.

  • Un proyecto de biblioteca de clases que implemente la extensión de proyecto.

Comience el tutorial creando ambos proyectos.

Para crear el proyecto VSIX

  1. Inicie Visual Studio.

  2. En la barra de menú, elija Archivo, Nuevo, Proyecto.

  3. En el cuadro de diálogo Nuevo proyecto , expanda los nodos Visual c# o Visual Basic y, a continuación el nodo Extensibilidad .

    [!NOTA]

    Este nodo solo está disponible si instala Visual Studio SDK.Para obtener más información, vea la sección Requisitos previos, anteriormente en este tema.

  4. En la parte superior del cuadro de diálogo, elija .NET Framework 4,5 en la lista de versiones de .NET Framework, y elija la plantilla Proyecto VSIX .

  5. En el cuadro Nombre , escriba ProjectExtensionPackage, y elija el botón Aceptar .

    El proyecto ProjectExtensionPackage aparece en Explorador de soluciones.

Para crear la extensión de proyecto

  1. En Explorador de soluciones, abra el menú contextual para el nodo de la solución, elija Agregary, a continuación Nuevo proyecto.

    [!NOTA]

    En los proyectos Visual Basic , el nodo de la solución aparece en Explorador de soluciones únicamente si la casilla Mostrar solución siempre se selecciona en General, Projects and Solutions, Options Dialog Box.

  2. En el cuadro de diálogo Nuevo proyecto , expanda los nodos Visual c# o Visual Basic y, a continuación Windows.

  3. En la parte superior del cuadro de diálogo, elija .NET Framework 4,5 en la lista de versiones de .NET Framework, y elija la plantilla de proyecto Biblioteca de clases .

  4. En el cuadro Nombre , escriba ProjectExtension, y elija el botón Aceptar .

    Visual Studio agrega el proyecto ProjectExtension a la solución y abre el archivo de código predeterminado Class1.

  5. Elimine el archivo de código Class1 del proyecto.

Configurar el proyecto

Antes de escribir el código que crea la extensión del elemento de proyecto, tiene que agregar los archivos de código y las referencias de ensamblado al proyecto de extensión.

Para configurar el proyecto

  1. Agregue un archivo de código denominado CustomProperty al proyecto ProjectExtension.

  2. Abrir el menú contextual para el proyecto ProjectExtension y, a continuación Agregar referencia.

  3. En el cuadro de diálogo Administrador de referencia – CustomProperty , elija el nodo Framework , y seleccione la casilla junto a los ensamblados System.ComponentModel.Composition y System.Windows.Forms.

  4. Elija el nodo Extensiones , active la casilla junto a los ensamblados Microsoft.VisualStudio.SharePoint y EnvDTE, y después elija el botón Aceptar .

  5. En Explorador de soluciones, bajo la carpeta Referencias para el proyecto ProjectExtension , elija EnvDTE.

  6. En la ventana Propiedades, cambie el valor de Incrustar tipos de interoperabilidad a False.

Definir la nueva propiedad de proyecto de SharePoint

Cree una clase que defina la extensión de proyecto y el comportamiento de la nueva propiedad.Para definir la nueva extensión de proyecto, la clase implementa la interfaz ISharePointProjectExtension.Implemente esta interfaz siempre que desee definir una extensión para un proyecto de SharePoint.También agregue ExportAttribute a la clase.Este atributo permite que Visual Studio detecte y cargue la implementación de ISharePointProjectExtension.Pase el tipo ISharePointProjectExtension al constructor del atributo.

Para definir la nueva propiedad de proyecto de SharePoint

  • Pegue el código siguiente en el archivo de código CustomProperty.

    Imports System
    Imports System.Linq
    Imports System.ComponentModel
    Imports System.ComponentModel.Composition
    Imports System.Windows.Forms
    Imports Microsoft.VisualStudio.SharePoint
    Imports EnvDTE
    
    Namespace Contoso.SharePointProjectExtensions.MapImagesFolder
    
        ' Export attribute: Enables Visual Studio to discover and load this extension.
        ' MapImagesFolderProjectExtension class: Adds a new Map Images Folder property to any SharePoint project.
        <Export(GetType(ISharePointProjectExtension))> _
        Public Class MapImagesFolderProjectExtension
            Implements ISharePointProjectExtension
    
            Public Sub Initialize(ByVal projectService As ISharePointProjectService) Implements ISharePointProjectExtension.Initialize
                AddHandler projectService.ProjectPropertiesRequested, AddressOf Me.projectService_ProjectPropertiesRequested
            End Sub
    
            Private Sub projectService_ProjectPropertiesRequested(ByVal sender As Object, ByVal e As SharePointProjectPropertiesRequestedEventArgs)
                Dim propertiesObject As CustomProjectProperties = Nothing
    
                ' If the properties object already exists, get it from the project's annotations.
                If False = e.Project.Annotations.TryGetValue(propertiesObject) Then
                    ' Otherwise, create a new properties object and add it to the annotations.
                    propertiesObject = New CustomProjectProperties(e.Project)
                    e.Project.Annotations.Add(propertiesObject)
                End If
    
                e.PropertySources.Add(propertiesObject)
            End Sub
        End Class
    
        Public Class CustomProjectProperties
            Private sharePointProject As ISharePointProject = Nothing
            Private Const MapImagesFolderPropertyDefaultValue As Boolean = False
            Private Const MapImagesFolderPropertyId = "ContosoMapImagesFolderProperty"
    
            Public Sub New(ByVal myProject As ISharePointProject)
                sharePointProject = myProject
            End Sub
    
            ' Represents the new boolean property MapImagesFolder.
            ' True = Map an Images folder to the project if one does not already exist; otherwise, do nothing.
            ' False = Remove the Images folder from the project, if one exists; otherwise, do nothing.
            <DisplayName("Map Images Folder")> _
            <DescriptionAttribute("Specifies whether an Images folder is mapped to the SharePoint project.")> _
            <DefaultValue(MapImagesFolderPropertyDefaultValue)> _
            Public Property MapImagesFolder As Boolean
                Get
                    Dim propertyStringValue As String = String.Empty
    
                    ' Try to get the current value from the .user file; if it does not yet exist, return a default value.
                    If Not sharePointProject.ProjectUserFileData.TryGetValue(MapImagesFolderPropertyId, propertyStringValue) Then
                        Return MapImagesFolderPropertyDefaultValue
                    Else
                        Return CBool(propertyStringValue)
                    End If
                End Get
    
                Set(ByVal value As Boolean)
                    If value Then
                        If Not ImagesMappedFolderInProjectExists(sharePointProject) Then
                            ' An Images folder is not mapped to the project, so map one.
                            Dim mappedFolder As IMappedFolder = sharePointProject.MappedFolders.Add(MappedFolderType.Images)
                            sharePointProject.ProjectService.Logger.WriteLine( _
                                mappedFolder.Name & " mapped folder added to the project.", LogCategory.Status)
                        End If
                    ElseIf (ImagesMappedFolderInProjectExists(sharePointProject) AndAlso UserSaysDeleteFile()) Then
                        ' An Images folder is mapped to the project and the user wants to remove it.
                        DeleteFolder()
                    End If
    
                    sharePointProject.ProjectUserFileData(MapImagesFolderPropertyId) = value.ToString()
                End Set
            End Property
    
            Private Function ImagesMappedFolderInProjectExists(ByVal sharePointProject As ISharePointProject) As Boolean
                Dim returnValue As Boolean = False
                For Each folder As IMappedFolder In sharePointProject.MappedFolders
                    ' Check to see if an Images folder is already mapped.
                    If (folder.FolderType = MappedFolderType.Images) Then
                        returnValue = True
                    End If
                Next
                Return returnValue
            End Function
    
            Private Function UserSaysDeleteFile() As Boolean
                ' Ask the user whether they want to delete the Images folder.
                Dim returnValue As Boolean = False
                If (MessageBox.Show("Do you want to delete the Images folder from the project?", _
                    "Delete the Images folder?", MessageBoxButtons.YesNo) = DialogResult.Yes) Then
                    returnValue = True
                End If
                Return returnValue
            End Function
    
            Private Sub DeleteFolder()
                ' The Visual Studio DTE object model is required to delete the mapped folder.
                Dim dteProject As EnvDTE.Project = _
                    sharePointProject.ProjectService.Convert(Of ISharePointProject, EnvDTE.Project)(sharePointProject)
                Dim targetFolderName As String = _
                    sharePointProject.MappedFolders.First(Function(mf) mf.FolderType = MappedFolderType.Images).Name
                Dim mappedFolderItem As EnvDTE.ProjectItem = dteProject.ProjectItems.Item(targetFolderName)
                mappedFolderItem.Delete()
    
                sharePointProject.ProjectService.Logger.WriteLine("Mapped Folder " & _
                    targetFolderName & " deleted", LogCategory.Status)
            End Sub
        End Class
    End Namespace
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel;
    using System.ComponentModel.Composition;
    using System.Windows.Forms;
    using Microsoft.VisualStudio.SharePoint;
    using EnvDTE;
    
    // Adds a new property called MapImagesFolder to any SharePoint project.
    // When MapImagesFolder is set to true, the Image folder is mapped to the project.
    // When MapImagesFolder is set to false, the Image folder is deleted from the project.
    namespace SP_Project_Extension
    {
        // Export attribute: Enables Visual Studio to discover and load this extension.
        [Export(typeof(ISharePointProjectExtension))]
    
        // Defines a new custom project property that applies to any SharePoint project.
        public class SPProjectExtension : ISharePointProjectExtension
        {
            // Implements ISharePointProjectService.Initialize, which determines the behavior of the new property.
            public void Initialize(ISharePointProjectService projectService)
            {
                // Handle events for when a project property is changed.
                projectService.ProjectPropertiesRequested +=
                    new EventHandler<SharePointProjectPropertiesRequestedEventArgs>(projectService_ProjectPropertiesRequested);
            }
    
            void projectService_ProjectPropertiesRequested(object sender, SharePointProjectPropertiesRequestedEventArgs e)
            {
                // Add a new property to the SharePoint project.
                e.PropertySources.Add((object)new ImagesMappedFolderProperty(e.Project));
            }
        }
    
        public class ImagesMappedFolderProperty
        {
            ISharePointProject sharePointProject = null;
            public ImagesMappedFolderProperty(ISharePointProject myProject)
            {
                sharePointProject = myProject;
            }
            static bool MapFolderSetting = false;
    
            [DisplayName("Map Images Folder")]
            [DescriptionAttribute("Specifies whether an Images folder is mapped to the SharePoint project.")]
            public bool MapImagesFolder
            // Represents the new boolean property MapImagesFolder.
            // True = Map an Images folder to the project if one does not already exist; otherwise, do nothing.
            // False = Remove the Images folder from the project, if one exists; otherwise, do nothing.
            {
                get
                {
                    // Get the current property value.
                    return MapFolderSetting;
                }
                set
                {
                    if (value)
                    {
                        if (!ImagesMappedFolderInProjectExists(sharePointProject))
                        {
                            // An Images folder is not mapped to the project, so map one.
                            IMappedFolder mappedFolder1 = sharePointProject.MappedFolders.Add(MappedFolderType.Images);
                            // Add a note to the logger that a mapped folder was added.
                            sharePointProject.ProjectService.Logger.WriteLine("Mapped Folder added:" + mappedFolder1.Name, LogCategory.Status);
                        }
                    }
                    else
                    {
                        if (ImagesMappedFolderInProjectExists(sharePointProject) && UserSaysDeleteFile())
                        {
                            // An Images folder is mapped to the project and the user wants to remove it.
                            // The Visual Studio DTE object model is required to delete the mapped folder.
                            // Reference the Visual Studio DTE model, get handles for the SharePoint project and project items.
                            EnvDTE.Project dteProject = sharePointProject.ProjectService.Convert<ISharePointProject, EnvDTE.Project>(sharePointProject);
                            string targetFolderName = sharePointProject.MappedFolders.First(mf => mf.FolderType == MappedFolderType.Images).Name;
                            EnvDTE.ProjectItem mappedFolderItem = dteProject.ProjectItems.Item(targetFolderName);
                            mappedFolderItem.Delete();
                            sharePointProject.ProjectService.Logger.WriteLine("Mapped Folder " + targetFolderName + " deleted", LogCategory.Status);
                        }
                    }
                    MapFolderSetting = value;
                }
    
            }
    
            private bool ImagesMappedFolderInProjectExists(ISharePointProject sharePointProject)
            {
                bool retVal = false;
                foreach (IMappedFolder folder in sharePointProject.MappedFolders)
                {
                    // Check to see if an Images folder is already mapped.
                    if (folder.FolderType == MappedFolderType.Images)
                        retVal = true;
                }
                return retVal;
            }
    
            private bool UserSaysDeleteFile()
            {
                // Prompt the user whether they want to delete the Images folder.
                bool retVal = false;
                if (MessageBox.Show("Do you want to delete the Images folder from the project?", "Delete the Images folder?", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    retVal = true;
                }
                return retVal;
    
            }
        }
    }
    

Compilar la solución

A continuación, compile la solución para asegurarse de que se compila sin errores.

Para compilar la solución

  • En la barra de menú, elija Generar, Compilar solución.

Crear un paquete VSIX para implementar la extensión de propiedad de proyecto

Para implementar la extensión de proyecto, utilice el proyecto VSIX en la solución para crear un paquete VSIX.Primero, configure el paquete VSIX modificando el archivo source.extension.vsixmanifest incluido en el proyecto VSIX.A continuación, cree el paquete VSIX compilando la solución.

Para crear y configurar el paquete VSIX

  1. En Explorador de soluciones, abra el menú contextual para el archivo source.extension.vsixmanifest, y después elija el botón Abrir .

    Visual Studio abre el archivo en el diseñador de manifiestos.La información que aparece en la pestaña Metadatos también aparece en Extensiones y actualizaciones. Todos los paquetes VSIX requieren el archivo extension.vsixmanifest.Para obtener más información sobre este archivo, vea Referencia de esquema de extensión VSIX.

  2. En el cuadro Nombre de producto , entre en Propiedad de proyecto personalizada.

  3. En el cuadro Autor , entre en Contoso.

  4. En el cuadro Descripción , escriba el Una propiedad de proyecto de SharePoint personalizada que alterna la asignación de la carpeta de recurso Images al proyecto.

  5. Elija la ficha Activos , y elija el botón Nuevo .

    El cuadro de diálogo Agregar nuevo activo aparece.

  6. En la lista Tipo , elija Microsoft.VisualStudio.MefComponent.

    [!NOTA]

    Este valor corresponde al elemento MEFComponent del archivo extension.vsixmanifest.Este elemento especifica el nombre de un ensamblado de extensión en el paquete VSIX.Para obtener más información, vea MEFComponent Element.

  7. En la lista Origen , elija el botón de opción Un proyecto de la solución actual .

  8. En la lista Proyecto , elija ProjectExtension.

    Este valor identifica el nombre del ensamblado que está compilando en el proyecto.

  9. Elija Aceptar para cerrar el cuadro de diálogo Agregar nuevo activo .

  10. En la barra de menú, elija Archivo, Guardar todos cuando termine, y luego cierre el diseñador de manifiestos.

  11. En la barra de menú, elija Generar, Compilar solución, y asegúrese de que el proyecto se compila sin errores.

  12. En Explorador de soluciones, abra el menú contextual para el proyecto ProjectExtensionPackage , y elija el botón Abrir carpeta en el Explorador de archivos .

  13. En Explorador de archivos, abra la carpeta de salida de compilación de ProjectExtensionPackage, y después comprueba que la carpeta contiene un archivo ProjectExtensionPackage.vsix.

    De forma predeterminada, la carpeta de resultado de compilación es ..\bin\Debug, que se encuentra bajo la carpeta que contiene el archivo de proyecto.

Probar la propiedad de proyecto

Ya puede probar la propiedad de proyecto personalizada.Es más fácil depurar y probar la nueva extensión de propiedad de proyecto en una instancia experimental Visual Studio.Esta instancia Visual Studio se crea cuando se ejecuta un VSIX u otro proyecto de extensibilidad.Después de depurar el proyecto, puede instalar la extensión en el sistema y continuar depurándola y probar en una instancia normal Visual Studio.

Para depurar y probar la extensión en una instancia experimental de Visual Studio

  1. Reinicie Visual Studio con credenciales administrativas, y vuelva a abrir la solución ProjectExtensionPackage.

  2. Inicie una compilación de depuración del proyecto o eligiendo la clave F5 o, en la barra de menús, eligiendo Depurar, Iniciar depuración.

    Visual Studio instala la extensión a %UserProfile%\AppData\Local\Microsoft\VisualStudio\11.0Exp\Extensions\Contoso\Custom Project Property \ 1,0 e inicia una instancia experimental Visual Studio.

  3. En la instancia experimental Visual Studio, cree un proyecto de SharePoint para una solución de granja, y use los valores predeterminados en los otros valores del asistente.

    1. En la barra de menú, elija Archivo, Nuevo, Proyecto.

    2. En la parte superior del cuadro de diálogo Nuevo proyecto , elija .NET Framework 3.5 en la lista de versiones de .NET Framework.

      Las extensiones de herramientas de SharePoint requieren características de esta versión .NET Framework.

    3. Bajo el nodo Plantillas , expanda el nodo Visual c# o Visual Basic , elija el nodo SharePoint y, a continuación el nodo 2010 .

    4. Elija la plantilla Proyecto de SharePoint 2010 , y escriba en ModuleTest como el nombre del proyecto.

  4. En Explorador de soluciones, elija el nodo del proyecto ModuleTest .

    Una nueva propiedad Map Images Folder personalizado aparece en la ventana Propiedades con un valor predeterminado de False.

  5. Cambie el valor de esa propiedad en True.

    Se agrega una carpeta de recurso Images al proyecto SharePoint.

  6. Cambie el valor de esa propiedad de nuevo a False.

    Si elige el botón en el cuadro de diálogo ¿Elimine la carpeta Images? , la carpeta de recurso Images se elimina del proyecto de SharePoint.

  7. Cierre la instancia experimental de Visual Studio.

Vea también

Conceptos

Extender los proyectos de SharePoint

Cómo: Agregar una propiedad a proyectos de SharePoint

Convertir los tipos de sistema de proyectos de SharePoint en otros tipos de proyecto de Visual Studio

Guardar datos asociados en extensiones del sistema de proyectos de SharePoint

Asociar datos personalizados con extensiones de herramientas de SharePoint