Create an application under default web site IIS - c#

I am trying to create a new application under default web site by using C# code. This is what I tried
public static bool CreateWebSite(Application application)
{
try
{
application.Alias = "Test";
application.PhysicalPath = #"C:\Test";
application.ApplicationPool = "TestAppPool";
using (ServerManager serverManager = new ServerManager())
{
serverManager.Sites["Default Web Site"].Applications.Add("/", application.PhysicalPath);
serverManager.CommitChanges();
}
return true;
}
catch (Exception se)
{
throw se;
}
}
But getting path already exists error can some one help me.

How can we set directory browsing enabled
You could try to use below command to set directory browsing enabled.
ServerManager server = new ServerManager();
Configuration config = server.GetWebConfiguration("TestMVC");
ConfigurationSection directoryBrowseSection = config.GetSection("system.webServer/directoryBrowse");
directoryBrowseSection["enabled"] = true;
directoryBrowseSection["showFlags"] = #"Date, Time, Size, Extension";
server.CommitChanges();
Result:

Related

Setting application pool to a specific iis application using servermanager web setup project

I'm trying to create an application pool before install and set that application pool for the installed application post install in a visual studio web setup project
Trying to filter out the applications under a site so that the newly created application pool applies only to a specific application with the name "websetup9090" in this case. Tried a few methods to compare the name of the applications but none of them worked
or
If there is any way to run the custom action to create the application pool before it reaches the Installation address UI page it would be even better as there is an option to select the application pool for the user via dropdown
The code below is called via custom action in the web setup project
protected override void OnBeforeInstall(IDictionary stateSaver)
{
ServerManager iisManager = new ServerManager();
bool chkPool = false;
chkPool = iisManager.ApplicationPools.Any(t => t.Name == "Pool99");
if (chkPool == false)
{
var myPool = iisManager.ApplicationPools.Add("Pool99");
myPool.ManagedPipelineMode = ManagedPipelineMode.Integrated;
myPool.ManagedRuntimeVersion = ".NET CLR version 4.0.30319";
myPool.Enable32BitAppOnWin64 = true;
iisManager.CommitChanges();
}
}
protected override void OnAfterInstall(IDictionary stateSaver)
{
ServerManager iisManager = new ServerManager();
var sites = iisManager.Sites;
foreach (Site site in sites)
{
if (site.Name == "Default Web Site")
{
Site mySite = site;
mySite.Stop();
var myPools = iisManager.ApplicationPools;
foreach (ApplicationPool pool in myPools)
{
if (pool.Name == "Pool99")
{
ApplicationPool myPool = pool;
foreach (var item in mySite.Applications)
{
if (item.Path.ToLower().IndexOf("websetup9090") > 0)
{
item.ApplicationPoolName = myPool.Name;
}
}
iisManager.CommitChanges();
myPool.Recycle();
}
}
iisManager.CommitChanges();
mySite.Start();
}
}
}
I resolved the issue with attaching application pool to the newly created application by moving the code in onAfterInstall to Commit method

Ho to take server offline / bring server online IIS web farm server programmatically

I am developing a C# application to automate process of deploying website to the server.The website is hosted in a web farm in WINDOWS SERVER 2012 R2. So the problem here is I am trying to take server offline or bring it online by means of some programming interface. but I couldn't find anything related inside Microsoft docs. How do I get the job done?
UPDATE:
As suggested by Timur I did as following, but it didn't work.
ServiceController p = new ServiceController("W3SVC","SERVER_IP");
p.Start();
p.WaitForStatus(ServiceControllerStatus.Running);
This is the sample that generated by configuration manager. It take server offline/online by change the Enabled property of server item in web farm collection.
using System;
using System.Text;
using Microsoft.Web.Administration;
internal static class Sample
{
private static void Main()
{
using (ServerManager serverManager = new ServerManager())
{
Configuration config = serverManager.GetApplicationHostConfiguration();
ConfigurationSection webFarmsSection = config.GetSection("webFarms");
ConfigurationElementCollection webFarmsCollection = webFarmsSection.GetCollection();
ConfigurationElement webFarmElement = FindElement(webFarmsCollection, "webFarm", "name", #"123213");
if (webFarmElement == null) throw new InvalidOperationException("Element not found!");
ConfigurationElementCollection webFarmCollection = webFarmElement.GetCollection();
ConfigurationElement serverElement = FindElement(webFarmCollection, "server", "address", #"11.1.1.1");
if (serverElement == null) throw new InvalidOperationException("Element not found!");
serverElement["enabled"] = false;
serverManager.CommitChanges();
}
}
private static ConfigurationElement FindElement(ConfigurationElementCollection collection, string elementTagName, params string[] keyValues)
{
foreach (ConfigurationElement element in collection)
{
if (String.Equals(element.ElementTagName, elementTagName, StringComparison.OrdinalIgnoreCase))
{
bool matches = true;
for (int i = 0; i < keyValues.Length; i += 2)
{
object o = element.GetAttributeValue(keyValues[i]);
string value = null;
if (o != null)
{
value = o.ToString();
}
if (!String.Equals(value, keyValues[i + 1], StringComparison.OrdinalIgnoreCase))
{
matches = false;
break;
}
}
if (matches)
{
return element;
}
}
}
return null;
}
}
IIS is a Windows service. Therefore the easiest way to start/stop it will be to do something along the lines of this SO answer.
You'll be looking for service name, which likely depends on your version.
UPD see an artist's impression on how your management tool might look like
var hostNames = new List<string> { "appServer1", "webServer1", "webServer2" };
foreach (var host in hostNames)
{
var svc = new ServiceController("W3SVC", host);
svc.Stop();
svc.WaitForStatus(ServiceControllerStatus.Stopped);
Thread.Sleep(10000);// or your custom logic
svc.Start();
svc.WaitForStatus(ServiceControllerStatus.Running);
}
bear in mind, you'll need to run this as a user with sufficient privileges to successfully change service state: as in you need to run this as Admin.
You've got at least two options to do it:
Run your IDE as admin
Update your application manifest as described in this answer
UPD2 apparently you can interface with WFF controller like so

Resolve 'configuration object is read only, because it has been committed by a call to ServerManager.CommitChanges()'?

I've written a custom action for an installer project that does the following:
Checks existing websites to see if any exist with the same name put
in by the user.
Creates the website in IIS if it doesn't exist.
Creates an application pool.
Assigns the application pool to the created website.
When it comes to assigning the application pool I get and error:
The configuration object is read only, because it has been committed
by a call to ServerManager.CommitChanges(). If write access is
required, use ServerManager to get a new reference.
This baffles me as it seems to suggest that I can't assign the newly created application pool with the ServerManager.CommitChanges() call. However, everything else works fine using this, which I wouldn't expect if this was an issue.
Here is my code:
I have a ServerManager instance created like so:
private ServerManager mgr = new ServerManager();
In my Install method I do the following:
Site site = CreateWebsite();
if (site != null)
{
CreateApplicationPool();
AssignAppPool(site);
}
Check existing websites - done in OnBeforeInstall method
private Site CheckWebsites()
{
SiteCollection sites = null;
Site site = null;
try
{
sites = mgr.Sites;
foreach (Site s in sites)
{
if (!string.IsNullOrEmpty(s.Name))
{
if (string.Compare(s.Name, targetSite, true) == 0) site = s;
}
}
}
catch{}
return site;
}
CreateWebSite method:
private Site CreateWebsite()
{
Site site = CheckWebsites();
if (site == null)
{
SiteCollection sites = mgr.Sites;
int port;
Int32.TryParse(targetPort, out port);
site = sites.Add(targetSite, targetDirectory, port);
mgr.CommitChanges();
}
else
{
//TO DO - if website already exists edit settings
}
return site;
}
Create App Pool
//non-relevant code...
ApplicationPool NewPool = mgr.ApplicationPools.Add(ApplicationPool);
NewPool.AutoStart = true;
NewPool.ManagedRuntimeVersion = "4.0";
NewPool.ManagedPipelineMode = ManagedPipelineMode.Classic;
mgr.CommitChanges();
Assign App Pool
private void AssignAppPool(Site site)
{
site.ApplicationDefaults.ApplicationPoolName = ApplicationPool; //ERRORS HERE
mgr.CommitChanges();
}
I can't see why a site could be created, an app pool created but then not assigned. Help.
I finally realised that the 'configuration object' referred to in the error was the 'site'. Seems obvious now, but basically I needed to re-get the site to then assign the app pool to it. I think this is allow the previous changes to take place and then pick them up. So I altered my code by removing the need to pass the Site into private void AssignAppPool() and just getting the site again like this:
Site site = mgr.Sites["TestWebApp"];

iis Creating new application and enabling Windows Authentication Fails

I can successfully create an Application Pool and an Application plus link them together.
What I am failing to do however is set the applications Windows Authentication to true and Anonymous Authentication to false.
I patched a hodge podge of examples into one to make this work but I keep getting the following error.
This configuration section cannot be used at this path. This happens
when the section is locked at a parent level. Locking is either by
default (overrideModeDefault="Deny"), or set explicitly by a location
tag with overrideMode="Deny" or the legacy allowOverride="false".
Now barring the obvious that overrideMode needs to likely equal Allow. How do I accomplish this?
public static bool CreateApplication(String websiteName, String applicationName, String appDIR,String appPoolName)
{
try
{
ServerManager iisManager = new ServerManager();
if (!applicationName.Contains("/"))
applicationName = "/" + applicationName;
var app = iisManager.Sites[websiteName].Applications.Add(applicationName, appDIR);
app.ApplicationPoolName = appPoolName;
var config = app.GetWebConfiguration();
var anonsection = config.GetSection("system.webServer/security/authentication/anonymousAuthentication", iisManager.Sites[websiteName].Name + applicationName);
//This is where it fails
anonsection["enabled"] = false;
var winsection = config.GetSection("system.webServer/security/authentication/windowsAuthentication", iisManager.Sites[websiteName].Name + applicationName);
winsection["enabled"] = true;
iisManager.CommitChanges();
return true;
}
catch
{
return false;
}
}
Use the following commands from an admin command prompt
%windir%\system32\inetsrv\appcmd unlock config -section:system.webServer/security/authentication/windowsAuthentication
%windir%\system32\inetsrv\appcmd unlock config -section:system.webServer/security/authentication/anonymousAuthentication
This will unlock those config sections.

IIS application creation by using Microsoft.Web.Administration library creates two application instead of one

I'm trying to automate IIS application creation and for this I'm using Microsoft.Web.Administration library. Here is part of code I'm using:
IISHelper.cs
public static void CreateApplicationPool(string applicationPoolName)
{
using (ServerManager serverManager = new ServerManager())
{
if (serverManager.ApplicationPools[applicationPoolName] != null)
return;
ApplicationPool newPool = serverManager.ApplicationPools.Add(applicationPoolName);
newPool.ManagedRuntimeVersion = "v4.0";
serverManager.CommitChanges();
}
}
public static void CreateSite(string siteName, string path)
{
using (ServerManager serverManager = new ServerManager())
{
var sites = serverManager.Sites;
if (sites[siteName] == null)
{
sites.Add(siteName, "http", "*:80:", path);
serverManager.CommitChanges();
}
}
}
public static void CreateApplication(string siteName, string applicationName, string path)
{
using (ServerManager serverManager = new ServerManager())
{
var site = GetSite(serverManager, siteName);
var applications = site.Applications;
if (applications["/" + applicationName] == null)
{
applications.Add("/" + applicationName, path);
serverManager.CommitChanges();
}
}
}
public static void CreateVirtualDirectory(string siteName, string applicationName, string virtualDirectoryName, string path)
{
using (ServerManager serverManager = new ServerManager())
{
var application = GetApplication(serverManager, siteName, applicationName);
application.VirtualDirectories.Add("/" + virtualDirectoryName, path);
serverManager.CommitChanges();
}
}
public static void SetApplicationApplicationPool(string siteName, string applicationPoolName)
{
using (ServerManager serverManager = new ServerManager())
{
var site = GetSite(serverManager, siteName);
if (site != null)
{
foreach (Application app in site.Applications)
{
app.ApplicationPoolName = applicationPoolName;
}
}
serverManager.CommitChanges();
}
}
And here is main code which calls methods from above mentioned IISHelper class
string siteName = "TestSite";
string applicationName = "TestApp";
string virtualDirectoryName = "TestVirtualDirectory";
string applicationPoolName = "TestAppPool";
string physicalPath = #"C:\inetpub\mynewsite";
IISHelper.CreateApplicationPool(applicationPoolName);
IISHelper.CreateSite(siteName, physicalPath);
IISHelper.CreateApplication(siteName, applicationName, physicalPath);
IISHelper.CreateVirtualDirectory(siteName, applicationName, virtualDirectoryName, physicalPath);
IISHelper.SetApplicationApplicationPool(siteName, applicationPoolName);
After execution of this code I'm getting successfully created application with site and appropriate application pool under the IIS, but when I'm selecting "View Application" in the menu of newly created application pool I'm seeing there two application, but I'm sure there must be only one application. I'm working on this to avoid two application creation but can't find a way. Here is a picture illustrating that:
So here is my question: Why after the above mentioned code execution two applications are created and how to modify the code to avoid that issue?
Every site must include a "Root Application" which is what you are seeing as the second app. Basically when you request your site above as 'http://example.com/' (or whatever host name you set in the bindings) you will be requesting from that root app, in addition you are creating /TestApp which will be requested when calling 'http://example.com/TestApp'. When you create the Site and you provide the physical path it internally creates a root app "/" for it.
To see this you can open %windir%\system32\inetsrv\applicationHost.config.
So technically what you are seeing is correct, but you might not actually want a new app? and only need the root app? Do you really need /TestApp to be in the URL?

Categories

Resources