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.
Aquí vemos el árbol de directorios de nuestro registro.
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
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:
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.