delphi delphi-2010 clipboard copy-paste

delphi - ¿Cómo puedo corregir los errores "No se puede abrir el portapapeles: acceso denegado"?



delphi-2010 clipboard (6)

Estoy usando el siguiente código para copiar texto en el portapapeles:

Clipboard.Open; try Clipboard.AsText := GenerateClipboardText; finally Clipboard.Close; end;

Aparentemente, al azar, aparece el mensaje "No se puede abrir el portapapeles: acceso denegado". Supongo que estos errores son causados ​​por otra aplicación que bloquea el portapapeles, pero parece que nunca hago nada con otras aplicaciones que deberían causar bloqueos.

Extrañamente, mis usuarios parecen estar reportando más errores con Vista y Windows 7 que con XP.

¿Hay alguna forma de comprobar si el portapapeles está bloqueado antes de intentar acceder a él?


Este no es un problema Delphi. Debido a que el portapapeles se puede bloquear en cualquier momento, incluso si lo comprueba, si el portapapeles no está bloqueado actualmente, podría bloquearse directamente después de la comprobación.

Tienes dos posibilidades aquí:

  1. No use la clase de Portapapeles de Delphi. En su lugar, use funciones API sin procesar, donde tendrá un control un poco más detallado sobre posibles situaciones de error.
  2. Espere que su código falle al agregar un manejador de excepciones. A continuación, agregue un código de reintento, es decir, vuelva a intentar establecer el texto tres veces, quizás con un retroceso exponencial, antes de lanzar su propio error.

Recomendaría la segunda solución, porque sería el enfoque más Delphi y al final dará como resultado un código más limpio.

while not Success do try //Set the clipboard Success := True; except on Exception do begin Inc(RetryCount); if RetryCount < 3 then Sleep(RetryCount * 100) else raise MyException.Create(''Cannot set clipboard''); end; end;


Intente comprobar GetClipboardOwner, si no es nulo y no es su Application.Handle, no puede Abrir para modificar su contenido.
E incluso parece ir bien, puede que ya no lo sea cuando lo haces.
Así que agrega una prueba excepto en un bucle hasta que la obtengas o renuncies bien (notificando al usuario, por ejemplo).


No hay forma de verificar algo y luego, dependiendo del resultado, hacer otra cosa con la expectativa de que no puede fallar, porque a menos que el control y la acción sean una operación atómica, siempre existe la posibilidad de que otro proceso o hilo haga lo mismo. en paralelo.

Esto es válido tanto si intenta abrir el portapapeles, abrir un archivo, crear o eliminar un directorio, simplemente debe intentar hacerlo, tal vez varias veces en un bucle, y manejar con gracia los errores.


Extrañamente, mis usuarios parecen estar reportando más errores con Vista y Windows 7 que con XP

Esto puede tener que ver con cómo Vista / Win7 se ocupa de la notificación del visor del portapapeles. Aunque todavía admiten la "cadena de visor del portapapeles" de XP, que envía un mensaje de notificación que debe enviarse de nuevo a cada oyente por turno (y si una aplicación no lo hace, las demás aplicaciones no reciben ninguna notificación). Comenzando con Vista, las aplicaciones se notifican directamente. Y no hay nada que evite que intenten acceder al portapapeles de una sola vez.

Analogía: tengo 3 hijos. Tengo un pastel. Con las reglas de XP, le digo al niño mayor que coma un poco, luego le digo al siguiente niño más grande que tome una porción. Ella obtiene su porción, le dice a su hermano, él le da la suya, y le dice a su hermano, quien se la da, y todo procede de una manera ordenada.
Problema: el niño del medio lleva la torta a su habitación, no le dice a la más joven, y la más joven se pierde.

Con Vista / Windows7, ese sistema aún existe. Pero las aplicaciones más nuevas pueden solicitar ser notificadas inmediatamente, tan pronto como llegue el pastel a la cocina. Grito "¡la torta está lista!" y todos aparecen al mismo tiempo y tratan de agarrar un poco. Pero solo hay un cuchillo para servir, por lo que deben seguir buscando el cuchillo, no obtenerlo y esperando la próxima oportunidad.


En primer lugar, tenga en cuenta que esto probablemente no sea un problema en su aplicación. Otras aplicaciones bloquearon el portapapeles o arruinaron la cadena de notificaciones y ahora su aplicación no puede acceder a ella. Cuando tengo problemas como este, reinicio la computadora y mágicamente se van ... bueno ... al menos hasta que vuelva a ejecutar la aplicación que crea el problema.

Este código (no verificado en Delphi) puede ayudarlo. No solucionará el problema: la cadena de notificación está rota (nada excepto un reinicio de PC alguna vez lo arreglará) pero solucionará el problema si una aplicación bloquea el portapapeles por un tiempo. Aumente las MaxRetries si esa molesta aplicación mantiene el portapapeles bloqueado durante UN PERÍODO MUY LARGO (segundos):

procedure Str2Clipboard(CONST Str: string; iDelayMs: integer); CONST MaxRetries= 5; VAR RetryCount: Integer; begin RetryCount:= 0; for RetryCount:= 1 to MaxRetries DO TRY inc(RetryCount); Clipboard.AsText:= Str; Break; EXCEPT on Exception DO if RetryCount = MaxRetries then RAISE Exception.Create(''Cannot set clipboard'') else Sleep(iDelayMs) END; end;

Además, puede ser una buena idea dejar caer el ''subir'' y convertirlo a una función y usarlo así:

if not Str2Clipboard then Log.AddMsg(''Dear user, other applications are blocking the clipboard. We have tried. We really did. But it didn''''t work. Try again in a few seconds.'');


Supongo que está ejecutando su aplicación en Win 8 o superior.

Simplemente haga clic con el botón derecho en su archivo .exe de la aplicación, vaya a la pestaña Compatibilidad y cambie el modo de compatibilidad en Windows XP o versiones anteriores. Funcionará, ¡garantizado!