Cómo funcionan el portapapeles y arrastrar y soltar — tratar correctamente la transferencia de datos OLE en aplicaciones empresariales

· Actualizado el: · · Windows, Portapapeles, Arrastrar y soltar, OLE, COM, Desarrollo en Windows, WinForms, WPF

Historial de revisiones (primera versión, publicada el 21 Aug 2026)
Primera publicación
Citar este artículo(DOI (archivo registrado): 10.5281/zenodo.22176597)

Los DOI siguientes remiten a versiones ya archivadas y pueden diferir del texto actual. Para citar el texto actual, utilice la URL de esta página.

Go Komura (2026). Cómo funcionan el portapapeles y arrastrar y soltar — tratar correctamente la transferencia de datos OLE en aplicaciones empresariales. KomuraSoft LLC. https://comcomponent.com/es/blog/windows-clipboard-drag-drop-ole-data-transfer/

DOI (archivo registrado)
10.5281/zenodo.22176597
DOI (última versión registrada)
10.5281/zenodo.22176598

«Al pegar una tabla de Excel, se deshace el formato.» «El contenido copiado en nuestra aplicación no llega a Word de la forma prevista.» «Queremos incorporar archivos arrastrándolos y soltándolos.» — Peticiones así aparecen a menudo al revisar aplicaciones empresariales.

Todas son operaciones cotidianas, pero si se piensa el portapapeles como «una caja que guarda un solo dato», se malinterpreta el mecanismo. En realidad coloca el mismo contenido en varios formatos a la vez y deja que el lado que pega elija el formato que entiende. Por eso la misma copia produce resultados distintos según dónde se pegue.

El problema de que el pegado falle al cerrar el origen involucra el «renderizado diferido», que produce los datos solo cuando hacen falta. Y el arrastrar y soltar OLE (D&D) entrega IDataObject, la misma representación de datos que el portapapeles OLE, a través de interfaces COM. Copiar y pegar y D&D son funciones emparentadas: comparten el formato de los datos y se diferencian en cómo se transportan.

Este artículo está dirigido a responsables de TI de pequeñas y medianas empresas y a desarrolladores de aplicaciones Windows. Primero cubre cómo funcionan los formatos, luego las implementaciones del lado que pega, del lado que copia y de la vigilancia, y después pasa a la gestión del historial, la sincronización y RDP y a las trampas del D&D OLE.

1. Primero la conclusión

Hay tres ejes que conviene retener.

  1. El lado que copia ofrece varios formatos y el lado que pega elige entre ellos. Lo básico es CF_UNICODETEXT para texto, CF_HDROP para una lista de rutas de archivo y el formato registrado «HTML Format» para texto con formato.1234
  2. Diseñar no solo el formato de los datos, sino también su validación y su vida útil. Validar los datos pegados como entrada externa no confiable. Un lado que copia y usa renderizado diferido implementa también la materialización al salir. Vigilar con AddClipboardFormatListener y WM_CLIPBOARDUPDATE, y prepararse para la competencia de lectura con reintentos.5678
  3. Dejar claro hasta dónde viajan los datos y qué ocurre una vez entregados. El historial, la sincronización en la nube y la redirección RDP son objetos de gestión. El D&D OLE exige inicialización STA mediante OleInitialize, y una suelta desde privilegios normales hacia una aplicación elevada la bloquea UIPI. Además, Move es un contrato bajo el cual desaparecen los datos originales.910111213

Si se quiere leer por objetivo, empezar por el capítulo siguiente.

Problema u objetivo Qué comprobar primero Capítulo
Una tabla de Excel pegada se deshace Los formatos que ofrece el lado que copia y el formato que elige el lado que pega Capítulos 2-4
Hacer usable en otras aplicaciones una copia de la nuestra Ofrecer varios formatos y conservar los datos después de salir Capítulo 5
Detectar una copia e importarla automáticamente Registro del listener y reintentos de lectura Capítulo 6
Dejar secretos fuera del historial, la sincronización y RDP Los formatos de exclusión del lado de la aplicación y la directiva de la organización Sección 6.3, capítulo 7
Implementar D&D; solo falla al estar elevada Inicialización OLE, el límite de privilegios, efectos y validación de rutas Capítulos 8-9

En el diagrama, una línea continua marca una relación que siempre se cumple y una línea discontinua una relación condicional (las condiciones están en la explicación de cada relación en la página de detalle). La lista completa de relaciones (20 en total, con evidencia y grado de certeza) y las definiciones de los conceptos principales están reunidas en la página de detalle del mapa de conocimiento (en japonés). Datos: JSON-LD / Turtle

2. Qué es de verdad el portapapeles — no «un solo dato» sino «el mismo contenido en varios formatos»

El portapapeles es un mecanismo para compartir datos entre aplicaciones. Las aplicaciones del mismo escritorio pueden usarlo, pero la unidad precisa de compartición es la estación de ventanas. Una sesión de usuario distinta o una sesión RDP tiene cada una su propio portapapeles. Que copiar y pegar funcione en RDP se debe a que la redirección une ambos (capítulo 7).

El principio rector es que el uso lo dirige el usuario. La postura oficial de diseño es no meter ni sacar datos a espaldas del usuario.1

Tras vaciar el portapapeles, el lado que copia coloca el mismo contenido en varios formatos, del más expresivo hacia abajo.6 En lo conceptual, copiar una tabla en una hoja de cálculo se alinea así.

Prioridad Formato Contenido
1 Formato privado de la aplicación Representación interna completa, incluidas fórmulas y formato (para pegar en la misma aplicación)
2 HTML Format Un fragmento HTML que conserva la estructura de la tabla y el formato
3 CSV Texto delimitado por celdas
4 CF_UNICODETEXT Texto sin formato separado por tabulaciones
5 Formato de imagen Un mapa de bits del aspecto de la tabla

Lo que extrae el lado que pega es el formato que entiende de esta lista. Word obtiene una tabla con formato y el Bloc de notas texto separado por tabulaciones porque ambos eligieron formatos distintos.

Dicho de otro modo, «el resultado depende del destino del pegado» no es en sí un error. Hay que mirar juntos la oferta del lado que copia y la elección del lado que pega.

Cómo la misma copia produce resultados distintos según dónde se pegueEl lado que copia coloca el mismo contenido en el portapapeles en varios formatos y el lado que pega elige el formato que entiende, de modo que Word obtiene una tabla con formato y el Bloc de notas texto separado por tabulacionesWord elige esteEl Bloc de notas elige esteLado que copia: hoja de cálculoPortapapeles (el mismo contenido en varios formatos)Formato privado de la aplicaciónHTML FormatCSVCF_UNICODETEXTTabla con formatoTexto separado por tabulaciones

A la inversa, las quejas de apertura —«se deshace el formato», «se pega algo raro»— se reducen casi todas a cómo uno de los dos lados elige u ofrece formatos. El capítulo 4 cubre el lado que pega y el capítulo 5 el lado que copia.

3. Formatos estándar y formatos registrados — CF_UNICODETEXT, CF_HDROP, HTML Format

3.1. Formatos estándar — usar el lado Unicode para el texto

Los formatos que el sistema operativo define de antemano se llaman formatos estándar. Estos son los que aparecen con más frecuencia en las aplicaciones empresariales.2

Formato Valor Contenido
CF_TEXT 1 Texto ANSI (dependiente de la página de códigos)
CF_UNICODETEXT 13 Texto Unicode. Este es el formato canónico para el texto
CF_HDROP 15 Una lista de rutas de archivo (un identificador HDROP)
CF_DIB 8 Un mapa de bits independiente del dispositivo
CF_LOCALE 16 El identificador de configuración regional asociado al texto

CF_TEXT y CF_UNICODETEXT son «formatos sintetizados» que el sistema convierte implícitamente entre sí. La conversión usa la página de códigos asociada a CF_LOCALE.2

Sin embargo, los caracteres que ANSI no puede representar se pierden en la conversión. Si se tratan símbolos propios de Unicode, caracteres combinantes y similares, dejarlo en manos de la conversión lleva a caracteres ilegibles. La regla es unificar las lecturas y escrituras de la aplicación en CF_UNICODETEXT, o DataFormats.UnicodeText en .NET.

Conversión implícita entre CF_UNICODETEXT y CF_TEXTLa aplicación solo lee y escribe CF_UNICODETEXT; el sistema sintetiza CF_TEXT por conversión implícita con la página de códigos de CF_LOCALE. Los caracteres que ANSI no puede representar se descartan en esta conversiónEl sistema convierte de forma implícita (página de códigos de CF_LOCALE)Lecturas y escrituras de la aplicaciónCF_UNICODETEXT (canónico)CF_TEXT (ANSI, dependiente de la página de códigos)Los caracteres no representables se descartan en la conversión (caldo de cultivo de caracteres ilegibles)

3.2. CF_HDROP — los archivos viajan como «una lista de rutas»

CF_HDROP es lo que usa el Explorador de archivos para copias de archivos y D&D. Lo primero que conviene recordar es que lo que viaja es una lista de rutas completas, no los archivos propiamente dichos.

Una estructura DROPFILES ocupa el inicio del bloque de memoria, seguida de cadenas de ruta separadas por caracteres NUL. Se coloca una cadena vacía al final, así que el bloque termina en un «NUL doble». En el encabezado, pFiles es el desplazamiento de inicio de la lista de rutas y fWide indica si las cadenas son Unicode.3

[DROPFILES header: pFiles=start offset of the path list, fWide=1 (Unicode)]
C:\data\a.txt(NUL)C:\data\b.txt(NUL)(NUL)

En código nativo se recuperan una a una con DragQueryFile; en .NET se reciben como string[] mediante DataFormats.FileDrop. El punto de que «solo viajan rutas, no los archivos propiamente dichos» vuelve a importar para el D&D en los capítulos 8 y 9.

Estructura del bloque de memoria de CF_HDROPUna estructura DROPFILES ocupa el inicio de la memoria global; pFiles da el desplazamiento de inicio de la lista de rutas y fWide indica si es Unicode. Siguen rutas completas separadas por NUL, que terminan con una cadena vacía como terminador de NUL doble. Solo viajan rutas, no los archivos propiamente dichosEstructura DROPFILES (pFiles = desplazamiento de inicio de la lista / fWide = 1)C:\\data\\a.txt + NULC:\\data\\b.txt + NULCadena vacía terminal (NUL doble)Solo viajan rutas, no los archivos propiamente dichos

3.3. Formatos registrados — RegisterClipboardFormat y «HTML Format»

Los datos que los formatos estándar no pueden expresar se comparten como formato registrado bajo un nombre que se elige. Se pasa un nombre a RegisterClipboardFormat y se obtiene un identificador de formato. Registrar el mismo nombre desde otra aplicación da el mismo identificador, de modo que acordar un nombre entre aplicaciones es el punto de contacto.1

Al pasar datos estructurados entre la propia suite de aplicaciones, se usa un nombre que no choque, por ejemplo KomuraSoft.Report.RowData.

HTML Format es «UTF-8 con un encabezado»

El formato registrado representativo es «HTML Format», un formato de texto con formato que se sitúa junto a RTF. El cuerpo es texto UTF-8, pero delante va un encabezado que enumera desplazamientos en bytes.4

Version:0.9
StartHTML:<byte position where the whole HTML starts>
EndHTML:<byte position where the whole HTML ends>
StartFragment:<byte position where the fragment starts>
EndFragment:<byte position where the fragment ends>
<html><body>
<!--StartFragment--><b>Negrita</b> texto del fragmento<!--EndFragment-->
</body></html>

Cada desplazamiento se mide desde el inicio de los datos, incluido el propio encabezado. StartHTML / EndHTML apuntan a todo el HTML, y StartFragment / EndFragment al inicio y el final del fragmento que seleccionó el usuario. La unidad son bytes, no caracteres.

Al generarlo, se ensambla en este orden.

  1. Reservar los campos de desplazamiento a un ancho fijo (por ejemplo, 10 dígitos).
  2. Construir el cuerpo HTML y codificarlo como UTF-8.
  3. Medir las posiciones de byte tras la codificación y reescribirlas en el encabezado.

En UTF-8 que contiene japonés, el recuento de caracteres y el recuento de bytes no coinciden. Equivocarse aquí recorta el principio o el final al pegar en otra aplicación.4

Cómo se relaciona el encabezado de HTML Format con los desplazamientosEn el encabezado, StartHTML y EndHTML apuntan a todo el HTML y StartFragment y EndFragment al fragmento que seleccionó el usuario, todos como posiciones de byte desde el inicio de los datos. Como el recuento de caracteres y el de bytes divergen en UTF-8, se rellenan con posiciones de byte medidas tras la codificaciónEncabezado (Version / StartHTML / EndHTML / StartFragment / EndFragment)HTML completo (StartHTML a EndHTML)Fragmento seleccionado (StartFragment a EndFragment)Cada desplazamiento = posición de byte desde el inicio de los datos (medida tras la codificación UTF-8 y reescrita)

Además de estos, CSV (DataFormats.CommaSeparatedValue en .NET) también se usa a menudo para datos tabulares. Para la interoperabilidad con Excel, ofrecer juntos HTML Format (con formato), CSV (solo valores) y CF_UNICODETEXT (separado por tabulaciones) funciona sea cual sea el destino del pegado.

4. Prácticas del lado que pega — prioridad de formatos y validación

4.1. Buscar desde los formatos enriquecidos hacia abajo

El lado que pega busca entre los formatos que puede tratar, empezando por el que más información lleva. Se puede usar el orden en que el lado que copia colocó los formatos, del más expresivo hacia abajo, o indicar una lista propia de prioridades.6

API de Win32 Cómo elige
EnumClipboardFormats Enumera en el orden en que el lado que copia los colocó; usar el primer formato reconocido
GetPriorityClipboardFormat Elige un formato disponible de la lista de prioridades que pasa el lado que pega

En .NET la ramificación queda así.

// Pegado de una tabla: buscar de enriquecido a plano
var data = Clipboard.GetDataObject();
if (data is null) return;

// Anunciar un formato no garantiza que la carga útil sea un string. Usar esta
// rama solo cuando también encaje el tipo; si no, caer al candidato siguiente
if (data.GetDataPresent(DataFormats.Html)
    && data.GetData(DataFormats.Html) is string html)
{
    // Validar el encabezado de HTML Format y luego importar como tabla
}
else if (data.GetDataPresent(DataFormats.CommaSeparatedValue))
{
    // Importar como CSV
}
else if (data.GetDataPresent(DataFormats.UnicodeText))
{
    // Importar como texto separado por tabulaciones
}

Esta es la respuesta a la queja de apertura de que una tabla de Excel pegada se deshace. La estructura de la tabla nunca llega a una aplicación que solo lee texto sin formato. Hasta dónde se acepta la lista de formatos es una decisión de diseño del lado que pega.

Ramificación de pegado que busca desde los formatos enriquecidos hacia abajoSi HTML Format está presente y la carga útil es un string, importar como tabla; si no, CSV; a falta de eso, texto separado por tabulaciones, bajando desde el formato más expresivo. Si no hay ningún candidato, rechazarSíNoSíNoSíNoIniciar el pegado¿HTML Format presente y la carga útil es un string?Validar el encabezado e importar como tabla¿CSV presente?Importar como CSV¿UnicodeText presente?Importar como texto separado por tabulacionesRechazar

4.2. Los datos pegados son entrada externa

Es fácil pasarlo por alto, pero el contenido del portapapeles es de origen externo, y no se sabe qué aplicación lo colocó. El propio Microsoft advierte en la documentación del portapapeles OLE que los datos del portapapeles no son de confianza y que hay que analizarlos con cuidado antes de usarlos en la aplicación.5

La sola presencia de un formato no dice que los datos se puedan importar. Comprobar también el tipo de la carga útil real y pasar las comprobaciones siguientes.

Qué validar Qué comprobar
El encabezado de HTML Format Si los desplazamientos apuntan fuera del rango. Algunas aplicaciones emiten encabezados rotos
Valores como números, fechas y códigos Si pasan la misma validación que la entrada en pantalla
El tamaño de los datos Si supera el límite de aceptación, como imágenes de cientos de megabytes o texto de millones de líneas

Tener en cuenta que la materialización empieza antes de poder comprobar el tamaño

En las defensas contra datos enormes, hay que distinguir la carga de qué etapa se puede impedir. GetData de .NET también dispara el renderizado diferido al llamarse y, en texto, materializa hasta una cadena administrada. Comprobar el tamaño solo después de la recuperación no impide la carga de esa materialización.

Si se examina con GlobalSize el HGLOBAL que devuelve GetClipboardData de Win32, se puede defender contra el hecho de empujar datos enormes hacia la conversión a cadena administrada y el análisis. En formatos de renderizado diferido, sin embargo, GetClipboardData mismo dispara el renderizado. No se puede impedir que el origen de la copia materialice los datos propiamente dichos.

Para que la interfaz no se congele, sacar la recuperación del subproceso de IU y rechazar los datos que superen el límite. Aun así, Clipboard de .NET exige STA. Usar un subproceso dedicado configurado en STA, no el grupo de subprocesos (MTA) de Task.Run (sección 5.1).

La idea de que «un valor que llega de fuera se valida antes de usarse, sea cual sea su camino» es la misma que se expone en «No confíe en el valor decodificado de un código QR sin validarlo». La suposición de que pegar es seguro porque es una acción del usuario es cómo se llega al incidente.

Validar los datos pegados antes de usarlosLos datos tomados del portapapeles pasan, en ese orden, por comprobaciones de presencia del formato, tipo de carga útil, límite de tamaño y contenido; si alguna falla, rechazar o caer al formato candidato siguienteTipo incorrectoDemasiado grandeNo válidoComprobar que el formato está presente (GetDataPresent)Comprobar el tipo de la carga útil (is string / string[])Comprobar el límite de tamañoValidar el contenido (encabezado, rutas, valores)ImportarRechazar / formato candidato siguiente

5. Prácticas del lado que copia — ofrecer varios formatos a la vez y el renderizado diferido

5.1. Colocar varios formatos a la vez

La práctica del lado que copia es el espejo de 4.1: ofrecer a la vez un formato enriquecido y uno plano. Con el DataObject de WinForms/WPF son unas pocas líneas.14

// WinForms (System.Windows.Forms). WPF tiene la misma forma con DataObject/Clipboard de System.Windows
var data = new DataObject();
data.SetData(DataFormats.Html, htmlFormatText);       // Cadena HTML Format con el encabezado
data.SetData(DataFormats.CommaSeparatedValue, csv);   // CSV
data.SetData(DataFormats.UnicodeText, plainText);     // Texto sin formato
Clipboard.SetDataObject(data, copy: true);            // copy:true = conservar tras salir de la aplicación

Aquí se separan el requisito de subproceso y la vida útil después de salir.

Requisito de subproceso: la clase Clipboard de .NET solo se puede usar desde un subproceso STA.14 El subproceso de IU de WinForms/WPF es STA por [STAThread], así que normalmente no es un problema, pero no se puede usar desde un subproceso en segundo plano que no sea STA. El fondo se explica en «Conocimientos básicos de STA/MTA en COM».

Vida útil después de salir: copy: true significa «conservarlo después de que la aplicación salga». Entenderlo junto con el renderizado diferido que sigue aclara por qué hace falta esta indicación.

5.2. Renderizado diferido — por qué «cerrar y ya no se puede pegar»

Generar cada uno de muchos formatos en cada copia significa trabajar incluso para formatos que nunca se usan. El mecanismo que lo evita es el renderizado diferido (delayed rendering).6

Al copiar, se pasa NULL como identificador de datos a SetClipboardData, y se registra no los datos propiamente dichos sino una promesa de «producirlos cuando se pidan». Cuando se solicita ese formato, llega WM_RENDERFORMAT al origen de la copia, y solo entonces se generan los datos.

Al salir, convertir la «promesa» en datos

Si el origen de la copia sale dejando formatos sin renderizar, el lado que pega ya no puede recibir esos datos. Este es el problema de «cerrar el origen y ya no se puede pegar».

Antes de salir, el origen de la copia tiene la responsabilidad de responder a WM_RENDERALLFORMATS y materializar cada formato no renderizado. Los formatos que no se materializaron se pierden cuando el origen de la copia sale.6

El flujo del renderizado diferido y «cerrar y ya no se puede pegar»El origen de la copia registra solo una promesa con un identificador NULL y materializa los datos con WM_RENDERFORMAT cuando llega una petición. Al salir tiene la responsabilidad de materializar cada formato con WM_RENDERALLFORMATS; si se omite, el formato se pierdeMaterializar con WM_RENDERALLFORMATSOmitir la materializaciónOrigen de la copia: registrar solo una promesa con SetClipboardData(format, NULL)El lado que pega solicita ese formatoWM_RENDERFORMAT → generar los datos en el actoEl origen de la copia está a punto de salirEl pegado sigue funcionando tras salirEse formato se pierde (cerrar y ya no se puede pegar)

En el portapapeles OLE se coloca un IDataObject con OleSetClipboard. En ese momento, lo que el portapapeles retiene es un puntero al objeto de datos.

Llamar a OleFlushClipboard al salir materializa los datos en el portapapeles, de modo que el pegado sigue funcionando tras salir.7 Clipboard.SetDataObject(data, copy: true) de .NET especifica este comportamiento de «conservar tras salir».

Cuando se copia un rango grande en Excel y luego se sale, el aviso que pregunta si se quiere conservar la gran cantidad de información en el portapapeles es la confirmación de si realizar esta materialización (el vaciado). En la propia aplicación también se diseñan el renderizado diferido y la materialización al salir como un conjunto.

Diferir no garantiza que la interfaz siga respondiendo

El renderizado diferido es una optimización de rendimiento, pero generar los datos pedidos se ejecuta de forma síncrona dentro del tratamiento de mensajes. El compromiso es que la interfaz se congela si la generación tarda.6

6. Prácticas para vigilar el portapapeles — listener, reintento y exclusión del historial

6.1. Usar AddClipboardFormatListener

Requisitos como «detectar el valor de un lector de códigos de barras o una copia del sistema de negocio central e importarla automáticamente» exigen vigilar los cambios del portapapeles. Históricamente hay tres métodos, pero hoy hay una sola respuesta correcta.8

Método Valoración
Leer periódicamente con un temporizador (sondeo) Derrochador, y puede perder cambios. No usar
SetClipboardViewer (cadena de visores) Un defecto en una aplicación de la cadena rompe toda la cadena. Se conserva solo por compatibilidad hacia atrás
AddClipboardFormatListener Recomendado. WM_CLIPBOARDUPDATE se entrega a la ventana registrada
Flujo de vigilancia del portapapelesRegistrarse con AddClipboardFormatListener al crear el identificador, y WM_CLIPBOARDUPDATE llega sea cual sea la aplicación que copia. Leer con reintentos y anular el registro de forma simétrica con RemoveClipboardFormatListener al destruir el identificadorAnular el registro de forma simétricaOnHandleCreated: AddClipboardFormatListenerEsperarAlguna aplicación copiaLlega WM_CLIPBOARDUPDATELeer con reintentos (sección 6.2)OnHandleDestroyed: RemoveClipboardFormatListener
// Implementación mínima en WinForms
public partial class MainForm : Form
{
    [DllImport("user32.dll", SetLastError = true)]
    static extern bool AddClipboardFormatListener(IntPtr hwnd);
    [DllImport("user32.dll", SetLastError = true)]
    static extern bool RemoveClipboardFormatListener(IntPtr hwnd);
    const int WM_CLIPBOARDUPDATE = 0x031D;

    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        AddClipboardFormatListener(Handle);
    }

    protected override void OnHandleDestroyed(EventArgs e)
    {
        // Anular el registro de forma simétrica, al ritmo de la destrucción y recreación del identificador
        RemoveClipboardFormatListener(Handle);
        base.OnHandleDestroyed(e);
    }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_CLIPBOARDUPDATE)
        {
            // Leer Clipboard.GetDataObject() aquí e importar si el formato es uno de los que se necesitan
        }
        base.WndProc(ref m);
    }
}

6.2. Reintentar cuando no se puede abrir

Solo una ventana a la vez puede abrir el portapapeles. Mientras otro proceso lo tiene abierto, OpenClipboard falla.6

Justo después de WM_CLIPBOARDUPDATE también, el origen de la copia u otra aplicación de vigilancia puede seguir operando sobre él. Tratar un fallo de lectura temporal como un suceso normal e incorporar lógica que espere unas decenas de milisegundos y reintente unas cuantas veces.

Un punto a tener en cuenta en .NET es que las sobrecargas que permiten indicar un recuento de reintentos y un intervalo existen solo en el lado de escritura, SetDataObject. El lado de lectura, GetDataObject y similares, no tiene ninguna.

Lado de lectura Tratamiento de la competencia
WinForms Capturar ExternalException, esperar y reintentar
WPF Capturar COMException, esperar y reintentar

La espera y el reintento en la lectura se implementan del lado de la aplicación.

Flujo de reintentos de lectura del portapapelesSolo una ventana a la vez puede abrir el portapapeles, así que una lectura justo después de la notificación de cambio puede fallar por competencia con otro proceso. Ante una excepción, esperar unas decenas de milisegundos y reintentar; al alcanzar el límite, renunciar esta vez y recogerlo en la siguiente actualizaciónÉxitoFallo (otra ventana lo está usando)Reintentar unas cuantas vecesLímite alcanzadoWM_CLIPBOARDUPDATEIntentar la lecturaImportar (validación del capítulo 4)Esperar unas decenas de milisegundosRenunciar esta vez (recogerlo en la siguiente actualización)

6.3. Dejarlo fuera del historial y de la sincronización — consideraciones para funciones de copia que tratan secretos

Windows tiene historial del portapapeles (Win+V) y sincronización entre dispositivos (portapapeles en la nube), y los datos que coloca una aplicación quedan sujetos a ambos de forma predeterminada. Una aplicación cuya función de copia transporta secretos como contraseñas o números de cuenta coloca también un formato registrado que excluye los datos del historial y de la sincronización.1

Formato registrado Qué suprime
ExcludeClipboardContentFromMonitorProcessing Excluye todo el contenido copiado tanto del historial como de la sincronización entre dispositivos
CanIncludeInClipboardHistory (DWORD 0) Solo el historial
CanUploadToCloudClipboard (DWORD 0) Solo la sincronización entre dispositivos

Los administradores de contraseñas mantienen las contraseñas copiadas fuera de Win+V mediante este mecanismo. Basta con pasar el nombre a RegisterClipboardFormat para obtener un identificador de formato y colocarlo junto a los datos ordinarios, así que merece la pena implementarlo en las aplicaciones empresariales que tratan secretos.

7. El portapapeles desde la perspectiva de TI — controlar el historial, la sincronización en la nube y RDP

Controlar el contenido copiado del lado de la aplicación y decidir qué permite la organización en conjunto son preguntas distintas. Lo que mira un administrador son tres cosas: historial, sincronización en la nube y redirección RDP.

El historial del portapapeles acumula el contenido copiado recientemente. El portapapeles en la nube lo sincroniza entre dispositivos que han iniciado sesión con la misma cuenta Microsoft o cuenta Microsoft Entra.10

Por práctico que sea, da lugar a residuos y desbordes: información personal copiada del sistema de negocio central permanece en el historial, o el contenido copiado en un PC de trabajo se sincroniza a un PC personal.

7.1. Controlar el historial y la sincronización entre dispositivos

Las dos directivas de control organizativo son estas.

Qué se controla GPO (Configuración del equipo > Plantillas administrativas > Sistema > Directivas del sistema operativo) Policy CSP (Intune) Valor predeterminado
Historial del portapapeles Permitir historial del Portapapeles Experience/AllowClipboardHistory Permitido
Sincronización entre dispositivos Permitir la sincronización del Portapapeles entre dispositivos Privacy/AllowCrossDeviceClipboard Permitido

Ambas están disponibles a partir de Windows 10 versión 1809; al deshabilitarlas, los elementos correspondientes de la aplicación Configuración quedan atenuados y la directiva surte efecto de inmediato.910

7.2. Controlar la transferencia entre sesiones RDP

La redirección del portapapeles de RDP (Escritorio remoto) une el PC local y la sesión remota. Como copiar y pegar funciona de forma predeterminada, también puede convertirse en una vía para sacar secretos de un servidor.

El ajuste que bloquea ambas direcciones es la directiva «No permitir la redirección del Portapapeles» (valor del Registro fDisableClip).11

Las versiones recientes de Windows Server y Windows 11 también han añadido directivas de control más fino, como limitar solo la dirección de servidor a cliente a texto. Prohibirlo de raíz o restringir dirección y formato por etapas es un equilibrio entre operación y seguridad.

Caminos por los que se extiende el contenido del portapapeles y los puntos de controlEl contenido copiado queda sujeto de forma predeterminada al historial y a la sincronización en la nube, y en RDP pasa a otra sesión por redirección. Cada uno se puede controlar por directiva, y el lado de la aplicación puede excluir contenido del historial y de la sincronización con los formatos de exclusiónPortapapelesHistorial (Win+V)Sincronización en la nube → otro dispositivoRedirección RDP → otra sesiónControl: AllowClipboardHistoryControl: AllowCrossDeviceClipboardControl: fDisableClipLado de la aplicación: excluir con ExcludeClipboardContentFromMonitorProcessing y similares (sección 6.3)

8. Arrastrar y soltar es COM — IDataObject + IDropSource + IDropTarget

8.1. Los mismos datos que el portapapeles, transportados de otra forma

El arrastrar y soltar OLE funciona con las tres partes siguientes.15

Rol Lo implementa Trabajo
IDataObject Origen del arrastre Los datos que se transportan. El mismo objeto de datos de varios formatos que el portapapeles
IDropSource Origen del arrastre Decidir si el arrastre continúa o se cancela, y la retroalimentación del cursor
IDropTarget Destino de la suelta Declarar la aceptación y recibir los datos en DragEnter/DragOver/DragLeave/Drop

El flujo de la operación es el siguiente.

  1. El origen del arrastre llama a DoDragDrop y arranca el bucle de arrastre.
  2. Cuando el ratón entra en una ventana de destino de suelta, se notifica a IDropTarget.
  3. El destino de la suelta declara si acepta y, al soltar, recupera el formato que necesita del IDataObject.

La documentación oficial también explica que D&D ofrece la misma funcionalidad que copiar y pegar del portapapeles, y que una aplicación que ya implementa copiar y pegar solo necesita un añadido pequeño.15 En otras palabras, el DataObject de varios formatos preparado en los capítulos 2 a 5 es también el dato que transporta D&D.

Flujo del arrastrar y soltar OLEEl origen del arrastre llama a DoDragDrop con un IDataObject como carga y empieza el bucle de arrastre; el IDropTarget del destino de la suelta declara la aceptación en DragEnter y DragOver, y en Drop elige y recupera un formato del IDataObjectDoDragDropEl ratón entra en la ventanaBotón soltadoOrigen del arrastre: IDataObject + IDropSourceBucle de arrastreIDropTarget.DragEnter/DragOver (declarar el Effect cada vez)IDropTarget.DropElegir y recuperar un formato del IDataObject

8.2. OleInitialize (STA) es obligatorio

Una ventana de destino de suelta se registra con RegisterDragDrop. Como requisitos previos, comprobar dos cosas: la inicialización OLE y el tratamiento de mensajes.

Usar OleInitialize para la inicialización. Si se usa CoInitialize / CoInitializeEx en su lugar, RegisterDragDrop falla con E_OUTOFMEMORY. OleInitialize inicializa COM como STA.12

El subproceso que registra debe ejecutar una bomba de mensajes. El D&D OLE es una función arraigada en ventanas y tratamiento de mensajes; omitirlo y otras aplicaciones se cuelgan durante un arrastre.12 El fondo es el mismo modelo de subprocesos que en «Conocimientos básicos de STA/MTA en COM».

En WinForms/WPF, recibir mediante eventos

En WinForms/WPF, el marco se encarga de la inicialización OLE y de las implementaciones de interfaz. El desarrollador escribe la declaración de aceptación y la importación real en eventos.

// WinForms: aceptar archivos soltados
listView1.AllowDrop = true;
listView1.DragEnter += (s, e) =>
{
    // Comprobar también que el origen permite Copy (algunos orígenes solo permiten Move/Link)
    e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop)
            && (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy
        ? DragDropEffects.Copy      // Aceptar: recibir como copia
        : DragDropEffects.None;     // No aceptar
};
listView1.DragDrop += (s, e) =>
{
    // Los datos de arrastre también son entrada externa. Aunque anuncien FileDrop, la
    // carga útil puede ser null o de otro tipo, y la propia recuperación puede fallar
    object data;
    try { data = e.Data.GetData(DataFormats.FileDrop); }
    catch (COMException) { return; }
    if (data is not string[] paths) return;
    foreach (var path in paths)
    {
        // Validar la ruta antes de importar (sección 9.3)
    }
};

El cuadro es el mismo en WPF. Recibir con AllowDrop="True" en el elemento y los eventos DragOver / Drop, y recuperar la matriz de rutas con e.Data.GetData(DataFormats.FileDrop).

Declarar la aceptación (el Effect) cada vez en DragEnter / DragOver es la convención de IDropTarget. Omitirlo y el cursor se queda en «no permitido». Comprobar no solo si el formato está presente sino también, como en el ejemplo de código, si el origen del arrastre permite Copy.

9. Trampas de D&D — elevación, Move y validación de rutas

9.1. No se puede soltar sobre una aplicación elevada a administrador

Soltar un archivo desde el Explorador de archivos sobre una aplicación iniciada con «Ejecutar como administrador» y no ocurre nada: no es un error de implementación, sino un diseño del sistema operativo. UIPI (User Interface Privilege Isolation) bloquea de forma predeterminada los mensajes de un proceso de menor integridad hacia una ventana de mayor integridad, así que las notificaciones de suelta del Explorador de archivos con privilegios normales (integridad media) nunca llegan a una aplicación elevada.13

Cómo UIPI bloquea una suelta sobre una aplicación elevadaUIPI bloquea de forma predeterminada la notificación de suelta del Explorador de archivos de integridad media hacia una aplicación elevada de integridad alta, así que nunca llega. Mantener la IU con privilegios normales y aislar el trabajo privilegiado, y la suelta llegaNotificación de sueltaBloqueado (valor predeterminado)PasaDelegar solo el trabajo privilegiadoExplorador de archivos (integridad media)UIPIAplicación elevada (integridad alta): sin respuestaIU con privilegios normales: llega la sueltaProceso separado que aísla el trabajo que necesita elevación

También hay una solución alternativa que permite de forma individual WM_DROPFILES y mensajes similares con ChangeWindowMessageFilterEx.13 Sin embargo, es una contramedida para la notificación de suelta del estilo antiguo mediante WM_DROPFILES, y no resuelve el D&D OLE en su conjunto.

La pauta de fondo es no ejecutar la aplicación elevada todo el tiempo. Si se aísla solo el trabajo que necesita elevación en un proceso distinto, la propia IU puede permanecer con privilegios normales y aceptar D&D. El diseño de aislamiento se detalla en «Windows: cómo separar en el código solo los procesos que necesitan permisos de administrador».

9.2. Qué significa DragDropEffects — Move es un contrato de que «el original desaparece»

Copy / Move / Link en DragDropEffects no son adorno del cursor; son un contrato entre el origen del arrastre y el destino de la suelta.

El origen del arrastre declara en DoDragDrop el conjunto de efectos que permite, y el destino de la suelta elige el efecto real. Por convención, cuando se acuerda Move, el origen del arrastre elimina los datos (el archivo).

Si el lado que recibe devuelve Move sin pensarlo, se acaba en «lo solté y el archivo original desapareció». En las importaciones de aplicaciones empresariales, hacer que el lado que recibe declare Copy de forma explícita el valor predeterminado seguro.

El contrato de DragDropEffects — con Move, el original desapareceEl origen del arrastre declara en DoDragDrop el conjunto de efectos que permite, y el destino de la suelta elige el efecto real. Como la convención es que el origen del arrastre elimina el archivo cuando se acuerda Move, un lado que recibe e importa debería indicar Copy de forma explícitaCopyMoveOrigen del arrastre: declarar los efectos permitidos (Copy | Move | Link)Destino de la suelta: elegir el efecto realEl archivo original permanece (el lado seguro para importaciones)El origen del arrastre elimina el archivo — de dónde viene «el original desapareció»

9.3. Validar las rutas soltadas

Lo que viaja en CF_HDROP/FileDrop son solo rutas (sección 3.2). Antes de importar, pasarlas por la misma validación que una entrada externa, igual que al pegar.

  • Archivo o carpeta: Decidir como especificación qué ocurre cuando se suelta una carpeta entera (importar de forma recursiva, o rechazar).
  • Marcadores de posición de OneDrive: Si la ruta existe pero el cuerpo del archivo no está en local —un archivo a petición—, al abrirlo arranca una descarga y falla sin conexión. Para el comportamiento y las contramedidas, véase OneDrive «Archivos bajo demanda» y las aplicaciones empresariales.
  • Rutas largas y especiales: Aceptar rutas más allá de MAX_PATH, rutas de red (UNC) y rutas en medios extraíbles solo tras confirmar que el procesamiento posterior puede tratarlas.
  • Recuento y tamaño total: Para que soltar miles de archivos no congele la IU, hacer la importación asincrónica y añadir un límite y una indicación de progreso.

10. Resumen

  • El portapapeles es un mecanismo que coloca el mismo contenido en varios formatos a la vez en un área única compartida dentro del mismo escritorio (estación de ventanas). Como el destino del pegado elige el formato, la misma copia produce resultados distintos.
  • El texto es CF_UNICODETEXT, los archivos son CF_HDROP y el texto con formato es el formato registrado HTML Format (encabezado de desplazamientos en bytes + UTF-8).
  • El lado que pega busca formatos de enriquecido a plano y valida el contenido como entrada externa. El lado que copia ofrece varios formatos a la vez y, si usa renderizado diferido, implementa también la materialización al salir (WM_RENDERALLFORMATS / OleFlushClipboard).
  • La vigilancia es AddClipboardFormatListener + WM_CLIPBOARDUPDATE. Prepararse para la competencia de OpenClipboard con reintentos, y excluir secretos del historial y de la sincronización con ExcludeClipboardContentFromMonitorProcessing y similares.
  • TI puede controlar el historial del portapapeles, la sincronización en la nube y la redirección RDP mediante GPO/Intune. Todos están permitidos de forma predeterminada, así que hay que decidir de forma deliberada en entornos que tratan secretos.
  • D&D es COM: IDropSource/IDropTarget entregan el mismo IDataObject que el portapapeles. RegisterDragDrop exige OleInitialize (STA).
  • Las sueltas sobre una aplicación elevada las bloquea UIPI. Move en DragDropEffects es un contrato de que «el original desaparece», y las rutas soltadas se validan antes de importar.

Para los usuarios, copiar y pegar y D&D son funciones tan poco llamativas como el aire. Precisamente por eso la experiencia se resiente tanto cuando aparecen «no se puede pegar», «se deshace» o «desapareció» — y, a la inversa, una aplicación que ofrece varios formatos y trata las sueltas a fondo hace más fluida, por sí sola, la operación cotidiana. Espero que esto sirva de base al sopesar la prioridad de las revisiones.

Artículos relacionados

Ámbitos de consulta relacionados

KomuraSoft LLC se encarga del diseño e implementación de la compatibilidad con copiar y pegar y arrastrar y soltar en aplicaciones empresariales (oferta de varios formatos, integración con Excel, importación de archivos soltados), de la investigación de causas de defectos como «se deshace al pegar» o «la copia desaparece», de la automatización de entrada mediante vigilancia del portapapeles y de implementar protecciones de información confidencial frente al historial y la sincronización. Los casos que involucran las capas inferiores de COM y OLE son bienvenidos aunque empiecen por aislar el síntoma.

Referencias

  1. Microsoft Learn, Clipboard Formats. Sobre que una ventana puede colocar la misma información en varios formatos de portapapeles; los formatos registrados mediante RegisterClipboardFormat (registrar el mismo nombre devuelve el mismo valor, de modo que las aplicaciones pueden compartirlo); los formatos sintetizados; y la exclusión de contenido del historial del portapapeles y de la sincronización en la nube con ExcludeClipboardContentFromMonitorProcessing, CanIncludeInClipboardHistory y CanUploadToCloudClipboard. ↩ ↩2 ↩3 ↩4

  2. Microsoft Learn, Standard Clipboard Formats. Sobre las definiciones de los formatos estándar CF_TEXT (ANSI), CF_UNICODETEXT, CF_HDROP, CF_DIB y CF_LOCALE, y sobre que el sistema convierte de forma implícita entre CF_TEXT y CF_UNICODETEXT usando la página de códigos asociada a CF_LOCALE. ↩ ↩2 ↩3

  3. Microsoft Learn, Shell Clipboard Formats. Sobre que CF_HDROP se compone de una estructura DROPFILES más una matriz de cadenas de ruta completa terminada en NUL doble; la recuperación de rutas individuales con DragQueryFile; y que los formatos de shell CFSTR_ exigen registro mediante RegisterClipboardFormat. ↩ ↩2

  4. Microsoft Learn, HTML Clipboard Format. Sobre que el nombre registrado es «HTML Format»; la estructura de encabezado con desplazamientos (en bytes) como Version, StartHTML, EndHTML, StartFragment y EndFragment; que la codificación es siempre UTF-8; y la convención de comentarios StartFragment/EndFragment. ↩ ↩2 ↩3

  5. Microsoft Learn, OleGetClipboard function (ole2.h). Sobre cómo obtener un IDataObject del portapapeles, y sobre la advertencia de que los datos del portapapeles no son de confianza y deben analizarse con cuidado antes de que la aplicación los use. ↩ ↩2

  6. Microsoft Learn, Clipboard Operations. Sobre que solo una ventana a la vez puede abrir el portapapeles; colocar formatos del más expresivo hacia abajo al copiar; la elección de formato al pegar con EnumClipboardFormats / GetPriorityClipboardFormat; el renderizado diferido al pasar NULL a SetClipboardData y las responsabilidades de WM_RENDERFORMAT / WM_RENDERALLFORMATS; y los compromisos del renderizado diferido. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7

  7. Microsoft Learn, OleFlushClipboard function (ole2.h). Sobre que tras OleSetClipboard el portapapeles solo retiene un puntero al objeto de datos; que OleFlushClipboard materializa los datos en el portapapeles de modo que el pegado sigue siendo posible tras salir de la aplicación; y vaciar el portapapeles con OleSetClipboard(NULL) cuando no hace falta conservar los datos al salir. ↩ ↩2

  8. Microsoft Learn, Using the clipboard. Sobre la comparación de las tres formas de vigilar el portapapeles (ventanas visor, números de secuencia y listeners de formato); que los programas nuevos deben usar un listener mediante AddClipboardFormatListener; que la cadena de visores es vulnerable a fallos en el mantenimiento de la cadena; y que los números de secuencia no son algo que se deba sondear. ↩ ↩2

  9. Microsoft Learn, Policy CSP - Experience. Sobre permitir o bloquear el historial del portapapeles con la directiva Experience/AllowClipboardHistory; la disponibilidad a partir de Windows 10 versión 1809; que el valor predeterminado es permitido; y el mapeo de GPO bajo «Sistema > Directivas del sistema operativo» con cambios que surten efecto de inmediato. ↩ ↩2

  10. Microsoft Learn, Policy CSP - Privacy. Sobre permitir o bloquear la sincronización del portapapeles entre dispositivos con la directiva Privacy/AllowCrossDeviceClipboard; que la sincronización tiene lugar entre dispositivos que han iniciado sesión con la misma cuenta Microsoft o cuenta Microsoft Entra; y que el valor predeterminado es permitido. ↩ ↩2 ↩3

  11. Microsoft Learn, Policy CSP - ADMX_TerminalServer. Sobre que TS_CLIENT_CLIPBOARD («No permitir la redirección del Portapapeles», valor del Registro fDisableClip) puede prohibir el uso compartido del portapapeles entre local y remoto en una sesión de Escritorio remoto, y sobre que la redirección está permitida de forma predeterminada. ↩ ↩2

  12. Microsoft Learn, RegisterDragDrop function (ole2.h). Sobre cómo registrar una ventana de destino de suelta y su IDropTarget; que la llamada siempre falla con E_OUTOFMEMORY cuando COM se inicializó con CoInitialize/CoInitializeEx, de modo que OleInitialize es obligatorio; y que la aplicación origen del arrastre se cuelga cuando el subproceso que llama no ejecuta una bomba de mensajes. ↩ ↩2 ↩3

  13. Microsoft Learn, ChangeWindowMessageFilterEx function (winuser.h). Sobre que UIPI es un mecanismo de seguridad que de forma predeterminada bloquea la recepción de mensajes de un remitente de menor integridad, y sobre permitir mensajes concretos (MSGFLT_ALLOW) con un filtro de mensajes por ventana. ↩ ↩2 ↩3

  14. Microsoft Learn, How to add data to the Clipboard (Windows Forms). Sobre colocar datos en varios formatos a la vez con DataObject y Clipboard.SetDataObject; añadirlos en varios formatos para que otras aplicaciones puedan reconocerlos; y que la clase Clipboard solo se puede usar desde un subproceso STA, de modo que hace falta [STAThread]. ↩ ↩2

  15. Microsoft Learn, Drag and Drop (COM). Sobre que el arrastrar y soltar OLE funciona con las tres partes IDropSource (origen del arrastre), IDropTarget (destino de la suelta) y DoDragDrop (el bucle que proporciona OLE); ofrecer la misma funcionalidad que copiar y pegar del portapapeles, de modo que una aplicación que ya lo implementa solo necesita un añadido pequeño; y los tipos de retroalimentación. ↩ ↩2

Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.

Estas páginas sitúan el tema en un contexto más amplio de servicios y decisiones.

El artículo está directamente relacionado con los siguientes servicios.

Preguntas frecuentes

Preguntas habituales en las consultas sobre el tema del artículo.

¿Por qué se deshace el formato al pegar en mi aplicación una tabla copiada de Excel?
Porque el portapapeles no guarda «un solo dato»: el mismo contenido se coloca a la vez en varios formatos (el formato privado de la aplicación, HTML Format, CSV, texto Unicode, etc.), y la aplicación de destino elige el formato que entiende y extrae ese. Cuando el formato se deshace, lo típico es que el destino solo lea texto sin formato (CF_UNICODETEXT). Si se quiere también la estructura de la tabla, hay que implementar el lado que pega de modo que prefiera HTML Format o CSV. A la inversa, si se quiere que otras aplicaciones peguen correctamente una copia hecha en la propia aplicación, hay que ofrecer a la vez, al copiar, un formato enriquecido y uno plano.
¿Por qué dejo de poder pegar después de cerrar la aplicación desde la que copié?
Porque el origen usa renderizado diferido (delayed rendering). Las aplicaciones que tratan datos grandes no colocan los datos propiamente dichos al copiar; registran en el portapapeles solo la promesa de «producirlos cuando se pidan». Si el origen termina entonces sin materializar los datos en respuesta a WM_RENDERALLFORMATS al cerrarse, se pierden los formatos aún no renderizados. Una aplicación que usa el portapapeles OLE (IDataObject) puede mantener posible el pegado tras salir llamando a OleFlushClipboard al cerrarse para materializar los datos.
¿Cómo puede mi propia aplicación vigilar los cambios del portapapeles?
El método recomendado hoy es registrar la propia ventana como listener con AddClipboardFormatListener y tratar el mensaje WM_CLIPBOARDUPDATE que llega cada vez que cambia el contenido. Leer el contenido periódicamente con un temporizador (sondeo) desperdicia trabajo, y la cadena de visores antigua basada en SetClipboardViewer se conserva solo por compatibilidad hacia atrás, porque un defecto en una aplicación de la cadena rompe toda la cadena. OpenClipboard al leer también puede fallar por competencia con otro proceso; un reintento tras una espera breve hace estable la lectura.
¿Hay forma de dejar secretos como contraseñas fuera del historial del portapapeles (Win+V)?
Hay dos vías, una del lado de la aplicación y otra del lado de las directivas. Del lado de la aplicación, si al copiar se coloca también el formato registrado ExcludeClipboardContentFromMonitorProcessing, ese contenido no entra ni en el historial ni en la sincronización entre dispositivos. También se puede controlar cada uno por separado con CanIncludeInClipboardHistory (solo el historial) y CanUploadToCloudClipboard (solo la sincronización). Este es el mecanismo que usan los administradores de contraseñas. Para detenerlo en toda la organización, se puede deshabilitar el propio historial y la sincronización en la nube con AllowClipboardHistory y AllowCrossDeviceClipboard mediante Directiva de grupo o Intune (Policy CSP).
¿Por qué no puedo arrastrar y soltar un archivo sobre una aplicación que se ejecuta como administrador?
Porque un mecanismo de seguridad llamado UIPI (User Interface Privilege Isolation) bloquea el envío de mensajes desde un proceso de menor integridad hacia una ventana de mayor integridad. El Explorador de archivos se ejecuta con privilegios normales (integridad media), así que las notificaciones de arrastrar y soltar no llegan a la ventana de una aplicación elevada. Se conoce una solución alternativa que permite mensajes concretos como WM_DROPFILES de forma individual con ChangeWindowMessageFilterEx, pero se limita a la notificación de suelta del estilo antiguo. El camino de fondo es dejar de diseñar la aplicación para que se ejecute siempre elevada y aislar en un proceso distinto solo el trabajo que necesita elevación.

Perfil del autor

Página de presentación del autor del artículo.

Go Komura

Representante de KomuraSoft LLC

Especializado en desarrollo de software para Windows, consultoría técnica e investigación de fallos, sobre todo en proyectos con sistemas existentes y errores difíciles de reproducir.

Volver al blog