15

A window handle sometimes of type int and other times of type IntPtr

int example:

 [DllImport("user32.dll")]
    static extern uint GetWindowThreadProcessId(int hWnd, int ProcessId);    

IntPtr example:

  [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);

I don't seem to be able to convert/cast from one to the other.

When I try this.ProcessID = GetWindowThreadProcessId(windowHandle.ToInt32(),0) I get an error cannot implicitly convert from uint to int

4
  • 7
    windowHandle.ToInt32() will work. Commented Aug 11, 2013 at 14:58
  • @Henk holterman I edited the question, but still doesn't compile
    – E Mett
    Commented Aug 11, 2013 at 15:02
  • 2
    You shouldn't edit away key parts of a question, add a next section. Commented Aug 11, 2013 at 15:05
  • 2
    Check your declaration of this.ProcessID Commented Aug 11, 2013 at 15:07

3 Answers 3

14

The SendMessage signature is

static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

or this

static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, StringBuilder lParam);

Don't exchange int and IntPtr. They are nearly equivalent only at 32 bits (equal in size). At 64 bits an IntPtr is nearly equivalent to a long (equal in size)

The GetWindowThreadProcessId signature is

static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

or

static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);

In this case, a ref or a out to "something" are managed references to something, so they are internally converted to IntPtr when passed to Native API. So out uint is, from the point of view of the Native API, equivalent to IntPtr.

Explanation: what is important is that the "length" of the parameters is the correct one. int and uint are equal for the called API. And a 32bit IntPtr is the same too.

Note that some types (like bool and char) have special handling by the marshaler.

You shouldn't EVER convert an int to an IntPtr. Keep it as an IntPtr and live happy. If you have to make some math operations not supported by IntPtr, use long (it's 64 bits, so until we will have Windows 128, there won't be any problem :-) ).

IntPtr p = ...
long l = (long)p;
p = (IntPtr)l;
2

I think that error cannot implicitly convert from uint to int refers to = statement. The field this.ProcessID is int, but GetWindowThreadProcessId returns uint.

Try this

this.ProcessID = unchecked((int)GetWindowThreadProcessId(windowHandle.ToInt32(),0))
1

I was getting "Arithmetic operation resulted in an overflow", whenever I was:

IntPtr handler = OpenSCManager(null, null, SC_MANAGER_CREATE_SERVICE);
if (handler.ToInt32() == 0) //throws Exception

instead of that:

IntPtr handler = OpenSCManager(null, null, SC_MANAGER_CREATE_SERVICE);
if (handler == IntPtr.Zero) //OK

Not the answer you're looking for? Browse other questions tagged or ask your own question.