0
HRESULT UrlCanonicalize(
  _In_     PCTSTR pszUrl,
  _Out_    PTSTR pszCanonicalized,
  _Inout_  DWORD *pcchCanonicalized,
  DWORD dwFlags
);

例子:

LPCTSTR pszURL  = URL.c_str();
LPSTR pszOutPut = new CHAR[ strUrl.length ];
DWORD* dwCount = new DWORD[  strUrl.length ];
hRes =  UrlCanonicalize( pszURL, pszOutPut,dwCount, URL_ESCAPE_UNSAFE );

输出:

E_INVALIDARG

E_INVALIDARG每次我尝试调用它时,此 API 都会失败并返回。请给我一个工作代码片段来调用该UrlCanonicalize函数。

4

2 回答 2

2

如果您了解 C++ 语言,该函数的 SDK 文档几乎会告诉您您需要了解的所有内容:

  • 您将包含您的 URL 的 C 风格的以 nul 结尾的字符串传递给它。
  • 您将它的指针传递给缓冲区以接收输出字符串。
  • 您向它传递一个或多个自定义函数行为的标志。
  • 最后,它会返回一个HRESULT值,即错误代码。如果成功,则该值为S_OK。如果失败,它将是其他一些错误代码。

它是这样工作的:

std::wstring originalURL(L"http://www.example.com/hello/cruel/../world/");

// Allocate a buffer of the appropriate length.
// It needs to be at least as long as the input string.
std::wstring canonicalURL(originalURL.length() + 1, L'\0');
DWORD length = originalURL.length() + 1;

// Call the function to modify the string.
HRESULT hr = UrlCanonicalize(originalURL.c_str(), // input string
                             &canonicalURL[0],    // buffer
                             &length,             // pointer to a DWORD that contains the length of the buffer
                             URL_UNESCAPE | URL_ESCAPE_UNSAFE);
if (SUCCEEDED(hr))
{
    // The function succeeded.
    // Your canonicalized URL is in the canonicalURL string.
    MessageBox(nullptr, canonicalURL.c_str(), L"The URL is:", MB_OK);   
}
else
{
    // The function failed.
    // The hr variable contains the error code.
    throw std::runtime_error("The UrlCanonicalize function failed.");
}

如果要确保缓冲区足够长(并避免处理该错误),请在分配时使用常量INTERNET_MAX_URL_LENGTH(在 中声明):WinInet.h

std::wstring canonicalURL(INTERNET_MAX_URL_LENGTH, L'\0');
DWORD length = INTERNET_MAX_URL_LENGTH;

您尝试的代码有几个问题:

  1. 您错误地初始化了dwCount变量。该函数需要一个指针,但这并不意味着您应该将变量声明为指针。你也不想要一个数组;这是一个单一的DWORD值。因此,您需要将其声明为常规DWORD,然后使用地址运算符 ( &) 向函数传递指向该变量的指针。现在,您正在传递函数垃圾,所以它失败了。

  2. 您正在使用 C 风格的字符串,在 C++ 代码中应该避免使用这种字符串。使用 C++ 字符串类(std::wstring用于 Windows 代码),它是异常安全的并为您管理内存。如您所知,c_str()成员函数使您可以轻松访问所有 C API 想要的 C 风格的以 nul 结尾的字符串。这很好用,您不需要自己使用原始字符数组。new尽可能避免。

第三个问题可能是您尝试使用 C++ 字符串类型std::string而不是std::wstring. 前者是 8 位字符串类型,在 Windows 环境下不支持 Unicode。你想要std::wstring,这是一个支持 Unicode 的宽字符串。如果您UNICODE为项目定义了符号(默认情况下),这就是所有 Windows API 函数所期望的。

于 2013-08-16T12:59:54.563 回答
0

干得好:

LPCTSTR pszURL = URL.c_str();
DWORD nOutputLength = strUrl.length * 2 + 32;
LPTSTR pszOutPut = new TCHAR[nOutputLength];
hRes = UrlCanonicalize( pszURL, pszOutPut, &nOutputLength, URL_ESCAPE_UNSAFE);

在第三个参数上,您提供了垃圾而不是指向初始化值的指针,因此您返回了 API 失败。MSDN为您准备了一切

指向一个值的指针,该值在输入时设置为 pszCanonicalized 缓冲区中的字符数。

于 2013-08-16T12:58:13.200 回答