Jump to content
Xtreme .Net Talk

Merrion

*Experts*
  • Posts

    269
  • Joined

  • Last visited

Everything posted by Merrion

  1. 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
  2. I'm having so many problems with this, I figured I'd attach the code for me/us to refer to....pqw.zip
  3. 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...
  4. How do I pass a variable length array of short values to an API call? I have tried <MarshalAs(UnmanagedTypes.LPArray)>pFields() As Short but it generates a loadlibrary exception... Any ideas? Thanks in advance, Duncan
  5. 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
  6. *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!*
  7. 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
  8. My mistake - it wasn't a pointer-to-struct at all...should have been: <StructLayout(LayoutKind.Sequential> _ Public Structure PRINTER_NOTIFY_OPTIONS Dim dwVersion As Int32 Dim dwFlags As Int32 Dim Count As Int32 Dim pTypeJob As PRINTER_NOTIFY_OPTIONS_TYPE End Structure
  9. 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
  10. 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...
  11. **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
  12. 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
  13. Man - I should sue Microsoft to get that hour of my life refunded! Thanks for your help, Duncan
  14. 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
  15. *Resolved* Last API error message Thanks muchly... Duncan
  16. 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
  17. Should these params be quoted? I'd have thought: asdf = SendMessage(hwndWinamp, WM_USER, 0, 0) ?
  18. 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
  19. *Resolved* Err.LastDllError Just what i was looking for - thanks...
  20. How can I get similar functionality to Err.LastDllError (from VB5/6) in VB.Net? I presume GetLastError api call is still suspect because of API functions that may trample on the error code being called internally by the programming language?
×
×
  • Create New...