
Merrion
*Experts*
-
Posts
269 -
Joined
-
Last visited
Content Type
Profiles
Forums
Blogs
Events
Articles
Resources
Downloads
Gallery
Everything posted by Merrion
-
Marshalling as a pointer to an array of shorts?
Merrion
replied to Merrion
's topic in Interoperation / Office Integration
OK - problem with FindNextPrinterChangeNotification:- I have declared the PrinterNotifyInfo structure that it wants in as a class thus: Imports System.Runtime.InteropServices <StructLayout(LayoutKind.Explicit)> _ Public Class PrinterNotifyOptions <FieldOffset(0)> Public dwVersion As Integer <FieldOffset(4)> Public dwFlags As Integer <FieldOffset(8)> Public Count As Integer '\\ --JOB_NOTIFY_OPTIONS_TYPE <FieldOffset(12)> Public wType As Int16 <FieldOffset(14)> Public wReserved0 As Int16 <FieldOffset(16)> Public dwReserved1 As Int32 <FieldOffset(20)> Public dwReserved2 As Int32 <FieldOffset(24)> Public FieldCount As Int32 <FieldOffset(28)> Public pFields As IntPtr #Region "Public Enumerated Types" Public Enum Printer_Notification_Types PRINTER_NOTIFY_TYPE = &H0 JOB_NOTIFY_TYPE = &H1 End Enum Public Enum Printer_Notify_Field_Indexes PRINTER_NOTIFY_FIELD_SERVER_NAME = &H0 PRINTER_NOTIFY_FIELD_PRINTER_NAME = &H1 PRINTER_NOTIFY_FIELD_SHARE_NAME = &H2 PRINTER_NOTIFY_FIELD_PORT_NAME = &H3 PRINTER_NOTIFY_FIELD_DRIVER_NAME = &H4 PRINTER_NOTIFY_FIELD_COMMENT = &H5 PRINTER_NOTIFY_FIELD_LOCATION = &H6 PRINTER_NOTIFY_FIELD_DEVMODE = &H7 PRINTER_NOTIFY_FIELD_SEPFILE = &H8 PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR = &H9 PRINTER_NOTIFY_FIELD_PARAMETERS = &HA PRINTER_NOTIFY_FIELD_DATATYPE = &HB PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR = &HC PRINTER_NOTIFY_FIELD_ATTRIBUTES = &HD PRINTER_NOTIFY_FIELD_PRIORITY = &HE PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY = &HF PRINTER_NOTIFY_FIELD_START_TIME = &H10 PRINTER_NOTIFY_FIELD_UNTIL_TIME = &H11 PRINTER_NOTIFY_FIELD_STATUS = &H12 PRINTER_NOTIFY_FIELD_STATUS_STRING = &H13 PRINTER_NOTIFY_FIELD_CJOBS = &H14 PRINTER_NOTIFY_FIELD_AVERAGE_PPM = &H15 PRINTER_NOTIFY_FIELD_TOTAL_PAGES = &H16 PRINTER_NOTIFY_FIELD_PAGES_PRINTED = &H17 PRINTER_NOTIFY_FIELD_TOTAL_BYTES = &H18 PRINTER_NOTIFY_FIELD_BYTES_PRINTED = &H19 PRINTER_NOTIFY_FIELD_OBJECT_GUID = &H1A End Enum Public Enum Job_Notify_Field_Indexes JOB_NOTIFY_FIELD_PRINTER_NAME = &H0 JOB_NOTIFY_FIELD_MACHINE_NAME = &H1 JOB_NOTIFY_FIELD_PORT_NAME = &H2 JOB_NOTIFY_FIELD_USER_NAME = &H3 JOB_NOTIFY_FIELD_NOTIFY_NAME = &H4 JOB_NOTIFY_FIELD_DATATYPE = &H5 JOB_NOTIFY_FIELD_PRINT_PROCESSOR = &H6 JOB_NOTIFY_FIELD_PARAMETERS = &H7 JOB_NOTIFY_FIELD_DRIVER_NAME = &H8 JOB_NOTIFY_FIELD_DEVMODE = &H9 JOB_NOTIFY_FIELD_STATUS = &HA JOB_NOTIFY_FIELD_STATUS_STRING = &HB JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR = &HC JOB_NOTIFY_FIELD_DOCUMENT = &HD JOB_NOTIFY_FIELD_PRIORITY = &HE JOB_NOTIFY_FIELD_POSITION = &HF JOB_NOTIFY_FIELD_SUBMITTED = &H10 JOB_NOTIFY_FIELD_START_TIME = &H11 JOB_NOTIFY_FIELD_UNTIL_TIME = &H12 JOB_NOTIFY_FIELD_TIME = &H13 JOB_NOTIFY_FIELD_TOTAL_PAGES = &H14 JOB_NOTIFY_FIELD_PAGES_PRINTED = &H15 JOB_NOTIFY_FIELD_TOTAL_BYTES = &H16 JOB_NOTIFY_FIELD_BYTES_PRINTED = &H17 End Enum #End Region Public Sub New() '\\ As it stands, version is always 2 dwVersion = 2 '\\ We must have at least one notification - status makes sense to test with... 'NotifyJobStatus = True FieldCount = 1 Dim pfld1 As Short = Job_Notify_Field_Indexes.JOB_NOTIFY_FIELD_STATUS '\\ Use pointer to array per your suggestion... pFields = Marshal.AllocHGlobal(2) Marshal.WriteInt16(pFields, 0, pfld1) End Sub End Class And when I pass it to FindFirstPrinterChangeNotification it goes OK but when a print job occurs and the wait object triggers I have to call FindNextPrinterChangeNotification to get the info that has changed which I have declared thus:- <DllImport("winspool.drv", EntryPoint:="FindNextPrinterChangeNotification", _ SetLastError:=True, CharSet:=CharSet.Ansi, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function FindNextPrinterChangeNotification _ (<InAttribute()> ByVal hChangeObject As IntPtr, _ <OutAttribute()> ByRef pdwChange As IntPtr, _ <InAttribute()> ByVal pPrinterNotifyOptions As PrinterNotifyOptions, _ <OutAttribute()> ByRef lppPrinterNotifyInfo As IntPtr _ ) As Boolean End Function Now when this is called the variable pdwChange is filled with the correct value to indicate what has changed but lppPrinterNotifyInfo is never non-zero. Any thoughts at all? Thanks in advance, Duncan -
Marshalling as a pointer to an array of shorts?
Merrion
replied to Merrion
's topic in Interoperation / Office Integration
I'm having so many problems with this, I figured I'd attach the code for me/us to refer to....pqw.zip -
Marshalling as a pointer to an array of shorts?
Merrion
replied to Merrion
's topic in Interoperation / Office Integration
FindFirstPrinterChangeNotification - the element pFields in NOTIFY_OPTIONS is a pointer to a variable length linear array of 16 bit integers corresponding to i.e. JOB_NOTIFY_FIELD_STATUS... -
which is probably a good thing as I'm not very experienced in this .Net stuff yet Anyway - the API Exception class is wrong...the API declaration for FormatMessage should be... #Region "API Declarations" <DllImport("kernel32.dll", EntryPoint:="FormatMessageA", _ CharSet:=CharSet.Ansi, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function FormatMessage(ByVal dwFlags As Format_Message_Flags, ByVal lpSource As Int32, ByVal dwMessageId As Int32, ByVal dwLanguageId As Int32, ByVal lpBuffer As StringBuilder, ByVal nSize As Int32, ByVal Arguments As Int32) As Int32 End Function #End Region
-
*Resolved* ThreadPool.RegisterWaitForSingleObject - what to pass as Object? Never mind - it's there so you can pass anything you need to the callback procedure *sigh - so much to learn!*
-
The function ThreadPool.RegisterWaitForSingleObject takes parameters WaitHandle, WaitOrTimerCallback, Object, Integer, Boolean WaitHandle is the handle to be waited on, WaitOrTimerCallback is a delegate sub, Integer is the timeout in millisecond (or -1 for infinite) Boolean is whether this is only fired once But what goes in Object ? Thanks in advance, Baffled of Ballsbridge
-
I'm using the FindFirstPrinterChangeNotification API call declared thus:- <DllImport("winspool.drv", EntryPoint:="FindFirstPrinterChangeNotification", _ SetLastError:=True, CharSet:=CharSet.Ansi, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Function FindFirstPrinterChangeNotification _ (ByVal mhPrinter As Int32, _ ByVal fwFlags As Int32, _ ByVal fwOptions As Int32, _ ByRef pPrintOptions As PRINTER_NOTIFY_OPTIONS ) As Int32 '\\ No code here .... End Function and the printer_notify _options thing is declared thus:- <StructLayoiut(LayoutKind.Sequential> _ Public Structure PRINTER_NOTIFY_OPTIONS Dim dwVersion As Int32 Dim dwFlags As Int32 Dim Count As Int32 <MarhalAs(UnmanagedType.LpStruct)> Dim pTypeJob As PRINTER_NOTIFY_OPTIONS_TYPE End Structure but when the code gets to the call it throws an exception "System.TypeLoadException" trying to pass a structure as an LPStruct. "Additional information: Can not marshal field pType of type PRINTER_NOTIFY_OPTIONS: Marshalling types to LPStruct is not supported on structure fields" I gather that the line:- <MarhalAs(UnmanagedType.LpStruct)> Dim pTypeJob As PRINTER_NOTIFY_OPTIONS_TYPE is wrong - but how do I pass a pointer to a structure as a member of another structure to an API call? Thanks in advance, Duncan
-
In fact AllocHGlobal seems to be a better solution as I don't know the array size and the <MarshalAs()> will only get the first element in that case...
-
**untested**`VarPtr equivalent It may be possible thus:- <StructLayout(LayoutKind.Sequential>_ Private Structure PRINTER_NOTIFY_OPTIONS_TYPE Dim wType As Int16 Dim wReserved0 As Int16 Dim dwReserved1 As Int32 Dim dwReserved2 As Int32 Dim Count As Int32 <MarshalAs(UnmanagedType.LPArray)>Dim pFields() As Int16 End Structure unfortunately I've a whole heap more converting of old VB6 code to go beforte I can test this out. Thanks in advance, Duncan
-
The structure PRINTER_NOTIFY_OPTIONS_TYPE has a pointer to a variable length array of 16 bit integer flags as it's last member. In VB-Classic I filled this by using the VarPtr keyword....how do I go about doing this in VB.Net? i.e. Private Structure PRINTER_NOTIFY_OPTIONS_TYPE Dim wType As Int16 Dim wReserved0 As Int16 Dim dwReserved1 As Int32 Dim dwReserved2 As Int32 Dim Count As Int32 '\\Number of elements in the array Dim pFields As Int32 '\\Pointer to the array End Type which is populated.... Dim arTypes(0) As Int16 arTypes(0) = Job_Notify_Indexes.JOB_NOTIFY_FIELD_STATUS With pTypeJob .wType = Printer_Notification_Types.JOB_NOTIFY_TYPE .Count = 1 '.pFields = ???? (was VarPtr(arTypes(0)) End With Thanks in advance, Duncan
-
Man - I should sue Microsoft to get that hour of my life refunded! Thanks for your help, Duncan
-
I have a component something like: <ToolboxBitmap("printer.bmp")> _ Public Class PrinterQueueWatch Implements Component '..... End Class which builds OK but when I add another project with a winform and make that the startup project and reference the PrintQueueWatch project from it nothing shows up in the Toolbox:Components list...what am I missing? Thanks in advance, Duncan
-
*Resolved* Last API error message Thanks muchly... Duncan
-
I am trying to get the last API error message thus:- Public Enum Format_Message_Flags FORMAT_MESSAGE_ALLOCATE_BUFFER = &H100 FORMAT_MESSAGE_IGNORE_INSERTS = &H200 FORMAT_MESSAGE_FROM_STRING = &H400 FORMAT_MESSAGE_FROM_HMODULE = &H800 FORMAT_MESSAGE_FROM_SYSTEM = &H1000 FORMAT_MESSAGE_ARGUMENT_ARRAY = &H2000 End Enum <DllImport("kernel32.dll", EntryPoint:="FormatMessageA", _ CharSet:=CharSet.Ansi, _ ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Private Function FormatMessage(ByVal dwFlags As Format_Message_Flags, ByVal lpSource As Int32, ByVal dwMessageId As Int32, ByVal dwLanguageId As Int32, ByVal lpBuffer As String, ByVal nSize As Int32, ByVal Arguments As Int32) As Int32 End Function Public Function GetAPIErrorMessageDescription(ByVal ApiErrNumber As Int32) As String Dim sError As New String("", MAX_MESSAGE_LENGTH) Dim lErrorMessageLength As Int32 lErrorMessageLength = FormatMessage(Format_Message_Flags.FORMAT_MESSAGE_FROM_SYSTEM, 0, ApiErrNumber, 0, sError, MAX_MESSAGE_LENGTH, 0) If lErrorMessageLength > 0 Then sError.Substring(0, lErrorMessageLength) End If GetAPIErrorMessageDescription = sError End Function But lErrorMessageLength seems to always return 0? I am using Windows XP. Thanks in advance, Duncan
-
Should these params be quoted? I'd have thought: asdf = SendMessage(hwndWinamp, WM_USER, 0, 0) ?
-
Err.LastDllError - what's the .Net equivalnet?
Merrion
replied to Merrion
's topic in Interoperation / Office Integration
Excellent - muchos gracias.. -
Err.LastDllError - what's the .Net equivalnet?
Merrion
replied to Merrion
's topic in Interoperation / Office Integration
It appears that you need to set the "SetLastError" attribute to make use of this e.g.: <System.Runtime.InteropServices.DLLImport("winspool.drv",EntryPoint:="GetJob",SetLastError:=True, _ CallingConvention:=CallingConvention.StdCall>_ Private Function GetJob(ByVal mhPrinter As Int32, _ ByVal dwJobId As Int32, _ ByVal Level As Print_Job_Command_Levels, _ ByVal lpJob As Int32, _ ByVal cbBuf As Int32, _ ByRef lpSizeNeeded As Int32) As Boolean End Function Incidentally - I'm not sure about "ByVal lpJob As Int32,". How should I pass a pointer to a byte buffer in? Thanks in advance, Duncan -
Err.LastDllError - what's the .Net equivalnet?
Merrion
replied to Merrion
's topic in Interoperation / Office Integration
*Resolved* Err.LastDllError Just what i was looking for - thanks...