Почему IUpdateSession::WebProxy не работает в Windows 10?
У меня есть некоторый внутренний код, который выполняет сканирование Центра обновления Майкрософт с помощью API Центра обновления Windows. Поскольку некоторые клиенты не имеют прямого доступа в Интернет, я явно установил WebProxy
свойство указывать на наш локальный прокси-сервер. Во время тестирования (в Windows 7) это работало идеально. Сейчас я тестирую его в Windows 10 (см. Сноску 1), и кажется, что настройки прокси игнорируются.
Клиент Windows Update был значительно переработан в Windows 10, поэтому, возможно, это ошибка или недокументированное ограничение в новой версии клиента, но с другой стороны, у меня мало предыдущего опыта использования COM, поэтому я могу что-то делать не так,
Наблюдаемые результаты, используя тестовый код, размещенный ниже:
Код работает в Windows 7 как требуется, независимо от того, в каком контексте безопасности он выполняется, и независимо от того, имеет ли клиент прямой доступ к Интернету и / или прокси-сервер, настроенный в настройках Интернета пользователя.
Код также работает на Windows 10, при условии, что клиент имеет прямой доступ в Интернет.
Код в основном работает в Windows 10, если у клиента нет прямого доступа к Интернету, но у пользователя, который его запускает, есть подходящий прокси-сервер, настроенный в его настройках Интернета. (См. Сноску 2.)
Код не работает в Windows 10, если у клиента нет прямого доступа в Интернет, а у пользователя, который его запускает, не настроен подходящий прокси-сервер. Вместо подключения к прокси-серверу, указанному в коде, он пытается подключиться к ряду внешних IP-адресов; после истечения времени ожидания всех попыток подключения возвращается 0x80072ee2, ERROR_INTERNET_TIMEOUT, в показанной строке. (Я могу получить очень похожее поведение в Windows 7, пропустив часть кода, которая устанавливает прокси-сервер.)
Кроме того, если я намеренно изменю URL-адрес прокси-сервера в коде, чтобы он указывал на несуществующий сервер, код перестает работать в Windows 7, как и ожидалось, но поведение в Windows 10 остается неизменным. Так что это действительно выглядит так, как будто Windows Update просто игнорирует WebProxy
имущество. (Свойство устанавливается; я могу прочитать его обратно из IUpdateSession
объект.)
Изменение режима загрузки при оптимизации доставки не помогает. Я пробовал все различные режимы, которые доступны через групповую политику. Добавление косой черты в прокси-URL нарушало код для Windows 7 и не имело никакого значения для Windows 10. Использование чистого DNS-имени вместо URL-адреса работало в Windows 7, но не имело никакого значения в Windows 10.
Поскольку код в конечном итоге предназначен для того, чтобы стать частью системной службы и / или запускаться удаленно, настройка параметров прокси-сервера на уровне пользователя не является идеальным вариантом, хотя я мог бы воспользоваться этим, если нет другого решения.
Это код, который я тестировал, урезанная версия исходного кода. Тестовый код фактически не обрабатывает результаты, если таковые имеются, поскольку проблема возникает до этого момента. Я скрыл реальное DNS-имя нашего прокси-сервера, но URL-адрес имеет следующую форму. Любой, кто хочет протестировать код в своей среде, конечно же, в любом случае должен будет указать его на своем прокси.
#include <windows.h>
#include <wuapi.h>
#include <stdio.h>
#define stringize1(x) L#x
#define stringize(x) stringize1(x)
#define fail() fail_fn(L"Fatal error at line " stringize(__LINE__))
void fail_fn(wchar_t * msg)
{
wprintf(L"%s\n", msg);
exit(1);
}
int wmain(int argc, wchar_t ** argv)
{
IUpdateSearcher* updateSearcher;
IWebProxy* webProxy;
IUpdateServiceManager2* serviceManager;
IUpdateServiceRegistration* serviceRegistration;
IUpdateSession* updateSession;
ISearchResult* results;
BSTR searchString, proxyString, bstrServiceID;
HRESULT hr;
if((hr = CoInitialize(NULL)) != S_OK) {
fail();
}
hr = CoCreateInstance(&CLSID_UpdateServiceManager, NULL, CLSCTX_INPROC_SERVER,
&IID_IUpdateServiceManager2, (void **)&serviceManager);
if (hr != S_OK) fail();
bstrServiceID = SysAllocString(L"7971f918-a847-4430-9279-4a52d1efe18d");
serviceManager->lpVtbl->AddService2(serviceManager, bstrServiceID,
asfAllowPendingRegistration | asfRegisterServiceWithAU,
NULL, &serviceRegistration);
if (hr != S_OK) fail();
hr = CoCreateInstance(&CLSID_UpdateSession, NULL, CLSCTX_INPROC_SERVER,
&IID_IUpdateSession, (LPVOID*)&updateSession);
if (hr != S_OK) fail();
hr = CoCreateInstance(&CLSID_WebProxy, NULL, CLSCTX_INPROC_SERVER,
&IID_IWebProxy, (void **)&webProxy);
if (hr != S_OK) fail();
hr = webProxy->lpVtbl->put_AutoDetect(webProxy, VARIANT_FALSE);
if (hr != S_OK) fail();
proxyString = SysAllocString(L"http://proxy.contoso.co.nz:80");
if (proxyString == NULL) fail();
hr = webProxy->lpVtbl->put_Address(webProxy, proxyString);
if (hr != S_OK) fail();
hr = updateSession->lpVtbl->put_WebProxy(updateSession, webProxy);
if (hr != S_OK) fail();
hr = updateSession->lpVtbl->CreateUpdateSearcher(updateSession, &updateSearcher);
if (hr != S_OK) fail();
hr = updateSearcher->lpVtbl->put_ServerSelection(updateSearcher, ssOthers);
if (hr != S_OK) fail();
hr = updateSearcher->lpVtbl->put_ServiceID(updateSearcher, bstrServiceID);
if (hr != S_OK) fail();
searchString = SysAllocString(L"IsInstalled=0 and Type='Software'");
hr = updateSearcher->lpVtbl->Search(updateSearcher, searchString, &results);
if (hr != S_OK) /* fails here */
{
wprintf(L"Error %0x\n", hr);
fail();
}
wprintf(L"Update search completed successfully.\n");
CoUninitialize();
exit(0);
}
Могу ли я что-нибудь сделать, чтобы это работало в Windows 10 так же, как в Windows 7?
(1) Я использую Windows 10 LTSB 2016. По сути, это то же самое, что Windows 10 версии 1607, также известная как Windows 10 Anniversary Update. Большинство моих клиентов не имеют обновлений за март, но в остальном они обновлены. Я также подтвердил, что проблема по-прежнему возникает на клиенте с установленными мартовскими обновлениями.
(2) Во время тестирования использование настроенного пользователем прокси дважды не удавалось, оба на недавно переустановленных компьютерах; как только он начинает работать, он продолжает работать. В этом случае сканирование все еще пытается подключиться к различным внешним IP-адресам, но тот факт, что время ожидания этих подключений не приводит к сбою сканирования. Я подозреваю, что все это как-то связано с режимом загрузки Delivery Optimization, но я все еще экспериментирую.
Приложение: случай, когда учетная запись пользователя, на которой выполняется код, имеет подходящий прокси-сервер, настроенный в их настройках Интернета, работает только тогда, когда код запускается в интерактивном режиме. В неинтерактивном контексте, например, в сервисе или запланированной задаче, это не работает. В настоящее время мне кажется, что на компьютере с Windows 10 невозможно получить доступ к Центру обновления Майкрософт из службы, если у вас нет прямого доступа в Интернет.