Dislocker/dislocker_client.py

586 lines
28 KiB
Python

import os
import json
import tkinter.messagebox
import customtkinter
from winotify import Notification, audio
import keyboard
import subprocess
import requests
import hashlib
import string
import random
import tkinter
import threading
import sys
import uuid
import time
import win32com.client
import pythoncom
from PIL import Image
app_name = "Dislocker"
dislocker_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
os.chdir(dislocker_dir)
sp_startupinfo = subprocess.STARTUPINFO()
sp_startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW
sp_startupinfo.wShowWindow = subprocess.SW_HIDE
resource_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "resource")
config_dir_path = "./config/"
client_config_path = config_dir_path + "client.json"
lang_dir_path = "./lang/"
lang_path = lang_dir_path + "lang_client.json"
if not os.path.isfile(client_config_path):
if not os.path.isdir(config_dir_path):
os.mkdir(config_dir_path)
client_config = {
"initial": True,
"auth_host_url": "http://localhost",
"pc_number": 1,
"master_password_hash": "",
"testing": False,
"eraser": True,
"erase_data": {
"example": {
"process_name": "example.exe",
"dir_path": "example"
}
},
"pc_uuid": "",
"pc_token": "",
"hard_lock": False,
"cover_image": "dislocker",
"language": "ja"
}
elif os.path.isfile(client_config_path):
with open(client_config_path, "r", encoding="utf-8") as r:
client_config = json.load(r)
if os.path.isfile(lang_path):
with open(lang_path, "r", encoding="utf-8") as r:
lang_json = json.load(r)
lang = lang_json[client_config["language"]]
else:
print("言語ファイルが見つかりません。")
lang_not_found = tkinter.messagebox.showerror(title=f"{app_name} | 重大なエラー", message=f"言語ファイルが見つかりません。\n言語ファイルが削除されているか、ファイル名が間違っている可能性があります。\n{app_name} は起動できません。")
def get_input_devices():
str_computer = "."
obj_wmi_service = win32com.client.Dispatch("WbemScripting.SWbemLocator")
obj_swem_services = obj_wmi_service.ConnectServer(str_computer, "root\\cimv2")
col_items = obj_swem_services.ExecQuery("Select * from Win32_PnPEntity where PNPDeviceID like 'HID%'")
input_devices = []
for obj_item in col_items:
input_devices.append({
"device_id": obj_item.DeviceID,
"PNPDeviceID": obj_item.PNPDeviceID,
"Description": obj_item.Description,
"device_name": obj_item.Name,
"Manufacturer": obj_item.Manufacturer,
"Service": obj_item.Service,
"FriendlyName": obj_item.Name, # デバイスとプリンターで表示される名前
"device_instance_path": obj_item.DeviceID # デバイスインスタンスパス
})
return input_devices
def device_register(**kwargs):
onetime = str(kwargs["onetime"])
mode = str(kwargs["mode"])
number = int(kwargs["number"])
device_instance_path = str(kwargs["device_instance_path"])
device_name = str(kwargs["device_name"])
device_register_json = {
"number": number,
"device_instance_path": device_instance_path,
"device_name": device_name,
"mode": mode,
"onetime": onetime
}
register_url = client_config["auth_host_url"] + "/device_register"
responce = requests.post(register_url, json=device_register_json)
if responce.status_code == 200:
print("デバイスの登録に成功しました。")
return {"result": 0, "about": "ok"}
elif responce.status_code == 401:
print("認証に失敗しました。")
return {"result": 1, "about": "auth_failed"}
else:
print("内部エラーによりデバイスの登録に失敗しました。")
return {"result": 1, "about": "error"}
def master_password_gen():
numbers = string.digits # (1)
password = ''.join(random.choice(numbers) for _ in range(10)) # (2)
password_hash = hashlib.sha256(password.encode()).hexdigest()
result = {"password": password, "password_hash": password_hash}
return result
def init(**kwargs):
task_exist = subprocess.run('tasklist /fi "IMAGENAME eq dislocker_client.exe"', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
if 'dislocker_client.exe' in task_exist.stdout:
task_count = task_exist.stdout.count("dislocker_client.exe")
if task_count == 1:
pass
else:
return 1
if client_config["initial"] == True:
pc_uuid = uuid.uuid4()
client_config["pc_uuid"] = str(pc_uuid)
if "pc_number" in kwargs:
client_config["pc_number"] = int(kwargs["pc_number"])
else:
tkinter.messagebox.showerror(title=f"{app_name} | {lang["init"]["msgbox"]["not_found_pc_number"]["title"]}", message=f"{lang["init"]["msgbox"]["not_found_pc_number"]["details"]}")
return 2
if "onetime" in kwargs:
onetime = str(kwargs["onetime"])
else:
tkinter.messagebox.showerror(title=f"{app_name} | {lang["init"]["msgbox"]["not_found_onetime_password"]["title"]}", message=f"{lang["init"]["msgbox"]["not_found_onetime_password"]["details"]}")
return 2
if "host_url" in kwargs:
client_config["auth_host_url"] = str(kwargs["host_url"])
else:
pass
register_url = client_config["auth_host_url"] + "/register"
register_json = {
"pc_number": int(client_config["pc_number"]),
"pc_uuid": str(pc_uuid),
"onetime": onetime
}
responce = requests.post(register_url, json=register_json)
if responce.status_code == 200:
print(f"{lang["init"]["print"]["init_ok"]}")
responce_json = responce.json()
pc_token = str(responce_json["pc_token"])
master_password_hash = str(responce_json["master_password_hash"])
master_password = str(responce_json["master_password"])
client_config["pc_token"] = pc_token
client_config["master_password_hash"] = master_password_hash
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | {lang["init"]["msgbox"]["init_ok"]["title"]}", message=f"{lang["init"]["msgbox"]["init_ok"]["details"]}\n\n{master_password}\n\n")
client_config["initial"] = False
with open(client_config_path, "w", encoding="utf-8") as w:
json.dump(client_config, w, indent=4, ensure_ascii=False)
return 2
elif responce.status_code == 400:
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | {lang["init"]["msgbox"]["exist_pc_number"]["title"]}", message=f"{lang["init"]["msgbox"]["exist_pc_number"]["details"]}")
return 2
elif responce.status_code == 401:
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | {lang["init"]["msgbox"]["wrong_onetime_password"]["title"]}", message=f"{lang["init"]["msgbox"]["wrong_onetime_password"]["details"]}")
return 2
elif responce.status_code == 500:
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | {lang["init"]["msgbox"]["internal_error"]["title"]}", message=f"{lang["init"]["msgbox"]["internal_error"]["details"]}")
return 2
else:
return 0
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
if client_config["testing"] == True:
pass
else:
self.block_taskmgr()
self.block_key()
shutup_window = keyboard.press_and_release('windows + d')
self.attributes('-fullscreen', True)
self.attributes('-topmost', True)
if client_config["hard_lock"] == True:
exit_explorer = subprocess.run('taskkill /f /im explorer.exe', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
if exit_explorer.returncode == 0:
pass
else:
signout_session = subprocess.run('shutdown /l /f /t 3', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
error_msgbox = tkinter.messagebox.showerror(title=f"{app_name} | {lang["App"]["msgbox"]["init_error"]["title"]}", message=f"{lang["App"]["msgbox"]["init_error"]["details"]}")
self.title(f"{app_name} | {lang["App"]["title"]}")
self.iconbitmap(default=resource_path + '\\icon\\dislocker.ico')
self.frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.frame.grid(row=0, column=0, sticky='nsew')
lock = Lock()
def exit(self):
self.unlock_taskmgr()
if client_config["hard_lock"] == True:
self.wake_explorer()
else:
pass
self.toast()
self.destroy()
def block_key(self):
block_keys = ['ctrl', 'alt', 'windows', 'shift', 'delete']
for i in block_keys:
keyboard.block_key(i)
def block_taskmgr(self):
block = subprocess.run('reg add HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System /v DisableTaskMgr /t REG_DWORD /d 1 /f', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
print(block)
def unlock_taskmgr(self):
unlock = subprocess.run('reg delete HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System /v DisableTaskMgr /f', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
print(unlock)
def wake_explorer(self):
wake_explorer = subprocess.Popen('explorer', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
def toast(self):
success = Notification(
app_id=f'{app_name}',
title=f'{lang["App"]["notification"]["success"]["title"]}',
msg=f'{lang["App"]["notification"]["success"]["details"]}',
icon=resource_path + '\\icon\\success.png'
)
success.set_audio(audio.Default, loop=False)
success.show()
def handler_close(self):
pass
class Lock(customtkinter.CTkToplevel):
def __init__(self):
super().__init__()
if client_config["testing"] == True:
self.title(f'{app_name} | {lang["Lock"]["gui"]["pc_number"]} {client_config["pc_number"]} | {lang["Lock"]["gui"]["testing"]}')
else:
self.title(f'{app_name} | {lang["Lock"]["gui"]["pc_number"]} {client_config["pc_number"]} | {lang["Lock"]["gui"]["locked"]}')
self.iconbitmap(default=resource_path + '\\icon\\dislocker.ico')
self.window_width = 760
self.window_height = 320
self.screen_width = self.winfo_screenwidth()
self.screen_height = self.winfo_screenheight()
self.center_x = int(self.screen_width/2 - self.window_width/2)
self.center_y = int(self.screen_height/2 - self.window_height/2)
self.geometry(f"{str(self.window_width)}x{str(self.window_height)}+{str(self.center_x)}+{str(self.center_y)}")
self.resizable(height=False, width=False)
self.attributes('-topmost', True)
self.grab_set()
self.lift()
self.protocol("WM_DELETE_WINDOW", self.handler_close)
self.emoji_font = customtkinter.CTkFont(family="Segoe UI Emoji", size=32)
self.title_font = customtkinter.CTkFont(family="meiryo", size=32, weight="bold")
self.pc_number_font = customtkinter.CTkFont(family="meiryo", size=64, weight="bold")
self.title_small_font = customtkinter.CTkFont(family="meiryo", size=16)
self.general_font = customtkinter.CTkFont(family="meiryo", size=18)
self.general_small_font = customtkinter.CTkFont(family="meiryo", size=12)
self.textbox_font = customtkinter.CTkFont(family="meiryo", size=14)
self.button_font = customtkinter.CTkFont(family="meiryo", size=14)
self.cover_img = customtkinter.CTkImage(light_image=Image.open(f'{resource_path}\\cover\\{client_config["cover_image"]}\\light.png'), dark_image=Image.open(f'{resource_path}\\cover\\{client_config["cover_image"]}\\dark.png'), size=(160, 320))
self.grid_columnconfigure(0, weight=1)
self.grid_columnconfigure(1, weight=6)
self.cover_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.cover_frame.grid(row=0, column=0, padx=0, pady=0, sticky="nsew", rowspan=4)
self.cover_img_label = customtkinter.CTkLabel(self.cover_frame, image=self.cover_img, text="")
self.cover_img_label.grid(row=0, column=0, padx=0, pady=0, sticky="w")
self.msg_title_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.msg_title_frame.grid(row=0, column=1, padx=10, pady=10, sticky="nsew")
self.msg_title_1 = customtkinter.CTkLabel(self.msg_title_frame, text=f'{lang["Lock"]["gui"]["msg_title_1"]}', font=self.title_font, justify="left")
self.msg_title_1.grid(row=0, column=0, padx=10, sticky="we")
self.pc_number_title_1 = customtkinter.CTkLabel(self.msg_title_frame, text=f'{lang["Lock"]["gui"]["pc_number_title_1"]} | {client_config["pc_number"]}', font=self.title_font, justify="right")
self.pc_number_title_1.grid(row=0, column=1, padx=10, sticky="e")
self.msg_title_2 = customtkinter.CTkLabel(self.msg_title_frame, text=f"{lang["Lock"]["gui"]["msg_title_2"]}", font=self.title_small_font, justify="left")
self.msg_title_2.grid(row=1, column=0, padx=10, columnspan=2, sticky="w")
self.msg_subtitle_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.msg_subtitle_frame.grid(row=1, column=1, padx=10, pady=0, sticky="nsew")
self.msg_subtitle_frame.grid_columnconfigure(0, weight=1)
self.msg_subtitle_1 = customtkinter.CTkLabel(self.msg_subtitle_frame, text=f'{lang["Lock"]["gui"]["msg_subtitle_1"]}', font=self.general_font, justify="left")
self.msg_subtitle_1.grid(row=0, column=0, padx=10, sticky="w")
self.msg_subtitle_2 = customtkinter.CTkLabel(self.msg_subtitle_frame, text=f'{lang["Lock"]["gui"]["msg_subtitle_2"]}', font=self.general_small_font, justify="left")
self.msg_subtitle_2.grid(row=1, column=0, padx=10, sticky="w")
self.input_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.input_frame.grid(row=2, column=1, padx=10, pady=0, sticky="nsew")
self.input_frame.columnconfigure(0, weight=1)
self.password_entry = customtkinter.CTkEntry(self.input_frame, placeholder_text=f'{lang["Lock"]["gui"]["password_entry"]}', show='*', font=self.textbox_font)
self.password_entry.grid(row=0, column=0, padx=10, sticky="ew")
self.password_entry.bind("<Return>", self.auth_start_ev)
self.button_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.button_frame.grid(row=3, column=1, padx=10, pady=10, sticky="nsew")
self.button_frame.columnconfigure(0, weight=3)
self.button_frame.columnconfigure(1, weight=1)
self.button_frame.columnconfigure(2, weight=1)
self.signin_button = customtkinter.CTkButton(self.button_frame, text=f'{lang["Lock"]["gui"]["signin_button"]}', command=self.auth_start, font=self.button_font)
self.signin_button.grid(row=0, column=2, padx=10, sticky="e")
self.signout_button = customtkinter.CTkButton(self.button_frame, text=f'{lang["Lock"]["gui"]["signout_button"]}', command=self.signout, font=self.button_font)
self.signout_button.grid(row=0, column=1, padx=10, sticky="e")
self.help_button = customtkinter.CTkButton(self.button_frame, text=f'{lang["Lock"]["gui"]["help_button"]}', command=self.help_dummy, font=self.button_font)
self.help_button.grid(row=0, column=0, padx=10, sticky="w")
self.keyboard_listener_thread = threading.Thread(target=self.keyboard_listener)
self.keyboard_listener_thread.daemon = True
self.keyboard_listener_thread.start()
def help_wakeup(self):
help = Help()
def keyboard_listener(self):
keyboard.add_hotkey('ctrl+shift+q', self.exit)
def hash_genarate(self, source):
hashed = hashlib.sha256(source.encode())
return hashed.hexdigest()
def auth_start(self):
auth_thread = threading.Thread(target=self.auth)
auth_thread.daemon = True
auth_thread.start()
def auth_start_ev(self, event):
auth_thread = threading.Thread(target=self.auth)
auth_thread.daemon = True
auth_thread.start()
def button_disable(self):
self.help_button.configure(state="disabled", fg_color="gray")
self.signin_button.configure(state="disabled", fg_color="gray")
self.signout_button.configure(state="disabled", fg_color="gray")
def button_enable(self):
self.help_button.configure(state="normal", fg_color="#3c8dd0")
self.signin_button.configure(state="normal", fg_color="#3c8dd0")
self.signout_button.configure(state="normal", fg_color="#3c8dd0")
def get_input_devices(self):
try:
pythoncom.CoInitialize()
str_computer = "."
obj_wmi_service = win32com.client.Dispatch("WbemScripting.SWbemLocator")
obj_swem_services = obj_wmi_service.ConnectServer(str_computer, "root\\cimv2")
col_items = obj_swem_services.ExecQuery("Select * from Win32_PnPEntity where PNPDeviceID like 'HID%'")
input_devices = []
for obj_item in col_items:
input_devices.append({
"device_id": obj_item.DeviceID,
"PNPDeviceID": obj_item.PNPDeviceID,
"Description": obj_item.Description,
"device_name": obj_item.Name,
"Manufacturer": obj_item.Manufacturer,
"Service": obj_item.Service,
"FriendlyName": obj_item.Name, # デバイスとプリンターで表示される名前
"device_instance_path": obj_item.DeviceID # デバイスインスタンスパス
})
pythoncom.CoUninitialize()
return input_devices
except pythoncom.com_error as e:
print("Error:", e)
return []
def auth(self):
self.button_disable()
password = str(self.password_entry.get())
#devices = self.get_input_devices()
devices = []
if len(password) == 10:
print(f'{lang["Lock"]["auth"]["print"]["try_master_password"]}')
master_password_hash = self.hash_genarate(str(self.password_entry.get()))
if client_config["master_password_hash"] == master_password_hash:
print(f'{lang["Lock"]["auth"]["print"]["success_master_password"]}')
self.exit()
else:
print(f'{lang["Lock"]["auth"]["print"]["error_master_password"]}')
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | {lang["Lock"]["auth"]["msgbox"]["wrong_password"]["title"]}", message=f"{lang["Lock"]["auth"]["msgbox"]["wrong_password"]["details"]}")
self.msg_subtitle_1.configure(text=f'{lang["Lock"]["auth"]["configure"]["wrong_password"]}')
self.button_enable()
self.deiconify()
print(f'{lang["Lock"]["auth"]["print"]["access_auth_server"]}')
auth_url = client_config["auth_host_url"] + "/verify"
auth_json = {
"pc_number": int(client_config["pc_number"]),
"pc_uuid": str(client_config["pc_uuid"]),
"pc_token": str(client_config["pc_token"]),
"devices": devices,
"password": self.hash_genarate(str(self.password_entry.get()))
}
try:
responce = requests.post(auth_url, json=auth_json)
if responce.status_code == 200:
print(f'{lang["Lock"]["auth"]["print"]["success_auth_server"]}')
self.exit()
elif responce.status_code == 401:
print(f'{lang["Lock"]["auth"]["print"]["error_wrong_password"]}')
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | {lang["Lock"]["auth"]["msgbox"]["wrong_password"]["title"]}", message=f"{lang["Lock"]["auth"]["msgbox"]["wrong_password"]["details"]}")
self.msg_subtitle_1.configure(text=f'{lang["Lock"]["auth"]["configure"]["wrong_password"]}')
self.button_enable()
self.deiconify()
elif responce.status_code == 500:
print(f'{lang["Lock"]["auth"]["print"]["error_internal_server"]}')
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | {lang["Lock"]["auth"]["msgbox"]["internal_error"]["title"]}", message=f"{lang["Lock"]["auth"]["msgbox"]["internal_error"]["details"]}")
self.msg_subtitle_1.configure(text=f'{lang["Lock"]["auth"]["configure"]["internal_error"]}')
self.button_enable()
self.deiconify()
except:
print(f'{lang["Lock"]["auth"]["print"]["cant_access_auth_server"]}')
master_password_hash = self.hash_genarate(str(self.password_entry.get()))
if client_config["master_password_hash"] == master_password_hash:
print(f'{lang["Lock"]["auth"]["print"]["success_master_password"]}')
self.exit()
else:
print(f'{lang["Lock"]["auth"]["print"]["error_master_password"]}')
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | {lang["Lock"]["auth"]["msgbox"]["cant_access_auth_server"]["title"]}", message=f"{lang["Lock"]["auth"]["msgbox"]["cant_access_auth_server"]["details"]}")
self.msg_subtitle_1.configure(text=f'{lang["Lock"]["auth"]["configure"]["cant_access_auth_server"]}')
self.button_enable()
self.deiconify()
def signout(self):
app.unlock_taskmgr()
self.destroy()
signout_command = subprocess.run('shutdown /l /f', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
print(signout_command)
def handler_close(self):
pass
def help_dummy(self):
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | {lang["Lock"]["auth"]["msgbox"]["help"]["title"]}", message=f"{lang["Lock"]["auth"]["msgbox"]["help"]["details"]}")
self.deiconify()
def wakeup_shutdown_background(self):
wakeup = subprocess.Popen(f'{dislocker_dir}\\dislocker_client_shutdown.exe', startupinfo=sp_startupinfo)
def exit(self):
try:
self.wakeup_shutdown_background()
except:
pass
self.destroy()
app.exit()
class Help(customtkinter.CTkToplevel):
def __init__(self):
super().__init__()
if client_config["testing"] == True:
self.title(f'{app_name} | ヘルプ | テストモード')
else:
self.title(f'{app_name} | ヘルプ')
self.iconbitmap(default=resource_path + '\\icon\\dislocker.ico')
self.geometry("600x400")
self.resizable(height=False, width=False)
self.attributes('-topmost', True)
self.grab_set()
self.lift()
self.protocol("WM_DELETE_WINDOW", self.handler_close)
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 未実装", message=f"ヘルプページは製作途中です。\nDiscordサーバーの指示に従って、認証を進めてください。")
self.destroy()
def handler_close(self):
self.destroy()
if __name__ == '__main__':
args = sys.argv
if len(args) >= 2:
if args[1] == "setup":
if len(args) == 4:
init_result = init(pc_number=args[2], onetime=args[3])
elif len(args) == 5:
init_result = init(pc_number=args[2], onetime=args[3], host_url=args[4])
else:
print("引数エラー。")
error_msgbox = tkinter.messagebox.showerror(title=f"{app_name} | 引数エラー", message=f"引数が多すぎるか、少なすぎます。\n引数がPC番号、ワンタイムパスワード、ホストURLの順で正しく指定されているか確認してください。")
if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"すでに {app_name} は実行されています。\n正常に起動しない場合は、既に起動しているプロセスを終了してから、もう一度起動してみてください。")
elif init_result == 2:
pass
else:
pass
elif args[1] == "deviceregister":
init_result = init()
if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"すでに {app_name} は実行されています。\n正常に起動しない場合は、既に起動しているプロセスを終了してから、もう一度起動してみてください。")
elif init_result == 2:
pass
else:
mode = input('登録するデバイスはキーボードとマウスのどちらですか?(keyboard/mouse): ')
input_devices = get_input_devices()
i = 0
for device in input_devices:
print(f"{str(i + 1)} 番目 | デバイス名: {device['device_name']} \n製造元: {device['Manufacturer']} \nデバイスインスタンスパス: {device['device_instance_path']}")
print("-" * 20)
i += 1
device_num = input('どのデバイスを登録しますか?番号で指定してください: ')
device_register_num = input('そのデバイスは何番目のデバイスとして登録しますか?番号で指定してください: ')
onetime = input('ワンタイムパスワードを入力してください: ')
device_register_result = device_register(onetime=onetime, mode=mode, number=int(device_register_num), device_instance_path=input_devices[int(device_num) - 1]["device_instance_path"], device_name=input_devices[int(device_num) - 1]["device_name"])
if device_register_result["result"] == 0:
print("登録されました。")
elif device_register_result["result"] == 1:
if device_register_result["about"] == "auth_failed":
print("認証に失敗しました。")
else:
print("エラーが発生しました。")
elif args[1] == "guitest":
init_result = init()
client_config["testing"] = True
app = App()
app.mainloop()
else:
print("引数エラー。")
else:
init_result = init()
if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"すでに {app_name} は実行されています。\n正常に起動しない場合は、既に起動しているプロセスを終了してから、もう一度起動してみてください。")
elif init_result == 2:
pass
else:
app = App()
app.protocol("WM_DELETE_WINDOW", app.handler_close)
app.mainloop()