Page 1 of 1

Reboot to the desired OS

Posted: Fri Nov 07, 2025 4:21 pm
by AZJIO
The code writes the Grub2 menu item number to a file, which is used to set the default item number. When selected in the GUI, the computer reboots into the OS that was selected. You don't have to wait for the Grub2 menu to make a choice.

Image

Download
video

grub.cfg (this code must be added before the menu items)

Code: Select all

search --no-floppy --fs-uuid --set=partfile UUID_где_файл
source (${partfile})/b/bootdefitem/def

Code: Select all

;- TOP
EnableExplicit

Define UserIntLang
Define ForceLang

CompilerSelect #PB_Compiler_OS
	CompilerCase #PB_OS_Windows
		Define *Lang
		If OpenLibrary(0, "kernel32.dll")
			*Lang = GetFunction(0, "GetUserDefaultUILanguage")
			If *Lang And CallFunctionFast(*Lang) = 1049 ; ru
				UserIntLang = 1
			EndIf
			CloseLibrary(0)
		EndIf
	CompilerCase #PB_OS_Linux
		If ExamineEnvironmentVariables()
			While NextEnvironmentVariable()
				If Left(EnvironmentVariableName(), 4) = "LANG" And Left(EnvironmentVariableValue(), 2) = "ru"
					UserIntLang = 1
					Break
				EndIf
			Wend
		EndIf
CompilerEndSelect

#CountStrLang = 5
Global Dim Lng.s(#CountStrLang)
Lng(1) = "Reboot"
Lng(2) = "With a reboot"
Lng(3) = "Reboot?"
Lng(4) = "Reboot to "
Lng(5) = "The file does not exist, do you want to create it?"


;- # Constants
#Window = 0
#File = 0

Structure OS_List
	name.s
	id.i
EndStructure

;- ● Global
Global Path$, arg$, shutdown$
Global reboot = 1
Global confirmation, item$
Global ini$, PathConfig$
Global NewMap OS_List.OS_List()
Global id, id2, eg, Style, AlignsLeft
Global widthBtn = 200
Global heightBtn = 40

Declare ForceDirectories(Dir.s)

CompilerIf #PB_Compiler_OS = #PB_OS_Linux
	Path$ = "/media/win11/b/bootdefitem/def"
	arg$ = "-r"
	shutdown$ = "shutdown"
CompilerElse
	Path$ = "C:\b\bootdefitem\def"
	arg$ = "-r -t 0"
	shutdown$ = "shutdown.exe"
CompilerEndIf

;- ● ini
PathConfig$ = GetPathPart(ProgramFilename())
ini$ = PathConfig$ + "GrubDef.ini"
If OpenPreferences(ini$)
	PreferenceGroup("set")
	Path$ = ReadPreferenceString("path", Path$)
	shutdown$ = ReadPreferenceString("shutdown", shutdown$)
	arg$ = ReadPreferenceString("arg", arg$)
	reboot = ReadPreferenceInteger("reboot", reboot)
	confirmation = ReadPreferenceInteger("confirmation", confirmation)
	ForceLang = ReadPreferenceInteger("forcelang", ForceLang)
	widthBtn = ReadPreferenceInteger("widthBtn", widthBtn)
	heightBtn = ReadPreferenceInteger("heightBtn", heightBtn)
	AlignsLeft = ReadPreferenceInteger("AlignsLeft", AlignsLeft)
	PreferenceGroup("item")
	ExaminePreferenceKeys()
	While  NextPreferenceKey()
		If Not FindMapElement(OS_List(), PreferenceKeyName())
			If AddMapElement(OS_List(), PreferenceKeyName(), #PB_Map_NoElementCheck)
				OS_List()\name = PreferenceKeyValue()
			EndIf
		EndIf
	Wend
	ClosePreferences()
Else
	MessageRequester("ini", "GrubDef.ini not found")
EndIf


; Здесь нужно прочитать флаг из ini-файла определяющий принудительный язык, где
; 0 - автоматически
; -1 - принудительно первый
; 1 - принудительно второй
; Тем самым будучи в России можно выбрать англ язык или будучи в союзных республиках выбрать русский язык
If ForceLang = 1
	UserIntLang = 0
ElseIf ForceLang = 2
	UserIntLang = 1
EndIf

Procedure SetLangTxt(PathLang$)
	Protected file_id, Format, i, tmp$
	
	file_id = ReadFile(#PB_Any, PathLang$) 
	If file_id ; Если удалось открыть дескриптор файла, то
		Format = ReadStringFormat(file_id) ;  перемещаем указатель после метки BOM
		i=0
		While Eof(file_id) = 0        ; Цикл, пока не будет достигнут конец файла. (Eof = 'Конец файла')
			tmp$ =  ReadString(file_id, Format) ; читаем строку
			tmp$ = RTrim(tmp$ , #CR$) ; коррекция если в Windows
			If Asc(tmp$) And Asc(tmp$) <> ';'
				i+1
				If i > #CountStrLang ; массив Lng() уже задан, но если строк больше нужного, то не разрешаем лишнее
					Break
				EndIf
; 				Lng(i) = ReplaceString(tmp$, "\n", #LF$)
				Lng(i) = tmp$
			Else
				Continue
			EndIf
		Wend
		CloseFile(file_id)
	EndIf
	; Else
	; SaveFile_Buff(PathLang$, ?LangFile, ?LangFileend - ?LangFile)
EndProcedure


; Если языковой файл существует, то использует его
If FileSize(PathConfig$ + "Lang.txt") > 10
	UserIntLang = 0
	SetLangTxt(PathConfig$ + "Lang.txt")
EndIf


If UserIntLang = 1
	Lng(1) = "Перезагрузка"
	Lng(2) = "С перезагрузкой"
	Lng(3) = "Перезагрузка?"
	Lng(4) = "Перезагрузка в "
	Lng(5) = "Файл не существует, хотите его создать?"
EndIf

If FileSize(Path$) = -1 And MessageRequester("", Path$ + #LF$ + #LF$ + Lng(5), #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
	If ForceDirectories(Path$)
		If CreateFile(#File, Path$, #PB_Ascii)
			WriteString(#File, "set default=" + Chr(34) + "0" + Chr(34), #PB_Ascii)
			CloseFile(#File)
		EndIf
	EndIf
EndIf


If OpenPreferences(Path$)
	item$ =  ReplaceString(ReadPreferenceString("set default", "-1"), Chr(34), "")
; 	curitem =  Val(ReplaceString(ReadPreferenceString("set default", "-1"), Chr(34), ""))
	ClosePreferences()
EndIf


;-┌──GUI──┐
If OpenWindow(#Window, 0, 0, widthBtn + 20, MapSize(OS_List()) * heightBtn + 50, Lng(1) + " (" + item$ + ")", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

	If AlignsLeft
		Style | #PB_Button_Left
	EndIf

	ForEach OS_List()
		ButtonGadget(id, 10, id * heightBtn + 10, widthBtn, heightBtn - 3, MapKey(OS_List()) + " " + OS_List()\name, Style)
		CompilerIf #PB_Compiler_OS = #PB_OS_Windows
			If MapKey(OS_List()) = item$
				SetGadgetState(id, #PB_Button_Default)
			EndIf
		CompilerEndIf
		OS_List()\id = id
		id + 1
	Next
	CheckBoxGadget(id , 10, id * heightBtn + 10, widthBtn, 30, Lng(2))
	SetGadgetState(id, reboot)
	id2 = id - 1

;-┌──Loop──┐
	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_Gadget
				eg = EventGadget()
				Select eg
					Case 0 To id2
; 						Ищем по id
						ForEach OS_List()
							If OS_List()\id = eg
; 								Debug OS_List()\name
								Break
							EndIf
						Next
						If CreateFile(#File, Path$, #PB_Ascii)
							WriteString(#File, "set default=" + Chr(34) + MapKey(OS_List()) + Chr(34), #PB_Ascii)
							CloseFile(#File)
						EndIf
						If GetGadgetState(id) & #PB_Checkbox_Checked
							If confirmation And MessageRequester(Lng(3), Lng(4) + OS_List()\name + "?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_No
								Continue
							EndIf
							RunProgram(shutdown$, arg$, "")
						EndIf
						CloseWindow(#Window)
						End
				EndSelect
			Case #PB_Event_CloseWindow
				CloseWindow(#Window)
				End
		EndSelect
	ForEver
EndIf

;==================================================================
;
; Author:    ts-soft     
; Date:       March 5th, 2010
; Explain:
;     modified version from IBSoftware (CodeArchiv)
;     on vista and above check the Request for "User mode" or "Administrator mode" in compileroptions
;    (no virtualisation!)
;==================================================================
Procedure ForceDirectories(Dir.s)
	Static tmpDir.s, Init
	Protected result
	
	If Len(Dir) = 0
		ProcedureReturn #False
	Else
		If Not Init
			tmpDir = Dir
			Init   = #True
		EndIf
		If (Right(Dir, 1) = #PS$)
			Dir = Left(Dir, Len(Dir) - 1)
		EndIf
		If (Len(Dir) < 3) Or FileSize(Dir) = -2 Or GetPathPart(Dir) = Dir
			If FileSize(tmpDir) = -2
				result = #True
			EndIf
			tmpDir = ""
			Init = #False
			ProcedureReturn result
		EndIf
		ForceDirectories(GetPathPart(Dir))
		ProcedureReturn CreateDirectory(Dir)
	EndIf
EndProcedure
The ini file (GrubDef.ini)

Code: Select all

[set]
widthBtn = 200
heightBtn = 40
AlignsLeft = 0
path = C:\b\bootdefitem\def
shutdown = shutdown.exe
arg = -r -t 0
reboot = 0
confirmation = 0
forcelang = 0

[item]
0 = Mint
1 = CachyOS
2 = Windows11
3 = Fedora
Linux

Code: Select all

[set]
widthBtn = 200
heightBtn = 40
AlignsLeft = 0
path = /media/win11/b/bootdefitem/def
shutdown = shutdown
arg = -r now
reboot = 0
confirmation = 0
forcelang = 0

[item]
0 = Mint
1 = CachyOS
2 = Windows11
3 = Fedora