Tell if an EnvDTE.Project is a Web Application

A Visual Studio Extension or Add-In might need to know whether or not a project is a web application (in my case, I needed to know whether I’ll expect app.congig or web.config). Due to a bug in Visual Studio, that is not so straight-forward. But thanks to Carlos J. Quintero, I got some code together.

If you need it, suit yourselves.

using System.Linq;
using EnvDTE;

namespace MuniHusseini.Demos
{
        public static bool IsWebProject(this Project project)
        {
            return project.Object is VsWebSite.VSWebSite || project.ProjectHasExtender("WebApplication");
        }

        public static bool ProjectHasExtender(this Project proj, string extenderName)
        {
            // See http://www.mztools.com/articles/2007/mz2007014.aspx for more information.

            try
            {
                // We could use proj.Extender(extenderName) but it causes an exception if not present and 
                // therefore it can cause performance problems if called multiple times. We use instead:

                var extenderNames = (object[])proj.ExtenderNames;

                return extenderNames.Length > 0 && extenderNames.Any(extenderNameObject => extenderNameObject.ToString() == extenderName);
            }
            catch
            {
                // Ignore
            }

            return false;
        }
    }
}

Write To Visual Studio’s Error List

When you’re developing an extension for Visual Studio, you might want to add errors, warnings or messages to Visual Studio’s Error List. Here is how to do it:

using System;
using Microsoft.VisualStudio.Shell;

namespace MunirHusseini.Demos
{
    internal static class TaskManager
    {
        private static ErrorListProvider _errorListProvider;

        public static void Initialize(IServiceProvider serviceProvider)
        {
            _errorListProvider = new ErrorListProvider(serviceProvider);
        }

        public static void AddError(string message)
        {
            AddTask(message, TaskErrorCategory.Error);
        }

        public static void AddWarning(string message)
        {
            AddTask(message, TaskErrorCategory.Warning);
        }

        public static void AddMessage(string message)
        {
            AddTask(message, TaskErrorCategory.Message);
        }

        private static void AddTask(string message, TaskErrorCategory category)
        {
            _errorListProvider.Tasks.Add(new ErrorTask
                {
                    Category = TaskCategory.User,
                    ErrorCategory = category,
                    Text = message
                });
        }
    }
}

Obviously, this method Initialize must be called prior to any other methods. The parameter serviceProvider can be the instance of the VSPackage. Example:

namespace MunirHusseini.Demos
{
    /// <summary>
    /// This is the class that implements the package exposed by this assembly.
    /// </summary>
    [PackageRegistration(UseManagedResourcesOnly = true)]
    [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
    [Guid(GuidList.guidMyDemoPkgString)]
    public sealed class MyDemoPackage : Package
    {
        /// <summary>
        /// Initialization of the package; this method is called right after the package is sited, so this is the place
        /// where you can put all the initialization code that rely on services provided by VisualStudio.
        /// </summary>
        protected override void Initialize()
        {
            base.Initialize();

            TaskManager.Initialize(this);

            // Some other package initialization here ...
        }
    }
}

Manually Applying XML Document Transform (XDT)

There might be situations where you might want to execute XDT of a web.config or app.config “manually” (i.e. apply the transformation in your code instead of letting not Visual Studio do the work). For example, this might be necessary when you want to examine the web.config or app.config file from within a Visual Studio extension. Fortunately, this is quite easy.
Continue reading

Get Project References From EnvDTE.Project

Suppose you’re developing a Visual Studio Extension and need to enumerate the references of a Visual Studio project. Here is how to do that:

public static IEnumerable<AssemblyName> CollectSettings(EnvDTE.Project project)
{
    var vsproject = project.Object as VSLangProj.VSProject;
    // note: you could also try casting to VsWebSite.VSWebSite

    foreach (VSLangProj.Reference reference in vsproject.References)
    {
        if (reference.SourceProject == null)
        {
            // This is an assembly reference
            var fullName = GetFullName(reference);
            var assemblyName = new AssemblyName(fullName);
            yield return assemblyName;
        }
        else
        {
            // This is a project reference
        }
    }
}

public static string GetFullName(VSLangProj.Reference reference)
{
    return string.Format("{0}, Version={1}.{2}.{3}.{4}, Culture={5}, PublicKeyToken={6}",
                            reference.Name,
                            reference.MajorVersion, reference.MinorVersion, reference.BuildNumber, reference.RevisionNumber,
                            reference.Culture.Or("neutral"),
                            reference.PublicKeyToken.Or("null"));
}

For the types in the namespace VSLangProj, you’ll need to reference VSLangProj.dll. EnvDTE.Project ist located in EnvDTE.dll. And just for completness, here’s the extension method used in the code above:

static class Extensions
{
    public static string Or(this string text, string alternative)
    {
        return string.IsNullOrWhiteSpace(text) ? alternative : text;
    }
}

Automatically Re-Create Stored Procedures In SQL Server

One day I discovered that the system table sysdepends in my database was not valid. I know that dropping and re-creating a stored procedure will update sysdepends for that single procedure, but what if I had 100s of stored procedures? Of course, there’s a script for that and for all who are too lazy to want to write that script themselves – here it is:

DECLARE  @name			NVARCHAR(128),
         @definition	NVARCHAR(MAX)

DECLARE cur CURSOR FOR
	SELECT		o.name, m.definition
	FROM		sys.sql_modules m 
	INNER JOIN	sys.objects o ON m.object_id = o.object_id
	WHERE		o.type = 'P'

OPEN cur

	FETCH cur INTO @name, @definition

	WHILE @@Fetch_Status = 0
	BEGIN
		EXEC('DROP PROCEDURE ' + @name)
		EXEC(@definition)
		
		FETCH cur INTO @name, @definition
	END

CLOSE cur

DEALLOCATE cur

A Flexible And Convenient Type Conversion Helper in C#

Every once in a while I need to convert objects of an unknown type into a known type; sometimes these types are only known at run time. In most cases I want the code to stay easy to read, so I don’t want to if-then-else the readybility of my code away.
Over the time, I have created a helper that performs the conversion in a convenient and fast way. Use it if you like.
Continue reading

Listing Objects Used in Stored Procedures (MS SQL)

Recently, I had to clean up a large data base. Some of the tables in that database were obsolete and needed to get deleted. Obsolete tables were not used in any stored procedures, so I needed to list all the tables used in stored procedures and subtract them from the set of all tables in the dataset to get the ones I could delete. So the starting point is to get a list of all objects used in a USP:
Continue reading