Marshal.PtrToStringAnsi не работает в службе Windows?

Я написал DLL, которая вызывает Windows Spooler API, чтобы получить имя принтера и имя драйвера принтера, он прекрасно работает в консольном приложении. Тем не менее, я ничего не получил, когда я вызываю DLL в приложении Windows Services.

Вот мой исходный код DLL (т.е. PrinterUtility):

PRINTER_ENUM_LOCAL = 0x00000002,
PRINTER_ENUM_CONNECTIONS = 0x00000004,
public ArrayList getAllLocalPrinterInfo(LogWriter logger)
    {
        ArrayList printerInfoList = getAllLocalPrinterInfoV2(PrinterEnumFlags.PRINTER_ENUM_LOCAL | PrinterEnumFlags.PRINTER_ENUM_CONNECTIONS);
        foreach (PrinterInfoV2 printerInfo in printerInfoList)
        {
           logger.write("In dll Printer Name pointer:" + printerInfo.pPrinterName+"\nIn dll Printer Name:" + Marshal.PtrToStringAnsi(printerInfo.pPrinterName));
            logger.write("In dll Driver Name pointer:" + printerInfo.pDriverName+"\nIn dll Driver Name:" + Marshal.PtrToStringAnsi(printerInfo.pDriverName));
        }
        //return allLocalPrinterInfo;
        return printerInfoList;
    }

public ArrayList getAllLocalPrinterInfoV2(PrinterEnumFlags Flags)
    {
        return enumPrinters(Flags, 2);
    }

private ArrayList enumPrinters(PrinterEnumFlags Flags, UInt32 level)
    {
        bool result;
        ArrayList printerInfo = new ArrayList();
        UInt32 returned, needed = 0;
        UInt32 flags = Convert.ToUInt32(Flags);

        //find required size for the buffer
        result = EnumPrinters(flags, null, level, IntPtr.Zero, 0, out needed, out returned);
        if (Marshal.GetLastWin32Error() != Convert.ToUInt32(CredUIReturnCodes.ERROR_INSUFFICIENT_BUFFER))
        {
            throw new Exception("EnumPrinters 1 failure, error code=" + Marshal.GetLastWin32Error());
        }
        else
        {
            IntPtr buffer = Marshal.AllocHGlobal((int)needed);
            result = EnumPrinters(flags, null, level, buffer, needed, out needed, out returned);
            if (result)
            {
                if ((level > 0) || (level < 5))
                {
                    Type type = typeof(PrinterInfoV1);
                    switch (level)
                    {
                        case 1:
                            type = typeof(PrinterInfoV1);
                            break;
                        case 2:
                            type = typeof(PrinterInfoV2);
                            break;
                        case 3:
                            type = typeof(PrinterInfoV3);
                            break;
                        case 4:
                            type = typeof(PrinterInfoV4);
                            break;
                    }
                    int offset = buffer.ToInt32();
                    int increment = Marshal.SizeOf(type);
                    for (int i = 0; i < returned; i++)
                    {
                        printerInfo.Add(Marshal.PtrToStructure(new IntPtr(offset), type));
                        offset += increment;
                    }
                    Marshal.FreeHGlobal(buffer);
                    return printerInfo;
                }
                else
                {
                    Marshal.FreeHGlobal(buffer);
                    throw new Exception("The value of level is out of range");
                }
            }
            else
            {
                Marshal.FreeHGlobal(buffer);
                throw new Exception("EnumPrinters 2 failure, error code=" + Marshal.GetLastWin32Error());
            }
        }
    }

   [DllImport("winspool.drv", SetLastError = true)]
    static extern bool EnumPrinters([InAttribute()] UInt32 Flags,
                                    [InAttribute()] string pPrinterName,
                                    [InAttribute()] UInt32 Level,
                                    [OutAttribute()] IntPtr pPrinter,
                                    [InAttribute()] UInt32 cbBuf,
                                    [OutAttribute()] out UInt32 pcbNeeded,
                                    [OutAttribute()] out UInt32 pcReturned);

Исходный код LogWriter:

  public class LogWriter
{
    EventLog eventLog = null;
    public LogWriter(System.Diagnostics.EventLog elog)
    {
        this.eventLog = elog;
    }
    public void write(String msg)
    {
        if (eventLog != null)
        {
            eventLog.WriteEntry(msg);
        }
    }
}

Вот исходный код сервисов:

    protected override void OnStart(string[] args)
    {
        serviceStatus.dwWaitHint = 100000;
        serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING;
        SetServiceStatus(this.ServiceHandle, ref serviceStatus);

        printerMonitorList = new ArrayList();
        try
        {

           ArrayList printerInfoList = printerUtility.getAllLocalPrinterInfo(logger);
            foreach (PrinterInfoV2 printerInfo in printerInfoList)
            {
                logger.write("In service Printer Name pointer:" + printerInfo.pPrinterName+"\nIn service Printer Name:" + Marshal.PtrToStringAnsi(printerInfo.pPrinterName));
                logger.write("In service Driver Name pointer:" + printerInfo.pDriverName+"\nIn service Driver Name:" + Marshal.PtrToStringAnsi(printerInfo.pDriverName));
            }
            serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING;
            SetServiceStatus(this.ServiceHandle, ref serviceStatus);
            logger.write(this.ServiceName + " Has Been Started");
        }
        catch (Exception err)
        {
            logger.write("Print Alert Service cannot be started:"+err.Message);
        }

В средстве просмотра событий я получил пустую строку для имени принтера и имени драйвера принтера. Тем не менее, я обнаружил, что DLL возвращает указатель как для имени принтера, так и для имени драйвера принтера. Поэтому я подозреваю, что функция Marshal.PtrToStringAnsi не работает в среде оконных служб.

0 ответов

Другие вопросы по тегам