2009-09-09 14 views
10

Estoy tratando de imprimir en una aplicación C# .NET 3.5 a una impresora de red y conseguir esta excepción:resultados PrintDocument.Print en Win32Exception La operación se ha completado con éxito

La operación se ha completado con éxito

¿Qué lo está causando y cómo se puede resolver?

System.ComponentModel.Win32Exception: The operation completed successfully 
    at System.Drawing.Printing.PrinterSettings.GetHdevmodeInternal() 
    at System.Drawing.Printing.PrinterSettings.GetHdevmode(PageSettings pageSettings) 
    at System.Drawing.Printing.PrintController.OnStartPrint(PrintDocument document, PrintEventArgs e) 
    at System.Windows.Forms.PrintControllerWithStatusDialog.OnStartPrint(PrintDocument document, PrintEventArgs e) 
    at System.Drawing.Printing.PrintController.Print(PrintDocument document) 
    at System.Drawing.Printing.PrintDocument.Print() 
  • la cuenta tiene permisos para imprimir con la impresora de red. Los permisos están configurados para Todos para imprimir.
  • la impresora se ha eliminado y vuelto a crear.
  • la configuración de la cola versus la impresión directamente en la impresora se ha cambiado en ambos sentidos.
  • otras impresoras en la máquina funcionan bien
  • otros clientes en la red y aplicaciones en esta misma máquina pueden imprimir a esta impresora sin problema.

Para reducir el problema, he creado una aplicación de consola simple. Funcionando como un usuario normal, la aplicación se imprime. Cuando se ejecuta como la cuenta de servicio, se equivoca para la cuenta de servicio.

enter image description here

La resolución a mi problema era que desinstalar el controlador que está causando el problema, e instalar un controlador antiguo.

+1

He recibido este error antes: el mensaje de error es realmente engañoso. Me imagino que tienes esto terminado, pero si no publicas algún código, te responderé. – Brandi

+0

@ p.campbell lo siento, no. Recuerdo que la falta de documentación sobre estos temas era extremadamente frustrante, así que lamento no poder ser de más ayuda. Tengo un par de preguntas antiguas que publiqué en ese momento sobre temas de impresión semi relacionados, no estoy seguro de si serán relevantes o no, o si ya las ha revisado. – Brandi

Respuesta

1

Es muy difícil responder sin código y una excepción que dice que todo está bien. Así que solo daré algunas ideas para rastrear el problema

  1. Pruébelo en una impresora local para asegurarse de que la aplicación funciona.
  2. Intente imprimir en la impresora en red usando el bloc de notas o algo similar
  3. Doble o triple comprobación de que el usuario de la aplicación se está ejecutando como tiene permisos para imprimir en la impresora de red.
  4. prueba en otra impresora en red (después de hacer 2 y 3 para que la impresora)
17

El mensaje desconcertante es causado por un error en el código PInvoke dentro del marco .NET. La llamada subyacente de winapi que falla es DocumentProperties() function. La declaración de PInvoke se ve así:

[DllImport("winspool.drv", CharSet=CharSet.Auto, SetLastError=true)] 
public static extern int DocumentProperties(...); 

la SetLastError propiedad es incorrecta. Como puede ver en el enlace de MSDN, la función indica un error al devolver un valor negativo. Y es no documentado para establecer el código de error devuelto por GetLastError().

La consecuencia de este error es que el marco llamará a Marshal.GetLastWin32Error() para obtener el código de error y obtendrá un valor aleatorio ya que DocumentProperties() no lo configuró. No es improbable un valor de 0, que produce el mensaje de excepción "La operación se completó correctamente".

Por lo tanto, debe ignorar el mensaje de excepción; es muy inútil, por supuesto. Desafortunadamente, esta función winapi cae dentro de una categoría de funciones, como la mayoría de las funciones GDI, que solo producen un código de retorno "no funcionó". No da pistas sobre dónde buscar el problema. Hay una razón medio decente para esta peculiaridad: Windows hace muy poco cuando llama al DocumentProperties(); la mayor parte del trabajo lo realiza el controlador de la impresora. No hay un conjunto de códigos de error reservados para imprimir en winapi. Todo es posible: los controladores de impresora no son trozos sutiles de código. El trabajo del controlador de la impresora es informarle sobre los problemas. Se supone que deben hacerlo al abrir su propia ventana. Teóricamente son de todos modos; la feroz competencia en ese segmento del mercado no deja mucho dinero para pagar un buen salario de programador en estos días.

Esto, por supuesto, no puede funcionar cuando imprime desde un servicio. No hay ninguna manera de ver esa ventana emergente, que es la razón principal por la que Microsoft fuertemente desalienta la impresión de un servicio. Ni usted ni el personal de TI de sus clientes tienen la oportunidad de diagnosticar problemas. Lea esto blog post para obtener notas adicionales sobre el uso de PrintDocument de un servicio.

A nadie le gusta recibir consejos como este, pero la escritura está en la pared. No lo hagas.

5

Para añadir a la respuesta de @ HansPassant, aquí está el código exacto en cuestión que produce la excepción:

Microsoft Fuente de referencia, PrinterSettings.cs

private IntPtr GetHdevmodeInternal(string printer) { 
    // Create DEVMODE 
    int modeSize = SafeNativeMethods.DocumentProperties(NativeMethods.NullHandleRef, NativeMethods.NullHandleRef, printer, IntPtr.Zero, NativeMethods.NullHandleRef, 0); 
    if (modeSize < 1) { 
     throw new InvalidPrinterException(this); 
    } 
    IntPtr handle = SafeNativeMethods.GlobalAlloc(SafeNativeMethods.GMEM_MOVEABLE, (uint)modeSize); // cannot be <0 anyway 
    IntPtr pointer = SafeNativeMethods.GlobalLock(new HandleRef(null, handle)); 

    //Get the DevMode only if its not cached.... 
    if (cachedDevmode != null) { 
     Marshal.Copy(cachedDevmode, 0, pointer, devmodebytes); 
    } 
    else { 
     int returnCode = SafeNativeMethods.DocumentProperties(NativeMethods.NullHandleRef, NativeMethods.NullHandleRef, printer, pointer, NativeMethods.NullHandleRef, SafeNativeMethods.DM_OUT_BUFFER); 
     if (returnCode < 0) { 
      throw new Win32Exception(); // <-------- 
     } 
    } 
0

También tuve este problema. En mi caso, utilicé un subproceso separado para imprimir el informe y lo sincronicé con el subproceso principal a través de "ManualResetEvent". (He desarrollado esto porque las fuerzas .Net dividen la lógica de impresión en los métodos de "PrintPage" ...).

El error ocurre debido a una incompatibilidad (que no puedo explicar la fuente) entre el controlador de la impresora y este entorno multihilo.

Resolví el problema cambiando la firma de mi método de lógica de impresión de "nulo" a "IEnumerable", y rompí el retorno de rendimiento, un método similar a las "CoRoutines" del motor de juegos Unity3d. De esta forma, no es necesario crear más de un hilo, y mi código de impresión se organiza.

+0

No estoy seguro de por qué esto fue downvoted, pero me ayudaste a solucionar un problema en el que estaba trabajando durante días. Para fines de prueba, lancé mi impresión en el hilo de la interfaz de usuario y funcionó, volví a iniciar la impresión desde otro hilo y actualicé el controlador de la impresora al último lanzamiento oficial de HP y funciona ahora. Antes estaba usando PCL6 6.2.6 universal de HP. A ese controlador no le gusta que lo llamen en un entorno multiproceso. –

+0

6.2.1, lo siento. HP Universal Printing PCL 6 (v6.2.1) –

Cuestiones relacionadas