I have defined LVITEM as follows:
<StructLayout(LayoutKind.Sequential)> Private Structure LVITEM
Dim mask As Int16
Dim iItem As Int16
Dim iSubItem As Int16
Dim state As Int16
Dim stateMask As Int16
<MarshalAs(UnmanagedType.LPWStr)> Dim pszText As IntPtr
Dim cchTextMax As Int16
Dim iImage As Int16
Dim lParam As Integer
Dim iIndent As Int16
End Structure
When I execute the following code I get an exception on the last line:
<code>
Dim lvi As LVITEM
''dwSize = Marshal.SizeOf(lvi) ' This does not work either
dwSize = 24
Dim SysShared As IntPtr
Dim StringMemory As IntPtr
lvi.mask = LVIF_TEXT
lvi.cchTextMax = 100
lvi.iSubItem = 0
SysShared = GetMemSharedNT(lPID, dwSize, hProcess)
StringMemory = GetMemSharedNT(lPID, 100, hProcess)
lvi.pszText = StringMemory
WriteProcessMemory(hProcess, SysShared, lvi, dwSize,
BytesWritten)
</code>
The error I get is
"Can not marshal field pszText of type LVITEM: Invalid managed/unmanaged
type combination (Int/UInt must be paired with I or U)."
I guess that pszText should be defined 'As String', but then I have a
problem making it point to the memory I have allocated.
Does anyone have any idea how to get round this? I have a sample in C from
this site
http://www.codeproject.com/threads/int64_memsteal.asp
but I would really prefer to do the whole thing in VB.NET.
TIA
Charles
Dragon - 01 Sep 2005 11:25 GMT
Hi Charles,
If you want to make pszText an IntPtr, you don't need MarshalAsAttribute
at all. If it was a String then yes, you need a marshalling attribute to
specify whether it is a LPStr, LPWStr, LPTStr or a ByValTStr. IntPtr can
be passed only as 4-byte integer, thus it don't need any marshalling
attribute.
BTW, your LVITEM declaration is wrong. All fields there are Int32's, not
Int16's.
HTH
Roman
> I have defined LVITEM as follows:
>
[quoted text clipped - 53 lines]
>
> Charles
Charles Law - 01 Sep 2005 11:50 GMT
Hi Roman
Thanks. I removed the MarshalAs attribute from the IntPtr and I no longer
get the exception.
I took the following LVITEM definition from the MSDN
<extract>
typedef struct _LVITEM {
UINT mask;
int iItem;
int iSubItem;
UINT state;
UINT stateMask;
LPTSTR pszText;
int cchTextMax;
int iImage;
LPARAM lParam;
#if (_WIN32_IE >= 0x0300)
int iIndent;
#endif
#if (_WIN32_IE >= 0x560)
int iGroupId;
UINT cColumns; // tile view columns
PUINT puColumns;
#endif
} LVITEM, *LPLVITEM;
</extract>
and duly converted the elements to .NET types, so doesn't that mean that an
int should be translated to int16 in .NET? With the exception that I
mentioned in the OP, this definition works for me, although I admit that it
also works using int32s.
Charles
> Hi Charles,
>
[quoted text clipped - 69 lines]
>>
>> Charles
Dragon - 01 Sep 2005 13:04 GMT
> and duly converted the elements to .NET types, so doesn't that mean that an
> int should be translated to int16 in .NET?
int (as well as UINT) is 4-byte integer, so it's .NET equivalent is
Int32 (Well it's actually UInt32 for UINT, but using UInt's in VB 2002/3
is a real pain).
Int16 is for short datatype.