dotnet / docs

This repository contains .NET Documentation.
https://learn.microsoft.com/dotnet
Creative Commons Attribution 4.0 International
4.29k stars 5.92k forks source link

Missing EntryPoint with "W" suffix on LibraryImport attribute code sample. #41186

Open yuvsust opened 5 months ago

yuvsust commented 5 months ago

Describe the issue or suggestion

In the P/Invoke doc (https://learn.microsoft.com/en-us/dotnet/standard/native-interop/pinvoke), the code sample is missing the EntryPoint with the "W" suffix in the LibraryImport attribute. As a result, the code sample is not working and creating a haze for the learners to deal with.

Existing code sample,

using System;
using System.Runtime.InteropServices;

public partial class Program
{
    // Import user32.dll (containing the function we need) and define
    // the method corresponding to the native function.
    [LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16, SetLastError = true)]
    private static partial int MessageBox(IntPtr hWnd, string lpText, string lpCaption, uint uType);

    public static void Main(string[] args)
    {
        // Invoke the function as a regular managed method.
        MessageBox(IntPtr.Zero, "Command-line message box", "Attention!", 0);
    }
}

Updated code sample that will work

using System;
using System.Runtime.InteropServices;

public partial class Program
{
    // Import user32.dll (containing the function we need) and define
    // the method corresponding to the native function.
    [LibraryImport("user32.dll", EntryPoint = "MessageBoxW", StringMarshalling = StringMarshalling.Utf16, SetLastError = true)]
    private static partial int MessageBox(IntPtr hWnd, string lpText, string lpCaption, uint uType);

    public static void Main(string[] args)
    {
        // Invoke the function as a regular managed method.
        MessageBox(IntPtr.Zero, "Command-line message box", "Attention!", 0);
    }
}

I want to contribute to that fix Please review the issue and let me know if I can contribute to this fix. Thanks.

nlov commented 1 month ago

I can confirm this issue as @yuvsust described. I believe this only arose as a side effect of the positive change to replace uses of DLLImport with LibraryImport a few months ago.

We could choose to have our code sample utilize the EntryPoint named parameter in the LibraryImport attribute:

public partial class Program
{
    // Import user32.dll (containing the function we need) and define
    // the method corresponding to the native function.
    [LibraryImport("user32.dll", EntryPoint = "MessageBoxW", StringMarshalling = StringMarshalling.Utf16, SetLastError = true)]
    private static partial int MessageBox(IntPtr hWnd, string lpText, string lpCaption, uint uType);

    public static void Main(string[] args)
    {
        // Invoke the function as a regular managed method.
        MessageBox(IntPtr.Zero, "Command-line message box", "Attention!", 0);
    }
}

or have them call the MessageBoxW function (instead of the MessageBox function) from user32.dll without adding the EntryPoint named parameter:

public partial class Program
{
    // Import user32.dll (containing the function we need) and define
    // the method corresponding to the native function.
    [LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16, SetLastError = true)]
    private static partial int MessageBoxW(IntPtr hWnd, string lpText, string lpCaption, uint uType);

    public static void Main(string[] args)
    {
        // Invoke the function as a regular managed method.
        MessageBoxW(IntPtr.Zero, "Command-line message box", "Attention!", 0);
    }
}