Files
lanceur-script/LanceurScripts.ahk
2026-03-24 07:50:47 +01:00

1576 lines
49 KiB
AutoHotkey

#Requires AutoHotkey v2.0
#SingleInstance Force
#Warn
; =============================================================================
; Lanceur de scripts v1 Benchmark de PC
; =============================================================================
; Vérifier si le script est lancé en tant qu'administrateur
if !A_IsAdmin {
try {
if A_IsCompiled
Run '*RunAs "' A_ScriptFullPath '"'
else
Run '*RunAs "' A_AhkPath '" "' A_ScriptFullPath '"'
}
ExitApp
}
; =============================================================================
; Variables globales (déclarées au niveau du script, pas besoin de 'global' ici)
; =============================================================================
selectedCategory := ""
highlightColor := "0xADD8E6"
defaultColor := "Default"
isSoftsCategory := false ; Flag pour savoir si on est dans la catégorie Softs
isSearchMode := false ; Flag pour savoir si on est en mode recherche
softsList := [] ; Liste des softs configurés
searchResults := [] ; Résultats de recherche
allScriptsCache := [] ; Cache de tous les scripts
cpuText := ""
ramText := ""
osText := ""
computerText := ""
ipText := ""
secureBootText := ""
sysInfoGroup := ""
lv := ""
motherboardText := ""
launchSelectedBtn := ""
quitBtn := ""
selectAllCheckbox := ""
logCheckbox := ""
extensionsBtn := ""
hiddenFilesBtn := ""
categoryLV := ""
searchEdit := ""
systemBtnList := []
scriptDir := A_ScriptDir
scriptsPath := scriptDir "\Scripts"
softsIniPath := scriptDir "\softs.ini" ; Fichier de configuration des softs
licencePath := A_ScriptDir "\..\Licence Geco.txt"
logPath := "C:\Geco\Log\Log_script.txt"
; =============================================================================
; Détection de la résolution et calcul des tailles
; =============================================================================
screenWidth := A_ScreenWidth
screenHeight := A_ScreenHeight
; Calcul des dimensions de la fenêtre selon la résolution
if (screenWidth <= 800 || screenHeight <= 600) {
; Mode WinPE / Petite résolution (800x600)
winWidth := 780
winHeight := 560
compactMode := true
} else if (screenWidth <= 1024 || screenHeight <= 768) {
; Résolution moyenne (1024x768)
winWidth := 950
winHeight := 700
compactMode := true
} else if (screenWidth <= 1366 || screenHeight <= 768) {
; Résolution laptop standard (1366x768)
winWidth := 1100
winHeight := 620
compactMode := false
} else {
; Grande résolution (1920x1080+)
winWidth := 1120
winHeight := 620
compactMode := false
}
; Dimensions des éléments selon le mode
if compactMode {
categoryWidth := 150
categoryHeight := winHeight - 200
lvRows := 15
btnSpacing := 38
fontSize := 9
sysInfoHeight := 75
} else {
categoryWidth := 180
categoryHeight := winHeight - 165
lvRows := 22
btnSpacing := 45
fontSize := 10
sysInfoHeight := 90
}
if !DirExist(scriptsPath) {
MsgBox "Le dossier '\Scripts' est introuvable dans: " scriptDir
ExitApp
}
; =============================================================================
; Fonctions utilitaires
; =============================================================================
; Fonction pour lire une valeur du registre avec valeur par défaut
SafeRegRead(regPath, valueName, defaultValue := "") {
try {
return RegRead(regPath, valueName)
} catch {
return defaultValue
}
}
; Fonction pour obtenir toutes les catégories uniques à partir des scripts
GetAllCategories(path) {
local cats := Map()
; Collecter les catégories depuis les fichiers PS1
Loop Files path "\*.ps1", "F" {
data := ParseMetadata(A_LoopFileFullPath)
if data && data.Has("Categorie") && data["Categorie"] {
categoriesList := StrSplit(data["Categorie"], ";")
for _, cat in categoriesList {
cat := Trim(cat)
if cat
cats[cat] := true
}
}
}
; Collecter les catégories depuis les fichiers BAT/CMD
Loop Files path "\*.bat", "F" {
data := ParseMetadata(A_LoopFileFullPath)
if data && data.Has("Categorie") && data["Categorie"] {
categoriesList := StrSplit(data["Categorie"], ";")
for _, cat in categoriesList {
cat := Trim(cat)
if cat
cats[cat] := true
}
}
}
Loop Files path "\*.cmd", "F" {
data := ParseMetadata(A_LoopFileFullPath)
if data && data.Has("Categorie") && data["Categorie"] {
categoriesList := StrSplit(data["Categorie"], ";")
for _, cat in categoriesList {
cat := Trim(cat)
if cat
cats[cat] := true
}
}
}
; Convertir le Map en Array
categoriesArray := []
for cat, _ in cats
categoriesArray.Push(cat)
; Trier les catégories par ordre alphabétique (tri à bulles corrigé)
categoriesArray := SortArray(categoriesArray)
return categoriesArray
}
; Fonction de tri à bulles corrigée pour les tableaux de chaînes
SortArray(arr) {
n := arr.Length
if n <= 1
return arr
Loop n - 1 {
swapped := false
Loop n - A_Index {
if StrCompare(arr[A_Index], arr[A_Index + 1]) > 0 {
temp := arr[A_Index]
arr[A_Index] := arr[A_Index + 1]
arr[A_Index + 1] := temp
swapped := true
}
}
if !swapped
break
}
return arr
}
; Fonction de tri pour les scripts (par ordre puis par nom)
SortScripts(scripts) {
n := scripts.Length
if n <= 1
return scripts
Loop n - 1 {
swapped := false
Loop n - A_Index {
; Comparer d'abord par ordre (numérique), puis par nom (alphabétique)
ordre1 := Integer(scripts[A_Index].ordre)
ordre2 := Integer(scripts[A_Index + 1].ordre)
shouldSwap := false
if (ordre1 > ordre2) {
shouldSwap := true
} else if (ordre1 = ordre2) && (StrCompare(scripts[A_Index].nom, scripts[A_Index + 1].nom) > 0) {
shouldSwap := true
}
if shouldSwap {
temp := scripts[A_Index]
scripts[A_Index] := scripts[A_Index + 1]
scripts[A_Index + 1] := temp
swapped := true
}
}
if !swapped
break
}
return scripts
}
; Fonction pour définir la hauteur des lignes d'un ListView
SetListViewRowHeight(lvCtrl, height) {
static LVM_SETIMAGELIST := 0x1003
static LVSIL_SMALL := 1
; Créer une ImageList avec la hauteur souhaitée
hIL := DllCall("ImageList_Create", "Int", 1, "Int", height, "UInt", 0, "Int", 1, "Int", 1, "Ptr")
; Associer l'ImageList au ListView
SendMessage(LVM_SETIMAGELIST, LVSIL_SMALL, hIL, lvCtrl.Hwnd)
}
; =============================================================================
; Gestion des Softs (catégorie spéciale)
; =============================================================================
; Créer le fichier softs.ini par défaut s'il n'existe pas
CreateDefaultSoftsIni() {
global softsIniPath
if !FileExist(softsIniPath) {
defaultContent := "
(
; =============================================================================
; Configuration des Softs - Lanceur de scripts
; =============================================================================
; Format: Nom|Chemin|Description
; Le chemin peut être relatif (ex: ..\SOFT\app.exe) ou absolu (ex: C:\Tools\app.exe)
; Utilisez %USBDRIVE% pour la racine de la clé USB
;
; Exemples:
; 7-Zip|..\SOFT\7-Zip\7zFM.exe|Gestionnaire d'archives
; Notepad++|..\SOFT\Notepad++\notepad++.exe|Éditeur de texte
; CPU-Z|%USBDRIVE%\SOFT\CPU-Z\cpuz.exe|Informations CPU
; =============================================================================
[Softs]
; Ajoutez vos softs ci-dessous (un par ligne)
; Format: Nom|Chemin|Description
)"
try {
FileAppend(defaultContent, softsIniPath, "UTF-8")
}
}
}
; Charger les softs depuis le fichier ini
LoadSoftsFromIni() {
global softsIniPath, scriptDir
softs := []
if !FileExist(softsIniPath)
return softs
; Déterminer la racine de la clé USB
usbDrive := RegExReplace(scriptDir, "\\[^\\]+$", "")
inSection := false
Loop Read softsIniPath {
line := Trim(A_LoopReadLine)
; Ignorer les lignes vides et commentaires
if (line = "" || SubStr(line, 1, 1) = ";")
continue
; Détecter la section [Softs]
if (line = "[Softs]") {
inSection := true
continue
}
; Si on est dans une autre section, arrêter
if (SubStr(line, 1, 1) = "[")
inSection := false
if !inSection
continue
; Parser la ligne: Nom|Chemin|Description
parts := StrSplit(line, "|")
if (parts.Length >= 2) {
nom := Trim(parts[1])
chemin := Trim(parts[2])
description := parts.Length >= 3 ? Trim(parts[3]) : ""
; Remplacer les variables
chemin := StrReplace(chemin, "%USBDRIVE%", usbDrive)
; Convertir chemin relatif en absolu
if (SubStr(chemin, 1, 2) = "..") {
chemin := scriptDir "\" chemin
}
; Vérifier si le fichier existe
if FileExist(chemin) {
; Récupérer la version du fichier
version := GetFileVersion(chemin)
softs.Push({
nom: nom,
chemin: chemin,
description: description,
version: version
})
}
}
}
return softs
}
; Récupérer la version d'un fichier exécutable
GetFileVersion(filePath) {
try {
; Obtenir la taille nécessaire pour les infos de version
size := DllCall("Version\GetFileVersionInfoSize", "Str", filePath, "Ptr", 0, "UInt")
if (size = 0)
return ""
; Allouer le buffer
buf := Buffer(size)
; Récupérer les infos de version
if !DllCall("Version\GetFileVersionInfo", "Str", filePath, "UInt", 0, "UInt", size, "Ptr", buf)
return ""
; Récupérer le pointeur vers VS_FIXEDFILEINFO
if !DllCall("Version\VerQueryValue", "Ptr", buf, "Str", "\", "Ptr*", &pFFI := 0, "UInt*", &len := 0)
return ""
; Lire les valeurs de version (structure VS_FIXEDFILEINFO)
fileVersionMS := NumGet(pFFI, 8, "UInt") ; dwFileVersionMS
fileVersionLS := NumGet(pFFI, 12, "UInt") ; dwFileVersionLS
; Extraire les 4 parties de la version
v1 := (fileVersionMS >> 16) & 0xFFFF
v2 := fileVersionMS & 0xFFFF
v3 := (fileVersionLS >> 16) & 0xFFFF
v4 := fileVersionLS & 0xFFFF
; Formater la version
if (v4 = 0) {
if (v3 = 0)
return v1 "." v2
return v1 "." v2 "." v3
}
return v1 "." v2 "." v3 "." v4
} catch {
return ""
}
}
; Extraire l'icône d'un exécutable
GetFileIcon(filePath) {
static iconCache := Map()
if iconCache.Has(filePath)
return iconCache[filePath]
; Extraire l'icône avec Shell32
hIcon := DllCall("Shell32\ExtractIcon", "Ptr", 0, "Str", filePath, "UInt", 0, "Ptr")
if (hIcon > 1) {
iconCache[filePath] := hIcon
return hIcon
}
return 0
}
; Créer une ImageList avec les icônes des softs
CreateSoftsImageList(softs) {
; Créer une ImageList 24x24 (ou 16x16 si tu préfères)
hIL := DllCall("ImageList_Create", "Int", 20, "Int", 20, "UInt", 0x21, "Int", softs.Length, "Int", 10, "Ptr")
for soft in softs {
hIcon := DllCall("Shell32\ExtractIcon", "Ptr", 0, "Str", soft.chemin, "UInt", 0, "Ptr")
if (hIcon > 1) {
DllCall("ImageList_AddIcon", "Ptr", hIL, "Ptr", hIcon, "Int")
DllCall("DestroyIcon", "Ptr", hIcon)
} else {
; Icône par défaut si pas d'icône trouvée
hDefaultIcon := DllCall("Shell32\ExtractIcon", "Ptr", 0, "Str", "shell32.dll", "UInt", 2, "Ptr")
DllCall("ImageList_AddIcon", "Ptr", hIL, "Ptr", hDefaultIcon, "Int")
DllCall("DestroyIcon", "Ptr", hDefaultIcon)
}
}
return hIL
}
; Afficher les softs dans le ListView
RefreshSoftsList() {
global lv, softsList
lv.Delete()
softsList := LoadSoftsFromIni()
if (softsList.Length = 0) {
lv.Add(, , "(Aucun soft configuré)", "Éditez softs.ini pour ajouter des softs", "", "")
return
}
; Créer et associer l'ImageList
hIL := CreateSoftsImageList(softsList)
SendMessage(0x1003, 1, hIL, lv.Hwnd) ; LVM_SETIMAGELIST, LVSIL_SMALL
; Ajouter les softs au ListView avec la version (colonne Ordre vide pour les softs)
for index, soft in softsList {
lv.Add("Icon" index, , soft.nom, soft.description, soft.version, "")
}
}
; Lancer un soft en administrateur
LaunchSoftAsAdmin(softPath) {
try {
Run '*RunAs "' softPath '"'
WriteLog("Soft: " softPath, "OK")
} catch Error as e {
MsgBox "Erreur lors du lancement: " e.Message
WriteLog("Soft: " softPath, "ERREUR")
}
}
; Ouvrir le fichier softs.ini pour édition
EditSoftsIni() {
global softsIniPath
CreateDefaultSoftsIni()
try {
Run 'notepad.exe "' softsIniPath '"'
} catch {
MsgBox "Impossible d'ouvrir le fichier de configuration."
}
}
; =============================================================================
; Fonctions de recherche
; =============================================================================
; Charger tous les scripts et softs en cache pour la recherche
LoadAllItemsCache() {
global scriptsPath, allScriptsCache
allScriptsCache := []
; Charger tous les scripts PS1
Loop Files scriptsPath "\*.ps1", "F" {
data := ParseMetadata(A_LoopFileFullPath)
if data {
allScriptsCache.Push({
nom: data.Get("Nom"),
description: data.Get("Description"),
version: data.Get("Version"),
ordre: data.Get("Ordre", "50"),
type: "ps1",
chemin: A_LoopFileFullPath,
categorie: data.Get("Categorie")
})
}
}
; Charger tous les scripts BAT
Loop Files scriptsPath "\*.bat", "F" {
data := ParseMetadata(A_LoopFileFullPath)
if data {
allScriptsCache.Push({
nom: data.Get("Nom"),
description: data.Get("Description"),
version: data.Get("Version"),
ordre: data.Get("Ordre", "50"),
type: "bat",
chemin: A_LoopFileFullPath,
categorie: data.Get("Categorie")
})
}
}
; Charger tous les scripts CMD
Loop Files scriptsPath "\*.cmd", "F" {
data := ParseMetadata(A_LoopFileFullPath)
if data {
allScriptsCache.Push({
nom: data.Get("Nom"),
description: data.Get("Description"),
version: data.Get("Version"),
ordre: data.Get("Ordre", "50"),
type: "cmd",
chemin: A_LoopFileFullPath,
categorie: data.Get("Categorie")
})
}
}
; Charger tous les softs
softs := LoadSoftsFromIni()
for soft in softs {
allScriptsCache.Push({
nom: soft.nom,
description: soft.description,
version: soft.version,
ordre: "",
type: "soft",
chemin: soft.chemin,
categorie: "📦 Softs"
})
}
}
; Événement quand le texte de recherche change
OnSearchChange(*) {
global searchEdit, isSearchMode, categoryLV
searchText := Trim(searchEdit.Value)
if (searchText = "") {
; Si la recherche est vide, revenir à la catégorie sélectionnée
isSearchMode := false
idx := categoryLV.GetNext()
if idx {
categoryName := categoryLV.GetText(idx, 1)
ShowCategory(categoryName)
}
return
}
; Activer le mode recherche
isSearchMode := true
; Désélectionner la catégorie dans le ListView
Loop categoryLV.GetCount() {
categoryLV.Modify(A_Index, "-Select")
}
; Effectuer la recherche
PerformSearch(searchText)
}
; Effectuer la recherche
PerformSearch(searchText) {
global lv, allScriptsCache, searchResults
; Recharger le cache si vide
if (allScriptsCache.Length = 0) {
LoadAllItemsCache()
}
lv.Delete()
searchResults := []
searchLower := StrLower(searchText)
; Rechercher dans tous les éléments
for item in allScriptsCache {
nomLower := StrLower(item.nom)
descLower := StrLower(item.description)
; Vérifier si le terme de recherche est dans le nom ou la description
if (InStr(nomLower, searchLower) || InStr(descLower, searchLower)) {
searchResults.Push(item)
}
}
; Afficher les résultats
if (searchResults.Length = 0) {
lv.Add(, , "(Aucun résultat)", "Essayez d'autres termes de recherche", "", "")
return
}
; Créer l'ImageList mixte (scripts + softs)
hIL := CreateSearchImageList(searchResults)
SendMessage(0x1003, 1, hIL, lv.Hwnd)
; Ajouter les résultats au ListView
for index, item in searchResults {
lv.Add("Icon" index, , item.nom, item.description, item.version, item.ordre)
}
}
; Créer une ImageList pour les résultats de recherche (mixte scripts et softs)
CreateSearchImageList(results) {
hIL := DllCall("ImageList_Create", "Int", 20, "Int", 20, "UInt", 0x21, "Int", results.Length, "Int", 10, "Ptr")
; Chemins des icônes système
psPath := A_WinDir "\System32\WindowsPowerShell\v1.0\powershell.exe"
cmdPath := A_WinDir "\System32\cmd.exe"
for item in results {
if (item.type = "ps1") {
; Icône PowerShell
if FileExist(psPath) {
hIcon := DllCall("Shell32\ExtractIcon", "Ptr", 0, "Str", psPath, "UInt", 0, "Ptr")
} else {
hIcon := DllCall("Shell32\ExtractIcon", "Ptr", 0, "Str", "shell32.dll", "UInt", 71, "Ptr")
}
} else if (item.type = "bat" || item.type = "cmd") {
; Icône CMD
if FileExist(cmdPath) {
hIcon := DllCall("Shell32\ExtractIcon", "Ptr", 0, "Str", cmdPath, "UInt", 0, "Ptr")
} else {
hIcon := DllCall("Shell32\ExtractIcon", "Ptr", 0, "Str", "shell32.dll", "UInt", 2, "Ptr")
}
} else {
; Icône du soft
hIcon := DllCall("Shell32\ExtractIcon", "Ptr", 0, "Str", item.chemin, "UInt", 0, "Ptr")
if (hIcon <= 1) {
hIcon := DllCall("Shell32\ExtractIcon", "Ptr", 0, "Str", "shell32.dll", "UInt", 2, "Ptr")
}
}
if (hIcon > 1) {
DllCall("ImageList_AddIcon", "Ptr", hIL, "Ptr", hIcon, "Int")
DllCall("DestroyIcon", "Ptr", hIcon)
}
}
return hIL
}
; Fonction pour créer le dossier de log s'il n'existe pas
CreateLogFolder() {
logDir := "C:\Geco\Log"
if !DirExist(logDir) {
try {
DirCreate(logDir)
} catch Error as e {
MsgBox "Erreur lors de la création du dossier de log: " e.Message
}
}
}
; Fonction pour écrire dans le log
WriteLog(scriptName, status := "OK") {
global logCheckbox, logPath
if !logCheckbox.Value
return
CreateLogFolder()
currentTime := FormatTime(A_Now, "dd/MM/yyyy HH:mm:ss")
logMessage := currentTime " : " scriptName " - " status "`n"
try {
FileAppend(logMessage, logPath, "UTF-8")
} catch Error as e {
MsgBox "Erreur lors de l'écriture du log: " e.Message
}
}
; Fonction pour analyser les métadonnées des scripts
ParseMetadata(filePath) {
local fileHandle := FileOpen(filePath, "r", "UTF-8")
if !fileHandle
return false
SplitPath(filePath, , , &ext)
isBatch := (ext = "bat" || ext = "cmd")
meta := Map("Nom", "", "Version", "", "Description", "", "Categorie", "", "Ordre", "50")
lineNum := 0
while !fileHandle.AtEOF {
line := Trim(fileHandle.ReadLine())
lineNum++
if isBatch {
if InStr(line, "REM Nom:") {
meta["Nom"] := RegExReplace(line, "^\s*REM\s*Nom:\s*", "")
} else if InStr(line, "REM Description:") {
meta["Description"] := RegExReplace(line, "^\s*REM\s*Description:\s*", "")
} else if InStr(line, "REM Version:") {
meta["Version"] := RegExReplace(line, "^\s*REM\s*Version:\s*", "")
} else if InStr(line, "REM Categorie:") {
meta["Categorie"] := RegExReplace(line, "^\s*REM\s*Categorie:\s*", "")
} else if InStr(line, "REM Ordre:") {
meta["Ordre"] := RegExReplace(line, "^\s*REM\s*Ordre:\s*", "")
}
} else {
if InStr(line, "# Nom:") {
meta["Nom"] := RegExReplace(line, "^\s*#\s*Nom:\s*", "")
} else if InStr(line, "# Description:") {
meta["Description"] := RegExReplace(line, "^\s*#\s*Description:\s*", "")
} else if InStr(line, "# Version:") {
meta["Version"] := RegExReplace(line, "^\s*#\s*Version:\s*", "")
} else if InStr(line, "# Categorie:") {
meta["Categorie"] := RegExReplace(line, "^\s*#\s*Categorie:\s*", "")
} else if InStr(line, "# Ordre:") {
meta["Ordre"] := RegExReplace(line, "^\s*#\s*Ordre:\s*", "")
}
}
if meta["Nom"] && meta["Version"] && meta["Description"] && meta["Categorie"] && meta["Ordre"] != "50"
break
; Limiter la lecture aux 30 premières lignes (les métadonnées sont en début de fichier)
if lineNum >= 30
break
}
fileHandle.Close()
return meta["Nom"] ? meta : false
}
; Fonction pour trouver le chemin complet d'un script par son nom et sa catégorie
FindScriptPath(scriptName, category) {
global scriptsPath
; Chercher dans les fichiers PowerShell
Loop Files scriptsPath "\*.ps1", "F" {
meta := ParseMetadata(A_LoopFileFullPath)
if meta && meta["Nom"] = scriptName {
categoriesList := StrSplit(meta["Categorie"], ";")
for _, cat in categoriesList {
if Trim(cat) = category {
return A_LoopFileFullPath
}
}
}
}
; Chercher dans les fichiers batch
Loop Files scriptsPath "\*.bat", "F" {
meta := ParseMetadata(A_LoopFileFullPath)
if meta && meta["Nom"] = scriptName {
categoriesList := StrSplit(meta["Categorie"], ";")
for _, cat in categoriesList {
if Trim(cat) = category {
return A_LoopFileFullPath
}
}
}
}
; Chercher dans les fichiers cmd
Loop Files scriptsPath "\*.cmd", "F" {
meta := ParseMetadata(A_LoopFileFullPath)
if meta && meta["Nom"] = scriptName {
categoriesList := StrSplit(meta["Categorie"], ";")
for _, cat in categoriesList {
if Trim(cat) = category {
return A_LoopFileFullPath
}
}
}
}
return ""
}
; =============================================================================
; Obtenir toutes les catégories
; =============================================================================
categories := GetAllCategories(scriptsPath)
if categories.Length = 0 {
MsgBox "Aucune catégorie trouvée dans les scripts. Assurez-vous que vos scripts contiennent une ligne 'REM Categorie:' ou '# Categorie:'."
ExitApp
}
; =============================================================================
; Interface graphique
; =============================================================================
myGui := Gui("Resize", "Lanceur de scripts v1")
myGui.SetFont("s" fontSize)
btnList := Map()
; Calcul des positions dynamiques
lvX := categoryWidth + 30
lvWidth := winWidth - categoryWidth - 190
lvHeight := winHeight - 220
btnY := 40 + lvHeight + 10
; Groupe des catégories avec ListView
categoryGroup := myGui.Add("GroupBox", "x10 y10 w" categoryWidth " h" (winHeight - 165), "Catégories")
; Barre de recherche
myGui.Add("Text", "x15 y28 w" (categoryWidth - 10), "🔍 Recherche:")
searchEdit := myGui.Add("Edit", "x15 y46 w" (categoryWidth - 10) " h22")
searchEdit.OnEvent("Change", OnSearchChange)
categoryLV := myGui.Add("ListView", "x15 y72 w" (categoryWidth - 10) " h" (winHeight - 230) " -Multi -Hdr", ["Catégorie"])
categoryLV.SetFont("s" fontSize)
; Ajouter la catégorie spéciale "Softs" en premier
categoryLV.Add(, "📦 Softs")
; Ajouter les catégories de scripts
for category in categories {
categoryLV.Add(, category)
}
categoryLV.OnEvent("ItemSelect", OnCategorySelect)
; Créer le fichier softs.ini par défaut s'il n'existe pas
CreateDefaultSoftsIni()
myGui.Add("Text", "x" lvX " y10 w" lvWidth " Center", "Cliquez sur un script pour le lancer ou cochez pour lancer en lot.")
; ListView principal avec cases à cocher
lv := myGui.Add("ListView", "x" lvX " y40 w" lvWidth " h" lvHeight " Checked grid", ["", "Nom", "Description", "Version", "Ordre"])
lv.SetFont("s" fontSize)
lv.OnEvent("DoubleClick", LaunchScript)
lv.OnEvent("ContextMenu", ShowContextMenu)
; Augmenter la hauteur des lignes pour plus de lisibilité
SetListViewRowHeight(lv, compactMode ? 20 : 24)
; Même chose pour le ListView des catégories
SetListViewRowHeight(categoryLV, compactMode ? 18 : 22)
; Boutons sous le ListView
launchSelectedBtn := myGui.Add("Button", "x" lvX " y" btnY " w180 h28", "Lancer les scripts cochés")
launchSelectedBtn.OnEvent("Click", LaunchSelectedScripts)
selectAllCheckbox := myGui.Add("Checkbox", "x" (lvX + 190) " y" btnY " w110 h28", "Tout sélectionner")
selectAllCheckbox.OnEvent("Click", ToggleSelectAll)
logCheckbox := myGui.Add("Checkbox", "x" (lvX + 310) " y" btnY " w90 h28", "Activer log")
logCheckbox.OnEvent("Click", LogCheckboxClick)
; =============================================================================
; Boutons système
; =============================================================================
spacing := btnSpacing
sysBtnX := winWidth - 145
sysBtnY := 40
sysBtnWidth := compactMode ? 120 : 140
sysBtnHeight := compactMode ? 32 : 40
systemButtons := [
["Gest. périphériques", OpenDeviceManager],
["Gestion alimentation", OpenPowerSettings],
["Msinfo32", OpenMsinfo],
["Panneau de conf", OpenControl],
["Extensions fichiers`n", ToggleExtensions],
["Fichiers cachés`n", ToggleHiddenFiles],
["Gest. de tâches", OpenTaskManager]
]
for each, pair in systemButtons {
btn := myGui.Add("Button", "x" sysBtnX " y" sysBtnY " w" sysBtnWidth " h" sysBtnHeight, pair[1])
btn.OnEvent("Click", pair[2])
systemBtnList.Push(btn)
sysBtnY += spacing
}
extensionsBtn := systemBtnList[5]
hiddenFilesBtn := systemBtnList[6]
; Fonction pour mettre à jour l'état des boutons
UpdateButtonStates() {
global extensionsBtn, hiddenFilesBtn, fontSize
regPath := "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
; Vérifier l'état des extensions
hideExtValue := SafeRegRead(regPath, "HideFileExt", 1)
if (hideExtValue = 1) {
extensionsBtn.Text := "Extensions fichiers`nDésactivé"
extensionsBtn.SetFont("s" fontSize " cRed")
} else {
extensionsBtn.Text := "Extensions fichiers`nActivé"
extensionsBtn.SetFont("s" fontSize " cGreen")
}
; Vérifier l'état des fichiers cachés
hiddenValue := SafeRegRead(regPath, "Hidden", 2)
if (hiddenValue = 2) {
hiddenFilesBtn.Text := "Fichiers cachés`nDésactivé"
hiddenFilesBtn.SetFont("s" fontSize " cRed")
} else {
hiddenFilesBtn.Text := "Fichiers cachés`nActivé"
hiddenFilesBtn.SetFont("s" fontSize " cGreen")
}
}
; Bouton Licence Geco
btn := myGui.Add("Button", "x" sysBtnX " y" sysBtnY " w" sysBtnWidth " h" sysBtnHeight, "Licence Geco")
btn.OnEvent("Click", OpenLicence)
systemBtnList.Push(btn)
; Bouton SOFT
btn := myGui.Add("Button", "x" sysBtnX " y" (sysBtnY + spacing) " w" sysBtnWidth " h" sysBtnHeight, "SOFT")
btn.OnEvent("Click", OpenSoftFolder)
systemBtnList.Push(btn)
; Bouton Quitter (rouge)
quitBtn := myGui.Add("Button", "x" sysBtnX " y" (sysBtnY + spacing * 2) " w" sysBtnWidth " h" sysBtnHeight, "Quitter")
quitBtn.SetFont("s" fontSize " cWhite Bold")
quitBtn.Opt("+Background0xCC0000") ; Rouge foncé
quitBtn.OnEvent("Click", (*) => ExitApp())
systemBtnList.Push(quitBtn)
; =============================================================================
; Fonctions pour les boutons système
; =============================================================================
OpenSoftFolder(*) {
scriptFullPath := A_ScriptFullPath
SplitPath(scriptFullPath, , &currentScriptDir)
usbRoot := RegExReplace(currentScriptDir, "\\[^\\]+$", "")
softPath := usbRoot "\SOFT"
if DirExist(softPath) {
Run "explorer.exe /select,`"" softPath "`""
} else {
Loop 26 {
driveLetter := Chr(64 + A_Index)
testPath := driveLetter ":\SOFT"
if DirExist(testPath) {
Run "explorer.exe `"" testPath "`""
return
}
}
MsgBox "Le dossier SOFT n'a pas été trouvé sur la clé USB ou sur les lecteurs disponibles."
}
}
OpenDeviceManager(*) {
Run "devmgmt.msc"
}
OpenPowerSettings(*) {
Run "powercfg.cpl"
}
OpenMsinfo(*) {
Run "msinfo32"
}
OpenControl(*) {
Run "control"
}
OpenTaskManager(*) {
Run "taskmgr.exe"
}
ToggleExtensions(*) {
regPath := "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
regValue := "HideFileExt"
current := SafeRegRead(regPath, regValue, 1)
newValue := current = 1 ? 0 : 1
RegWrite newValue, "REG_DWORD", regPath, regValue
SendMessage(0x1A, 0, StrPtr("Environment"), , "ahk_class Progman")
UpdateButtonStates()
}
ToggleHiddenFiles(*) {
regPath := "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
regValue := "Hidden"
current := SafeRegRead(regPath, regValue, 2)
newValue := current = 2 ? 1 : 2
RegWrite newValue, "REG_DWORD", regPath, regValue
SendMessage(0x1A, 0, StrPtr("Environment"), , "ahk_class Progman")
UpdateButtonStates()
}
OpenLicence(*) {
global licencePath
if FileExist(licencePath)
Run '"' licencePath '"'
else
MsgBox "Le fichier 'Licence Geco.txt' est introuvable à l'emplacement attendu:`n" licencePath
}
; =============================================================================
; Gestion des événements GUI
; =============================================================================
myGui.OnEvent("Size", GuiResize)
GuiResize(thisGui, MinMax, Width, Height) {
global categoryGroup, categoryLV, sysInfoGroup, lv, cpuText, ramText, osText
global computerText, ipText, secureBootText, motherboardText, systemBtnList
global launchSelectedBtn, selectAllCheckbox, logCheckbox
global categoryWidth, btnSpacing, sysInfoHeight, compactMode, lvX
if (MinMax = -1)
return
; Hauteur du groupe catégories (s'arrête avant les infos système)
categoryGroup.Move(, , , Height - 165)
categoryLV.Move(, , , Height - 230)
lvNewWidth := Width - categoryWidth - 190
lvNewHeight := Height - 220
lv.Move(, , lvNewWidth, lvNewHeight)
newBtnY := 40 + lvNewHeight + 10
launchSelectedBtn.Move(lvX, newBtnY)
selectAllCheckbox.Move(lvX + 190, newBtnY)
logCheckbox.Move(lvX + 310, newBtnY)
startY := 40
for index, sysBtn in systemBtnList {
sysBtn.Move(Width - 145, startY)
startY += btnSpacing
}
sysInfoGroup.Move(10, Height - sysInfoHeight - 30, Width - 20, sysInfoHeight)
cpuText.Move(20, Height - sysInfoHeight - 10)
ramText.Move(20, Height - sysInfoHeight + 10)
osText.Move(20, Height - sysInfoHeight + 30)
computerText.Move(Width / 2, Height - sysInfoHeight - 10)
ipText.Move(Width / 2, Height - sysInfoHeight + 10)
secureBootText.Move(Width / 2, Height - sysInfoHeight + 30)
motherboardText.Move(20, Height - sysInfoHeight + 50)
AdjustColumns(lvNewWidth)
}
AdjustColumns(totalWidth) {
global lv
totalWidth := totalWidth - 5
col1Width := Floor(totalWidth * 0.05) ; Icône
col2Width := Floor(totalWidth * 0.24) ; Nom
col3Width := Floor(totalWidth * 0.50) ; Description
col4Width := Floor(totalWidth * 0.10) ; Version
col5Width := Floor(totalWidth * 0.08) ; Ordre
lv.ModifyCol(1, col1Width)
lv.ModifyCol(2, col2Width)
lv.ModifyCol(3, col3Width)
lv.ModifyCol(4, col4Width)
lv.ModifyCol(5, col5Width " Center") ; Centrer l'ordre
}
; =============================================================================
; Gestion des catégories et scripts
; =============================================================================
OnCategorySelect(LV, Item, Selected) {
if Selected {
categoryName := LV.GetText(Item, 1)
ShowCategory(categoryName)
}
}
ShowCategory(categoryName, *) {
global selectedCategory, selectAllCheckbox, isSoftsCategory
selectedCategory := categoryName
; Vérifier si c'est la catégorie Softs
if (categoryName = "📦 Softs") {
isSoftsCategory := true
RefreshSoftsList()
} else {
isSoftsCategory := false
RefreshList(categoryName)
}
selectAllCheckbox.Value := 0
}
RefreshList(category) {
global scriptsPath, lv
lv.Delete()
scripts := []
; Collecter tous les scripts PS1 de cette catégorie
Loop Files scriptsPath "\*.ps1", "F" {
data := ParseMetadata(A_LoopFileFullPath)
if data && data.Has("Categorie") {
categoriesList := StrSplit(data["Categorie"], ";")
for _, cat in categoriesList {
if Trim(cat) = category {
scripts.Push({
nom: data.Get("Nom"),
description: data.Get("Description"),
version: data.Get("Version"),
ordre: data.Get("Ordre", "50"),
type: "ps1"
})
break
}
}
}
}
; Collecter tous les scripts BAT/CMD de cette catégorie
Loop Files scriptsPath "\*.bat", "F" {
data := ParseMetadata(A_LoopFileFullPath)
if data && data.Has("Categorie") {
categoriesList := StrSplit(data["Categorie"], ";")
for _, cat in categoriesList {
if Trim(cat) = category {
scripts.Push({
nom: data.Get("Nom"),
description: data.Get("Description"),
version: data.Get("Version"),
ordre: data.Get("Ordre", "50"),
type: "bat"
})
break
}
}
}
}
Loop Files scriptsPath "\*.cmd", "F" {
data := ParseMetadata(A_LoopFileFullPath)
if data && data.Has("Categorie") {
categoriesList := StrSplit(data["Categorie"], ";")
for _, cat in categoriesList {
if Trim(cat) = category {
scripts.Push({
nom: data.Get("Nom"),
description: data.Get("Description"),
version: data.Get("Version"),
ordre: data.Get("Ordre", "50"),
type: "cmd"
})
break
}
}
}
}
scripts := SortScripts(scripts)
; Créer l'ImageList pour les icônes de scripts
hIL := CreateScriptsImageList()
SendMessage(0x1003, 1, hIL, lv.Hwnd) ; LVM_SETIMAGELIST, LVSIL_SMALL
; Ajouter les scripts avec leurs icônes
for script in scripts {
; Icon1 = PowerShell (bleu), Icon2 = CMD/BAT (noir)
iconIndex := (script.type = "ps1") ? 1 : 2
lv.Add("Icon" iconIndex, , script.nom, script.description, script.version, script.ordre)
}
}
; Créer l'ImageList pour les icônes CMD et PowerShell
CreateScriptsImageList() {
; Créer une ImageList 20x20
hIL := DllCall("ImageList_Create", "Int", 20, "Int", 20, "UInt", 0x21, "Int", 2, "Int", 2, "Ptr")
; Icône PowerShell (depuis powershell.exe)
psPath := A_WinDir "\System32\WindowsPowerShell\v1.0\powershell.exe"
if FileExist(psPath) {
hIconPS := DllCall("Shell32\ExtractIcon", "Ptr", 0, "Str", psPath, "UInt", 0, "Ptr")
} else {
; Icône par défaut si PowerShell non trouvé
hIconPS := DllCall("Shell32\ExtractIcon", "Ptr", 0, "Str", "shell32.dll", "UInt", 71, "Ptr")
}
if (hIconPS > 1) {
DllCall("ImageList_AddIcon", "Ptr", hIL, "Ptr", hIconPS, "Int")
DllCall("DestroyIcon", "Ptr", hIconPS)
}
; Icône CMD (depuis cmd.exe)
cmdPath := A_WinDir "\System32\cmd.exe"
if FileExist(cmdPath) {
hIconCMD := DllCall("Shell32\ExtractIcon", "Ptr", 0, "Str", cmdPath, "UInt", 0, "Ptr")
} else {
; Icône par défaut si CMD non trouvé
hIconCMD := DllCall("Shell32\ExtractIcon", "Ptr", 0, "Str", "shell32.dll", "UInt", 2, "Ptr")
}
if (hIconCMD > 1) {
DllCall("ImageList_AddIcon", "Ptr", hIL, "Ptr", hIconCMD, "Int")
DllCall("DestroyIcon", "Ptr", hIconCMD)
}
return hIL
}
; =============================================================================
; Menu contextuel
; =============================================================================
ShowContextMenu(GuiCtrlObj, Item, IsRightClick, X, Y) {
global isSoftsCategory, softsList
if !IsRightClick || !Item
return
lv.Modify(Item, "Select")
contextMenu := Menu()
; Menu différent selon si on est dans Softs ou non
if isSoftsCategory {
contextMenu.Add("Lancer en admin", (*) => LaunchSoftFromMenu(Item))
contextMenu.Add("Ouvrir l'emplacement", (*) => OpenSoftLocation(Item))
contextMenu.Add() ; Séparateur
contextMenu.Add("Éditer softs.ini", (*) => EditSoftsIni())
contextMenu.Add("Rafraîchir la liste", (*) => RefreshSoftsList())
} else {
contextMenu.Add("Éditer le script", (*) => EditScript(Item))
contextMenu.Add("Copier le script sur le PC", (*) => CopyScriptToPC(Item))
}
contextMenu.Show()
}
; Lancer un soft depuis le menu contextuel
LaunchSoftFromMenu(itemIndex) {
global softsList
if (itemIndex <= softsList.Length) {
LaunchSoftAsAdmin(softsList[itemIndex].chemin)
}
}
; Ouvrir l'emplacement du soft dans l'explorateur
OpenSoftLocation(itemIndex) {
global softsList
if (itemIndex <= softsList.Length) {
softPath := softsList[itemIndex].chemin
Run 'explorer.exe /select,"' softPath '"'
}
}
CopyScriptToPC(itemIndex) {
global selectedCategory, scriptsPath
nom := lv.GetText(itemIndex, 2)
if !nom
return
sourceFile := FindScriptPath(nom, selectedCategory)
if !sourceFile {
MsgBox "Script non trouvé: " nom
return
}
destFolder := DirSelect("*" A_Desktop, 3, "Choisir le dossier de destination")
if !destFolder
return
SplitPath(sourceFile, &fileName)
destFile := destFolder "\" fileName
try {
FileCopy(sourceFile, destFile, 1)
MsgBox "Script copié avec succès vers:`n" destFile, "Copie réussie"
WriteLog("Copie de " nom " vers " destFile, "OK")
} catch Error as e {
MsgBox "Erreur lors de la copie:`n" e.Message, "Erreur"
WriteLog("Copie de " nom, "ERREUR")
}
}
EditScript(itemIndex) {
global selectedCategory, scriptsPath
nom := lv.GetText(itemIndex, 2)
if !nom
return
scriptFile := FindScriptPath(nom, selectedCategory)
if !scriptFile {
MsgBox "Script non trouvé: " nom
return
}
SplitPath(scriptFile, , , &ext)
isPs1 := (ext = "ps1")
try {
if isPs1 {
if FileExist(A_WinDir "\System32\WindowsPowerShell\v1.0\powershell_ise.exe") {
Run A_WinDir "\System32\WindowsPowerShell\v1.0\powershell_ise.exe -File `"" scriptFile "`""
} else {
Run "notepad.exe `"" scriptFile "`""
}
} else {
Run "notepad.exe `"" scriptFile "`""
}
WriteLog("Édition de " nom, "OK")
} catch Error as e {
MsgBox "Erreur lors de l'ouverture de l'éditeur: " e.Message
WriteLog("Édition de " nom, "ERREUR")
}
}
; =============================================================================
; Sélection et lancement des scripts
; =============================================================================
LogCheckboxClick(*) {
global logCheckbox
if logCheckbox.Value {
WriteLog("Logging activé", "INFO")
}
}
ToggleSelectAll(*) {
global lv, selectAllCheckbox
isChecked := selectAllCheckbox.Value
Loop lv.GetCount() {
if isChecked {
lv.Modify(A_Index, "Check")
} else {
lv.Modify(A_Index, "-Check")
}
}
}
LaunchScript(*) {
global selectedCategory, isSoftsCategory, softsList, isSearchMode, searchResults
idx := lv.GetNext()
if !idx
return
nom := lv.GetText(idx, 2)
; Si on est en mode recherche
if isSearchMode {
if (idx <= searchResults.Length) {
item := searchResults[idx]
if (item.type = "soft") {
LaunchSoftAsAdmin(item.chemin)
} else {
LaunchScriptByPath(item.chemin, item.type)
}
}
return
}
; Si c'est la catégorie Softs, lancer le soft
if isSoftsCategory {
if (idx <= softsList.Length) {
LaunchSoftAsAdmin(softsList[idx].chemin)
}
return
}
LaunchScriptByName(nom)
}
LaunchScriptByName(nom) {
global selectedCategory, scriptsPath
scriptPath := FindScriptPath(nom, selectedCategory)
if !scriptPath {
MsgBox "Script non trouvé: " nom
WriteLog(nom, "INTROUVABLE")
return
}
SplitPath(scriptPath, , , &ext)
if (ext = "ps1") {
try {
RunWait 'powershell.exe -NoProfile -ExecutionPolicy Bypass -File "' scriptPath '"'
WriteLog(nom, "OK")
} catch Error as e {
WriteLog(nom, "ERREUR")
MsgBox "Erreur lors de l'exécution du script: " e.Message
}
} else {
try {
RunWait '"' scriptPath '"'
WriteLog(nom, "OK")
} catch Error as e {
WriteLog(nom, "ERREUR")
MsgBox "Erreur lors de l'exécution du script: " e.Message
}
}
}
; Lancer un script par son chemin direct (utilisé par la recherche)
LaunchScriptByPath(scriptPath, scriptType) {
if (scriptType = "ps1") {
try {
RunWait 'powershell.exe -NoProfile -ExecutionPolicy Bypass -File "' scriptPath '"'
WriteLog(scriptPath, "OK")
} catch Error as e {
WriteLog(scriptPath, "ERREUR")
MsgBox "Erreur lors de l'exécution du script: " e.Message
}
} else {
try {
RunWait '"' scriptPath '"'
WriteLog(scriptPath, "OK")
} catch Error as e {
WriteLog(scriptPath, "ERREUR")
MsgBox "Erreur lors de l'exécution du script: " e.Message
}
}
}
LaunchSelectedScripts(*) {
global lv
checkedScripts := []
Loop lv.GetCount() {
if lv.GetNext(A_Index - 1, "Checked") = A_Index {
scriptName := lv.GetText(A_Index, 2)
if scriptName
checkedScripts.Push(scriptName)
}
}
if checkedScripts.Length = 0 {
MsgBox "Aucun script sélectionné.", "Information"
return
}
result := MsgBox("Voulez-vous lancer " checkedScripts.Length " script(s) sélectionné(s) ?", "Confirmation", "YesNo")
if result = "No"
return
WriteLog("Lancement en lot de " checkedScripts.Length " script(s)", "INFO")
for scriptName in checkedScripts {
LaunchScriptByName(scriptName)
}
WriteLog("Fin du lancement en lot", "INFO")
MsgBox "Tous les scripts sélectionnés ont été lancés.", "Information"
}
; =============================================================================
; Fonctions d'information système
; =============================================================================
GetCPUInfo() {
try {
for obj in ComObject("WbemScripting.SWbemLocator").ConnectServer(, "root\CIMV2").ExecQuery("SELECT Name FROM Win32_Processor")
return obj.Name
} catch {
return "Information non disponible"
}
}
GetRAMInfo() {
try {
totalRAM := 0
for obj in ComObject("WbemScripting.SWbemLocator").ConnectServer(, "root\CIMV2").ExecQuery("SELECT Capacity FROM Win32_PhysicalMemory")
totalRAM += obj.Capacity
return Format("{:.2f} Go", totalRAM / 1073741824)
} catch {
return "Information non disponible"
}
}
GetOSInfo() {
try {
for obj in ComObject("WbemScripting.SWbemLocator").ConnectServer(, "root\CIMV2").ExecQuery("SELECT Caption, Version FROM Win32_OperatingSystem")
return obj.Caption " (" obj.Version ")"
} catch {
return "Information non disponible"
}
}
GetIPAddress() {
try {
for obj in ComObject("WbemScripting.SWbemLocator").ConnectServer(, "root\CIMV2").ExecQuery("SELECT IPAddress FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE")
if IsObject(obj.IPAddress)
return obj.IPAddress[0]
} catch {
return "Information non disponible"
}
return "Non connecté"
}
GetSecureBootStatus() {
secureBootEnabled := SafeRegRead("HKLM\SYSTEM\CurrentControlSet\Control\SecureBoot\State", "UEFISecureBootEnabled", 2)
if (secureBootEnabled = 1)
return "Activé"
else if (secureBootEnabled = 0)
return "Désactivé"
return "Non pris en charge"
}
GetMotherboardInfo() {
try {
for obj in ComObject("WbemScripting.SWbemLocator").ConnectServer(, "root\CIMV2").ExecQuery("SELECT Product FROM Win32_BaseBoard")
return obj.Product
} catch {
return "Information non disponible"
}
}
SetSecureBootColor(status) {
global secureBootText
if (status = "Activé")
secureBootText.Opt("+c0x008000") ; Vert
else if (status = "Désactivé")
secureBootText.Opt("+c0xFF0000") ; Rouge
else if (status = "Non pris en charge")
secureBootText.Opt("+c0x0000FF") ; Bleu
else
secureBootText.Opt("+c0x000000") ; Noir par défaut
}
; =============================================================================
; Initialisation de l'interface
; =============================================================================
; Charger le cache pour la recherche
LoadAllItemsCache()
; Sélectionner automatiquement la catégorie "📦 Softs" (première dans la liste)
categoryLV.Modify(1, "Select")
ShowCategory("📦 Softs")
; Groupe informations système
sysInfoY := winHeight - sysInfoHeight - 30
sysInfoGroup := myGui.Add("GroupBox", "x10 y" sysInfoY " w" (winWidth - 20) " h" sysInfoHeight, "Informations Système")
sysInfoGroup.SetFont("s" fontSize " Bold")
infoY1 := sysInfoY + 20
infoY2 := sysInfoY + 38
infoY3 := sysInfoY + 56
infoY4 := sysInfoY + 74
halfWidth := winWidth / 2
cpuText := myGui.Add("Text", "x20 y" infoY1 " w" (halfWidth - 30), "CPU: " GetCPUInfo())
ramText := myGui.Add("Text", "x20 y" infoY2 " w" (halfWidth - 30), "RAM: " GetRAMInfo())
osText := myGui.Add("Text", "x20 y" infoY3 " w" (halfWidth - 30), "OS: " GetOSInfo())
computerText := myGui.Add("Text", "x" halfWidth " y" infoY1 " w" (halfWidth - 30), "Nom PC: " A_ComputerName)
ipText := myGui.Add("Text", "x" halfWidth " y" infoY2 " w" (halfWidth - 30), "Adresse IP: " GetIPAddress())
secureBootStatus := GetSecureBootStatus()
secureBootText := myGui.Add("Text", "x" halfWidth " y" infoY3 " w" (halfWidth - 30), "Secure Boot: " secureBootStatus)
SetSecureBootColor(secureBootStatus)
if !compactMode {
motherboardText := myGui.Add("Text", "x20 y" infoY4 " w" (winWidth - 40), "Carte Mère: " GetMotherboardInfo())
} else {
motherboardText := myGui.Add("Text", "x20 y" infoY4 " w" (winWidth - 40), "")
}
; Mise à jour de l'état des boutons et affichage
UpdateButtonStates()
myGui.Show("w" winWidth " h" winHeight)