为什么IUpdateSession :: WebProxy不能在Windows 10上运行?

时间:2017-03-20 00:51:38

标签: windows proxy com windows-10 wuapi

我有一些内部代码使用Windows Update API执行Microsoft Update扫描。由于某些客户端没有直接的Internet访问权限,因此我明确将WebProxy属性设置为指向本地代理服务器。在测试期间(在Windows 7上),这似乎完美无缺。现在我在Windows 10上测试它(见脚注1),似乎忽略了代理设置。

在Windows 10中,Windows Update客户端已经显着修改,因此可能这是新版本客户端中的错误或未记录的限制,但是另一方面,我以前很少使用COM,所以我可能做错了。

观察结果,使用下面发布的测试代码:

  • 代码在Windows 7上按照需要运行,无论其运行的安全上下文如何,无论客户端是否具有直接Internet访问权限和/或用户配置的代理服务器,互联网设置。

  • 该代码也适用于Windows 10,前提是客户端可以直接访问互联网。

  • 如果客户端没有直接的Internet访问权限,但运行它的用户在其Internet设置中配置了合适的代理服务器,则代码 主要适用于Windows 10。 (见脚注2)。

  • 如果客户端没有直接的Internet访问权限且运行它的用户没有配置合适的代理,则代码在Windows 10上工作。它不是连接到代码中指定的代理,而是尝试连接到一系列外部IP地址;一旦所有这些连接尝试最终超时,它将在显示的行上返回0x80072ee2,ERROR_INTERNET_TIMEOUT。 (通过省略设置代理服务器的部分代码,我可以在Windows 7上获得非常类似的行为。)

此外,如果我故意将代码中的代理URL更改为指向不存在的服务器,则代码将停止在Windows 7上运行,正如预期的那样,但Windows 10上的行为保持不变。所以它确实看起来好像Windows Update只是忽略了WebProxy属性。 (该属性正在设置;我可以从IUpdateSession对象读回来。)

更改投放优化下载模式似乎没有帮助。我已尝试通过组策略提供的所有不同模式。向代理URL添加尾部斜杠打破了Windows 7的代码,对Windows 10没有任何影响。在Windows 7上使用裸DNS名称而不是URL,但在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周年更新)基本相同。我的大多数客户都没有3月更新,但在其他方面是最新的。我还确认在安装了March更新的客户端上仍然会出现问题。

(2)在测试期间,使用用户配置的代理在两次重新安装的机器上都失败了;一旦它开始工作,它就会继续工作。在这种情况下,扫描仍会尝试连接到各种外部IP地址,但这些连接超时的事实不会导致扫描失败。我怀疑这一切都与Delivery Optimization下载模式有关,但我还在尝试。

附录:代码运行的用户帐户以及在其Internet设置中配置的合适代理服务器的情况仅在代码以交互方式运行时才有效。在非交互式上下文中,例如服务或计划任务,这工作。目前,在我看来,在Windows 10计算机上无法从服务访问Microsoft Update,除非您可以直接访问Internet。

0 个答案:

没有答案