Compartir a través de


Redireccionamiento de la biblioteca de vínculos dinámicos

El cargador DLL es la parte del sistema operativo (SO) que resuelve las referencias a archivos DLL, los carga y los vincula. El redireccionamiento de la biblioteca de vínculos dinámicos (DLL) es una de las técnicas por las que puede influir en el comportamiento del cargador DLL y controlar qué uno de varios archivos DLL candidatos carga realmente.

Otros nombres de esta característica son .local, Dot Local, DotLocaly Dot Local Debugging.

Problemas de versiones de DLL

Si la aplicación depende de una versión específica de un archivo DLL compartido y otra aplicación se instala con una versión más reciente o anterior de ese archivo DLL, que puede causar problemas de compatibilidad e inestabilidad; puede hacer que la aplicación empiece a producir un error.

El cargador DLL busca en la carpeta desde la que se cargó el proceso de llamada (la carpeta del ejecutable) antes de buscar en otras ubicaciones del sistema de archivos. Por lo tanto, una solución alternativa es instalar el archivo DLL que la aplicación necesita en la carpeta del archivo ejecutable. Eso hace que el archivo DLL sea privado de forma eficaz.

Pero eso no resuelve el problema para COM. Se pueden instalar y registrar dos versiones incompatibles de un servidor COM (incluso en ubicaciones diferentes del sistema de archivos), pero solo hay un lugar para registrar el servidor COM. Por lo tanto, solo se activará el servidor COM registrado más reciente.

Puede usar el redireccionamiento para resolver estos problemas.

Carga y prueba de archivos binarios privados

Las reglas que sigue el cargador dll garantizan que los archivos DLL del sistema se carguen desde las ubicaciones del sistema de Windows, por ejemplo, la carpeta del sistema (%SystemRoot%\system32). Esas reglas evitan ataques de plantación: donde un adversario coloca el código que escribieron en una ubicación en la que pueden escribir y, a continuación, convencer a algún proceso para cargarlo y ejecutarlo. Pero las reglas del cargador también dificultan el trabajo en los componentes del sistema operativo, ya que para ejecutarlas es necesario actualizar el sistema; y eso es un cambio muy impactante.

Pero puede usar el redireccionamiento para cargar copias privadas de archivos DLL (con fines como pruebas o medir el impacto en el rendimiento de un cambio de código).

Si quiere contribuir al código fuente en el repositorio público de GitHub de WindowsAppSDK, querrá probar los cambios. Y, de nuevo, es un escenario para el que puede usar el redireccionamiento para cargar las copias privadas de archivos DLL en lugar de las versiones que se incluyen con Windows App SDK.

Sus opciones

De hecho, hay dos maneras de asegurarse de que la aplicación usa la versión del archivo DLL que quiere que:

Sugerencia

Si es desarrollador o administrador, debe usar el redireccionamiento de DLL para las aplicaciones existentes. Esto se debe a que no requiere ningún cambio en la propia aplicación. Pero si va a crear una nueva aplicación o actualizar una aplicación existente y quiere aislar la aplicación de posibles problemas, cree un componente en paralelo.

Opcional: configurar el Registro

Para habilitar la redirección de DLL en toda la máquina, debe crear un nuevo valor del Registro. En la clave HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options, cree un nuevo valor DWORD con el nombre DevOverrideEnable. Establezca el valor en 1 y reinicie el equipo. O bien, use el comando siguiente (y reinicie el equipo).

reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options" /v DevOverrideEnable /t REG_DWORD /d 1

Con ese valor del Registro establecido, se respeta la redirección de DLL DotLocal incluso si la aplicación tiene un manifiesto de aplicación.

Creación de un archivo o carpeta de redireccionamiento

Para usar el redireccionamiento de DLL, creará un archivo de redireccionamiento o una carpeta de redireccionamiento (en función del tipo de aplicación que tenga), como veremos en las secciones posteriores de este tema.

Cómo redirigir archivos DLL para aplicaciones empaquetadas

Una aplicación empaquetada requiere una estructura de carpetas especial para el redireccionamiento de DLL. La siguiente ruta de acceso es donde el cargador se verá cuando se habilite la redirección:

<Drive>:\<path_to_package>\microsoft.system.package.metadata\application.local\

Si puede editar el .vcxproj archivo, una manera cómoda de hacer que esa carpeta especial se cree e implemente con el paquete es agregar algunos pasos adicionales a la compilación en .vcxproj:

<ItemDefinitionGroup>
    <PreBuildEvent>
        <Command>
            del $(FinalAppxManifestName) 2&gt;nul
            <!-- [[Using_.local_(DotLocal)_with_a_packaged_app]] This makes the extra DLL deployed via F5 get loaded instead of the system one. -->
            if NOT EXIST $(IntDir)\microsoft.system.package.metadata\application.local MKDIR $(IntDir)\microsoft.system.package.metadata\application.local
            if EXIST "&lt;A.dll&gt;" copy /y "&lt;A.dll&gt;" $(IntDir)\microsoft.system.package.metadata\application.local 2&gt;nul
            if EXIST "&lt;B.dll&gt;" copy /y "&lt;B.dll&gt;" $(IntDir)\microsoft.system.package.metadata\application.local 2&gt;nul
        </Command>
    </PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
    <!-- Include any locally built system experience -->
    <Media Include="$(IntDir)\microsoft.system.package.metadata\application.local\**">
        <Link>microsoft.system.package.metadata\application.local</Link>
    </Media>
</ItemGroup>

Veamos algunas de las acciones que hace esa configuración.

  1. Configure un PreBuildEvent para la experiencia de Inicio sin depuración de Visual Studio (o Iniciar depuración).

    <ItemDefinitionGroup>
      <PreBuildEvent>
    
  2. Asegúrese de que tiene la estructura de carpetas correcta en el directorio intermedio.

    <!-- [[Using_.local_(DotLocal)_with_modern_apps]] This makes the extra DLL deployed via Start get loaded instead of the system one. -->
    if NOT EXIST $(IntDir)\microsoft.system.package.metadata\application.local MKDIR $(IntDir)\microsoft.system.package.metadata\application.local
    
  3. Copie los archivos DLL que haya compilado localmente (y desee usar en preferencia a los archivos DLL implementados por el sistema) en el application.local directorio. Puede seleccionar archivos DLL desde casi cualquier lugar (se recomienda usar las macros disponibles para .vcxproj). Asegúrese de que esos archivos DLL se compilan antes de que este proyecto lo haga; de lo contrario, faltarán. Aquí se muestran dos comandos de copia de plantilla ; use tantos como necesite y edite los <path-to-local-dll> marcadores de posición.

      if EXIST "<path-to-local-dll>" copy /y "<path-to-local-dll>" $(IntDir)\microsoft.system.package.metadata\application.local 2&gt;nul
      if EXIST "<path-to-local-dll>" copy /y "<path-to-local-dll>" $(IntDir)\microsoft.system.package.metadata\application.local 2&gt;nul
      </Command>
    </PreBuildEvent>
    
  4. Por último, indique que desea incluir el directorio especial y su contenido en el paquete implementado.

    <ItemGroup>
      <!-- Include any locally built system experience -->
      <Media Include="$(IntDir)\microsoft.system.package.metadata\application.local\**">
        <Link>microsoft.system.package.metadata\application.local</Link>
      </Media>
    </ItemGroup>
    

El enfoque descrito aquí (mediante un directorio intermedio) mantiene la limpieza de la inscripción del control de código fuente y reduce la posibilidad de confirmar accidentalmente un binario compilado.

A continuación, todo lo que debe hacer es volver a implementar el proyecto. Para obtener una implementación limpia y completa (re), es posible que también tenga que desinstalar o limpiar la implementación existente en el dispositivo de destino.

Copiar los archivos binarios manualmente

Si no puedes usar tu .vcxproj en la forma que se muestra anteriormente, puedes lograr los mismos extremos a mano en el dispositivo de destino con un par de sencillos pasos.

  1. Determine la carpeta de instalación del paquete. Puede hacerlo en PowerShell emitiendo el comando Get-AppxPackagey buscando la installLocation que se devuelve.

  2. Use ese InstallLocation para cambiar las ACL para permitirse crear carpetas o copiar archivos. Edite los <InstallLocation> marcadores de posición de este script y ejecute el script:

    cd <InstallLocation>\Microsoft.system.package.metadata
    takeown /F . /A
    icacls  . /grant Administrators:F
    md <InstallLocation>\Microsoft.system.package.metadata\application.local
    
  3. Por último, copie manualmente los archivos DLL que haya compilado localmente (y desee usar en preferencia a los archivos DLL implementados por el sistema) en el application.local directorio y [re]iniciar la aplicación.

Comprobar que todo funcionó

Para confirmar que el archivo DLL correcto se está cargando en tiempo de ejecución, puede usar Visual Studio con el depurador asociado.

  1. Abra la ventana Módulos (Depurar>módulos> de Windows).
  2. Busque el archivo DLL y asegúrese de que la ruta de acceso indica la copia redirigida y no la versión implementada por el sistema.
  3. Confirme que solo se carga una copia de un archivo DLL determinado.

Cómo redirigir archivos DLL para aplicaciones sin empaquetar

El archivo de redireccionamiento debe denominarse <your_app_name>.local. Por lo tanto, si el nombre de la aplicación es Editor.exe, asigne el nombre al archivo Editor.exe.localde redirección. Debe instalar el archivo de redireccionamiento en la carpeta del ejecutable. También debe instalar los archivos DLL en la carpeta del ejecutable.

El contenido de un archivo de redireccionamiento se omite; su presencia solo hace que el cargador de DLL compruebe primero la carpeta del ejecutable cada vez que carga un archivo DLL. Para mitigar el problema COM, esa redirección se aplica tanto a la ruta de acceso completa como a la carga parcial de nombres. Por lo tanto, el redireccionamiento se produce en el caso COM y también independientemente de la ruta de acceso especificada en LoadLibraryoLoadLibraryEx. Si el archivo DLL no se encuentra en la carpeta del ejecutable, la carga sigue su orden de búsqueda habitual. Por ejemplo, si la aplicación C:\myapp\myapp.exe llama a LoadLibrary mediante la siguiente ruta de acceso:

C:\Program Files\Common Files\System\mydll.dll

Y si ambos C:\myapp\myapp.exe.local y C:\myapp\mydll.dll existen, luego LoadLibrary carga C:\myapp\mydll.dll. De lo contrario, LoadLibrary carga C:\Program Files\Common Files\System\mydll.dll.

Como alternativa, si existe una carpeta denominada C:\myapp\myapp.exe.local y contiene mydll.dll, LoadLibrary carga C:\myapp\myapp.exe.local\mydll.dll.

Si usa el redireccionamiento de DLL y la aplicación no tiene acceso a todas las unidades y directorios en el orden de búsqueda, LoadLibrary deja de buscar en cuanto se deniega el acceso. Si no usa el redireccionamiento de DLL, LoadLibrary omite los directorios a los que no puede acceder y, a continuación, continúa buscando.

Se recomienda instalar archivos DLL de aplicación en la misma carpeta que contiene la aplicación; incluso si no usa el redireccionamiento de DLL. Esto garantiza que la instalación de la aplicación no sobrescriba otras copias del archivo DLL (lo que provoca un error en otras aplicaciones). Además, si sigue este procedimiento recomendado, otras aplicaciones no sobrescriben la copia del archivo DLL (y no hacen que se produzca un error en la aplicación).