使用“wininet”和“windows.h”时如何解决“IServiceProvider”不明确?

Posted

技术标签:

【中文标题】使用“wininet”和“windows.h”时如何解决“IServiceProvider”不明确?【英文标题】:How to solve "IServiceProvider" is ambiguous when using "wininet" and "windows.h"? 【发布时间】:2020-12-23 15:34:33 【问题描述】:

我正在尝试使用wininetInternetCheckConnection 函数检查互联网连接是否存在。

这是我的 CheckerClass:,它处理检查过程。

#pragma once
#include <Windows.h>
#include <wininet.h>
#pragma comment(lib,"wininet.lib")
#include <String>

public ref class CheckerClass

public:
    static std::string hasInternet() 
        bool bConnect = InternetCheckConnection(L"https://www.google.com", FLAG_ICC_FORCE_CONNECTION, 0);
        if (bConnect)
            return "Has Internet!";
        else
            return "No Internet!";
        
    
;

但我收到以下错误,我无法解决。

Error (active)  E1986   an ordinary pointer to a C++/CLI ref class or interface class is not allowed
Error (active)  E0266   "IServiceProvider" is ambiguous
Error   C3699   '*': cannot use this indirection on type 'IServiceProvider' 

经过搜索,我发现这是因为使用using namespace System,但我在上面的类中没有。

但是,我在使用上述类的 Main 类中有以下内容。

#pragma once
#include<string>
#include "CheckerClass.h"
namespace CppCLRWinformsProjekt 

    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    using std::string;

    public ref class Form1 : public System::Windows::Forms::Form
    
    public:

        CheckerClass checkerClass;
        
        Form1(void)
        
            InitializeComponent();
            string result = checkerClass.hasInternet();
            this->label_output->Text = gcnew System::String(result.c_str());
        

    .....

谁能解释一下发生了什么,我该如何解决上述问题?

【问题讨论】:

这些是 .h 文件,您还没有找到#includes 的 .cpp 文件。并包含使用命名空间系统,从而搞砸了 Windows.h 声明。您应该得到诊断的一个明显错误是 checkerClass 变量,必须声明为 CheckerClass^。 @HansPassant - 我认为课程有问题。 【参考方案1】:

你有什么样的CheckerClass?类通常分为两个文件。这意味着您应该拥有CheckerClass.hCheckerClass.cpp。上面这两个文件中的代码在哪里?

无论如何,这是基于您的代码的工作类示例。

在您的CheckerClass.h 文件中,您应该有;

#include <string>
#ifndef CHECKER_CLASS_H
#define CHECKER_CLASS_H
using std::string;
class CheckerClass 

private:
    //declare private variables here, if you need one.
public:

    CheckerClass(); 
    
    string hasInternet(); //The function
;
#endif

然后类的实现进入CheckerClass.cpp文件;

#include "CheckerClass.h"
#include "string"
#include "windows.h"
#include "wininet.h"
#pragma comment(lib,"wininet.lib")

CheckerClass::CheckerClass() 
    //initialize variable here if needed.


std::string CheckerClass::hasInternet() 
    bool bConnect = InternetCheckConnection(L"https://www.google.com", FLAG_ICC_FORCE_CONNECTION, 0);
    if (bConnect) 
        return "has Internet";
    
    else 
        return "no internet";
    

那么你现在可以用你的代码得到结果了;

string result = checkerClass.hasInternet();
this->label_output->Text = gcnew System::String(result.c_str());

这将避免您遇到的冲突和错误。

【讨论】:

所以基本上,发生冲突是因为我没有正确初始化我的类。我对h 文件和cpp 文件有点困惑。我认为在 C++ 和 Java 上创建类的概念是一样的。谢谢!【参考方案2】:

这是因为using namespace System;Windows.h中的名字冲突,

Windows.h 间接介绍了servprov.h。而servprov.h 有这样的定义:typedef interface IServiceProvider IServiceProvider; 其中IServiceProvider与System命名空间中的IServiceProvider冲突,造成不确定性。

解决方法是使用全限定名称,而不是 System 命名空间,例如 System::IServiceProvider

【讨论】:

你能告诉我更多吗?我应该在哪里做?因为我尝试从主类中删除与System 相关的命名空间,但仍然遇到同样的问题。我尝试在CheckerClass 上使用System::IServiceProvider,但仍然遇到同样的问题。 您可以尝试注释掉所有using namespace System; 使用IServiceProvider 时,请改用System::IServiceProvider。还有另一种可能。查看包含的文件是否在子文件中启用了两个命名空间设置。例如,using namespace System;using namespace System::IO; 冲突是由包含的文件之一中的重复设置引起的。 所以基本上,发生冲突是因为我没有正确初始化我的类。我对h 文件和cpp 文件有点困惑。我认为在 C++ 和 Java 上创建类的概念是一样的。谢谢!

以上是关于使用“wininet”和“windows.h”时如何解决“IServiceProvider”不明确?的主要内容,如果未能解决你的问题,请参考以下文章

Wininet上传文件TCHAR问题

C++ Wininet 自定义 http 标头

WinInet 输出中的随机字符

WinInet 未定义标识符

WinInet 只下载网页的一部分

判断内外网环境