We run various jobs using a Windows 2003 server. Some of these jobs send app pool commands to web servers running IIS 6 (recycle, start, stop). Now we have a Windows 2008 web server running IIS 7, and we want to send the same commands. This is all done using C#.
This is the code we use to send commands for IIS 6:
var methodToInvoke = "Stop"; // could be "Stop", "Start", or "Recycle"
var co = new ConnectionOptions
{
Impersonation = ImpersonationLevel.Impersonate,
Authentication = AuthenticationLevel.PacketPrivacy
};
var objPath = string.Format("IISApplicationPool.Name='W3SVC/AppPools/{0}'", appPoolName);
var scope = new ManagementScope(string.Format(#"\\{0}\root\MicrosoftIISV2", machineName), co);
using (var mc = new ManagementObject(objPath))
{
mc.Scope = scope;
mc.InvokeMethod(methodToInvoke, null, null);
}
This code doesn't work for IIS 7 due to underlying changes, so we're currently trying this:
using (ServerManager serverManager = ServerManager.OpenRemote(machineName))
{
var appPool = serverManager.ApplicationPools[appPoolName];
if (appPool != null)
{
appPool.Stop(); // or app.Start() or app.Recycle()
serverManager.CommitChanges();
}
}
The above code works fine on my workstation, which runs Windows 7 (and, thus, IIS 7.5). However, it does not work when I deploy this code to our application server. It get this error:
System.InvalidCastException:
Unable to cast COM object of type 'System.__ComObject' to interface type
'Microsoft.Web.Administration.Interop.IAppHostWritableAdminManager'.
This operation failed because the QueryInterface call on the COM component for the
interface with IID '{FA7660F6-7B3F-4237-A8BF-ED0AD0DCBBD9}' failed due to the following error:
Interface not registered (Exception from HRESULT: 0x80040155).
From my research, this is due to the fact that IIS 7 is not available on the Windows Server 2003 server. (I did include the Microsoft.Web.Administration.dll file.)
So my questions are:
Is it possible for the above code for IIS 7 to work at all from a Windows 2003 server?
If no to #1, is there a better way of doing this?
From reading around it doesn't appear to be possible to do what you're looking for. It's not enough to include the dll files.
According to http://forums.iis.net/t/1149274.aspx..
In order to use Microsoft.Web.Administration you need to have IIS installed, at the bare minimum you need to install the Configuration API's which are brought through installing the Management Tools.
Unfortunately there is no SDK that enables this and it has several dependencies on other components that wouldn't let you just take it to another machine and make it work (such as COM objects, DLL's, etc).
I'd be interested in knowing if you've found a way round this.
Thanks
Try controlling the IIS pool with DirectoryEntry instead.
See this topic:
Check the status of an application pool (IIS 6) with C#
Microsoft.Web.Administration, it relies on System.Web.dll which was provided by framework 4, not client profile.
Related
For a project I am working on I have to interface with a third-party DCOM library. I started with COM interop and this worked just fine locally, then I switched to DCOM and now I keep getting an unauthorized access exception (0x80070005) when trying to bind an event handler to the exposed event. Below is a summary of what I do in code:
public void connect(string server)
{
object dcomObj = null;
var guidB = Guid.Parse("c8c1f57f-0d7c-40b3-b17c-2eac12512006");
var typ = Type.GetTypeFromCLSID(guidB, server, true);
object[] url = { new UrlAttribute(server) };
dcomObj = Activator.CreateInstance(typ, null, url);
user = (RemoteObjectInterface)dcomObj ;
user.getState(); //works fine locally and remotely
user.stateChange += this.User_StateChange; //only works locally
}
I tried setting every permission I could find on the web but I without success. Does anyone have an Idea as to why only the binding of events fails?
RemoteObjectInterface inherits from both the IRemoteObjectEvents and the IRemoteObject. These interface come from the interop ms generated for me when I imported the original dll.
The server is a windows server 2003 VM in virtual box with a bridged network adapter. On the server Everyone is admin (including guest) and limits are set to full access and defaults are set to full access. I am building and running my code on c# .net 4.5.2 from a Windows 10 machine using visual studio 2015.
The sample application that comes with the SDK also fails when I try to use it remotely, the server registers the user but the sample application never realizes that it logged in successfully, I suspect that this behaviour is related to the failing of event binding.
TL;DR I can get and use a remote object but when I try to add an event handler I get an unauthorized exception (0x80070005), why does this happen on event binding? And how do I fix it?
I had the same problem.
For me the issue was I had a AD running on the same device and had to disable the loopback check in the registry. Other solution could be better I assume, but for me the registry hack will do.
I am trying to write a WCF service that would run in IIS 8 and would use the Expression Encoder SDK to open a video file and then encode it as a WMV. The following code works fine when it's in a desktop application I wrote earlier.
Job job = new Job();
job.ApplyPreset(Preset.FromFile(HttpRuntime.AppDomainAppPath + "Profiles\\" + profile + ".xml"));
job.CreateSubfolder = false;
job.SaveJobFileToOutputDirectory = false;
job.OutputDirectory = Path.GetDirectoryName(input);
MediaItem item;
item = new MediaItem(input);
item.OutputFileName = "{Original file name}.wmv";
job.MediaItems.Add(item);
job.EncodeProgress += new EventHandler<EncodeProgressEventArgs>(job_EncodeProgress);
job.EncodeCompleted += new EventHandler<EncodeCompletedEventArgs>(job_EncodeCompleted);
job.Encode();
But when I try to run this code in a WCF service running on IIS I get the following error
The type initializer for 'Microsoft.Expression.Encoder.SkuManager' threw an exception.
at Microsoft.Expression.Encoder.SkuManager.IsFeaturedSupported(Feature feature)
at MS.Internal.Expression.Encoder.FastProperties.FastPropertyCreate.ShouldAddProp(IFastProperty property, PropertyType propType)
at MS.Internal.Expression.Encoder.FastProperties.FastPropertyCreate.CreatePropertiesArray[T](Type classType, PropertyType propType)
at MS.Internal.Expression.Encoder.FastProperties.FastPropertyCreate.GetProperties[T](PropertyType propType)
at MS.Internal.Expression.Encoder.Persistence.JobPersistence.GetJobFilePropertiesCore[T](JobPropertiesMode mode)
at MS.Internal.Expression.Encoder.Persistence.JobPersistence.GetJobFileProperties[T](JobPropertiesMode mode)
at Microsoft.Expression.Encoder.JobBase.CreateDefaultValues(JobBase job)
at Microsoft.Expression.Encoder.JobBase..ctor()
at Microsoft.Expression.Encoder.Job..ctor()
I can run this code in a regular desktop application on the server, but not in a WCF service running on the same machine.
It turns out it was a permissions problem in IIS.
In order for any program to use the Expression Encoder SDK it needs to be running under an identity that can access the Expression Encoder program installed on the machine.
So in IIS the "ApplicationPoolIdentity" identity that the WCF service was running on didn't have permissions to launch the Expression Encoder program that was installed on the machine by the "Administrator" account.
To fix this you can do one of two things.
When you are installing Expression Encoder allow "All Users" to be able to launch it.
When you install your WCF service on IIS make sure it's running in an application pool that can launch Expression Encoder
I had this same issue in an iis8 web site (not hosting any wcf service tho) and yes i also discovered that IIS needs to run under permissions that can execute expression encoder. BUT one day it just stopped working and started throwing the same error:
"The type initializer for 'Microsoft.Expression.Encoder.SkuManager' threw an exception."
Even though the AppPool's identity was a good one. I pulled my hair out for a day or so then realized that somehow the binaries that VS copies to the local bin directory didn't want to be run in IIS. Somehow corrupted or dll mismatch with expression's installation???. I had to delete the contents of the bin directory and, then VS replaced them, and it worked. Setting CopyLocal to false for those references did not work (conceivably it might be nice to just use from the gac).
I currently have an application written in C# that adds a website to IIS7 on the current machine and it works perfectly, the code is as follows
var iisManager = new ServerManager();
var sites = iisManager.Sites;
var site = sites.Add("WebsiteName", "C:\Website", 80);
var application = site.Applications[0];
application.ApplicationPoolName = appPool;
iisManager.CommitChanges();
I have to create a version of this code that will add a website to IIS on a remote machine located on the same network. That code is as follows.
var iisManager= ServerManager.OpenRemote("machineName"); //I've also tried machines IP
var sites = iisManager.Sites["Default Web Site"];
var site = Sites.Applications.Add("WebsiteName", "C:\Website", 80);
site.ApplicationPoolName = appPool;
iisManager.CommitChanges();
When machineName is the machine executing the code, it adds the website to IIS. However when machineName is the remote machine, I get the following exception
Retrieving the COM class factory for remote component with CLSID {2B72138B-3F5E-4502-8052-803546CE3364} from "remote machine name" failed due to the following error: 80070005 "remote machine"
The exception occurs when executing
var iisManager= ServerManager.OpenRemote("machineName");
Before executing the above code I use impersonation to impersonate an Administrator.
I can remote into the machine and even create a file on the machine using C# code.
I assume there is an issue with permissions on the remote machine or it could be because it's a VM, I'm really not sure.
The code 80070005, is fairly general and represents restricted access but I don't understand why considering I am impersonating an Admin.
I am executing the code on a Windows 7 sp1 x64 machine and the remote VM is running Windows Server 2008 sp2 x64.
If anyone has any ideas how to fix this issue or another way to add a website to IIS on a remote machine, I'd love to hear them.
Thanks
First of all you run your visual studio as administrator and OFF windows firewall of server then see it will work for Remote server
I have one console application which list website binding in IIS
using (var directoryEntry = new DirectoryEntry("IIS://localhost/w3svc/" + GetWebSiteId())) {
var bindings = directoryEntry.Properties["ServerBindings"];
}
I call this console application from ASP.NET via process
var process = new Process {
StartInfo = new ProcessStartInfo {
FileName = "c:/app.exe",
Arguments = "check",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
Everything works fine on development machine under Widows 7 / IIS 7.5, but when i test on Windows 2012 / IIS 8 im getting "Access is denied" error.
Error log
"System.Runtime.InteropServices.COMException (0x80070005): Access is denied.
at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
at System.DirectoryServices.DirectoryEntry.Bind()
at System.DirectoryServices.DirectoryEntry.get_IsContainer()
at System.DirectoryServices.DirectoryEntries.ChildEnumerator..ctor(DirectoryEntry container)
at System.DirectoryServices.DirectoryEntries.GetEnumerator()
at IISSubdomainManagement.Program.GetWebSiteId()
at IISSubdomainManagement.Program.TotalBindings()
at IISSubdomainManagement.Program.Main(String[] args)"
p.s Application pool identity is "ApplicationPoolIdentity"
I forget to mention, my console app works fine on my server when I run it from CMD
You need to give permission to the IUSR account to access and execute C:\app.exe. This link should provide you with the necessary information to find the right account.
You have probably granted the permission to 'ApplicationPoolIdentity' rather than to the virtual account that actually corresponds to that Application Pool. Read through the Microsoft's description or search online for virtual identity IIS, etc.
On your development machine, you probably have some sort of Full Admin rights, so it is not as restricted.
If you still have problems after that, I would recommend replicating the error with a Process Monitor running, so you can see exactly what process is accessing which resource with which identity. However, I would recommend replicating the issue on your development machine rather than running Process Monitor on the production. It takes a little bit of learning to be able to run it efficiently.
In IIS 7/8 go Control Panel / Program And Features / Turn Windows features on or off, and check all items from: Web Managment Tools, (it's include: IIS Managment Service, II 6 Managment Compatibility)
This Solution worked for me ==>
http://blogs.msdn.com/b/jpsanders/archive/2009/05/13/iis-7-adsi-error-system-runtime-interopservices-comexception-0x80005000-unknown-error-0x80005000.aspx?CommentPosted=true#commentmessage
I am trying to connect to IIS programmatically. I find there are a ton of examples online, but I can't seem to get any to work and have tried quite a few variations
Every time I try the following code the object that is returned has this error for each property: ..."threw an exception of type 'System.Runtime.InteropServices.COMException'"
using System.DirectoryServices;
String serverName = "serverName";
DirectoryEntry IIS = new DirectoryEntry("IIS://" + serverName + "/W3SVC");
IIS = new DirectoryEntry("IIS://" + serverName + "/W3SVC", "administrator", "mypassword");
IIS = new DirectoryEntry("IIS://" + serverName + "/W3SVC/1/ROOT", "administrator", "mypassword");
I am using Windows Directory user accounts and I have a bunch of sites running on IIS. I am trying this code on a windows xp development machine trying to connect to a windows 2008 Server with IIS 7. Anyone know what I am doing wrong?
Your account may not have launch permissions on the COM object wrapping the IIS calls. You may need to try adding yourself to the admin group on the box hosting IIS to get this to work.
Make sure you have the IIS6 management compatibility feature installed on the target server- you can't do remote management via ADSI on IIS7 without it.
Make sure that IIS is installed on your client machine - your program will throw a System.Runtime.InteropServices.COMException if it isn't installed.
This counts when you are looking at IIS on a remote machine too, the machine running your app will need IIS too.
EDIT: Also, I've recently discovered an assembly specifically for connecting to and configuring IIS7 - Microsoft.Web.Administration. Might be worth looking at whether you have access to this (or can get access, it should be on the machine with IIS7 in any case) and see what it can do. I'm afraid I've not used it myself, so I can't tell you if it'll do what you want, but it's another option to look into.
Finally, there's the option of System.Management and WMI scripts.
Dim scope As New Management.ManagementScope("\\" & server & "\root\MicrosoftIISv2")
scope.Connect()
Dim query As New Management.ObjectQuery("select * from IISWebVirtualDirSetting")
Dim searcher As New Management.ManagementObjectSearcher(scope, query)
For Each obj As Management.ManagementObject In searcher.Get()
DoSomethingWith(obj)
Next
The list of properties on obj is at http://msdn.microsoft.com/en-us/library/ms525005.aspx, there's also some more different queries you can run - just dig around on MSDN for more.