I'm a big fan of convenience tools. One of my biggest pet peeves with Visual Studio.NET is that you can't create a custom IIS virtual directory with exactly the settings you want when you want to add a Web Application to a solution. I found myself dealing with this inconvenience so often, I finally decided to do something about it. I created an Addin solution that will pop up a form, allow you to choose (and even create) a physical folder, set the various properties for your VRoot that you would normally be required to do separately from the IIS Management Console, and then when you are ready to add your new web application, all you need to do is change the default "WebApplication1" to the name of your new VRoot, and you are "good to go". Your web project, for example, can now be a subfolder of your class library that you were working on, and you can zip up the whole folder including the web application subfolder very nicely.
Besides being a great time - saver, my little exercise is a good tutorial in how easy it is to create a VS.NET addin with the features of your choosing.
To create an Addin, you need to choose the "Extensibility" project type under "Other Projects" in the New Project wizard, and select the "Visual Studio.Net Addin" type. SImply follow the wizard, and 90% of your code wil be written for you. In fact, you'll notice when you download the solution at the link below that I never even changed the installer project from "MyAddin1" to "IISMgrAddin" because I actually started out with a solution with the default name.
Now the key part of any Addin project is the Connect class, in whuch the ideal place to spawn your UI is the Exec method.. This is where the addin infrastructure hands everything off and where you get to do YOUR thing. In this case, all I need to do is load a WIndows Form that displays the various properties I want to set (almost exactly the ones that you would use if you did it from IIS MMC snapin), and then I call into a separate utility worker class that does the actual Directory Services stuff to perform the IIS work.
My Exec method looks like this:
public void Exec(string commandName, EnvDTE.vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
{
handled = false;
if(executeOption == EnvDTE.vsCommandExecOption.vsCommandExecOptionDoDefault)
{
if(commandName == "MyAddin1.Connect.IISMgrAddin")
{
IISMgrAddin.frmISMgr frm = new IISMgrAddin.frmISMgr();
frm.Show();
handled = true;
return;
}
}
}
You can see all I needed to do was create an instance of my UI and show it. The rest is basically just a Winforms app that you would write if it were not an addin at all. Not one line of code needs to be different! In fact, you can use this basic Addin technique to add almost anything you would write as a WinForms app and turn it into a brilliant VS.NET addin project.
The main block of work is done by my IISMgr class which I reproduce here:
using System;
using System.DirectoryServices;
namespace IISMgrAddin
{
/// <summary>
/// Summary description for IISManager.
/// </summary>
public class IISManager
{
/// <summary>
/// Constructor
/// </summary>
/// <summary>
/// Default constructor uses localhost as default server
/// </summary>
public IISManager()
{
}
public string CreateVDir(string WebSite, string VDirName, string Path, bool RootDir, bool chkRead,bool chkWrite, bool chkExecute, bool chkScript, bool chkAuth, int webSiteNum, string serverName)
{
string sRet=String.Empty;
System.DirectoryServices.DirectoryEntry IISSchema;
System.DirectoryServices.DirectoryEntry IISAdmin;
System.DirectoryServices.DirectoryEntry VDir;
bool IISUnderNT;
//
// Determine version of IIS
//
IISSchema = new System.DirectoryServices.DirectoryEntry("IIS://" +serverName + "/Schema/AppIsolated");
if (IISSchema.Properties["Syntax"].Value.ToString().ToUpper() == "BOOLEAN")
IISUnderNT = true;
else
IISUnderNT = false;
IISSchema.Dispose();
//
// Get the admin object
//
IISAdmin = new System.DirectoryServices.DirectoryEntry("IIS://" +serverName + "/W3SVC/" + webSiteNum + "/Root");
//
// If we're not creating a root directory
//
if (!RootDir)
{
//
// If the virtual directory already exists then delete it
//
foreach(System.DirectoryServices.DirectoryEntry v in IISAdmin.Children)
{
if (v.Name == VDirName)
{
// Delete the specified virtual directory if it already exists
try
{
IISAdmin.Invoke("Delete", new string [] { v.SchemaClassName, VDirName });
IISAdmin.CommitChanges();
}
catch(Exception ex)
{
sRet+=ex.Message;
}
}
}
}
//
// Create the virtual directory
//
if (!RootDir)
{
VDir = IISAdmin.Children.Add(VDirName, "IIsWebVirtualDir");
}
else
{
VDir = IISAdmin;
}
//
// Setup the VDir
//
VDir.Properties["AccessRead"][0] = chkRead;
VDir.Properties["AccessExecute"][0] = chkExecute;
VDir.Properties["AccessWrite"][0] = chkWrite;
VDir.Properties["AccessScript"][0] = chkScript;
VDir.Properties["AuthNTLM"][0] = chkAuth;
VDir.Properties["EnableDefaultDoc"][0] = true;
VDir.Properties["EnableDirBrowsing"][0] = false;
VDir.Properties["DefaultDoc"][0] = true;
VDir.Properties["Path"][0] = Path;
//
// NT doesn't support this property
//
if (!IISUnderNT)
{
VDir.Properties["AspEnableParentPaths"][0] = true;
}
//
// Set the changes
//
VDir.CommitChanges();
//
// Make it a web application
//
if (IISUnderNT)
{
VDir.Invoke("AppCreate", false);
}
else
{
VDir.Invoke("AppCreate", 1);
}
sRet+= "VRoot " +VDirName + " created!";
return sRet;
}
#region Properties
public string ServerName
{
get
{
return _serverName;
}
set
{
_serverName = value;
}
}
#endregion
public static string VirDirSchemaName = "IIsWebVirtualDir";
#region Private Members
private string _serverName;
#endregion
}
}
|
Debugging Addin projects can be a little confusing because a new instance of the IDE is spawned which is supposed to have your addin "in it" so you can actually test it out and set breakpoints in your code. However, after you have done a few of these, it almost becomes second nature. They are a lot of fun to make, and if you have a good idea for some useful utility, you may want to consider the advantages of putting it at the developer's fingertips where they can access it right from within the IDE where it is most intuitive, rather than having to run it as a separate application.
"Make Vroot Here" utility
We also have a neat little console utlitly that makes ther required virtual directory with all the required permissions in the folder you run it in. Also, the first time you run this, it install registry entries that enable a context menu item for Windows explorer. Just right-click on any folder, choose "Make Vroot Here" and you are done! You can get this little doozy here.
If you just want to use the product, run the installer MSI that's located in the Release folder of the MyAddin1Setup folder. All the source code is there in the solution for you to experiment with. Have fun!
|