如何在C++中打开一个URL?

36

我该如何在我的C++程序中打开一个URL?

在Ruby中,你可以这样做:

%x(open https://google.com)

在C++中有什么等价的方法?我想知道是否有跨平台的解决方案。但如果没有,我更喜欢Unix/Mac :)

以下是我的代码:

#include <stdio.h>
#include <string.h>
#include <fstream>

int main (int argc, char *argv[])
{
    char url[1000] = "https://www.google.com";

    std::fstream fs;
    fs.open(url);
    fs.close();

    return 0;
}

3
像Qt这样的库提供了一种独立于平台的方法来实现此操作。C++语言本身没有提供这个功能。 - drescherjm
Curl很好,正如其他人所指出的那样。但是在您使用的环境中可能有类似的东西。使用它会更好,因为您不必添加额外的库,并且它更符合您应用程序的风格。 - mike jones
你想从C ++代码启动默认浏览器并打开URL,还是想将网页下载到C ++应用程序中以便自己处理HTML? - drescherjm
10个回答

58
您的问题可能有两种不同的含义:
1.) 用浏览器打开一个网页。
#include <windows.h>
#include <shellapi.h>
...
ShellExecute(0, 0, L"http://www.google.com", 0, 0 , SW_SHOW );

这应该可以工作,它会使用相关联的程序打开文件。应该会打开浏览器,通常是默认的Web浏览器。


2.) 获取网页的代码并自己渲染或执行其他操作。为此,我建议阅读 这个 或 /和 这个


希望这至少有点帮助。

编辑:没有注意到您要求UNIX,这仅适用于Windows。


这只适用于Windows,对吧?我的意思是ShellExecute。不管怎样,谢谢。 - rodrigoalvesvieira
2
这是一个仅适用于 Windows 平台的解决方案,用于启动默认浏览器打开 URL。虽然 OP 提到了跨平台性,但 Qt 会为此任务提供相当沉重的负担。 - drescherjm
只是为了让这个问题更有趣一些:如果我想从我的C/C++代码中运行一个普通的终端程序,有没有办法?例如,运行cd命令。 - rodrigoalvesvieira
你可以使用system()函数来启动一个程序。我的意思是可执行程序而不是文档。 - drescherjm
2
第三个参数不应该是宽字符字符串:去掉 L 或使用 ShellExecuteW - Salvador
1
@Salvador ShellExecute 是一个宏,它会扩展为 ShellExecuteAShellExecuteW。我没有看到有人使用编译设置来使其在现今扩展为 A 版本。 - ST3

29

使用libcurl,这里有一个简单的示例

编辑:如果你想从C++启动一个Web浏览器,你可以在POSIX系统上使用system调用一个shell命令:

system("<mybrowser> http://google.com");
通过将<mybrowser>替换为您想要启动的浏览器。

4
你的更新正是我想要的。请前往以下链接查看应用程序:https://gist.github.com/rodrigoalvesvieira/662e400f34dd9de38176 - rodrigoalvesvieira

9
以下是使用winsock在Windows代码中的示例。
#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include <string>
#include <locale>
#pragma comment(lib,"ws2_32.lib")
using namespace std;

string website_HTML;
locale local;


void get_Website(char *url );

int main ()
{
    //open website
    get_Website("www.google.com" );

    //format website HTML
    for (size_t i=0; i<website_HTML.length(); ++i) 
        website_HTML[i]= tolower(website_HTML[i],local);

    //display HTML
    cout <<website_HTML;

    cout<<"\n\n";



    return 0;
}



//***************************
void get_Website(char *url )
{
    WSADATA wsaData;
    SOCKET Socket;
    SOCKADDR_IN SockAddr;


    int lineCount=0;
    int rowCount=0;

    struct hostent *host;
    char *get_http= new char[256];

        memset(get_http,' ', sizeof(get_http) );
        strcpy(get_http,"GET / HTTP/1.1\r\nHost: ");
        strcat(get_http,url);
        strcat(get_http,"\r\nConnection: close\r\n\r\n");

        if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) 
        {
            cout << "WSAStartup failed.\n";
            system("pause");
            //return 1;
        }

        Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
        host = gethostbyname(url);

        SockAddr.sin_port=htons(80);
        SockAddr.sin_family=AF_INET;
        SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);

        cout << "Connecting to "<< url<<" ...\n";

        if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) != 0)
        {
            cout << "Could not connect";
            system("pause");
            //return 1;
        }

        cout << "Connected.\n";     
        send(Socket,get_http, strlen(get_http),0 );

        char buffer[10000];

        int nDataLength;
            while ((nDataLength = recv(Socket,buffer,10000,0)) > 0)
            {       
                int i = 0;

                while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') 
                {                    
                    website_HTML+=buffer[i];                     
                    i += 1;
                }               
            }
        closesocket(Socket);
        WSACleanup();

            delete[] get_http;
}

4
这实际上是当前主题标题所说的,但我相信从评论中可以看出问题实际上是“如何使用平台无关的方法从C++代码中打开默认浏览器中的URL?” - drescherjm

7
我在Windows中遇到了完全相同的问题。
我注意到在OP's gist中,他在第21行使用了string("open "),然而,使用它会遇到这个错误:
'open'不是内部或外部命令
经过研究,我发现open是MacOS打开事物的默认命令。在Windows或Linux上有所不同。
Linux: xdg-open <URL> Windows: start <URL>

对于像我一样使用 Windows 操作系统的用户,你可以使用以下方法:

std::string op = std::string("start ").append(url);
system(op.c_str());

4

我使用ShellExecuteA()的运行效果好多了。据说使用"system()"存在很多安全风险。这是我自己编写代码得出的结论。

void SearchWeb( string word )
{    
    string base_URL = "http://www.bing.com/search?q=";
    string search_URL = "dummy";
    search_URL = base_URL + word;

    cout << "Searching for: \"" << word << "\"\n";

    ShellExecuteA(NULL, "open", search_URL.c_str(), NULL, NULL, SW_SHOWNORMAL);
}

附言:如果我没记错的话,它使用的是WinAPI,因此它不是多平台解决方案。


感谢您发现引号错误。显然,当我复制我的代码时,有些东西被删除了。 - ahogen

4
已经有关于Windows的答案了。在Linux中,我注意到open https://www.google.com命令可以从终端启动浏览器,因此您可以尝试:

system("open https://your.domain/uri");

system(("open "s + url).c_str()); // c++

https://linux.die.net/man/1/open


@SebastianMach 我附上了错误的链接。应该是 man 1 open。我刚刚修复了它。 - recolic
如果url是用户定义的,则会创建远程执行漏洞。 - rubenwardy
@rubenwardy 没错。可以通过使用 execv 或在伪造命令之前检查 URL 来修复漏洞。 - recolic
如果您不知道程序名称,您将如何使用execv?或者您只会将open用作程序名称吗? - rubenwardy
@rubenwardy 你可以使用 /usr/bin/xdg-open 或者 /usr/bin/cygstart - recolic

3

对于Linux环境,您可以使用xdg-open。它在大多数发行版上默认安装。与接受的答案相比,它的优点是它会打开用户首选的浏览器。

$ xdg-open https://google.com
$ xdg-open steam://run/10

当然,你可以将此代码包装在一个system()调用中。

2

C语言不像你提到的脚本语言那样高级。但如果你想避免使用基于socket的编程,可以尝试使用Curl。Curl是一个很棒的C库,具有许多功能。我已经使用了多年,并且始终推荐它。它还包括一些独立的程序,用于测试或shell使用。


1
@rodrigoalves Curl 可在几乎所有操作系统上使用,包括许多不同版本的 Windows 和 Linux。学习它是非常值得的时间投资,因为它有许多出色的功能。 - user2513931
是的。我经常使用终端,主要用于测试API输出等。但从未在C++程序内部使用过。 - rodrigoalvesvieira

0
这是一个跨平台的版本,用于打开URL。
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#define SystemOpenURL(url) system("start " url);
#elif __APPLE__
#define SystemOpenURL(url) system("open " url);
#elif __linux__
#define SystemOpenURL(url) system("xdg-open" url);
#else
#error "Unknown compiler"
#endif

-4
创建一个函数并使用已经被Software_Developer提到的winsock复制代码。
例如:
#ifdef _WIN32

// this is required only for windows

if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
{

  //...

}

#endif

Winsock代码在这里

#ifdef _WIN32

WSACleanup();

#endif

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接