Registro de Windows en Go (Golang)

En otra entrada comenté sobre un proyecto que estaba haciendo que era relativo a respaldos. Como el cliente usa ODBC de Windows (DSN) para conectar a la base de datos, y los datos de conexión para cada cliente es diferente, tenía que buscar la manera de hacerlo sin complicar tanto la herramienta. En este post vamos a ver cómo conectarnos al registro de Windows en Go, que es el lenguaje que estoy usando.

NOTA: acá no veremos cómo crear valores o editarlos, pero tendrás una manera de buscar cómo hacerlo a partir de la documentación.

Windows Registry

Primero que nada vamos a utilizar la librería de Go para conectarnos al registro de Windows. El paquete es golang.org/x/sys.

Esta librería permite interacciones con el sistema operativo y nos permitirá el acceso al registro de Windows sin tanto problema. Esta será golang.org/x/sys/windows/registry.

Empezamos importando la librería:

package main

import (
    "fmt"
    "golang.org/x/sys/windows/registry"
)

var (
    registryKey = "SOFTWARE\\ODBC\\ODBC.INI\\"
)

registryKey es la dirección hasta el directorio donde se encuentra nuestra lista de ODBCs. Aunque dice ODBC.INI no es un archivo, sino un directorio.

registro de windows odbc

Aquí vemos el árbol de directorios de nuestro registro.

registro de windows valores

Una vez seleccionado el directorio de ODBC, vemos que están los datos para conexión:

  • DATABASE
  • PORT
  • PWD
  • SERVER
  • UID

Ahora que ya tenemos identificado todo, vamos a crearnos el código para acceder e ello.

Código de Go para leer el registro de Windows

Primero iniciamos el proyecto:

mkdir win-registry && cd win-registry

go mod init win-registry 

go get golang.org/x/sys/windows/registry

Para organizarnos, creamos un struct con los datos de la conexión:

...
type Regedit struct {
    Hostname string
    Port     string
    Database string
    User     string
    Password string
}

Ahora creamos la función para leer nuestro DSN:

func getStringValue(dsnName, keyName string) string {
    var access uint32 = registry.QUERY_VALUE
    regKey, err := registry.OpenKey(registry.CURRENT_USER, registryKey+"\\"+dsnName, access)

    if err != nil {
        if err != registry.ErrNotExist {
            return ""
        }
        return ""
    }

    id, _, err := regKey.GetStringValue(keyName)
    if err != nil {
        return ""
    }
    return id
}

En registry.OpenKey le enviamos tres parámetros, el punto de entrada a nuestro directorio, el directorio y los permisos de acceso, que este caso son de lectura, lo que indicamos con registry.QUERY_VALUE.

Para finalizar, creamos el main:

func main() {
    r := Regedit{}

    dsn := "nombre_de_ODBC"

    r.Hostname = getStringValue(dsn, "SERVER")
    r.Port = getStringValue(dsn, "PORT")
    r.Database = getStringValue(dsn, "DATABASE")
    r.User = getStringValue(dsn, "UID")
    r.Password = getStringValue(dsn, "PWD")

    fmt.Printf("Host    : %s\n", r.Hostname)
    fmt.Printf("Port    : %s\n", r.Port)
    fmt.Printf("Database: %s\n", r.Database)
    fmt.Printf("User    : %s\n", r.User)
    fmt.Printf("Password: %s\n", r.Password)
}

El nombre que debemos usar para la variable dsn es el directorio adecuado dentro del registryKey declarado al inicio.

Con esto deberías poder leer el registro de Windows en Golang. Solo compilamos:

go mod init

go build

win-registry.exe
compilar windows registry golang

BONUS: Compilar para Windows desde Linux

Yo inicié el proyecto desde Linux, porque es más cómoda mi computadora y decidí dejar este módulo al final, ya luego me pasaría a la máquina Windows para finalizar. Dicho sea de paso que estaba haciéndolo en Visual Studio Code.

Cuando agregas la librería te aparecerá un error en VSCode, que en pocas palabras te dice que no puede importarlas porque no entiende el sistema operativo.

could not import golang.org/x/sys/windows/registry (no required module provides package "golang.org/x/sys/windows/registry")compiler[BrokenImport](https://pkg.go.dev/golang.org/x/tools/internal/typesinternal#BrokenImport)

error while importing golang.org/x/sys/windows/registry: build constraints exclude all Go files in /home/manuelhdez/go/pkg/mod/golang.org/x/[email protected]/windows/registrycompiler

Para resolverlo, crea un archivo en .vscode\settings.json y agrega lo siguiente:

{
    "go.toolsEnvVars": {"GOOS":"windows","GOARCH": "amd64"}
}

Con esto los errores deberían desaparecer. Pero si tratas de compilar te aparecerá lo siguiente:

Registro de Windows en Go

Esto es porque yo estoy en Linux, pero quiero que el archivo resultante sea compilado para Windows. Ahora vamos a compilar de la siguiente manera:

GOOS=windows GOARCH=amd64 go build

Ahora ya puedes compilar sin errores. Con el inconveniente que no vas a poder hacerlo funcionar, recordemos que el objetivo es leer el Registro de Windows 🙂

Gracias por leer.


Posted

in

, ,

by