Neha

New Member
Joined
Apr 3, 2009
Messages
2
Hello, my application has a feature that shows printers details as tree node and I use EnumPrinters API to fill nodes of this tree. i.e., the provider name, domain names and printer names etc. We have used Lazy loading concept in this tree formation. EnumPrinters API is called for any node level details and count on output records is used to fetch next inner level detail for any node. when EnumPrinters is called for any printername given it works fine on all platforms except VISTA. I have also attached sample code to give idea on APIs used. Below code words fine on all platforms, but on vista it returns error code 87. Does Vista needs special changes in code to handle the scenario? Whats wrong is going on here for Vista?//Code Starts from here. This is C# console application. Enumprinters gives error in second call to GetPrinters() when called for printer names on Vista.usingSystem; usingSystem.Runtime.InteropServices;usingSystem.Runtime.Serialization;classPlatformInvokeTest{[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] private class PRINTER_INFO_1{ public int flags; public IntPtr pDescription; public IntPtr pName; public IntPtr pComment; }[StructLayout(LayoutKind.Sequential)] private struct PRINTER_INFO_2{ public IntPtr pServerName; public IntPtr pPrinterName; public IntPtr pShareName; public IntPtr pPortName; public IntPtr pDriverName; public IntPtr pComment; public IntPtr pLocation; public IntPtr pDevMode; public IntPtr pSepFile; public IntPtr pPrintProcessor; public IntPtr pDatatype; public IntPtr pParameters; public IntPtr pSecurityDescriptor; public Int32 Attributes; public Int32 Priority; public Int32 DefaultPriority; public Int32 StartTime; public Int32 UntilTime; public Int32 Status; public Int32 cJobs; public Int32 AveragePPM; } public struct PrinterInfo_1{ public int flags; public string Name; public string Description; public string Comment; } public struct PrinterInfo_2{ public string ServerName; public string PrinterName; public string ShareName; public string PortName; public string DriverName; public string Comment; public string Location; public int Status; }[DllImport("winspool.drv", SetLastError = true, CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool EnumPrinters( [MarshalAs(UnmanagedType.U4)] PRINTER_ENUM flags, [MarshalAs(UnmanagedType.LPTStr)] string sName, uint iLevel, IntPtr pPrinterDesc, uint iSize, [MarshalAs(UnmanagedType.U4)] ref uint iNeeded, [MarshalAs(UnmanagedType.U4)] ref uint iReturned ); public enum PRINTER_ENUM{DEFAULT = 0x00000001,LOCAL = 0x00000002,CONNECTIONS = 0x00000004,NAME = 0x00000008,REMOTE = 0x00000010,SHARED = 0x00000020,NETWORK = 0x00000040} public enum DETAIL_TYPE{Providername = 0x00000001,Printername = 0x00000002,printerdetail = 0x00000004,None = 0x00000008,} public sealed class Win32Error{ private Win32Error() { } public const int ERROR_INSUFFICIENT_BUFFER = 122; } static PrinterInfo_1[] GetPrinterInfoFromMemory( IntPtr prInfo,uint numPrinters, DETAIL_TYPE type) { PRINTER_INFO_1 pi = new PRINTER_INFO_1(); PrinterInfo_1[] pInfo = new PrinterInfo_1[numPrinters]; for (int i = 0; i < numPrinters; i++) { Marshal.PtrToStructure(prInfo, pi); pInfo.flags = pi.flags;pInfo.Name =Marshal.PtrToStringAuto(pi.pName); pInfo.Description =Marshal.PtrToStringAuto(pi.pDescription); pInfo.Comment =Marshal.PtrToStringAuto(pi.pComment); prInfo =new IntPtr(prInfo.ToInt32() + Marshal.SizeOf(typeof(PRINTER_INFO_1))); if (type == DETAIL_TYPE.Printername) {printerArray.Add(pInfo.Name);}} return pInfo; } static PrinterInfo_1[] GetPrinters(PRINTER_ENUM printerKind, string strName, DETAIL_TYPE type) { PrinterInfo_1[] pInfo = new PrinterInfo_1[0]; uint iNeeded = 0, iReturned = 0, iSize = 0; IntPtr printers = IntPtr.Zero; if (!EnumPrinters(printerKind, strName,1,printers,0, ref iNeeded, ref iReturned) ){ int err = Marshal.GetLastWin32Error(); if (err != Win32Error.ERROR_INSUFFICIENT_BUFFER) {} // ThrowEnumPrinterException();}iSize = iNeeded; if (iNeeded != 0) { try{printers =Marshal.AllocHGlobal(new IntPtr(iSize)); if (!EnumPrinters(printerKind, strName,1,printers,iSize, ref iNeeded, ref iReturned) ){ // ThrowEnumPrinterException();} else{pInfo = GetPrinterInfoFromMemory(printers, iReturned, type);}} finally{ if (printers != IntPtr.Zero) Marshal.FreeHGlobal(printers); }} return pInfo; } static System.Collections.ArrayList printerArray; public static void Main() {printerArray =new System.Collections.ArrayList(); string printerName = "Microsoft Office Document Image Writer"; GetPrinters(PRINTER_ENUM.LOCAL, null, DETAIL_TYPE.Printername); for (int i = 0; i < printerArray.Count; i++) {GetPrinters(PRINTER_ENUM.NAME, printerArray.ToString(), DETAIL_TYPE.None); }}}
 


Solution
It seems like you are experiencing an issue with the EnumPrinters API when running your code on Windows Vista, specifically encountering an error code 87. Error code 87 typically indicates an incorrect parameter passed to a Windows API function. In your code snippet, the issue might be related to how you are handling memory allocations and data structures when calling EnumPrinters for printer names on Vista. Here are a few points to consider and potential areas to investigate:
  1. Memory Allocation: Ensure that memory is allocated correctly for the data structures used in the EnumPrinters call. Check if the memory allocation and deallocation are done properly, especially when handling the PRINTER_INFO_1 and PRINTER_INFO_2...
It seems like you are experiencing an issue with the EnumPrinters API when running your code on Windows Vista, specifically encountering an error code 87. Error code 87 typically indicates an incorrect parameter passed to a Windows API function. In your code snippet, the issue might be related to how you are handling memory allocations and data structures when calling EnumPrinters for printer names on Vista. Here are a few points to consider and potential areas to investigate:
  1. Memory Allocation: Ensure that memory is allocated correctly for the data structures used in the EnumPrinters call. Check if the memory allocation and deallocation are done properly, especially when handling the PRINTER_INFO_1 and PRINTER_INFO_2 structures.
  2. Error Handling: It's important to handle errors properly. Verify that the error checking and handling mechanisms are correctly implemented in your code.
  3. Platform Compatibility: Windows Vista might have slightly different behavior in handling certain API calls compared to other Windows versions. Consider checking the documentation for EnumPrinters API specifically for Windows Vista to see if there are any platform-specific considerations or requirements.
  4. Parameter Passing: Double-check the parameters being passed to EnumPrinters, especially the flags and the level parameters. Ensure that they align with the expected values and data types.
  5. Memory Alignment: Make sure that the memory alignment of the data structures matches the requirements set by the Windows API functions.
  6. Debugging: You can use debugging tools to trace the issue more precisely. Debug the code on Windows Vista to see where exactly the error is occurring. Given the complexity of the issue, debugging the code on a Windows Vista machine and carefully examining the memory handling and API parameter passing would be crucial steps in resolving the error code 87 you are encountering.
 


Solution
Back
Top