Tower
Tower

Reputation: 102795

How do I solve this "P/Invoke declarations should be portable"?

This code:

[DllImport("shell32", CharSet=CharSet.Unicode)]
private static extern int SHGetFileInfo(string pszPath, uint dwFileAttributes, out SHFILEINFO psfi, uint cbFileInfo, uint flags);

Causes the following Code Analysis problem:

CA1901 P/Invoke declarations should be portable

As it is declared in your code, the return type of P/Invoke 'IconUtil.SHGetFileInfo(string, uint, out IconUtil.SHFILEINFO, uint, uint)' will be 4 bytes wide on 64-bit platforms. This is not correct, as the actual native declaration of this API indicates it should be 8 bytes wide on 64-bit platforms. Consult the MSDN Platform SDK documentation for help determining what data type should be used instead of 'int'.

What am I supposed to do? I tried "consulting MSDN", but I'm not really sure what the problem even means.


I also get this for the same line:

CA1060 Move P/Invokes to NativeMethods class

Because it is a P/Invoke method, 'IconUtil.SHGetFileInfo(string, uint, out IconUtil.SHFILEINFO, uint, uint)' should be defined in a class named NativeMethods, SafeNativeMethods, or UnsafeNativeMethods.

Upvotes: 3

Views: 3307

Answers (2)

David Heffernan
David Heffernan

Reputation: 612993

The MSDN page that the warning refers to is the documentation of the native function SHGetFileInfo. It gives the signature as:

DWORD_PTR SHGetFileInfo(
  __in     LPCTSTR pszPath,
  DWORD dwFileAttributes,
  __inout  SHFILEINFO *psfi,
  UINT cbFileInfo,
  UINT uFlags
);

So the first warning is referring to the fact that DWORD_PTR is a pointer sized unsigned integer. That means you should use UIntPtr.

The next thing that jumps out is that the SHFILEINFO struct is indicated as __inout. That means you need to pass it by ref.

So the p/invoke declaration should be:

[DllImport("shell32", CharSet=CharSet.Unicode)]
private static extern UIntPtr SHGetFileInfo(
    string pszPath, 
    uint dwFileAttributes, 
    ref SHFILEINFO psfi, 
    uint cbFileInfo, 
    uint flags
);

The final warning is simple to resolve. Simply place your p/invoke declaration inside a class named NativeMethods.

Upvotes: 4

Tower
Tower

Reputation: 102795

I solved the first problem by changing return type of int to IntPtr.

Upvotes: 0

Related Questions