131 lines
3.4 KiB
Go
131 lines
3.4 KiB
Go
//go:build windows
|
|
|
|
package tools
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
var (
|
|
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
|
procSetConsoleMode = kernel32.NewProc("SetConsoleMode")
|
|
procGetConsoleMode = kernel32.NewProc("GetConsoleMode")
|
|
procCreateMutex = kernel32.NewProc("CreateMutexW")
|
|
procCloseHandle = kernel32.NewProc("CloseHandle")
|
|
)
|
|
|
|
const ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
|
|
|
|
var mutexHandle syscall.Handle
|
|
|
|
func init() {
|
|
enableVirtualTerminal()
|
|
|
|
}
|
|
|
|
func enableVirtualTerminal() {
|
|
handle := os.Stdout.Fd()
|
|
var mode uint32
|
|
|
|
// Получаем текущий режим консоли
|
|
_, _, _ = procGetConsoleMode.Call(uintptr(handle), uintptr(unsafe.Pointer(&mode)))
|
|
|
|
// Добавляем флаг поддержки ANSI
|
|
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
|
|
|
// Устанавливаем новый режим
|
|
_, _, _ = procSetConsoleMode.Call(uintptr(handle), uintptr(mode))
|
|
}
|
|
|
|
func RunBatScript(script string) (string, error) {
|
|
// Создание временного файла
|
|
tmpFile, err := os.CreateTemp("", "script-*.bat")
|
|
if err != nil {
|
|
return "", fmt.Errorf("ошибка создания temp-файла: %w", err)
|
|
}
|
|
defer os.Remove(tmpFile.Name())
|
|
|
|
// Запись скрипта в файл
|
|
if _, err := tmpFile.WriteString(script); err != nil {
|
|
return "", fmt.Errorf("ошибка записи в temp-файл: %w", err)
|
|
}
|
|
tmpFile.Close()
|
|
|
|
// Выполняем файл через cmd
|
|
cmd := exec.Command("cmd", "/C", tmpFile.Name())
|
|
output, err := cmd.CombinedOutput()
|
|
|
|
return string(output), err
|
|
}
|
|
|
|
// Функция для логирования вывода процесса в консоль
|
|
func Logs_console(process *exec.Cmd, check bool) error {
|
|
|
|
if check {
|
|
// Настраиваем pipes для захвата вывода
|
|
stdout, err := process.StdoutPipe()
|
|
CheckError(err)
|
|
stderr, err := process.StderrPipe()
|
|
CheckError(err)
|
|
|
|
// Запускаем процесс
|
|
process.Start()
|
|
|
|
// Захватываем stdout и stderr для вывода логов
|
|
go func() {
|
|
scanner := bufio.NewScanner(stdout)
|
|
for scanner.Scan() {
|
|
fmt.Println(scanner.Text())
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
scanner := bufio.NewScanner(stderr)
|
|
for scanner.Scan() {
|
|
fmt.Println(scanner.Text())
|
|
}
|
|
}()
|
|
} else {
|
|
// Просто запускаем процесс без логирования
|
|
return process.Start()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CheckSingleInstance проверяет, не запущена ли программа уже через мьютекс
|
|
func CheckSingleInstance() bool {
|
|
mutexName, _ := syscall.UTF16PtrFromString("Global\\vServer_SingleInstance")
|
|
|
|
handle, _, err := procCreateMutex.Call(
|
|
0,
|
|
0,
|
|
uintptr(unsafe.Pointer(mutexName)),
|
|
)
|
|
|
|
if handle == 0 {
|
|
return false // не удалось создать мьютекс
|
|
}
|
|
|
|
mutexHandle = syscall.Handle(handle)
|
|
|
|
// Если GetLastError возвращает ERROR_ALREADY_EXISTS (183), значит мьютекс уже существует
|
|
if err.(syscall.Errno) == 183 {
|
|
return false // программа уже запущена
|
|
}
|
|
|
|
return true // успешно создали мьютекс, программа не запущена
|
|
}
|
|
|
|
// ReleaseMutex освобождает мьютекс при завершении программы
|
|
func ReleaseMutex() {
|
|
if mutexHandle != 0 {
|
|
procCloseHandle.Call(uintptr(mutexHandle))
|
|
mutexHandle = 0
|
|
}
|
|
} |