Исправь ошибки чтобы нормально запускалось
import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext
import random
import re
import os
import subprocess
import shutil
import threading
import time
from datetime import datetime
import logging

# Настройка логирования
logging.basicConfig(level=logging.INFO, format='[%(asctime)s] %(levelname)s - %(message)s')


class VMManagerApp:
    """
    Класс для управления GUI и логикой приложения
    """

    def init(self, root):
        self.root = root
        self.root.title("Генератор Серийного Номера и Управление Виртуальной Машиной")
        self.root.geometry("1300x950")
        self.root.resizable(True, True)

        # Переменные
        self.vmrun_path = r"C:\Program Files (x86)\VMware\VMware Workstation\vmrun.exe"
        self.stop_event = threading.Event()
        self.continuous_var = tk.BooleanVar(value=False)

        # Поля ввода
        self.file_entry = tk.Entry(self.root, width=80)
        self.guest_user_entry = tk.Entry(self.root, width=30)
        self.guest_pass_entry = tk.Entry(self.root, width=30, show="")
        self.command_entry = tk.Entry(self.root, width=80)
        self.num_runs_entry = tk.Entry(self.root, width=15)
        self.pause_entry = tk.Entry(self.root, width=15)
        self.upload_host_entry = tk.Entry(self.root, width=80)
        self.guest_upload_entry = tk.Entry(self.root, width=80)
        self.guest_download_entry = tk.Entry(self.root, width=80)
        self.host_download_entry = tk.Entry(self.root, width=80)
        self.host_output_entry = tk.Entry(self.root, width=80)

        # Виджет логов
        self.log_widget = scrolledtext.ScrolledText(self.root, width=160, height=25)
        self.setup_gui()

    def setup_gui(self):
        """
        Настройка графического интерфейса пользователя
        """
        # Установка предопределённых путей
        self.upload_host_entry.insert(0, r"c:\icloudreg\out.txt")
        self.guest_upload_entry.insert(0, "/Users/deno/Desktop/flow.txt")
        self.host_download_entry.insert(0, r"c:\icloudreg\ok.txt")
        self.guest_download_entry.insert(0, "/Users/deno/Desktop/activated vm1.txt")
        self.host_output_entry.insert(0, r"c:\icloudreg\output.txt")

        # Создание виджетов и размещение на сетке
        self.create_label_and_entry("Путь к файлу конфигурации VMX:", self.file_entry, 0, self.browse_file)
        self.create_label_and_entry("Гость Username:", self.guest_user_entry, 1)
        self.guest_user_entry.insert(0, "deno")
        self.create_label_and_entry("Гость Password:", self.guest_pass_entry, 1, column=2)
        self.guest_pass_entry.insert(0, "qwas")
        self.create_label_and_entry("Команда для выполнения:", self.command_entry, 2, button=False)
        self.command_entry.insert(0, "/usr/bin/osascript /Users/Deno/ISMS.applescript")

        self.create_label_and_entry("Количество запусков команды:", self.num_runs_entry, 3)
        self.num_runs_entry.insert(0, "5")
        self.create_label_and_entry("Пауза между итерациями (секунды):", self.pause_entry, 3, column=2)
        self.pause_entry.insert(0, "60")

        self.create_label_and_entry("Файл для загрузки на гостевую систему:", self.upload_host_entry, 4, self.browse_upload_host)
        self.create_label_and_entry("Путь на гостевой системе для загрузки файла:", self.guest_upload_entry, 5, button=False)
        self.create_label_and_entry("Путь к файлу на гостевой системе для выгрузки:", self.guest_download_entry, 6, button=False)
        self.create_label_and_entry("Путь на хостовой системе для сохранения выгруженного файла:", self.host_download_entry, 7, self.browse_download_host)
        self.create_label_and_entry("Путь к выходному файлу на хостовой системе для сохранения извлечённых строк:", self.host_output_entry, 8, self.browse_output_host)

        # Галочка для непрерывной работы
        continuous_checkbox = tk.Checkbutton(self.root, text="Непрерывная работа", variable=self.continuous_var)
        continuous_checkbox.grid(row=9, column=1, padx=5, pady=5, sticky='w')

        # Кнопки запуска и остановки
        tk.Button(self.root, text="Запустить Скрипт", command=self.handle_run_script).grid(row=9, column=2, padx=5, pady=5, sticky='w')
        tk.Button(self.root, text="Стоп", command=self.stop_script, bg="red", fg="white").grid(row=9, column=3, padx=5, pady=5, sticky='w')

        # Логи
        tk.Label(self.root, text="Логи:", font=('Arial', 12, 'bold')).grid(row=10, column=0, padx=5, pady=5, sticky='nw')
        self.log_widget.grid(row=11, column=0, columnspan=6, padx=5, pady=5, sticky='nsew')
        self.create_context_menu(self.log_widget)
        self.log_widget.bind("<Key>", lambda e: "break")

        # Настройка расширения столбцов и строк
        self.root.grid_columnconfigure(1, weight=1)
        self.root.grid_columnconfigure(3, weight=1)
        self.root.grid_columnconfigure(5, weight=1)
        self.root.grid_rowconfigure(11, weight=1)

    def create_label_and_entry(self, label_text, entry_widget, row, browse_command=None, column=0, button=True):
        """
        Вспомогательная функция для создания метки, поля ввода и кнопки обзора
        """
        tk.Label(self.root, text=label_text).grid(row=row, column=column, padx=5, pady=5, sticky='e')
        entry_widget.grid(row=row, column=column + 1, padx=5, pady=5, columnspan=4, sticky='we')
        self.create_context_menu(entry_widget)
        if button and browse_command:
            tk.Button(self.root, text="Обзор", command=browse_command).grid(row=row, column=column + 5, padx=5, pady=5, sticky='w')

    def create_context_menu(self, widget):
        """
        Создание контекстного меню для виджета
        """
        context_menu = tk.Menu(widget, tearoff=0)
        context_menu.add_command(label="Копировать", command=lambda: widget.event_generate('<<Copy>>'))
        context_menu.add_command(label="Вставить", command=lambda: widget.event_generate('<<Paste>>'))
        context_menu.add_command(label="Вырезать", command=lambda: widget.event_generate('<<Cut>>'))
        widget.bind("<Button-3>", lambda event: self.show_context_menu(event, context_menu))

    @staticmethod
    def show_context_menu(event, menu):
        """
        Показать контекстное меню
        """
        try:
            menu.tk_popup(event.x_root, event.y_root)
        finally:
            menu.grab_release()

    def browse_file(self):
        """
        Диалог выбора файла конфигурации VMX
        """
        user_profile = os.environ.get('USERPROFILE', r'C:\Users\Default')
        default_dir = os.path.join(user_profile, 'Documents', 'Virtual Machines')
        file_path = filedialog.askopenfilename(
            title="Выберите конфигурационный файл VMX",
            initialdir=default_dir,
            filetypes=[("VMX файлы", ".vmx"), ("Все файлы", ".")]
        )
        if file_path:
            self.file_entry.delete(0, tk.END)
            self.file_entry.insert(0, file_path)

    def browse_upload_host(self):
        """
        Диалог выбора файла для загрузки на гостевую систему
        """
        file_path = filedialog.askopenfilename(
            title="Выберите текстовый файл для загрузки на гостевую систему",
            filetypes=[("Текстовые файлы", ".txt"), ("Все файлы", ".")]
        )
        if file_path:
            self.upload_host_entry.delete(0, tk.END)
            self.upload_host_entry.insert(0, file_path)

    def browse_download_host(self):
        """
        Диалог выбора файла для сохранения на хостовой системе
        """
        file_path = filedialog.asksaveasfilename(
            title="Выберите место для сохранения файла",
            defaultextension=".txt",
            filetypes=[("Текстовые файлы", ".txt"), ("Все файлы", ".")]
        )
        if file_path:
            self.host_download_entry.delete(0, tk.END)
            self.host_download_entry.insert(0, file_path)

    def browse_output_host(self):
        """
        Диалог выбора выходного файла на хостовой системе
        """
        file_path = filedialog.asksaveasfilename(
            title="Выберите место для сохранения выходного файла",
            defaultextension=".txt",
            filetypes=[("Текстовые файлы", ".txt"), ("Все файлы", ".")]
        )
        if file_path:
            self.host_output_entry.delete(0, tk.END)
            self.host_output_entry.insert(0, file_path)

    def stop_script(self):
        """
        Остановка выполнения скрипта
        """
        self.stop_event.set()
        self.log_message("Запрос на остановку выполнения скрипта.")

    def handle_run_script(self):
        """
        Обработка нажатия кнопки "Запустить Скрипт"
        """
        # Получение значений из полей ввода
        file_path = self.file_entry.get().strip()
        guest_user = self.guest_user_entry.get().strip()
        guest_password = self.guest_pass_entry.get().strip()
        command = self.command_entry.get().strip()
        num_runs_str = self.num_runs_entry.get().strip()
        pause_duration_str = self.pause_entry.get().strip()
        continuous = self.continuous_var.get()
        upload_host_path = self.upload_host_entry.get().strip()
        guest_upload_path = self.guest_upload_entry.get().strip()
        guest_download_path = self.guest_download_entry.get().strip()
        host_download_path = self.host_download_entry.get().strip()
        host_output_path = self.host_output_entry.get().strip()

        # Валидация входных данных
        if not file_path:
            messagebox.showwarning("Внимание", "Пожалуйста, выберите файл конфигурации.")
            return
        if not guest_user or not guest_password:
            messagebox.showwarning("Внимание", "Пожалуйста, введите гостевые учетные данные.")
            return
        if not command:
            messagebox.showwarning("Внимание", "Пожалуйста, введите команду для выполнения.")
            return
        if not num_runs_str.isdigit() or int(num_runs_str) < 1:
            messagebox.showwarning("Внимание", "Пожалуйста, введите корректное количество запусков (целое число больше 0).")
            return
        if not pause_duration_str.isdigit() or int(pause_duration_str) < 0:
            messagebox.showwarning("Внимание", "Пожалуйста, введите корректную паузу в секундах (целое число 0 или больше).")
            return

        num_runs = int(num_runs_str)
        pause_duration = int(pause_duration_str)

        # Сброс события остановки
        self.stop_event.clear()

        # Запуск скрипта в отдельном потоке
        threading.Thread(
            target=self.run_script,
            args=(
                file_path, guest_user, guest_password, command, num_runs, pause_duration, continuous,
                upload_host_path, guest_upload_path, guest_download_path, host_download_path, host_output_path
            ),
            daemon=True
        ).start()

        mode = "Непрерывная работа" if continuous else "Однократное выполнение"
        self.log_message(f"Запуск выполнения скрипта с параметрами:\n"
                         f"- Файл конфигурации: {file_path}\n"
                         f"- Количество запусков команды: {num_runs}\n"
                         f"- Пауза между итерациями: {pause_duration} секунд\n"
                         f"- Режим: {mode}")

    def log_message(self, message):
        """
        Логирование сообщений в виджет логов
        """
        logging.info(message)
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.log_widget.insert(tk.END, f"[{current_time}] {message}\n")
        self.log_widget.see(tk.END)

    def run_script(self, file_path, guest_user, guest_password, command, num_runs, pause_duration, continuous,
                   upload_host_path, guest_upload_path, guest_download_path, host_download_path, host_output_path):
        """
        Основная логика выполнения скрипта
        """
        vmrun_path = self.vmrun_path

        if not os.path.isfile(vmrun_path):
            self.log_message(f"[ERROR] vmrun.exe не найден по пути: {vmrun_path}")
            return

        if not os.path.isfile(file_path):
            self.log_message(f"[ERROR] Файл VMX не найден: {file_path}")
            return

        # Основной цикл выполнения
        while not self.stop_event.is_set():
            # Здесь разместите логику вашего скрипта, которую вы хотите выполнить
            self.log_message("Начало выполнения скрипта...")
            # Для примера будем имитировать некоторую работу
            time.sleep(2)
            self.log_message("Завершение выполнения скрипта.")
            if not continuous:
                break

    def run(self):
        self.root.mainloop()


# Дополнительные функции вне класса
def generate_serial_number():
    """
    Генерация серийного номера для iMacPro1,1
    """
    base = "C02"
    week_code = random.choice(["T", "U", "V", "W", "X", "Y"])
    model_code = "41"
    location_code = random.choice(["KY", "KX", "KW", "KV", "KU", "KT"])
    unique_id = ''.join(random.choices('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', k=4))
    return f"{base}{week_code}{model_code}{location_code}{unique_id}"


def generate_mac_suffix():
    """
    Генерация последних 3 октетов MAC-адреса
    """
    return ':'.join(['{:02X}'.format(random.randint(0, 255)) for _ in range(3)])


def update_config_file(file_path):
    """
    Обновление конфигурационного файла виртуальной машины
    """
    backup_path = file_path + ".bak"
    shutil.copyfile(file_path, backup_path)

    if not os.path.isfile(file_path):
        raise FileNotFoundError(f"Файл не найден: {file_path}")

    with open(file_path, 'r', encoding='windows-1251') as file:
        config_lines = file.readlines()

    new_serial = generate_serial_number()
    new_mac_suffix = generate_mac_suffix()

    new_config = []
    for line in config_lines:
        if line.startswith("serialNumber = "):
            line = f'serialNumber = "{new_serial}"\n'
        elif line.startswith("ethernet0.Address = "):
            current_mac = re.search(r'"([^"])"', line).group(1)
            mac_parts = current_mac.split(':')
            if len(mac_parts) == 6:
                new_mac = ':'.join(mac_parts[:3] + new_mac_suffix.split(':'))
                line = f'ethernet0.Address = "{new_mac}"\n'
        new_config.append(line)

    with open(file_path, 'w', encoding='windows-1251') as file:
        file.writelines(new_config)

    return new_serial, new_mac_suffix


if name == "main":
    root = tk.Tk()
    app = VMManagerApp(root)
    app.run()