(编辑)情节变厚:相同的代码(无需模拟!)从 Windows 7 客户端成功运行,但不是从 Windows 2008 R2 客户端!这是有问题的代码。(原始消息遵循以下代码。)
var entry = new DirectoryEntry("IIS://" + tbHost.Text + "/W3SVC", tbUsername.Text, tbPassword.Password);
foreach (DirectoryEntry site in entry.Children)
{
Console.Write("Site {0}\n", site.Name);
foreach (PropertyValueCollection prop in site.Properties)
Console.Write("{0}={1}\n", prop.PropertyName, prop.Value);
}
我在这里读到,对于 IIS 提供程序,您在创建DirectoryEntry
对象时无法传递凭据。你必须做模仿。因此,我尝试了以下代码,但是当我尝试读取属性时,仍然收到带有“未知错误(0x80005000)”文本的 COMException,就像我之前尝试为DirectoryEntry
构造函数传递用户名和密码时所做的一样。这是纲要:
LogonUser()
成功,凭据正常。在我发现我必须使用LOGON32_LOGON_NEW_CREDENTIALS
而不是LOGON32_LOGON_INTERACTIVE
.- 远程计算机不在同一个域中。实际上,它根本不在域中。事实上,我把它的名字放在了客户的
hosts
文件中,这样我就可以通过名字找到它了。 - 在目标机器上运行Metabase Explorer显示我想要读取的密钥确实存在。(见文章末尾的图片。)
.
const int LOGON32_LOGON_INTERACTIVE = 2;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_PROVIDER_WINNT50 = 3;
const int LOGON32_PROVIDER_WINNT40 = 2;
const int LOGON32_PROVIDER_WINNT35 = 1;
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int LogonUser(String lpszUserName, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
[DllImport("kernel32.dll")]
extern static int GetLastError();
(...)
IntPtr myToken = IntPtr.Zero;
if (LogonUser(tbUsername.Text, tbHost.Text, tbPassword.Password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref myToken) == 0)
{
int causingError = GetLastError();
throw new System.ComponentModel.Win32Exception(causingError);
}
WindowsImpersonationContext myMission = WindowsIdentity.Impersonate(myToken);
string mbUri = "IIS://" + tbHost.Text + "/MimeMap";
DirectoryEntry myDirEntry = new DirectoryEntry(mbUri);
Console.Write("{0}\n", myDirEntry.Properties["KeyType"]);
myDirEntry.Close();
myMission.Undo();
if (myToken != IntPtr.Zero)
CloseHandle(myToken);