I found this code:
using System.DirectoryServices;
...
void Recycle(string appPool)
{
string appPoolPath = "IIS://servername/W3SVC/AppPools/" + appPool;
using (DirectoryEntry appPoolEntry = new DirectoryEntry(appPoolPath))
{
appPoolEntry.Invoke("Recycle", null);
appPoolEntry.Close();
}
}
But when I try to use this code I have this error:
Exception has been thrown by the target of an invocation., StackTrace: at System.DirectoryServices.DirectoryEntry.Invoke(String methodName, Object[] args)
What I'm doing wrong?
or how can get info about status of my application pool, and how can I start and stop my app pool without any special permissions?
I'am using built-in account: NetworkService
Try to use Microsoft.Web.Administration.ServerManager and Microsoft.Web.Administration.ApplicationPool classes.
Example:
var serverManager = new ServerManager();
var appPool = serverManager.ApplicationPools.FirstOrDefault(ap => ap.Name.Equals("AppPoolName"));
appPool.Start();
Related
I have created a method to get hosted web sites from IIS server as following code snippet.
ServerManager serverManager = new ServerManager();
try
{
foreach (Site site in serverManager.Sites)
{
Console.WriteLine(site);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
When i run it in my local machine it's working perfectly(Windows 7 /IIS 7 with 32bits).but when i run it in server machine(Windows server 2003 R2 with IIS 6) it's not working.It gives following Error
Retrieving the COM class factory for component with CLSID {2B>
52-803546CE3344} failed due to the following error: 80040154>
d (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).
Any help will be great full ?
I have used System.DirectoryServices instead of using Microsoft.Web.Administration and it solved my problem.It will work with the IIS6 and IIS7 as well.
public class IisManager
{
public static int IisVersion
{
get
{
int iisVersion;
using (RegistryKey iisKey = Registry.LocalMachine.OpenSubKey(#"Software\Microsoft\InetStp"))
{
if (iisKey == null)
throw new Exception("IIS is not installed.");
iisVersion = (int)iisKey.GetValue("MajorVersion");
}
return iisVersion;
}
}
public static IList<IisWebSite> GetIisSites()
{
List<IisWebSite> sites = new List<IisWebSite>();
using (DirectoryEntry iisRoot = new DirectoryEntry("IIS://localhost/W3SVC"))
{
iisRoot.RefreshCache();
sites.AddRange(iisRoot.Children.Cast<DirectoryEntry>().Where(w => w.SchemaClassName.ToLower(CultureInfo.InvariantCulture) == "iiswebserver").Select(w => new IisWebSite(w.Name, w.Properties["ServerComment"].Value.ToString())));
}
return sites;
}
public static IList<string> GetIisAppPools()
{
List<string> pools = new List<string>();
using (DirectoryEntry poolRoot = new DirectoryEntry("IIS://localhost/W3SVC/AppPools"))
{
poolRoot.RefreshCache(); pools.AddRange(poolRoot.Children.Cast<DirectoryEntry>().Select(p => p.Name));
}
return pools;
}
}
Check out this blog post, most specifically, the last paragraph. It's very possible that it's a 32bit vs 64bit DLL compilation conflict
Both the customer and I were creating 32-bit .NET applications, and
the COM interface for the FTP runtime state is implemented in a
64-bit-only DLL. Once we both changed our projects to compile for
64-bit platforms, we were both able to get the code to run.
(Coincidentally, all I had was a 32-bit system when I wrote my
original blog, so I probably would have run into this sooner if I had
owned a 64-bit system way back then. ;-])
http://blogs.iis.net/robert_mcmurray/archive/2012/06/29/error-class-not-registered-0x80040154-when-querying-ftp-runtime-state.aspx
My app uses Nancy Selfhosting. When I launch it without admin rights I get a System.Net.HttpListenerException "Access Denied".
Here is the code:
static void Main(string[] args)
{
var nancyHost = new Nancy.Hosting.Self.NancyHost(new Uri("http://localhost:80/"));
nancyHost.Start();
Application.Run();
}
I have also tried different ports without success. Strangely, I dont get any Exceptions when launching a HttpListener that listens to the same Url. What could be causing this exception?
You need to set the self-host configuration to not rewrite the localhost route via the RewriteLocalhost property.
namespace NancyApplication1
{
using System;
using Nancy.Hosting.Self;
class Program
{
static void Main(string[] args)
{
var uri = new Uri("http://localhost:3579");
var config = new HostConfiguration();
// (Change the default RewriteLocalhost value)
config.RewriteLocalhost = false;
using (var host = new NancyHost(config, uri))
{
host.Start();
Console.WriteLine("Your application is running on " + uri);
Console.WriteLine("Press any [Enter] to close the host.");
Console.ReadLine();
}
}
}
}
I found this out by trying and failing a bit, but this page explains the reason behind.
Alternatively - From the documentation:
Note that on Windows hosts a HttpListenerException may be thrown with an Access Denied message. To resolve this the URL has to be added to the ACL.
Also but the port may need to be opened on the machine or corporate firewall to allow access to the service.
Add to ACL by running the following command:
netsh http add urlacl url=http://+:8080/ user=DOMAIN\username
if you need to remove from ACL:
netsh http delete urlacl url=http://+:8080/
You can hosting Nancy with Kestrel. It's really simple:
public void Main(string[] args)
{
var owinHost = new WebHostBuilder()
.UseStartup<Startup>()
.UseUrls("http://+:12345/")
.Build();
owinHost.Run();
}
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseOwin(x => x.UseNancy());
}
}
The only difficulty is to prepare all the dlls (30+) required. We should definitely use NuGet to resolve all the dependencies.
I want to mount vhd from my private container. After google I get that it is only possible through .net. I am more of a JAVA person. I need a batch script or code in c# (So that I can get an exe file) which can automatically run at startup and mount vhd. So I decided to create a console app in order to get exe file.(I have very less knowledge c#/Visual studio) I am using following C# console application to do this.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Threading;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure.Internal;
namespace WorkerRole1
{
public class WorkerRole : RoleEntryPoint
{
public override void Run()
{
// This is a sample worker implementation. Replace with your logic.
Trace.WriteLine("WorkerRole1 entry point called", "Starting");
MountDrive();
//while (true)
//{
// Thread.Sleep(10000);
// Trace.WriteLine("Working", "Information");
//}
}
public override bool OnStart()
{
// Set the maximum number of concurrent connections
ServicePointManager.DefaultConnectionLimit = 12;
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
return base.OnStart();
}
public void MountDrive()
{
string connectionStringSettingName = "DefaultEndpointsProtocol=http;AccountName=abc;AccountKey=xyz";
string azureContainerName = "vhds";
string vhdName = "myvhd.vhd";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionStringSettingName);
//CloudStorageAccount storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
LocalResource localCache = RoleEnvironment.GetLocalResource("MyAzureDriveCache");
CloudDrive.InitializeCache(localCache.RootPath, localCache.MaximumSizeInMegabytes);
Trace.WriteLine("RootPath =====" + localCache.RootPath);
Trace.WriteLine("MaximumSizeInMegabytes =====" + localCache.MaximumSizeInMegabytes);
// Just checking: make sure the container exists
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
blobClient.GetContainerReference(azureContainerName).CreateIfNotExist();
// Create cloud drive
CloudDrive myCloudDrive = storageAccount.CreateCloudDrive(
blobClient
.GetContainerReference(azureContainerName)
.GetPageBlobReference(vhdName)
.Uri.ToString()
);
Trace.WriteLine("Uri =====" + blobClient
.GetContainerReference(azureContainerName)
.GetPageBlobReference(vhdName)
.Uri.ToString());
try
{
myCloudDrive.Create(1024);
}
catch (CloudDriveException ex)
{
// handle exception here
// exception is also thrown if all is well but the drive already exists
}
string driveLetter = myCloudDrive.Mount(50, DriveMountOptions.Force);//Here It throws a Exception
Trace.WriteLine("Drive =====" + driveLetter);
for (int i = 0; i < 10; i++)
{
System.IO.File.WriteAllText(driveLetter + "\\" + i.ToString() + ".txt", "Test");
}
}
}
}
But I keep getting exception ERROR_DEVFABRIC_LOCAL_MOUNT_ONLY at
string driveLetter = myCloudDrive.Mount(50, DriveMountOptions.Force);
Please tell me where am I going wrong?
When RoleEnvironment.IsAvailable is set to false, this means you are not running in a Windows Azure Web/Worker/VM Role. The Windows Azure Drive only works when mounted in these roles (since it depends on RoleEnvironment).
More information can be found in the whitepaper.
ERROR_DEVFABRIC_LOCAL_MOUNT_ONLY means that when you are running locally you must mount the drive form development storage.
change the following line:
string connectionStringSettingName = "UseDevelopmentStorage=true";
or even better use RoleEnvironment.GetConfigurationSettingValue, like:
string connectionStringSettingName = RoleEnvironment.GetConfigurationSettingValue("DriveConnectionString");
and set the Setting in the service configuration (files)
How can I get all (physical) wwwroot directories (home directories) of an IIS with C# from the IIS metabase?
If you're using IIS6:
You need to add a reference to System.DirectoryServices in Visual Studio in the Add References .NET assemblies tab:
using System;
using System.DirectoryServices;
namespace ListRootAppPathsIIS6
{
class Program
{
static void Main(string[] args)
{
using (DirectoryEntry de = new DirectoryEntry("IIS://Localhost/W3SVC"))
{
foreach (DirectoryEntry w3svc in de.Children)
{
if (w3svc.SchemaClassName == "IIsWebServer")
{
string rootPath =
String.Format("IIS://Localhost/W3SVC/{0}/root", w3svc.Name);
using (DirectoryEntry root = new DirectoryEntry(rootPath))
{
string info = String.Format("{0} - {1} - {2}",
w3svc.Name,
w3svc.Properties["ServerComment"].Value,
root.Properties["Path"].Value);
Console.WriteLine(info);
}
}
}
}
Console.ReadLine();
}
}
}
If you're using IIS7:
Add a reference to C:\Windows\System32\inetsrv\Microsoft.Web.Administration.dll
using System;
using System.Linq;
using Microsoft.Web.Administration;
namespace ListRootAppPathsIIS7
{
class Program
{
static void Main(string[] args)
{
using(ServerManager serverManager = new ServerManager())
{
foreach (var site in serverManager.Sites)
{
var app = site.Applications.Where(a => a.Path == "/").First();
var vdir = app.VirtualDirectories.Where(v => v.Path == "/").First();
string info = String.Format("{0} - {1} - {2}",
site.Id,
site.Name,
Environment.ExpandEnvironmentVariables(vdir.PhysicalPath));
Console.WriteLine(info);
}
}
Console.ReadLine();
}
}
}
The first method (using System.Directoryservices) will work with IIS7 provided you've installed the IIS6 management compatibilities bits.
In both cases you need to be running as an Administrator.
You could call out to
C:\Windows\system32\inetsrv\appcmd.exe list vdir
(using the API to get the right folder of course). And filter for "site\" (for the default site "Default Web Site/". I assume there is some API to do this (but, certainly for older IIS versions, this was very script orientated, so would require dealing with IDispatch to invoke methods and property-gets).
This does require an elevated process on IIS7 and 7.5 (unless sufficient rights to IIS have been delegated).
I want to query for a list of services running as a specific user on a remote machine and then check the health of each. I'm building a custom console.
ServiceController.GetServices("machineName") returns an array of ServiceController objects for a particular machine.
This:
namespace AtYourService
{
using System;
using System.ServiceProcess;
class Program
{
static void Main(string[] args)
{
ServiceController[] services = ServiceController.GetServices();
foreach (ServiceController service in services)
{
Console.WriteLine(
"The {0} service is currently {1}.",
service.DisplayName,
service.Status);
}
Console.Read();
}
}
}
produces:
The Application Experience service is currently Running.
The Andrea ST Filters Service service is currently Running.
The Application Layer Gateway Service service is currently Stopped.
The Application Information service is currently Running.
etc...
Of course, I used the parameterless version to get the services on my machine.
To use the ServiceController method I'd check out the solution with impersonation implemented in this previous question: .Net 2.0 ServiceController.GetServices()
FWIW, here's C#/WMI way with explicit host, username, password:
using System.Management;
static void EnumServices(string host, string username, string password)
{
string ns = #"root\cimv2";
string query = "select * from Win32_Service";
ConnectionOptions options = new ConnectionOptions();
if (!string.IsNullOrEmpty(username))
{
options.Username = username;
options.Password = password;
}
ManagementScope scope =
new ManagementScope(string.Format(#"\\{0}\{1}", host, ns), options);
scope.Connect();
ManagementObjectSearcher searcher =
new ManagementObjectSearcher(scope, new ObjectQuery(query));
ManagementObjectCollection retObjectCollection = searcher.Get();
foreach (ManagementObject mo in retObjectCollection)
{
Console.WriteLine(mo.GetText(TextFormat.Mof));
}
}
You can use wmi for this (System.Management). You can also use ServiceController.GetServices().
This will check you system's service name with your desired service name which you can mention on parameter
namespace ServiceName
{
using System;
using System.ServiceProcess;
class Service
{
public static bool IsServiceInstalled(string serviceName)
{
ServiceController[] services = ServiceController.GetServices();
foreach (ServiceController service in services)
{
if (service.ServiceName == serviceName)
return true;
}
return false;
}
}
}