2017-04-13 173 views
2

當試圖使用C#中的VB.NET程序集中創建的P/Invoke聲明時,我注意到string參數成爲ref string參數。瞭解VB.NET P/Invoke聲明中的VBByRefStr

仔細檢查發現,例如, 「VBByRefStr:使Visual Basic .NET中改變非託管代碼串,並有結果反映在託管代碼中的值

Public Declare Unicode Function RegDeleteValue Lib "advapi32.dll" Alias "RegDeleteValueW" (_ 
    ByVal hKey As IntPtr, ByVal lpValueName As String) As UInteger 

我讀被編譯成

[DllImport(...)]public static extern uint RegDeleteValue(
    IntPtr hKey, [MarshalAs(UnmanagedType.VBByRefStr)] ref string lpValueName); 

MSDN。此值僅支持平臺調用,這是Visual Basic中ByVal字符串的默認值。「

我還是不明白。爲什麼在C#中只有string lpValueName(參見pinvoke.net- 編輯:對於​​作爲Damien_The_Unbeliever指出,簽名與RegDeleteValue相同),但在VB.NET中有奇怪的VBByRefStr?我應該在VB.NET中使用<MarshalAs(UnmanagedType.LPWStr)>來聲明C#中的ref嗎?或者是否有任何不利影響?

+0

不是說它有很大的不同,但你的pinvoke鏈接是* *不同*功能。 'RegDeleteKey'!='RegDeleteValue'。我無法在advapi32中找到['RegDeleteValue'](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724851(v = vs.85).aspx)的PInvoke頁面 –

+0

My不好,當我沒有找到'RegDeleteValue'時,看起來像是在''RegDeleteKey''結尾。對困惑感到抱歉。但是,主要的觀察結果也與'RegDeleteKey'一樣:-) –

回答

3

這是爲了向後兼容VB6 Declare語句。

當使用ByVal x As String時,您表示想要將VB UTF-16「String」類型轉換爲ASCII表示形式,將指向該ASCII緩衝區的指針傳遞給該參數,並且在調用成功之後,將該緩衝區的內容轉換回原始的UTF-16字符串。

隨後在VB.NET中對此進行了增強以支持Unicode API調用。但是,我會想象VBByRefStr常量表示.NET中的編組必須完全遵循VB6中的方法。

如果您想要UnmanagedType.LPWStr的標準編組,然後使用屬性。

+0

有道理,謝謝解釋!我想我應該整體擺脫VB6風格的'Declare'語句,並使用'DllImport'來代替 –