Configurar la opción de abrir ítems con un simple clic a través de la API de Windows y de un script VBS

Un usuario del foro preguntaba si es posible cambiar a la opción de abrir archivos o carpetas con un simple clic, que está situada en Explorador de Windows, menú Organizar, Opciones de carpeta y búsqueda, pestaña General. El objetivo principal era incluir este automatismo como parte del proceso de instalación de un programa.

Cuando se plantean este tipo de preguntas, siempre pienso inmediatamente en el usuario de esa aplicación y en cómo tras instalarla considero que ha perdido parte del control de su máquina. No es buena idea que un programa tome la decisión unilateral de modificar configuraciones personales del usuario. En primer lugar habría que volver a pensar en por qué esa aplicación requiere un cambio en una configuración personal para funcionar correctamente. Si el cambio fuese estrictamente necesario y justificado, lo ideal sería indicarle esto al usuario a través de un mensaje y seguidamente dirigirle al panel de Opciones de carpeta (control.exe folders) para sea él personalmente el que cambie la configuración requerida. De esta manera, el usuario es consciente del cambio que ha realizado en su configuración personal, si es que finalmente decide llevarla a cabo.

Microsoft es consciente de que muchas aplicaciones interfieren con la configuración personal del usuario y por ello, especialmente desde Windows 7, ha ido restringiendo ciertas partes del sistema para que no dispongan de acceso a través de la interfaz de programación de Windows. Para el caso que nos ocupa, aún disponemos del acceso a una API que nos sirve para lo que estamos busando: SHGetSetSettings. Como se indica en la página de documentación, si la llamamos con el segundo parámetro establecido en SSF_DOUBLECLICKINWEBVIEW podremos cambiar esta configuración del explorador.

El resultado final de la llamada anterior es la modificación del valor binario ShellState de la clave de registro HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer. A simple vista este valor de registro tiene un aspecto un tanto críptico, pero voy a detallar a continuación su estructura para verlo todo más claro.

¿Cómo interpretar el valor de registro ShellState?

El primer parámetro de la función SHGetSetSettings es una estructura de nombre SHELLSTATE, documentada en MSDN, y presente en el fichero de cabecera Shlobj.h. Esta estructura está formada por un conjunto de flags binarios, cada uno de los cuales controla un determinado aspecto de la configuración del explorador. SHELLSTATE es una estructura bastante antigua, ciertos campos ya no se aplican a versiones recientes de Windows, y además es una estructura propensa a cambios (cada versión de Windows suele introducir un par de nuevos flags y algunos de sus valores se han transladado a otros sitios del registro, más fácilmente controlables mediante directivas). Por esta razón, tanto el valor de registro como su API asociada podrían dejar de funcionar en un futuro sin previo aviso.

Para que esta información persista en el tiempo, la estructura SHELLSTATE junto con su tamaño se almacenan en el valor de registro ShellState antes mencionado. Si lo abrimos en Editor del Registro veremos que comienza por 24 00 00 00. Estos primeros 4 bytes (un entero sin signo) indican el tamaño total, es decir, 36 bytes (nótese que el editor nos está mostrando el dato en hexadecimal). Después del tamaño, le sigue la estructura SHELLSTATE en sí, escrita en bloques de 1 byte de derecha a izquierda. Como vemos en la documentación de MSDN, el flag que nos interesa modificar es fDoubleClickInWebView, el sexto bit. Si lo establecemos en cero, activaremos la opción de abrir ítems con un simple clic; si lo establecemos en 1, los abriremos con un doble clic (comportamiento por defecto).

Por tanto, para respetar el resto de bits de la estructura ShellState lo que podemos hacer es anotar el valor hexadecimal del quinto byte del valor de registro (recuerde que los bytes del primero al cuarto inclusive expresan el tamaño del valor de registro). Con dicho valor anotado, abrimos la calculadora de Windows y la configuramos en modo “Programador” y “hexadecimal”. Introducimos el valor que hemos anotado en el paso anterior y pulsamos “And”, “20”, “Not”, “=”. (20 es el valor hexadecimal correspondiente a poner un 1 binario en la sexta posición). Si en vez de poner el correspondiente bit a 1, queremos ponerlo a 0, la operación que hay que hacer es “Or”, “20”, “=”. Hay más información sobre cómo hacer operaciones a nivel de bit en Wikipedia, por ejemplo.

Para terminar, dejo una posible implementación en lenguaje Visual Basic Script:

'
' Small example of VBScript code that switches between "double click to open items" and "single click to open
' items" by editing the ShellState binary value in the registry.
' It depends on the layout of the SHELLSTATE structure, so it might cease to work in future versions of
' Windows.
'
' For unmanaged code, the best way to achieve this is using the SHGetSetSettings function with the
' second parameter set to SSF_DOUBLECLICKINWEBVIEW
'
' (c) Daniel Martín
'
Const HKEY_CURRENT_USER = &H80000001
strComputer = "."
Set objRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
Set objWMIService = GetObject("winmgmts:"& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set objShell = CreateObject("Wscript.Shell")

strPath = "Software\Microsoft\Windows\CurrentVersion\Explorer"
strBinValue = "ShellState"

objRegistry.GetBinaryValue HKEY_CURRENT_USER, strPath, strBinValue, uBinaryShellState
uBinaryNewShellState = uBinaryShellState ' Keep user settings
uBinaryNewShellState(4) = uBinaryShellState(4) Xor 32 ' But toggle the fDoubleClickInWebView bit
objRegistry.SetBinaryValue HKEY_CURRENT_USER, strPath, strBinValue, uBinaryNewShellState

If (Return = 0) And (Err.Number = 0) Then
    If ((uBinaryShellState(4) Or 32) = uBinaryShellState(4)) Then
        MsgBox "Single click to open items was applied successfully. Restarting Explorer..."
    Else
        MsgBox "Double click to open items was applied successfully. Restarting Explorer..."
    End If
    Set colProcessList = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'explorer.exe'")
    For Each objProcess in colProcessList
        objProcess.Terminate(1)
    Next
    objShell.Run "explorer.exe"
Else
    MsgBox "An error occurred: " + Err.Number
End If

3 thoughts on “Configurar la opción de abrir ítems con un simple clic a través de la API de Windows y de un script VBS

  1. Daniel hola, mil gracias como siempre por compartir tu experiencia!

    Tengo una pregunta, muy novata tal vez pero que no me queda claro.
    Tú nos comentas que los primeros cuatro valores expresan el tamaño del valor del registro, y segun lo que entendí, el sexto es el que determina el comportamiendo de uno o un doble click?

    ¿Por qué el cambio se reproduce es en el quinto byte? Por ejemplo al establecerlo como un Clic es: 24 00 00 00 18 28, con doble click sin embargo es: 24 00 00 00 38 28

    ¿O estoy confundiendo con lo que hablabas de que el cambio está en el sexto bit?

    ¿No sería más cómodo para una aplicación marcar el cambio en la clave de registro con la función de RegSetKeyValue?

    ¡Mil gracias!

  2. @Sergio Calderón: En formato binario lo verás más claramente:

    18 = 0001 1000
    38 = 0011 1000

    Como ves, es el sexto bit empezando desde el menos significativo el que cambia: Esta a 0 cuando lo estableces como “clic simple” (flag desactivado), y a 1 cuando lo estableces como “doble clic” (flag activado).

    Sí, con RegSetKeyValue puedes hacerlo, pero antes debes crear la estructura ShellState, rellenarla con la configuración del usuario (para respetarla y no sobreescribirla) y anteponerle su tamaño.

    Sin embargo, no hay motivo para hacer esto; si hay posibilidad de acceder a la API nativa de Windows (en ciertos lenguajes de script esto no es posible) lo ideal el usar SHGetSetSettings, que aunque no está garantizada en versiones posteriores de Windows, es más general y menos farragosa que hacer el cambio manualmente mediante RegSetKeyValue.

  3. Hola que tal Daniel, me contacto contigo del programa MVP de Microsoft me encantaria conocer un poco más de las actividades que realizas en cuanto a tecnologías Microsoft, espero me permitas estar en contacto.

    Deje mi correo electrónico espero me permitas el que estemos en contacto y podamos platicar sobre el reconicimiento que da el programa MVP a profesonales como tú.

    Si pudieras hacerme llegar tus datos como nombre completo y correo electrónico te lo agradecería enormemente.
    a-danam@microsoft.com

Leave a Reply to dmartin Cancel reply

Your email address will not be published. Required fields are marked *