Solved

Creating Website Dynamically IIS 7

Posted on 2014-04-28
19
434 Views
Last Modified: 2014-05-14
Hi all,

I am creating websites dynamically in IIS, before I do this I have a 'does website exist' check.

    public static bool DoesWebsiteExist(string websiteName)
    {
        bool result = false;

        DirectoryEntry w3svc = new DirectoryEntry("IIS://localhost/w3svc", iis_login, iis_password);

        foreach (DirectoryEntry site in w3svc.Children)
        {
            if (site.Properties["ServerComment"] != null)
            {
                if (site.Properties["ServerComment"].Value != null)
                {
                    if (string.Compare(site.Properties["ServerComment"].Value.ToString(), websiteName, false) == 0)
                    {
                        result = true;
                    }
                }
            }
        }

        return result;
    }

Open in new window


however, I am getting an Access is Denied error from the DirectoryEntry.

Now the iis_user and iis_password are a user/password combination for a user in IIS Manage Users.

Any ideas what I am doing wrong here?
0
Comment
Question by:flynny
  • 10
  • 9
19 Comments
 
LVL 7

Expert Comment

by:Utkarsh Kulkarni
ID: 40029538
It seems, your application does not has rights to create directory in IIS (i.e. creating directory in c:/inetpub/wwwroot/...).

Give proper permissions to this folder. Also, is your application is web or windows ?
Web Application does not have this permission by default for security reasons.
0
 

Author Comment

by:flynny
ID: 40031642
ok what user should i give writing rights to?

i.e. will it be IIS_USERS?
0
 
LVL 7

Expert Comment

by:Utkarsh Kulkarni
ID: 40031766
If your application is windows application, then you need to give permission for Trusted installer / admin user etc.
If its web application, then give it to IIS_USERs.
0
 

Author Comment

by:flynny
ID: 40032180
ok after adding the permissions for IIS_USERS and debugging on the following line

DirectoryEntry w3svc = new DirectoryEntry("IIS://localhost/w3svc");

        foreach (DirectoryEntry site in w3svc.Children)

Open in new window


it is throwing the following error;

Error: Unknown error (0x80005000)

any ideas?
0
 
LVL 7

Expert Comment

by:Utkarsh Kulkarni
ID: 40032232
Need to look thorough. Is it web application or windows application ?
0
 

Author Comment

by:flynny
ID: 40032280
its a web application running on IIS7 and is running on the same server I am trying to create the site on.
0
 
LVL 7

Expert Comment

by:Utkarsh Kulkarni
ID: 40037023
I will suggest couple of changes

1. Make the Identity of the application pool for this site (using which you are trying to create new site) to "Local System" (Note - This is highest privileged account)
2. Give full control to "Trusted installer" user/user group. (Ref - Permission for "wwwroot" folder)
0
 

Author Comment

by:flynny
ID: 40050434
Apologies for my delay in coming back to you.

Point 1 has solved the issue and it now runs smoothly. However the sites are not appearing in IIS?

The directory is create, the application pool is create and I can see this in IIS. However whilst the code runs it is not appearing in IIS??
    static void CreateVDir(string metabasePath, string vDirName, string physicalPath)
    {
        //  metabasePath is of the form "IIS://<servername>/<service>/<siteID>/Root[/<vdir>]"
        //    for example "IIS://localhost/W3SVC/1/Root" 
        //  vDirName is of the form "<name>", for example, "MyNewVDir"
        //  physicalPath is of the form "<drive>:\<path>", for example, "C:\Inetpub\Wwwroot"
        Console.WriteLine("\nCreating virtual directory {0}/{1}, mapping the Root application to {2}:",
            metabasePath, vDirName, physicalPath);

        Global.log.Debug(String.Format("Debug: Creating virtual directory :{0}/{1}: mapping the Root application to :{2}:", metabasePath, vDirName, physicalPath));

        try
        {
            DirectoryEntry site = new DirectoryEntry(metabasePath);
            string className = site.SchemaClassName.ToString();
            if ((className.EndsWith("Server")) || (className.EndsWith("VirtualDir")))
            {
                DirectoryEntries vdirs = site.Children;
                DirectoryEntry newVDir = vdirs.Add(vDirName, (className.Replace("Service", "VirtualDir")));
                newVDir.Properties["Path"][0] = physicalPath;
                newVDir.Properties["AccessScript"][0] = true;
                // These properties are necessary for an application to be created.
                newVDir.Properties["AppFriendlyName"][0] = vDirName;
                newVDir.Properties["AppIsolated"][0] = "1";
                newVDir.Properties["AppRoot"][0] = "/LM" + metabasePath.Substring(metabasePath.IndexOf("/", ("IIS://".Length)));

                newVDir.CommitChanges();

                Console.WriteLine(" Done.");
            }
            else
                Console.WriteLine(" Failed. A virtual directory can only be created in a site or virtual directory node.");
        }
        catch (Exception ex)
        {
            Console.WriteLine("Failed in CreateVDir with the following exception: \n{0}", ex.Message);
        }
    }

Open in new window



Here is the print out from the logging
2014-05-06 14:25:32,702 [9] DEBUG Global - Debug: ABOUT TO CHECK WEBSITE EXISTS!
2014-05-06 14:25:33,130 [9] DEBUG Global - Debug: Does Website Exist? False
2014-05-06 14:25:33,440 [9] DEBUG Global - Debug: Website does not exist!
2014-05-06 14:25:33,441 [9] DEBUG Global - Debug: Website directory is :C:\Inetpub\Wwwroot\Sites\BIGBANG:
2014-05-06 14:25:33,443 [9] DEBUG Global - Debug: Creating application pool named :IIS://Localhost/W3SVC/AppPools/BIGBANG:
2014-05-06 14:25:33,709 [9] DEBUG Global - Debug: Creating virtual directory :IIS://Localhost/W3SVC/1/Root//BIGBANG: mapping the Root application to :C:\Inetpub\Wwwroot\Sites\BIGBANG:

Open in new window

0
 
LVL 7

Expert Comment

by:Utkarsh Kulkarni
ID: 40050447
It will not create the website but it creates Virtual directory under root website.
E.g. your default website runs on port 80. So this newly created website is virtual directory hence its url will be like http://localhost:80/<foldername>/
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 

Author Comment

by:flynny
ID: 40050482
apologies after further debuggin its actually throwing this error which i misse dwhen logging

Failed in CreateVDir with the following exception :Unknown error (0x80005000):

Open in new window

0
 
LVL 7

Expert Comment

by:Utkarsh Kulkarni
ID: 40050494
Is it appearing for all ?
0
 
LVL 7

Expert Comment

by:Utkarsh Kulkarni
ID: 40050512
0
 

Author Comment

by:flynny
ID: 40050534
Thanks for your reply I really appreciate your help.

ok after further debugging it is throwing the error when it hits this line;

string className = site.SchemaClassName;

Open in new window


(I have tried with and without the redundant .ToString() call).
0
 
LVL 7

Expert Comment

by:Utkarsh Kulkarni
ID: 40050560
You can add couple of checks like
1. Is site has value for SchemaClassName
2. using Convert.ToString() method

e.g. If site.SchemaClassName.Length() >0 or if site!=null
This might give you an idea.
0
 

Author Comment

by:flynny
ID: 40050723
Hi,

thanks for the advice. I have done the following;

            Global.log.Debug(String.Format("Debug: DirectoryEntry :{0}:", site));

            if(site == null)
                Global.log.Debug("Debug: site is NULL");

Open in new window


with the following being output, so it appears 'site' is not null

2014-05-06 16:15:16,347 [25] DEBUG Global - Debug: DirectoryEntry :System.DirectoryServices.DirectoryEntry:

Open in new window

0
 

Author Comment

by:flynny
ID: 40050932
ok i change the code tot he following and this is working

        string siteDirectory = "C:\\Inetpub\\Wwwroot\\Sites\\" + subdomain;

        Global.log.Debug(String.Format("Debug: Website directory is :{0}:", siteDirectory));

        ServerManager serverMgr = new ServerManager();
        Site mySite = serverMgr.Sites.Add(subdomain + ".mydom.com", siteDirectory, 8080);
        serverMgr.ApplicationPools.Add(subdomain);
        mySite.ApplicationDefaults.ApplicationPoolName = subdomain;
        mySite.TraceFailedRequestsLogging.Enabled = true;
        mySite.TraceFailedRequestsLogging.Directory = siteDirectory;
        serverMgr.CommitChanges();

       // CreateAppPool("IIS://Localhost/W3SVC/AppPools", subdomain);
       // CreateVDir("IIS://Localhost/W3SVC/1/Root/", subdomain, siteDirectory);
       // AssignVDirToAppPool("IIS://Localhost/W3SVC/1/Root/" + subdomain, subdomain);
        CopySite(defaultSiteDirectory, siteDirectory);

Open in new window


however, how do I add the site bindings to the site? i.e. so that subdomain.mydom.com is the bound domain tot he site?

also how do I change the .net version assigned to the pool?

thanks for all the help.
0
 
LVL 7

Expert Comment

by:Utkarsh Kulkarni
ID: 40052833
You can use ServerManager class for this

To create an application pool use  Microsoft.Web.Administration and set the .NET Framework version to 4.0, do this:

using Microsoft.Web.Administration;
...

using(ServerManager serverManager = new ServerManager())
{
  ApplicationPool newPool = serverManager.ApplicationPools.Add("MyNewPool");
  newPool.ManagedRuntimeVersion = "v4.0";
  serverManager.CommitChanges();
}

You should add a reference to Microsoft.Web.Administration.dll which can be found in:

%SYSTEMROOT%\System32\InetSrv


As you are using Directory Entry use following

newpool.Properties["ManagedRuntimeVersion"].Value = "v4.0";

newPool.InvokeSet("ManagedPipelineMode", new object[] { 0 });


Entire Reference you can get at

http://patelshailesh.com/index.php/create-a-website-application-pool-programmatically-using-csharp
0
 

Author Comment

by:flynny
ID: 40053316
Many thanks for this this is working.

Is it possible to add further bindings to the site, as i mentioned before the site is now setup and appearing in IIS but there are now urls bound to the site?
0
 
LVL 7

Accepted Solution

by:
Utkarsh Kulkarni earned 500 total points
ID: 40053369
You can add with Properties collection

site.Properties["Serverbindings"].Clear();
site.Properties["Serverbindings"].Add(":" + port + ":");

Else you can loop through Properties collection for exact attribute (and its value) and then right the code for setting it.
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now