My application is accessing MicrosoftIIsv2 namespace in local and remote system.
And the error that I am receiving is:
Win32:Access Denied at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
Here is the code snippet (Local Host)
ConnectionOptions options = new ConnectionOptions();
ObjectQuery query;
ManagementScope scope;
options.Authentication = AuthenticationLevel.PacketPrivacy;
options.Impersonation = ImpersonationLevel.Impersonate;
options.EnablePrivileges = true;
scope = new ManagementScope("root\\MicrosoftIISv2",options);
scope.Connect();
query = new ObjectQuery("SELECT * FROM IIsApplicationPool");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection objectCollection = searcher.Get();
I have been on this problem for way too long. Here are the number of solutions to this problem that I have found on internet.
Modifying connectionOption:
options.Authentication = AuthenticationLevel.PacketPrivacy;
options.EnablePrivileges = true;
This doesn't seem to solve the problem.
Modifying Security privileges in MicrosoftIISv2 namespace in wmimgmt.msc for both local and remote host.
(Had high hopes with this thing but it didn't change the result)
Changed Privileged rights in Access permission and Launch and Activation Permission in dcomcnfg for both host.
(This neither changed the result)
Allow my Visual Studio to run as Administrator.
Voila! Now I can access and retrieve IIS details from my Local Host.
But when this code running(as Administrator) in local computer tries to access MicrosoftIIsv2 namespace in remote computer with Administrator credential I again get Win32:Access Denied.
Can someone please tell me what to do .
Thank you in advance.
Update 1:As per MSDN Win32:Access Denied is received when->
Requests that use console applications in the Windows System32 directory, such as Cmd.exe, are denied access unless the remote user making the request is an authenticated member of the Administrators group.
This would mean that I have to change ACL of "inetmgr.exe" on each remote computer (which exist in system32 directory) which would be a hectic task to perform.
Troubleshooting Common IIS Errors.
Related
Below is my code to read IIS applications in a remote machine which in in domain using WMI.
var connOptions = new ConnectionOptions
{
Username = "USERNAME",
Password = "PASSWORD",
Authority = "ntlmdomain:DOMAINNAME",
EnablePrivileges = true,
Impersonation = ImpersonationLevel.Impersonate
};
var scope = new ManagementScope(#"\\SERVERNAME\root\WebAdministration", connOptions);
var WMIQuery = new ObjectQuery("SELECT * FROM Application");
var searcher = new ManagementObjectSearcher(scope, WMIQuery);
//Connect to WMI
scope.Connect();
//Write the list of Applications info
foreach (ManagementObject queryObj in searcher.Get())
{
Console.WriteLine("SiteName: {0} - {1}", queryObj["SiteName"], queryObj["Path"]);
}
It fails with following exception:
System.Management.ManagementException was caught
Message=Access denied
Source=System.Management
StackTrace:
at System.Management.ManagementException.ThrowWithExtendedInfo(ManagementStatus errorCode)
at System.Management.ManagementObjectSearcher.Get()
at Program.Main(String[] args)
InnerException:
Remedies I tried:
I followed the suggestion given in Handling Remote Connections Under UAC but with no success.
Quoting it:
If your computer is part of a domain, connect to the target computer
using a domain account that is in the local Administrators group of
the remote computer. Then UAC access token filtering will not affect
the domain accounts in the local Administrators group. Do not use a
local, nondomain account on the remote computer, even if the account
is in the Administrators group.
Added and assigned full control to the user in Computer Management -> Services and Applications -> WMI control -> View properties -> Navigate to Root/WebAdministration -> Security.
Solved by setting Authentication property of ConnectionOptions to 'AuthenticationLevel.PacketPrivacy'
Details at : Access Denied for WMI
please help me as i need to kill/ restart a process remotely.
I have tried this but no luck for me. Error was - "Couldn't connect to remote machine"
Process[] prs = Process.GetProcesses("SERVERNAME");
foreach (Process pr in prs)
{
if (pr.ProcessName == "process")
{
pr.Kill();
}
}
I also try this one but still doesn't work and got this error:
"Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"
ManagementScope scope = new ManagementScope("\\\\SERVERNAME\\root\\cimv2");
scope.Connect();
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Process WHERE Name='process'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
ManagementObjectCollection objectCollection = searcher.Get();
foreach (ManagementObject managementObject in objectCollection)
{
managementObject.InvokeMethod("Terminate", null);
}
I hope someone has a solution for this.Thanks in advance!
Well, the errors are actually telling you exactly what's wrong. Your application is failed connecting to the remote machine. This can happen for some reasons:
The remote computer is unavailable (not exists)
The remote computer doesn't have WMI open for remote connection, or it's firewall-ed on the remote machine or on the way.
You don't have a permission to perform this action. Since i don't see anywhere in your code impersonation, then the connection will be using the current process token (which account it is? depends on your configuration on the application pool, or in your web.config if you use tag, by default - it's NT AUTHORITY). You probably don't have permissions to access the remote machine using WMI with the credentials you're running at. It can be solved by impersonation in your code, in the web.config, or in the application pool settings to an account which has the sufficient permission (if you're in domain, ask your IT department for an account).
Good luck.
Add this to your web.config with the appropriate account (the one with permissions).
<identity impersonate="true" userName="UserWithPermissions" password="pw" />
I want to install a MSI package on a remote computer.
The local and remote computer both are members of a domain called "adn.lan"
and the user/password I pass as parameter to connection has full access to remote machine.
When I set connection.Authority to "ntdlmdomain:adran.lan" the return parameter shows the "Invalid parameter" and when I leave it as null and make it as remarked, the connect() would connect successfully but when it try to install package the return parameter shows that the addressed package is inaccessible.
Here is the code I've tried with.
ConnectionOptions connection = new ConnectionOptions();
//connection.Authority = "ntdlmdomain:adn.lan"; // "kerberos:" + domain + #"\" + machine;
connection.Username = username;
connection.Password = password;
//connection.Impersonation = ImpersonationLevel.Identify ;
connection.Authentication = AuthenticationLevel.Packet;
ManagementScope scope = new ManagementScope("\\\\RemoteMachineName\\root\\CIMV2", connection);
scope.Connect();
ManagementPath p = new ManagementPath("Win32_Product");
ManagementClass classInstance = new ManagementClass(scope, p, null);
ManagementBaseObject inParams = classInstance.GetMethodParameters("Install");
inParams["AllUsers"] = true;
inParams["Options"] = string.Empty;
inParams["PackageLocation"] = "\\\\LocalMachineName\\Share\\Prescription.msi";
ManagementBaseObject outParams = classInstance.InvokeMethod("Install", inParams, null);
string retVal = outParams["ReturnValue"].ToString();
When I set theconnection.Impersonation to Identity the result would be "Access denied".
If I understand your question and followup comment, you found that it would not work when the package path was on a different machine than the target machine (i.e. a UNC path, normally accessible from the target machine). But the installation works when you copy the package to the target machine and pass a local path on the target machine.
I believe the reason for the failure is due to the nature of DCOM impersonation levels.
Impersonate allows you to use the credentials of the caller on the target machine -- but not to connect from the target machine to another machine. To make that second hop using the same credentials requires Delegate level. (Problem is, that has security risks, so all the guidance says "warning warning warning" and everything makes it hard by default.)
When you asked the target machine to access the installation package on a separate network location, that was a "second hop" which would require credentials, but impersonate meant you could only use your credentials on the target machine, not passed from there to the remote file location.
TechNet has a nice summary of the impersonation levels, see Table 6.6 DCOM Impersonation Levels at the top of WMI Security Settings.
p.s. For fun, you might see if there's a way to do it without copying to the target machine. If you could find a way to expose the installation package file to the network in a way that allowed anonymous access, I wonder if that second hop would be allowed since only anonymous credentials were needed? Not sure though. And there might be an awful lot of guessing and testing going on, if you're anything like me : )
I have a C# exe that needs to be run using WMI and access a network share. However, when I access the share I get an UnauthorizedAccessException. If I run the exe directly the share is accessible. I am using the same user account in both cases.
There are two parts to my application, a GUI client that runs on a local PC and a backend process that runs on a remote PC. When the client needs to connect to the backend it first launches the remote process using WMI (code reproduced below). The remote process does a number of things including accessing a network share using Directory.GetDirectories() and reports back to the client.
When the remote process is launched automatically by the client using WMI, it cannot access the network share. However, if I connect to the remote machine using Remote Desktop and manually launch the backend process, access to the network share succeeds.
The user specifed in the WMI call and the user logged in for the Remote Desktop session are the same, so the permissions should be the same, shouldn't they?
I see in the MSDN entry for Directory.Exists() it states "The Exists method does not perform network authentication. If you query an existing network share without being pre-authenticated, the Exists method will return false." I assume this is related? How can I ensure the user is authenticated correctly in a WMI session?
ConnectionOptions opts = new ConnectionOptions();
opts.Username = username;
opts.Password = password;
ManagementPath path = new ManagementPath(string.Format("\\\\{0}\\root\\cimv2:Win32_Process", remoteHost));
ManagementScope scope = new ManagementScope(path, opts);
scope.Connect();
ObjectGetOptions getOpts = new ObjectGetOptions();
using (ManagementClass mngClass = new ManagementClass(scope, path, getOpts))
{
ManagementBaseObject inParams = mngClass.GetMethodParameters("Create");
inParams["CommandLine"] = commandLine;
ManagementBaseObject outParams = mngClass.InvokeMethod("Create", inParams, null);
}
Having followed the link suggested by Isalamon above (thanks) I followed Jestro's advice and have rewritten using psexec.exe (which can be downloaded from http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx) instead of WMI. It feels like a bit of a kludge to do it this way, but it seems to work.
New code for anyone who is experiencing similar problems:
Process proc = new Process();
proc.StartInfo.FileName = "PsExec.exe";
proc.StartInfo.Arguments = string.Format("\\\\{0} -d -u {1}\\{2} -p {3} {4}",
remoteHost,
domain,
username,
password,
commandLine);
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.UseShellExecute = false;
proc.Start();
WMI just uses impersonation when executing the remote process, which does not give you network access. If you are ok going outside managed code, you can just map a UNC path in the remote process WMI started using whatever credentials you want. Then, you have the network access you want. I use NetUseAdd and NetUseDel from netapi32.dll to map the UNC path. See http://pinvoke.net/ for details on the using the APIs.
I know you've sorted it by using PSEXEC, which is a fantastic program, but if you did want to go back to WMI, have you tried enabling the following in your ConnectionOptions:
The flag EnablePrivileges
setting the Impersonation to ImpersonationLevel.Impersonate
Which does the following:
Gets or sets a value indicating whether user privileges need to be
enabled for the connection operation. This property should only be
used when the operation performed requires a certain user privilege to
be enabled (for example, a machine restart).
http://msdn.microsoft.com/en-us/library/system.management.connectionoptions.enableprivileges.aspx
Gets or sets the COM impersonation level to be used for operations in this connection.
http://msdn.microsoft.com/en-us/library/system.management.connectionoptions.impersonation.aspx
I think they should tell your WMI to actually allow the program to have the correct credentials and thus access your network share
You can write all you commands to batch file to the remote machine which includes net use (no need to use a drive letter) to do an authentication. Works fine that way. I am still working on an alternative.
I have two XP Pro SP3 machines. I disabled the firewall in both. The workgroup name is WORKGROUP. I have an administrator account with identical username/password in both. My code to connect is the following:
ConnectionOptions options = new ConnectionOptions();
options.Username = myUsername;
options.Password = myPassword;
options.Authority = "ntdlmdomain:WORKGROUP"; // Commenting this or not makes no difference
ManagementScope scope = new ManagementScope(String.Format("\\\\{0}\\{1}", hostname, Namespace), options);
scope.Connect();
I always get a System.UnauthorizedAccessException with the text:
"Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"
The above code works between two machines that are part of the same AD domain. What am I doing wrong?
This question, which is all about WMI remote access and nothing to do with C# (I expect you would get the same error with other WMI query tools - for example, WBEMtest), has come up multiple times on Server Fault: see http://www.google.com/search?q=site%3Aserverfault.com+wmi+access+denied&ie=utf-8&oe=utf-8&aq=t
This is a common WMI issue. See the WMI FAQ, or the documentation on securing remote WMI connections.
Adjust the local security policy and services to allow everyone and also in-folder options to disable sharing. After doing this I was able to connect to two XP machines in the workgroup by WMI.