Проблема с виртуальным сервером IIS WMI
-
23-08-2019 - |
Вопрос
Мне было поручено выяснить, что вызывает проблему с этим фрагментом кода:
public static ArrayList GetEthernetMacAddresses()
{
ArrayList addresses = new ArrayList();
ManagementClass mc = new ManagementClass("Win32_NetworkAdapter");
// This causes GetInstances(options)
// to return all subclasses of Win32_NetworkAdapter
EnumerationOptions options = new EnumerationOptions();
options.EnumerateDeep = true;
foreach (ManagementObject mo in mc.GetInstances(options)) {
string macAddr = mo["MACAddress"] as string;
string adapterType = mo["AdapterType"] as string;
if (!StringUtil.IsBlank(macAddr) && !StringUtil.IsBlank(adapterType))
{
if (adapterType.StartsWith("Ethernet")) {
addresses.Add(macAddr);
}
}
}
return addresses;
}
На наших виртуальных серверах (Win2003) это работает при запуске как часть консольного приложения, но не из веб-службы, работающей в IIS (на том же компьютере).
Альтернативно я могу использовать этот код в веб-службе IIS (на виртуальном сервере) и получать правильные возвращаемые значения:
public static string GetMacAddresses()
{
ManagementClass mgmt = new ManagementClass(
"Win32_NetworkAdapterConfiguration"
);
ManagementObjectCollection objCol = mgmt.GetInstances();
foreach (ManagementObject obj in objCol)
{
if ((bool)obj["IPEnabled"])
{
if (sb.Length > 0)
{
sb.Append(";");
}
sb.Append(obj["MacAddress"].ToString());
}
obj.Dispose();
}
}
Почему работает второй, а не первый?
Почему только при вызове через веб-службу IIS на виртуальной машине?
Любая помощь будет оценена по достоинству.
ОБНОВЛЯТЬ: После долгих разговоров по телефону со всеми уровнями поддержки MS пришли к выводу, что это «как задумано».
Поскольку это находится на уровне драйвера виртуального сетевого адаптера, ответ заключался в том, что нам следует изменить наш код, «чтобы обойти проблему».
Это означает, что вы не можете надежно протестировать код на виртуальных серверах, если у вас нет того же кода, который вы используете на физических серверах, поскольку мы не можем гарантировать, что серверы являются точными копиями...
Решение
Хорошо, поэтому я написал этот код, чтобы проверить проблему:
public void GetWin32_NetworkAdapter()
{
DataTable dt = new DataTable();
dt.Columns.Add("AdapterName", typeof(string));
dt.Columns.Add("ServiceName", typeof(string));
dt.Columns.Add("AdapterType", typeof(string));
dt.Columns.Add("IPEnabled", typeof(bool));
dt.Columns.Add("MacAddress", typeof(string));
//Try getting it by Win32_NetworkAdapterConfiguration
ManagementClass mgmt = new ManagementClass("Win32_NetworkAdapter");
EnumerationOptions options = new EnumerationOptions();
options.EnumerateDeep = true;
ManagementObjectCollection objCol = mgmt.GetInstances(options);
foreach (ManagementObject obj in objCol)
{
DataRow dr = dt.NewRow();
dr["AdapterName"] = obj["Caption"].ToString();
dr["ServiceName"] = obj["ServiceName"].ToString();
dr["AdapterType"] = obj["AdapterType"];
dr["IPEnabled"] = (bool)obj["IPEnabled"];
if (obj["MacAddress"] != null)
{
dr["MacAddress"] = obj["MacAddress"].ToString();
}
else
{
dr["MacAddress"] = "none";
}
dt.Rows.Add(dr);
}
gvConfig.DataSource = dt;
gvConfig.DataBind();
}
Когда он запускается на физическом компьютере IIS, я получаю следующее:Физический сервер IIS http://img14.imageshack.us/img14/8098/physicaloutput.gif
Тот же код на виртуальном сервере IIS:Виртуальный сервер http://img25.imageshack.us/img25/4391/virtualoutput.gif
Видите разницу? Это на первой линии.Виртуальный сервер не возвращает строку «AdapterType».Вот почему исходный код дал сбой.
Это наводит на интересную мысль.Если виртуальный сервер должен быть «виртуальным» представлением реального сервера IIS, почему он не возвращает те же значения?
Другие советы
Почему они возвращают разные результаты?Возможно, из-за разных учетных записей пользователей вы получите разные результаты при запуске с консоли и из службы.
Почему (1) не работает, а (2) работает?Возможно ли, что нулевой результат для адаптераType возвращает нулевое значение?Если да, то будет ли код обрабатывать это условие?