Converting VB6 Type to C# struct - c#

Public Type WIN32_FIND_DATA
dwFileAttributes As Long
ftCreationTime As FILETIME
ftLastAccessTime As FILETIME
ftLastWriteTime As FILETIME
nFileSizeHigh As Long
nFileSizeLow As Long
dwReserved0 As Long
dwReserved1 As Long
cFileName As String * MAX_PATH
cAlternate As String * 14
End Type
This is my original VB6 code and the converted C# code is
public struct WIN32_FIND_DATA
{
long dwFileAttributes;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
long nFileSizeHigh;
long nFileSizeLow;
long dwReserved0;
long dwReserved1;
cFileName As String * max_path;
cAlternate As String * 14
}
How to convert cFileName As String * max_path into C#

It seems that you want to marshal this struct (e.g. when calling FindFirstFileEx, FindNextFile API functions); if it's your case
using System.Runtime.InteropServices;
...
[StructLayout(LayoutKind.Sequential)]
struct WIN32_FIND_DATA
{
public uint dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] // MAX_PATH = 260
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}
see original WIN32_FIND_DATA declaration for details

Related

Convert the _WTSClient struct from C++ to C#

I have been trying to convert this struct to C# for the last couple of days, but to no avail...
https://msdn.microsoft.com/en-us/library/windows/desktop/bb736369(v=vs.85).aspx
typedef struct _WTSCLIENT {
TCHAR ClientName[CLIENTNAME_LENGTH + 1];
TCHAR Domain[DOMAIN_LENGTH + 1 ];
TCHAR UserName[USERNAME_LENGTH + 1];
TCHAR WorkDirectory[MAX_PATH + 1];
TCHAR InitialProgram[MAX_PATH + 1];
BYTE EncryptionLevel;
ULONG ClientAddressFamily;
USHORT ClientAddress[CLIENTADDRESS_LENGTH + 1];
USHORT HRes;
USHORT VRes;
USHORT ColorDepth;
TCHAR ClientDirectory[MAX_PATH + 1];
ULONG ClientBuildNumber;
ULONG ClientHardwareId;
USHORT ClientProductId;
USHORT OutBufCountHost;
USHORT OutBufCountClient;
USHORT OutBufLength;
TCHAR DeviceId[MAX_PATH + 1];
} WTSCLIENT, *PWTSCLIENT;
This is my attempt so far:
[StructLayout( LayoutKind.Sequential )]
public struct _WTSCLIENT {
[MarshalAs( UnmanagedType.LPTStr )]
public String ClientName;
[MarshalAs( UnmanagedType.LPTStr )]
public String Domain;
[MarshalAs( UnmanagedType.LPTStr )]
public String UserName;
[MarshalAs( UnmanagedType.LPTStr )]
public String WorkDirectory;
[MarshalAs( UnmanagedType.LPTStr )]
public String InitialProgram;
public Byte EncryptionLevel;
public uint ClientAddressFamily;
[MarshalAsAttribute( UnmanagedType.ByValArray)]
public byte[] ClientAddress;
public ushort HRes;
public ushort VRes;
public ushort ColorDepth;
[MarshalAs( UnmanagedType.LPTStr )]
public String ClientDirectory;
public uint ClientBuildNumber;
public uint ClientHardwareId;
public ushort ClientProductId;
public ushort OutBufCountHost;
public ushort OutBufCountClient;
public ushort OutBufLength;
[MarshalAs( UnmanagedType.LPTStr )]
public String DeviceId;
}
I use it like this:
WTSQuerySessionInformation( serverHandle, si.SessionID, WTS_INFO_CLASS.WTSClientInfo, out clientInfoPtr, out bytes );
clientInfo = (_WTSCLIENT)Marshal.PtrToStructure( clientInfoPtr, typeof( _WTSCLIENT ) );
...but it bombs out silently, so obviously I have not matched the structure...
Can anyone help me with the struct conversion to C#
TIA...
--
Dag.
Try
[StructLayout(LayoutKind.Sequential)]
public struct WTSCLIENT
{
private const int CLIENTNAME_LENGTH = 20;
private const int DOMAIN_LENGTH = 17;
private const int USERNAME_LENGTH = 20;
private const int MAX_PATH = 260;
private const int CLIENTADDRESS_LENGTH = 30;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CLIENTNAME_LENGTH + 1)]
public string ClientName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = DOMAIN_LENGTH + 1)]
public string Domain;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = USERNAME_LENGTH + 1)]
public string UserName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
public string WorkDirectory;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
public string InitialProgram;
public byte EncryptionLevel;
public uint ClientAddressFamily;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = CLIENTADDRESS_LENGTH + 1)]
public ushort[] ClientAddress;
public ushort HRes;
public ushort VRes;
public ushort ColorDepth;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
public string ClientDirectory;
public uint ClientBuildNumber;
public uint ClientHardwareId;
public ushort ClientProductId;
public ushort OutBufCountHost;
public ushort OutBufCountClient;
public ushort OutBufLength;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]
public string DeviceId;
}
It should work. Its Marshal.SizeOf is the "right" one, both at 32 and 64 bits, both Ansi and Unicode.
If you are using the Unicode version of the methods change the first line to:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
You could try the P/Invoke Interop Assistant
For your ULONG ClientBuildNumber; and all other ULONG s in C++, you have used the C# type uint. It could be an error that your definition of ULONG is a different size than uint.
Maybe you can try using ulong in C# (unsigned 64-bit, 0 to 18,446,744,073,709,551,615). This should match the standard Microsoft C++ ULONG definition.
MSDN C++
MSDN C# ulong

How to set a specific timezone for windows CE By C#

hi everyone i need to make the time zone for my windows CE 6 changed to
"(GMT +03:00) Kuwait, Riyadh"
and this my code
[DllImport("coredll.dll", CharSet = CharSet.Auto)]
private static extern int GetTimeZoneInformation(out TimeZoneInformation lpTimeZoneInformation);
[DllImport("coredll.dll", CharSet = CharSet.Auto)]
private static extern bool SetTimeZoneInformation(ref TimeZoneInformation lpTimeZoneInformation);
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public int wYear;
public int wMonth;
public int wDayOfWeek;
public int wDay;
public int wHour;
public int wMinute;
public int wSecond;
public int wMilliseconds;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct TimeZoneInformation
{
public int bias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string standardName;
public SYSTEMTIME standardDate;
public int standardBias;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string daylightName;
public SYSTEMTIME daylightDate;
public int daylightBias;
}
how can I use this code to set the time zone for the specific one
please any one can help me.
I found the solution by adding a registry file with this script.
[HKEY_LOCAL_MACHINE\Time Zones]
"Default"="Arab Standard Time"

Another PInvoke - error message says source not found?

The struct that i have built in c# when run against the function does not give me one of the error message that tell me something is wrong with the struct. It says that a source file could not be found. Again, I don't know much about this DLL b/c of lack of documentation. But I am still thinking it is because I set the struct up wrong. Most likely i'm thinking the 3rd struct where it is referencing a struct within the struct.
i was hoping for some feedback on the work I did.
Thanks for the assistance.
This is what was provided in C:
int BatchTotal_Transactions(int transType, pTGiftCardReqBatchTotal req, pTGiftCardRespBatchTotal resp, int (*Com)(char *));
typedef struct _tagGiftCardReqBatchTotal
{
char Password[9];
char OperatorID[9];
char BatchNum[14];
char StartDate[11];
char EndDate[11];
unsigned char Type;
} TGiftCardReqBatchTotal, *pTGiftCardReqBatchTotal;
typedef struct _tagGiftCardRespBatchTotal
{
char Result;
char TerminalId[17];
unsigned char DispMsgControl;
char DispMsg[256];
char Display[41];
char Date[11];
char Time[9];
char RespCode[4];
char BatchNum[14];
char ErrorFlag;
char CustLang;
char UserLang;
char OpenDate[17];
char ClosedDate[17];
char StartDate[11];
char EndDate[11];
char BatchStatus;
int CardTypeNum;
TGiftCardTotals GctHost[MAX_CARD_CODES];
TGiftCardTotals GctTRS[MAX_CARD_CODES];
} TGiftCardRespBatchTotal, *pTGiftCardRespBatchTotal;
typedef struct _tagGiftCardTotals
{
unsigned short CardCode;
unsigned short PurchaseNum;
long PurchaseTotal;
unsigned short RefundNum;
long RefundTotal;
unsigned short RedemptionNum;
long RedemptionTotal;
unsigned short CorrectionNum;
long CorrectionTotal;
long PurchaseBenefitTotal;
long RefundBenefitTotal;
long RedemptionBenefitTotal;
} TGiftCardTotals, *pTGiftCardTotals;
And this is how I did it in C#:
[DllImport("batch.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
public static extern int BatchTotal_Transactions(int transType, ref giftCardReqBatchTotal req, ref giftCardRespBatchTotal resp, IntPtr com);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct _tagGiftCardReqBatchTotal
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public string Password;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public string OperatorID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string BatchNum;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string StartDate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string EndDate;
public byte Type;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct _tagGiftCardRespBatchTotal
{
public byte Result;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string TerminalId;
public byte DispMsgControl;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string DispMsg;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public string Display;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string Date;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public string Time;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public string RespCode;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string BatchNum;
public byte ErrorFlag;
public byte CustLang;
public byte UserLang;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string OpenDate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string ClosedDate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string StartDate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string EndDate;
public byte BatchStatus;
int CardTypeNum;
[MarshalAs(UnmanagedType.Struct, SizeConst = 1024)]
public _tagGiftCardTotals GctHost;
[MarshalAs(UnmanagedType.Struct, SizeConst = 1024)]
public _tagGiftCardTotals GctTRS;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct _tagGiftCardTotals
{
public UInt16 CardCode;
public UInt16 PurchaseNum;
public int PurchaseTotal;
public UInt16 RefundNum;
public int RefundTotal;
public UInt16 RedemptionNum;
public int RedemptionTotal;
public UInt16 CorrectionNum;
public int CorrectionTotal;
public int PurchaseBenefitTotal;
public int RefundBenefitTotal;
public int RedemptionBenefitTotal;
}
Are you sure the error isn't the following:
Specified module could not be found.
If this is the error then it is because the dll could not be found. Make sure the dll is in your path:
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.value.aspx

union marshalling issue in C#

I have union inside structure and the structure looks like
struct tDeviceProperty {
DWORD Tag;
DWORD Size;
union _DP value;
};
typedef union _DP
{
short int i;
LONG l;
ULONG ul;
float flt;
double dbl;
BOOL b;
double at;
FILETIME ft;
LPSTR lpszA;
LPWSTR lpszW;
LARGE_INTEGER li;
struct tBinary bin;
BYTE reserved[40];
} __UDP;
struct tBinary {
ULONG size;
BYTE * bin;
};
from the tBinary structure bin has to be converted to tImage (structure is given below)
struct tImage {
DWORD x;
DWORD y;
DWORD z;
DWORD Resolution;
DWORD type;
DWORD ID;
diccid_t SourceID;
const void *buffer;
const char *Info;
const char *UserImageID;
};
to use the same in c# I have done marshaling but not giving proper values when converting the pointer to structure. The C# code is follows,
tBinary tBin = new tBinary();
IntPtr tBinbuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(tBin));
Marshal.StructureToPtr(tBin.bin, tBinbuffer, false);
tDeviceProperty tDevice = new tDeviceProperty();
tDevice.bin = tBinbuffer;
IntPtr tDevicebuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(tDevice));
Marshal.StructureToPtr(tDevice.bin, tDevicebuffer, false);
Battary tbatt = new Battary();
tbatt.value = tDevicebuffer;
IntPtr tbattbuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(tbatt));
Marshal.StructureToPtr(tbatt.value, tbattbuffer, false);
result = GetDeviceProperty(ref tbattbuffer);
Battary v = (Battary)Marshal.PtrToStructure(tbattbuffer, typeof(Battary));
tDeviceProperty v2 = (tDeviceProperty)Marshal.PtrToStructure(tDevicebuffer, typeof(tDeviceProperty));
tBinary v3 = (tBinary)Marshal.PtrToStructure(tBinbuffer, typeof(tBinary));
[StructLayout(LayoutKind.Explicit)]
public struct tDeviceProperty
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.U2)]
public ushort i;
[FieldOffset(2)]
[MarshalAs(UnmanagedType.I4)]
public int l;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.U4)]
public uint ul;
[FieldOffset(10)]
[MarshalAs(UnmanagedType.R4)]
public float flt;
[FieldOffset(14)]
[MarshalAs(UnmanagedType.R8)]
public double dbl;
[FieldOffset(22)]
[MarshalAs(UnmanagedType.I4)]
public int b;
[FieldOffset(26)]
[MarshalAs(UnmanagedType.R8)]
public double at;
[FieldOffset(34)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr ft;
[FieldOffset(42)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr lpszA;
[FieldOffset(43)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr lpszW;
[FieldOffset(45)]
[MarshalAs(UnmanagedType.U8)]
public ulong li;
[FieldOffset(53)]
[MarshalAs(UnmanagedType.Struct)]
public IntPtr bin;
[FieldOffset(61)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr reserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct tBinary
{
public int size;
public IntPtr bin;
}
[StructLayout(LayoutKind.Sequential)]
public struct Battary
{
public uint Tag;
public uint Size;
public IntPtr value;
}
[StructLayout(LayoutKind.Sequential)]
public struct tDiccBatteryStatus
{
public uint RefreshWear;
public uint TotalWear;
public ushort Voltage;
public ushort Battery;
public int BatteryOK;
public int NeedRefresh;
public int NeedChange;
public ushort Temperature;
public int Charge;
public byte State;
public byte ExternalPowered;
public int CapacityLeft;
}
I think that the reason of the failure is the tDeviceProperty declaration. Infact, its member value is an union, but in the tDeviceProperty you apply constatly increasing offset, while they shall have the same value.
This is because the union members start at the same offset, sharing the same space of the other members. The size of the union is determines by the maximum size of the fields declared in the union.
Indeed, using your code:
[StructLayout(LayoutKind.Explicit, Size = )]
public struct tDeviceProperty
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.U2)]
public ushort i;
[FieldOffset(2)]
[MarshalAs(UnmanagedType.I4)]
public int l;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.U4)]
public uint ul;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.R4)]
public float flt;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.R8)]
public double dbl;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.I4)]
public int b;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.R8)]
public double at;
[FieldOffset(6)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr ft;
[FieldOffset(6)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr lpszA;
[FieldOffset(6)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr lpszW;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.U8)]
public ulong li;
[FieldOffset(6)]
[MarshalAs(UnmanagedType.Struct)]
public IntPtr bin;
[FieldOffset(6)]
//[MarshalAs(UnmanagedType.Struct)]
public IntPtr reserved;
}
Check also my recent question/answer.

Using p/invoke to call a function from a C api

I have a C api and I am using p/invoke to call a function from the api in my C# application. The function signature is:
int APIENTRY GetData (CASHTYPEPOINTER cashData);
Type definitions:
typedef CASHTYPE* CASHTYPEPOINTER;
typedef struct CASH
{
int CashNumber;
CURRENCYTYPE Types[24];
} CASHTYPE;
typedef struct CURRENCY
{
char Name[2];
char NoteType[6];
int NoteNumber;
} CURRENCYTYPE;
How would be my C# method signature and data types?
Thank you.
You need to specify the array sizes using SizeConst:
using System;
using System.Runtime.InteropServices;
public static class MyCApi
{
[StructLayout(LayoutKind.Sequential)]
public struct CASHTYPE
{
public int CashNumber;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)]
public CURRENCYTYPE[] Types;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CURRENCYTYPE
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)]
public string Name;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)]
public string NoteType;
public int NoteNumber;
}
[DllImport("MyCApi.dll")]
public static extern int GetData(ref CASHTYPE cashData);
}
I think it may look like this
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public struct CASH{
public int CashNumber;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)]
public CURRENCY Types[24];
}
[ StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct CURRENCY {
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=2 )]
public string Name;
[MarshalAs( UnmanagedType.ByValTStr, SizeConst=6 )]
public string NoteType;
public int NoteNumber;
}
class Wrapper {
[DllImport("my.dll")]
public static extern int GetData(ref CASH cashData}
}

Categories