Get the tcp port web site is served on - c#

I need to get a tcp port of the specified web site on IIS 7 and IIS 6 using C#. I have a console application that knows the web site's name. It should find a port this web site is served on.

you can get with servervariables
Request.ServerVariables["SERVER_PORT"]

I think I can use System.DirectoryServices for IIS 6 and Microsoft.Web.Administration for IIS 7.

OK. I'm going to give you a different answer since you commented that my last answer was not the answer to your question.
Try adding a global.asax file to your asp.net application. It will have functions to handle different events on the server. For the Application_Start function, you can have some code to save the port number that the web site is running on in a file or database somewhere.
Then, the console application can access the same file or database to find the port number.
If that doesn't suit you, then perhaps a better question to ask on SO would be "How can I programmatically read the IIS settings for a web site at run time?"

By default IIS binds to port 80 (default http port) but I am sure the answer is not that simple.
Maybe you could have used the admin scripts in IIS 6.0, to iterate through the IIS objects to find the port number, but this assumes the script is physically running on the server.
The only other option is run scan of each 65535 port to see if there a html listener using wget maybe.

FOR IIS 7 ;-)
private bool checkPortIsOpen(string portNumer)
{
ServerManager serverMgr = new ServerManager();
int index = 0;
bool isOpen = true;
foreach (Site mySite in serverMgr.Sites)
{
foreach (Microsoft.Web.Administration.ConfigurationElement binding in mySite.GetCollection("bindings"))
{
string protocol = (string)binding["protocol"];
string bindingInfo = (string)binding["bindingInformation"];
if (protocol.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
string[] parts = bindingInfo.Split(':');
if (parts.Length == 3)
{
string port = parts[1];
if(port.Equals(portNumer.ToString()))
{
isOpen = false;
webSite_portInUse = mySite.Name;
}
}
}
index++;
}
}
return isOpen;
}

Had to figure this out myself today, and got the answer I wanted, so figured I'd post it into this old thread.
You can determine the port by reading the IIS Metabase, which in IIS6 and above is an xml document.
In IIS6 get the file systemroot\system32\inetserv\metabase.xml and look at the node
/configuration/MBProperty/IIsWebServer[#ServerComment=$websitename]/serverBindings
In IIS7 get the file systemroot\system32\inetserv\config\applicationHost.config
(it is xml, despite the .config extension) and look at the node
/configuration/system.applicationHost/sites/site[#name='$websitename']

Related

Get IIS default installation directory

From what I can tell all ASP.NET web applications are placed into C:\inetpub folder by default. But is there any way to retrieve this folder in a C# code? Or do I just hard code it?
PS. I need this as a default folder for my C# program that installs my web application.
The following is limited to my experience so . . . YMMV
I do not believe that there is a true default location.
IIS will host a site in any folder that IIS has access permissions for. To determine what folder that might be, you can query the existing site list.
BUT
All is not lost. You can figure out where those sites are!
In a new IIS installation you can locate the directory of the "Default Site" created during the IIS installation.
Just keep in mind that there are no guarentees that the site will remain there. Personally, I delete the Default Site as soon as I start to configure IIS.
In IIS 7+
Site locations can be found in an XML file under IIS's configuration folder.
%systemroot%\System32\inetsrv\config\
In the XML file applicationHost.config see
The XML Node path is:
/configuration/system.applicationHost/sites/
From there you can iterate through each child node to see the various folder locations. For example, the default site will probably be listed as:
child node: site name="Default Web Site" id="1"
The .Net Way
Another trick would be to query IIS directly via .Net.
Here is the API documentation
Here are some methods to keep in your back pocket:
private static Site GetSite(string siteName)
{
Site site = (from s in (new ServerManager().Sites) where s.Name == siteName select s).FirstOrDefault();
if (site == null)
throw new Exception("The Web Site Name \"" + siteName + "\" could not be found in IIS!");
return site;
}
private static ApplicationCollection GetApplications(Site site)
{
//HttpContext.Current.Trace.Warn("Site ID3: " + site + "/n");
ApplicationCollection appColl = site.Applications;
return appColl;
}
private static String GetHostName(Site site)
{
BindingCollection bindings = site.Bindings;
String bind = null;
foreach (Binding binding in bindings)
if (binding.Host != null)
return binding.ToString();
return bind;
}
Update!
While I can't guarantee that this location will remain after install, you can also query the registry:
Check out HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\InetStp\pathWWWRoot\
I'm posting this as a seperate answer as its a completely different solution:
Do not worry where other apps are installed!
Use Web Deploy (and if you're getting creative with Web Publish, you can even set specific folder permissions)
If you need to do this pragmatically/have no access to those nifty tools...
Choose a location and set permissions on the folder to ensure that IIS is able to access it.
Then using the IIS API's register your new site.
Oh and you'll need to check those app pool permissions too

Checking whether a folder exists under an IIS application using C#

I'm working on a web based deployment tool in C# which deploys applications remotely on IIS 7.
I've reached a point where where I'm able to deploy an application. Now I need to see if the application that is deployed has a a certain directory before attempting to set permissions on it (Since the tool would deploy different applications which may or may not have that folder).
There are two approaches that I took:
I've checked for classes that I can use under the ServerManager namespace. I can get a handle on an application deployed under a certain application pool using:
var iis = ServerManager.OpenRemote("serverName")
var iisApplication = iis.Sites[site].Applications["appName"];.
Now I can get the virtual directories under the application using :
var virtualDirectory = iisApplication.VirtualDirectories;
But then I'm not able to see a whole lot of folders which are under that virtual directory. For axample, my application is deployed as test and iisApplication.VirtualDirectories.First() gives me /test. I was want to be able to /test/_ApplicationLogs which is the directory I want to set permissions on.
My next approach was to use DirectoryEntry. Here, I'm not able to figure out the metabase path to use for my application. Is there a standard metabase path used for IIS 7?
For an application called test deployed locally, what would the metabase path be? And would I be able to get all the children so that I can use DirectoryEntry.Exists?
For now, I have a workaround. I can use the WhatIf (set it true) property under DeploymentSyncOptions, do a sync and then check if an object got added. If it did, the directory does not exist. Code :
var syncOptions = new DeploymentSyncOptions();
syncOptions.WhatIf = true;
using (deploymentObject)
{
var result = deploymentObject.SyncTo(
DeploymentWellKnownProvider.SetAcl,
"Default Web Site/path_to_folder",
destinationBaseOptions,
syncOptions);
if (result.ObjectsAdded != 0)
{
syncOptions.WhatIf = false;
deploymentObject.SyncTo(DeploymentWellKnownProvider.SetAcl,
"Default Web Site/path_to_folder",
destinationBaseOptions,
syncOptions);
}
}

Accessing IIS site information in Silverlight

I need to get the site name and port number of the IIS sites in the Silverlight Application. How to get that?
You should be able to get this info from Application.Current.Host.Source
string server = Application.Current.Host.Source.Host;
int port = Application.Current.Host.Source.Port;

How can I programmatically stop or start a website in IIS (6.0 and 7.0) using MsBuild?

I have Windows Server 2003 (IIS 6.0) and Windows Server 2008 (IIS 7.0) servers, and I use MSBuild for deploying web applications.
I need to do a safe deploy, and do this:
Stop a website in IIS 6 (or an Application in IIS 7), not stop AppPool.
Check if the website is stopped; not running.
If the website is stopped, do another task for deploy.
Start the website IIS 6 (or Application in IIS 7),
How can I achieve this?
Update: Key for me: IIS6WebSite and IIS6AppPool (and for IIS7), do wait for stopped status when try Stop Website or AppPool?
When I execute Stop Action for Website (or Stop Action for AppPool), I need be sure 100% that Website is stopped, and then, and only if Website is Stopped, I can execute other targets.
By adding a reference to Microsoft.Web.Administration (which can be found inX:\Windows\System32\inetsrv, or your systems equivalent) you can achieve nice managed control of the situation with IIS7, as sampled below:
namespace StackOverflow
{
using System;
using System.Linq;
using Microsoft.Web.Administration;
class Program
{
static void Main(string[] args)
{
var server = new ServerManager();
var site = server.Sites.FirstOrDefault(s => s.Name == "Default Web Site");
if (site != null)
{
//stop the site...
site.Stop();
if (site.State == ObjectState.Stopped)
{
//do deployment tasks...
}
else
{
throw new InvalidOperationException("Could not stop website!");
}
//restart the site...
site.Start();
}
else
{
throw new InvalidOperationException("Could not find website!");
}
}
}
}
Obviously tailor this to your own requirements and through your deployment build script execute the resulting application.
Enjoy. :)
Write a script, e.g. PowerShell, which will stop/start IIS web site programmatically relying on command-line argument, e.g. start-stop.ps1 /stop 1
Put it into MsBuild script as a custom step
Check this to find out how to restart IIS AppPool
IIS WMI objects reference
So you have your answer above for IIS7. What you're missing is IIS6. So here you go. This is using a COM interop object as that's all that is available for IIS 6. Also, because it's in vb, you'll have to figure out how to convert it. http://www.codeproject.com/Articles/16686/A-C-alternative-for-the-Visual-Basic-GetObject-fun should get you on the right track. you could also create a vb project just for this code but that's kind of silly.
Dim WebServiceObj As Object
dim IisSiteId as Integer = 0
WebServiceObj = GetObject("IIS://localhost/W3SVC/" & IisSiteId)
WebServiceObj.Stop()
WebServiceObj.Start()

Programmatic check if the IIS6 compatibility role is enabled/disabled in IIS7

How can I check with C# if the IIS6 compatibility role is enabled/disabled on IIS7 ?
you can check read the value in the registry
HKEY_LOCAL_MACHINE\Software\Microsoft\InetStp\Components\WMICompatibility
or, you can ouput the content of servermanagercmd to an xml file and parse that file looking for the iis6 compatibility component
ServerManagerCmd -query [SaveFile.xml]
If your doing this on R2, servermanagercmd is now deprecated so you might want to use powershell to achieve the same check.
Here are some powershell examples, in this case done remotely http://www.techmumbojumblog.com/?p=217
The WMI approach from the previous answer is probably good as well, espcialy if you have more configuration tasks to perform on the IIS, after validating that the compatibility tool is install.
btw, if you do find configuration settings that are not handled by the compatibility component, here is what I found doing it from C#, what I was configuring through wmi back in iis6 worked fine at the website level and under(website, virtual dir and pools), but to configure the webserver level, I had to use the the api that's installed with iis7, Microsoft.Web.Administration.dll from System32\inetsrv.
using Microsoft.Web.Administration;
Please, someone give a good answer for this!
As motivation, here's a very bad answer =)
// Ok, this is stupid, but I can't find any other way to do this
// Detect whether we're in integrated mode or not
#warning GIANT HACK FOR IIS7 HERE
try
{
var x = HttpContext.Current.CurrentNotification;
_isIntegratedMode = true;
}
catch (PlatformNotSupportedException)
{
_isIntegratedMode = false;
}
catch (NullReferenceException)
{
_isIntegratedMode = true;
}
This is what our code currently does to figure this out (yes, I know it's appallingly bad - hence the warnings)
You probably can do that by programmatically querying the WMI provider of IIS7. http://learn.iis.net/page.aspx/162/managing-sites-with-iis-7039s-wmi-provider/
I don't know if you can do that through powershell.

Categories