Visual Studio 2010: My very first SharePoint project extension

This is my first time writing an extension for Visual Studio 2010 and specifically for the SharePoint 2010 project template.
I have recently started developing on the new platform and of course I love it but I still miss a lot of things from SPVisualDev (which I know Tony is working on for 2010 right now) and so I thought I´d make my very own “XCopy” extension that pushes all the files from my VS project into the SharePointRoot (aka 14 hive).
The problem (or not really) is that in 2010 we can´t do an standard XCOPY of the 14-hive in VS studio (partly because it doesn´t exists). We now have a things called mapped folders that map to their corresponding folder in the 14-hive.
It looks like this:


The mapped folder “UserControls” is mapped to the \Template\CONTROLTEMPLATES folder in the 14 Hive (or SharePointRoot).   

So I wan´t to make an extension that copies the content in these mapped files to their corresponding folder in the SharePointRoot. The first thing to do is to download the new VSIX template for extending VS2010.
The SDK which includes the VSIX template can be downloaded from here.   

Some other great resources can be found here:
Channel 9   

 The next thing is to prepare my VS enviroment for extension. Open up the options for the extension manager and click the “load per user extensions” checkbox as can be seen below.    


OK, now VS has been setup for extensions. Let´s continue with the extension project.
Start by creating a new VSIX extension project which is responsible for packaging the VSIX file. One more project is added to the solution which will include my extension. This a standard class library.   


The VS solution should look something the screenshot above. Next we will prepare the VSIX to package my extension which lives in the other project (that is by design).   

Opening the VSIX manifest file in the editor looks like this:


Click on “Add Content” to pull this dialog.   


Point to the extensions project as a MEF Component.   

OK, now we have set up the VSIX to build the extension for use so let’s have a look at the code for the PushDownFiles extension.   

    public class PushDownMenuItem : ISharePointProjectExtension
        ISharePointProjectService svc;

        private void WriteToOutputWindow(string format, params string[] parameters)
            WriteToOutputWindow(string.Format(format, parameters));
        private void WriteToOutputWindow(string message)
            if (svc == null)
            svc.Logger.WriteLine(message, LogCategory.Message);

        private string BuildSharePointPath(ISharePointProjectItemFile file)
            var fullpath = Path.Combine(file.DeploymentRoot.Replace("{SharePointRoot}\\", svc.SharePointInstallPath), file.DeploymentPath, file.Name);
            return fullpath;

        public void Initialize(ISharePointProjectService projectService)
            projectService.ProjectMenuItemsRequested += HandleProjectMenuItemsRequested;
            svc = projectService;

        void HandleProjectMenuItemsRequested(object sender, SharePointProjectMenuItemsRequestedEventArgs e)
            var menuitem = e.ActionMenuItems.Add("Push down files");
            menuitem.Click += HandleClick;

        void HandleClick(object sender, MenuItemEventArgs e)
            var project = e.Owner as ISharePointProject;

            if (project == null)


        private void CopyFiles(ISharePointProjectItemCollection projectItems)
            int CopiedFiles = 0;

            foreach (var projectItem in projectItems)
                foreach (var file in projectItem.Files)
                    if (file.DeploymentType == DeploymentType.NoDeployment)

                    CopyFile(file.FullPath, BuildSharePointPath(file));

            WriteToOutputWindow("Copied {0} files to the SharePointRoot", CopiedFiles.ToString());

        private void CopyFile(string from, string to)
            WriteToOutputWindow("Copying file '{0}', to '{1}'", from, to);

            var dir = Directory.GetParent(to);
            if (dir.Exists == false)
                WriteToOutputWindow("Directory '{0}' was not found and therefore created.", dir.FullName);

            File.Copy(from, to, true);



I´m not going to explain all the code but some things to mention are:
The extension is exporting type of ISharePointProjectExtension (this is the MEF part). 
The BuildSharePointPath method might look a bit strange. Why not use SPUtility.GetGenericSetupPath method? If you have read my last post you will know that I can´t call 64bit SharePoint code from 32bit Visual Studio code.

The extension will simply go through all the files in the project and copy those that are not DeploymentType.NoDeployment (.cs files etc) to the SharePointRoot.   

After compiling the VSIX project my extension is now available as an installable file that we simply can double click to install. After installation open the extension manager and enable the extension as seen below.   


I have uploaded the VSIX file to my skydrive.
The next thing is to implement copy on save (as SPVisualDev does).


, ,

  1. Visual Studio 2010 extension for helping SharePoint 2010 debugging « Second Life of a Hungarian SharePoint Geek

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: