I am trying to do something like this in C#. I found out how to call Win32 methods from C# using P/Invoke from this link. However I met some difficulties in implementing P/I
iirc LPCTSTR breaks down to: LP == Long Pointer // relic from 16- to 32-bit thunking
C == Constant
TSTR == TStr // TString, kind of a placeholder that would get substituted for different kinds of strings depending on various C headers and #defines
what it means to you: it is a pointer to a string, for C# just use string and you'll be okay.
PDH_STATUS is a pointer to a DH_STATUS struct, so you will need to define a C# structure to match.
Check out P/Invoke.Net for some examples of using p/invoke on standard Windows headers, structures, and functions. The website is kind of klunky, you just have to keep clicking and expanding items in the left column.
P/Invoke isn't well documented, but once you map the structure and the extern function call you should be in business.
What is LPCTSTR, and to what data type does it map in C#?
LPCTSTR
is a typedef for const TCHAR*
.
TCHAR
is an attempt to abstract away the fact that the Windows API exists in both "ANSI" (char
strings in a locale-specific encoding) and "Unicode" (UTF-16) versions. There is no actual PdhOpenQuery
function; there is a PdhOpenQueryA
function that takes an ANSI string and a PdhOpenQueryW
function that takes a UTF-16 string.
C# uses UTF-16 strings, so you'll want to prefer the "W" version of these functions. Use PdhOpenQueryW
. Then the first parameter has C++ type const wchar_t*
. The C# type is [MarshalAs(UnmanagedType.LPWStr)] string
.
How to map a pointer type DWORD_PTR? The pinvoke article says DWORD maps to UInt32, but how about pointers?
DWORD_PTR
isn't a pointer. It's an unsigned integer big enough to hold a pointer. The equivalent C# type is System.UIntPtr
.
I think PDH_STATUS and PDH_HQUERY are specific struct to the library (I'm not sure yet). how do I map these?
PDH_STATUS
appears to be just an int
.
PDH_HQUERY
is a pointer to a handle (another pointer), but you can just pretend it's an integer and use IntPtr
.
Putting it all together, your declaration should be:
[DllImport("Pdh.dll")]
static extern int PdhOpenQueryW(
[MarshalAs(UnmanagedType.LPWStr)] string szDataSource,
UIntPtr dwUserData,
out IntPtr phQuery);
[DllImport("Pdh.dll")] static extern Int32 PdhOpenQuery(string szDataSource, IntPtr dwUserData, ref IntPtr phQuery);