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

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.

Related

Creation of Firewall rule during installation: netsh or WindowsFirewall API?

I'm building an installer for our program here, and I would like to add a firewall rule upon installation.
I've researched a bit and there are 2 approaches I've found:
Running a netsh command
Programmaticaly with the firewall API
Regarding netsh- there are 2 types of commands documented-
"netsh firewall add allowedprogram C:\MyApp\MyApp.exe "My
Application" ENABLE",
and-
"netsh advfirewall firewall add rule name="My Application" dir=in
action=allow program="C:\MyApp\MyApp.exe" enable=yes"
..which operating system(s) support which? I guess I could just run both just to be sure
(I would like to support xp,vista and win7)
Regarding the firewallAPI- are there any benefits to using it? It seems a bit more complicated on the surface (I'll need to find out which OS I'm running on for starters, since I will need to connect to a different dll in vista).
If your simply checking to see if the Firewall is enabled; you could do:
NetFwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", false);
INetFwMgr Manage = (INetFwMgr)Activator.CreateInstance(NetFwMgrType);
bool Firewallenabled = Manage.LocalPolicy.CurrentProfile.FirewallEnabled;
Then you could add your application to the authorized applications;
INetFwAuthorizedApplications applications;
INetFwAuthorizedApplication application;
// Input Application Name
application.Name = “Internet Explorer”;
// Locate .exe
application.ProcessImageFileName = "C:\\Program Files\\Internet Explorer\\iexplore.exe"
// Enable
application.Enabled = true;
// Authorize the Application
Type NetFwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", false);
INetFwMgr Manage = (INetFwMgr)Activator.CreateInstance(NetFwMgrType);
applications = (INetFwAuthorizedApplications)mgr.LocalPolicy.CurrentProfile.AuthorizedApplications;
applications.Add(application);
You'll need access to these COM Objects:
NetFwTypeLib
HNetCfg.FwMgr
Keep in mind that these are written with older COM objects for XP SP2; where Microsoft suggest you use: INetFwPolicy2. It will work though for Vista, 7, and 8. Here is some documentation including the article with several examples using the older code; don't know if this helps. Hopefully it does.
Vista, 7, 8
XP Service Pack 2:
Blog with those examples in detail; and explanations.

How to ping URL from code behind

I have one issue that i want to ping URL from code behind (EXE project) by which i can know environment of Azure application on which my EXE is running.
string dep = RoleEnvironment.DeploymentId.ToString();
WebRequest req = WebRequest.Create("http://" + dep + ".cloudapp.net");
HttpWebResponse rep= null;
try
{
rep = (HttpWebResponse)req.GetResponse();
}
catch (Exception)
{
//if environment is production then this URL will not work
//do some functionality
}
So by above code i would like to do some functionality when it will production environment
,above logic is works well but would like to get some perfect solution like ping command that if URL exist then return true otherwise false.
Please suggest me some good logic here
Thanks in advance.
No, I don't think that will work - if you have production code running then the check will always be successful, even if you call it from staging.
Check the answer to this:
Azure Detect Staging vs Production
which provides a more robust answer to your real question.
How about initiating a socket that tries to connect to the server over port 80 (HTTP)?
that'll be a good indication whether the site is up or not.
The only way to "ping" a resource is to get an error code. just make sure it's just a get operation so that no change occurs on the server.
You know when you deploy whether the app is deployed to live or test/staging so why don't you just set something on the web.config. Then you can just do
If (ConfigurationManager.AppSettings["Envirmonment"] == "Live")
{
//do live stuff
}
else
{
//do testing stuff.
}

.Net's Directory Services throws a strange exception

I have a small C# solution used to check users credentials. It works fine for two of my teammates, but on my PC I get an exception.
The relevant code:
PrincipalContext context = new PrincipalContext(ContextType.Domain);
if (context.ValidateCredentials(System.Environment.UserDomainName + "\\" + usr, pwd))
return true;
else
return false;
And the exception is:
DirectoryOperationException, "The server cannot handle directory requests.".
I tried creating context with the explicit server name and the 636 port number, but this didn't help as well.
Any ideas?
I had this problem too using IIS Express and VS 2010. What fixed it for me was a comment on another thread.
Validate a username and password against Active Directory?
but i'll save you the click and search... :) Just add ContextOpations.Negotiate to you Validate Credentials call like below.
bool valid = context.ValidateCredentials(user, pass, ***ContextOptions.Negotiate***);
I had this issue: things were working on my dev machine but didn't work on the server. Turned out that IIS on the server was set up to run as LocalMachine. I changed it to NetworkService (the default) and things started working.
So basically check the user of the app pool if this is running on IIS.
I had to just create a new app pool and assign it .NET 2.0, then assign the new app pool to our web app, and it started working. We had .NET 3.5 SP2, so the hotfix wasn't ideal for us. Since the WWW service is usually Local System, I questioned that too. But since it was .NET and security related, I gave a shot at the app pool first and it worked.
Perhaps you need the hotfix?
FIX: DirectoryOperationException exception
And you are an Admin or the id that your service is running under is an Admin on your PC right?
I take it you already looked into this:
System.DirectoryServices.Protocols
"You may receive a less than helpful DirectoryOperationException(“The server cannot handle directory requests.”) what isn’t quite so amusing about this is that it didn’t even try to communicate with the server. The solution was to add the port number to the server. So instead of passing “Server” to open the LdapConnection, I passed “server:636”. By the way, LDAPS is port 636 – rather than the 389 port used by LDAP."
Good point, I wouldn't expect that Win7/.NET 3.5 would need that patch. How about the info provided in this question:
Setting user's password via System.DirectoryServices.Protocols in AD 2008 R2

Get the tcp port web site is served on

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']

How can I programmatically determine if I have write privileges using C# in .Net?

How can I determine if I have write permission on a remote machine in my intranet using C# in .Net?
The simple answer would be to try it and see. The Windows security APIs are not for the faint of heart, and may be possible you have write permission without having permission to view the permissions!
Been there too, the best and most reliable solution I found was this:
bool hasWriteAccess = true;
string remoteFileName = "\\server\share\file.name"
try
{
createRemoteFile(remoteFileName);
}
catch (SystemSecurityException)
{
hasWriteAccess = false;
}
if (File.Exists(remoteFileName))
{
File.Delete(remoteFileName);
}
return hasWriteAccess;
Check out this forum post.
http://bytes.com/forum/thread389514.html
It describes using the objects in the System.Security.AccessControl namespace to get a list of the ACL permissions for a file. It's only available in .NET 2.0 and higher. I think it also assumes that you have an SMB network. I'm not sure what it would do if you were using a non-Windows network.
If you aren't on .NET 2.0 or higher, it's the usual pInvoke and Win32 API jazz.
ScottKoon is write about checking the windows ACL permissions. You can also check the managed code permissions using CAS (Code Access Security). This is a .Net specific method of restricting permissions. Note, if the user doesn't have write permissions then the code will never have write permissions (even if CAS says it does) - the most restrictive permissions between the two win.
CAS is pretty easy to use - you can even add declarative attributes you the start of your methods. You can read more at MSDN

Categories