示例#1
0
def get_game_install_dir_path(target_app_id):
    logger.info('Get install dir path')
    # レジストリを見て、Steamのインストール先を探す
    # 32bitを見て、なければ64bitのキーを探しに行く。それでもなければそもそもインストールされていないと判断する
    try:
        steam_install_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
                                           "SOFTWARE\\Valve\\Steam")
    except OSError:
        try:
            steam_install_key = winreg.OpenKey(
                winreg.HKEY_LOCAL_MACHINE,
                "SOFTWARE\\WOW6432Node\\Valve\\Steam")
        except OSError:
            raise Exception(_("ERR_NOT_FIND_STEAM_REGKEY"))

    logger.info('Find steam_install_key in reg')

    try:
        steam_install_path, key_type = winreg.QueryValueEx(
            steam_install_key, "InstallPath")
    except FileNotFoundError:
        raise Exception(_("ERR_NOT_FIND_INSTALLPATH_IN_STEAM_REGKEY"))

    steam_install_key.Close()
    logger.info('steam_install_path=%s, key_type=%s', steam_install_path,
                key_type)

    # 基本問題ないと思うが念の為
    if key_type != winreg.REG_SZ:
        raise Exception("invald value")

    # デフォルトのsteamappsフォルダを探す
    steam_apps_path = __(steam_install_path, "steamapps")
    if os.path.exists(steam_apps_path) is False:
        raise Exception(_("ERR_NOT_EXIST_DEFAULT_STEAMAPPS_DIR"))

    logger.info('steam_apps_path=%s', steam_apps_path)

    # acfがあるフォルダを列挙
    acf_dir_paths = [steam_apps_path]
    acf_dir_paths.extend(get_lib_folders_from_vdf(steam_apps_path))

    logger.info('acf_dir_paths=%s', acf_dir_paths)

    # 各ディレクトリについて処理
    game_install_dir_path = None
    for dir_path in acf_dir_paths:
        game_install_dir_path = get_game_install_dir(dir_path, target_app_id)
        if game_install_dir_path is None:
            continue
        else:
            break

    logger.info('game_install_dir_path=%s', game_install_dir_path)

    if game_install_dir_path is None:
        raise Exception(_("ERR_NOT_FIND_TARGET_GAME_ON_YOUR_PC"))

    return game_install_dir_path
示例#2
0
 def done(self):
     try:
         self.result()
         r['text'] = _('TASK_FINISH')
         time.sleep(1)
     except Exception as exp:
         messagebox.showerror(_('ERROR_BOX_TITLE'),
                              _('ERROR_BOX_MESSAGE') + ":\n" + str(exp))
     finally:
         r['text'] = original_text
示例#3
0
def uninstaller(uninstall_info_list):
    logger.info('uninstall')

    for info in uninstall_info_list:
        final_check_file = info['final_check_file']
        remove_target_paths = info['remove_target_paths']

        logger.info('remove_target_paths=%s', remove_target_paths)

        base_path = '.'

        if 'app_id' in info:
            base_path = get_game_install_dir_path(info['app_id'])
            if os.path.exists(__(base_path, "claes.exe")):
                logger.info('claes uninstall mode')
                sb.call(__(base_path, "claes.exe /uninstall-all"))

        elif 'game_dir_name' in info:
            base_path = __(get_my_documents_folder(), "Paradox Interactive",
                           info['game_dir_name'])
            # Modダウンローダーをuninstallモードで起動
            if os.path.exists(__(base_path, "claes.exe")):
                logger.info('claes uninstall mode')
                sb.call(__(base_path, "claes.exe /uninstall-all"))

        logger.info('base_path=%s', base_path)

        # 最終チェックファイルがあるかを確認する。このファイルがあるかどうかで本当にインストールされているか判断する
        if os.path.exists(__(base_path, final_check_file)) is False:
            raise Exception(_('ERR_NOT_EXIST_FINAL_CHECK_FILE'))

        for path in remove_target_paths:
            remove_util(__(base_path, path))

    logger.info('finish')
示例#4
0
def get_lib_folders_from_vdf(steam_apps_path):
    logger.info('get lib folders from vdf')

    # vdfファイルを探す
    library_folders_vdf_path = __(steam_apps_path, "libraryfolders.vdf")
    if os.path.exists(library_folders_vdf_path) is False:
        raise Exception(_("ERR_NOT_FIND_LIBRARYFOLDERS_VDF"))

    logger.info('library_folders_vdf_path=%s', library_folders_vdf_path)

    # vdfファイルにある"[数字]" "xxxx"をさがす
    install_dir_pattern = re.compile(r'\s*"[0-9a-zA-Z]+"\s+"(.*)')
    logger.info('install_dir_pattern=%s', install_dir_pattern)

    game_libs_paths = []
    with open(library_folders_vdf_path,
              mode='r',
              encoding="utf8",
              errors='ignore') as target_vdf_file:
        logger.info('open %s', library_folders_vdf_path)
        for line in target_vdf_file:
            result = install_dir_pattern.match(line)
            if result is not None:
                game_libs_paths.append(
                    __(
                        result.group(1).strip("\"").replace("\\\\", "\\"),
                        "steamapps"))

    logger.info('game_libs_paths=%s', game_libs_paths)

    return game_libs_paths
示例#5
0
def get_my_documents_folder():
    logger.info('get my documents folder')

    # APIを使って探す
    buf = ctypes.create_unicode_buffer(MAX_PATH + 1)
    if ctypes.windll.shell32.SHGetSpecialFolderPathW(None, buf, 0x1005, False):
        logger.info('search done. buf.value=%s', buf.value)
        return buf.value
    else:
        raise Exception(_("ERR_SHGetSpecialFolderPathW"))
示例#6
0
def get_game_install_dir(dir_path, target_app_id):
    logger.info('get game install dir')

    # インストールディレクトリにあるsteamapps/appmanifest_[APPID].acfを探す
    target_app_acf_path = __(dir_path,
                             "appmanifest_{}.acf".format(target_app_id))

    logger.info('target_app_acf_path=%s', target_app_acf_path)

    # なければ終了
    if os.path.exists(target_app_acf_path) is False:
        return None

    # acfファイルにある"installdir" "xxxx"をさがす
    install_dir_pattern = re.compile(r'\s*"installdir"\s+"(.*)')
    game_install_dir_name = None
    with open(target_app_acf_path, mode='r', encoding="utf8",
              errors='ignore') as target_app_acf_file:
        logger.info('open %s', target_app_acf_path)
        for line in target_app_acf_file:
            result = install_dir_pattern.match(line)
            if result is not None:
                game_install_dir_name = result.group(1).strip("\"")
                break

        logger.info('game_install_dir_name=%s', game_install_dir_name)

        if game_install_dir_name is None:
            raise Exception(_("ERR_INVALID_ACF"))

    # パスを確認
    game_install_dir_path = __(dir_path, "common", game_install_dir_name)

    if os.path.exists(game_install_dir_path) is False:
        raise Exception(_("ERR_NOT_EXIST_GAME_INSTALL_DIR"))

    logger.info('game_install_dir_path=%s', game_install_dir_path)

    return game_install_dir_path
示例#7
0
    def threader(r, func):
        original_text = r['text']
        r['text'] = _('TASK_DO')

        feature = executor.submit(func)

        def done(self):
            try:
                self.result()
                r['text'] = _('TASK_FINISH')
                time.sleep(1)
            except Exception as exp:
                messagebox.showerror(_('ERROR_BOX_TITLE'),
                                     _('ERROR_BOX_MESSAGE') + ":\n" + str(exp))
            finally:
                r['text'] = original_text

        feature.add_done_callback(done)
示例#8
0
def install(install_dir_path, target_zip_url, final_check_file):
    logger.info('install')

    final_check_file_path = __(install_dir_path, final_check_file)
    logger.info('final_check_file_path=%s', final_check_file_path)

    # 最終チェックファイルがあるかを確認する
    if os.path.exists(final_check_file_path) is False:
        raise Exception(_('ERR_NOT_EXIST_FINAL_CHECK_FILE'))

    # 最終チェックファイルがある場所に対してファイルを展開する
    final_check_file_dir = os.path.dirname(final_check_file_path)
    logger.info('final_check_file_dir=%s', final_check_file_dir)

    path, headers = urllib.request.urlretrieve(target_zip_url)

    logger.info('path=%s,headers=%s', path, headers)

    with zipfile.ZipFile(path) as existing_zip:
        existing_zip.extractall(final_check_file_dir)

    logger.info('zip unpacked')
示例#9
0
def about():
    logger.info('open About dialog')
    messagebox.showinfo(_('ABOUT_BOX_TITLE'), _('ABOUT_BOX_MESSAGE'))
示例#10
0
    # ログ設定
    # https://beenje.github.io/blog/posts/logging-to-a-tkinter-scrolledtext-widget/
    log_queue = queue.Queue()
    queue_handler = QueueHandler(log_queue)
    logger.addHandler(queue_handler)
    formatter = logging.Formatter('%(asctime)s: %(message)s')
    queue_handler.setFormatter(formatter)

    logger.info('GUI setup')

    repo_url = "https://raw.githubusercontent.com/matanki-saito/SimpleInstaller/master/"

    executor = concurrent.futures.ThreadPoolExecutor(max_workers=2)

    root = tkinter.Tk()
    root.title(_('TITLE'))

    root.geometry("300x300")

    # ノートブック
    style = ttk.Style()
    style.configure("BW.TLabel", foreground="black", background="white")
    nb = ttk.Notebook(width=300, height=200, style="BW.TLabel")

    # タブの作成
    tab2 = tkinter.Frame(nb, pady=0, relief='flat')
    tab3 = tkinter.Frame(nb, pady=0, relief='flat')
    tab4 = tkinter.Frame(nb, pady=0, relief='flat')

    nb.add(tab2, text=_('TAB_JPMOD'), padding=0)
    nb.add(tab3, text=_('TAB_INFO'), padding=0)