2013-08-16 95 views
0
HRESULT UrlCanonicalize(
    _In_  PCTSTR pszUrl, 
    _Out_ PTSTR pszCanonicalized, 
    _Inout_ DWORD *pcchCanonicalized, 
    DWORD dwFlags 
); 

例子:如何正確調用UrlCanonicalize API函數?

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 

此API失敗,每次我試圖把它稱爲一次返回E_INVALIDARG。請給我一個工作代碼片段來調用UrlCanonicalize函數。

+1

你爲什麼不展示你的拳頭? –

+0

@ MariusBancila->你可以給這個函數的代碼片段嗎? – Rono

+1

如果您向我們展示您嘗試過的代碼會更具教育意義。這樣,我們可以告訴你爲什麼它不起作用以及如何解決它。你不能通過複製和粘貼其他人的代碼來學習任何東西。 –

回答

2

如果你知道C++語言,the SDK documentation for the function幾乎告訴你,你需要知道的一切:

  • 你傳遞一個包含您的網址C風格的空終止字符串。
  • 您將指針傳遞給緩衝區以接收輸出字符串。
  • 您傳遞一個或多個自定義函數行爲的標誌。
  • 最後,它返回一個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,然後使用address-of運算符(&)將函數傳遞給該變量的指針。現在,你正在傳遞函數垃圾,所以它失敗了。

  2. 你正在使用C風格的字符串,你應該避免在C++代碼中使用。使用C++字符串類(適用於Windows代碼的std::wstring),這是異常安全的併爲您管理內存。正如你已經知道的那樣,c_str()成員函數可以讓你輕鬆訪問像所有C API所需的C風格的nul結尾的字符串。這工作正常,你不需要自己使用原始字符數組。儘可能避免new

潛在的,第三個問題是,你要使用C++字符串類型std::string,而不是std::wstring。前者是8位字符串類型,不支持Windows環境中的Unicode。您需要std::wstring,這是一個支持Unicode的寬字符串。如果您爲項目定義了UNICODE符號(這是默認設置),那麼這就是所有Windows API函數所期望的。

+0

- >很好地解釋說,你對支持很有幫助。 – Rono

+0

我對上述解決方案有個小問題,我的網址在UrlCanonicalize api調用後沒有編碼 – Rono

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 has it all for you:

一個指向一個值的指針,該值在輸入時被設置爲pszCanonicalized緩衝區中的字符數。

+0

Thx夥計真的很有幫助 – Rono