feat: add source code — app.py, run.py, build scripts, NSIS, requirements

This commit is contained in:
MR CYBER
2026-07-12 18:44:34 -07:00
parent 3db1201879
commit 8fc01894ac
15 changed files with 12484 additions and 0 deletions
+241
View File
@@ -0,0 +1,241 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Package IgnorableNamespaces="desktop8 build" xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4" xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5" xmlns:uap7="http://schemas.microsoft.com/appx/manifest/uap/windows10/7" xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10" xmlns:desktop2="http://schemas.microsoft.com/appx/manifest/desktop/windows10/2" xmlns:desktop6="http://schemas.microsoft.com/appx/manifest/desktop/windows10/6" xmlns:desktop8="http://schemas.microsoft.com/appx/manifest/desktop/windows10/8" xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10" xmlns:com2="http://schemas.microsoft.com/appx/manifest/com/windows10/2" xmlns:com3="http://schemas.microsoft.com/appx/manifest/com/windows10/3" xmlns:build="http://schemas.microsoft.com/developer/appx/2015/build" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest">
<Identity Name="MicrosoftCorporationII.WindowsSubsystemForAndroid" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Version="2407.40000.4.0" ProcessorArchitecture="x64" />
<Properties>
<DisplayName>ms-resource:WsaPackageDisplayName</DisplayName>
<PublisherDisplayName>Microsoft Corp.</PublisherDisplayName>
<Logo>Images\StoreLogo.png</Logo>
<desktop6:FileSystemWriteVirtualization>disabled</desktop6:FileSystemWriteVirtualization>
<desktop6:RegistryWriteVirtualization>disabled</desktop6:RegistryWriteVirtualization>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.22000.120" MaxVersionTested="10.0.22000.120" />
<PackageDependency Name="Microsoft.UI.Xaml.2.8" MinVersion="8.2208.12001.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.VCLibs.140.00.UWPDesktop" MinVersion="14.0.33728.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
<PackageDependency Name="Microsoft.VCLibs.140.00" MinVersion="14.0.33519.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
</Dependencies>
<Resources>
<Resource Language="EN-US" />
<Resource Language="EN-GB" />
<Resource uap:Scale="200" />
<Resource Language="af-za" />
<Resource Language="ar-sa" />
<Resource Language="az-latn-az" />
<Resource Language="bg-bg" />
<Resource Language="bs-latn-ba" />
<Resource Language="ca-es" />
<Resource Language="cs-cz" />
<Resource Language="cy-gb" />
<Resource Language="da-dk" />
<Resource Language="de-de" />
<Resource Language="el-gr" />
<Resource Language="es-es" />
<Resource Language="es-mx" />
<Resource Language="et-ee" />
<Resource Language="eu-es" />
<Resource Language="fa-ir" />
<Resource Language="fi-fi" />
<Resource Language="fr-ca" />
<Resource Language="fr-fr" />
<Resource Language="gl-es" />
<Resource Language="he-il" />
<Resource Language="hi-in" />
<Resource Language="hr-hr" />
<Resource Language="hu-hu" />
<Resource Language="id-id" />
<Resource Language="is-is" />
<Resource Language="it-it" />
<Resource Language="ja-jp" />
<Resource Language="ka-ge" />
<Resource Language="kk-kz" />
<Resource Language="ko-kr" />
<Resource Language="lt-lt" />
<Resource Language="lv-lv" />
<Resource Language="ms-my" />
<Resource Language="nb-no" />
<Resource Language="nl-nl" />
<Resource Language="nn-no" />
<Resource Language="pl-pl" />
<Resource Language="pt-br" />
<Resource Language="pt-pt" />
<Resource Language="qps-ploc" />
<Resource Language="qps-ploca" />
<Resource Language="qps-plocm" />
<Resource Language="ro-ro" />
<Resource Language="ru-ru" />
<Resource Language="sk-sk" />
<Resource Language="sl-si" />
<Resource Language="sq-al" />
<Resource Language="sr-cyrl-rs" />
<Resource Language="sr-latn-rs" />
<Resource Language="sv-se" />
<Resource Language="th-th" />
<Resource Language="tr-tr" />
<Resource Language="uk-ua" />
<Resource Language="vi-vn" />
<Resource Language="zh-cn" />
<Resource Language="zh-tw" />
<Resource uap:Scale="100" />
<Resource uap:Scale="125" />
<Resource uap:Scale="150" />
<Resource uap:Scale="400" />
</Resources>
<Applications>
<Application Id="App" Executable="WsaClient\WsaClient.exe" EntryPoint="Windows.FullTrustApplication">
<uap:VisualElements DisplayName="ms-resource:WsaDisplayName" Description="ms-resource:WsaDescription" BackgroundColor="transparent" Square150x150Logo="Images\MedTile.png" Square44x44Logo="Images\AppList.png" AppListEntry="none">
<uap:DefaultTile Wide310x150Logo="Images\WideTile.png" Square71x71Logo="Images\SmallTile.png" Square310x310Logo="Images\LargeTile.png" />
<uap:SplashScreen Image="Images\SplashScreen.png" />
</uap:VisualElements>
<Extensions>
<desktop:Extension Category="windows.toastNotificationActivation">
<desktop:ToastNotificationActivation ToastActivatorCLSID="18AF5090-C390-45D6-9FF1-CA3E608503B0" />
</desktop:Extension>
<uap:Extension Category="windows.protocol">
<uap3:Protocol Name="wsa" Parameters="/launch %1" />
</uap:Extension>
<uap:Extension Category="windows.protocol">
<uap3:Protocol Name="wsa-client" Parameters="/deeplink %1" />
</uap:Extension>
<uap5:Extension Category="windows.startupTask" uap10:Parameters="/restart 0">
<uap5:StartupTask TaskId="ContinuousVirtualMachine" Enabled="false" />
</uap5:Extension>
<uap5:Extension Category="windows.startupTask" uap10:Parameters="/partiallyrunning">
<uap5:StartupTask TaskId="PartiallyRunningVirtualMachine" Enabled="false" />
</uap5:Extension>
<uap3:Extension Category="windows.appExecutionAlias">
<uap3:AppExecutionAlias>
<desktop:ExecutionAlias Alias="WsaClient.exe" />
</uap3:AppExecutionAlias>
</uap3:Extension>
<desktop6:Extension Category="windows.service" Executable="WsaService\WsaService.exe" EntryPoint="WsaService.Service">
<desktop6:Service Name="WsaService" StartupType="manual" StartAccount="localSystem" />
</desktop6:Extension>
<com2:Extension Category="windows.comServer">
<com2:ComServer>
<com:ExeServer Executable="WsaClient\WsaClient.exe" LaunchAndActivationPermission="O:SYG:SYD:(A;;11;;;IU)(A;;11;;;S-1-15-2-4120862662-1149765626-4064695116-299589112-4208539117-2961988684-1460418210)S:(ML;;NX;;;ME)">
<com:Class Id="A6727475-2A07-4ACC-9FA6-58347FDF7A37" DisplayName="CLSID_VirtioGpuDevice" />
</com:ExeServer>
<com3:ServiceServer ServiceName="WsaService" LaunchAndActivationPermission="O:SYG:SYD:(A;;11;;;IU)">
<com3:Class Id="D738F5F3-7527-4DD6-BA47-D75688104C46" DisplayName="CLSID_WsaServer" />
</com3:ServiceServer>
<com:ExeServer Executable="WsaClient\WsaClient.exe">
<com:Class Id="18AF5090-C390-45D6-9FF1-CA3E608503B0" DisplayName="CLSID_WsaToastActivator" />
<com:Class Id="df32c7a1-a920-458d-a5c5-0e627f222be9" DisplayName="CLSID_WsaWnsRefreshHandler" />
<com:Class Id="5c3e8567-7095-47c0-98e5-1d196ffcc857" DisplayName="CLSID_WsaWnsPushHandler" />
<com:Class Id="BAF81707-7A8C-4A96-8B01-A9F16E444905" DisplayName="CLSID_WsaSession" />
</com:ExeServer>
<com:SurrogateServer DisplayName="WslDeviceHost_Virtio" AppId="58AC9971-23C7-45EA-933F-7B155AA16FC2">
<com:Class Id="5A167A26-2D39-4456-B802-61F1ABE83D84" Path="wsldevicehost.dll" ThreadingModel="Both" />
<com:Class Id="5a918e2f-d58a-48d9-be09-36ea1615a7f2" Path="wsldevicehost.dll" ThreadingModel="Both" />
<com:Class Id="16479D2E-F0C3-4DBA-BF7A-04FFF0892B07" Path="wsldevicehost.dll" ThreadingModel="Both" />
</com:SurrogateServer>
<com:ExeServer Executable="WsaClient\WsaClient.exe" LaunchAndActivationPermission="O:SYG:SYD:(A;;11;;;IU)(A;;11;;;S-1-15-2-4120862662-1149765626-4064695116-299589112-4208539117-2961988684-1460418210)S:(ML;;NX;;;ME)">
<com:Class Id="286DD941-F692-41ED-A20D-8E8AA9181B10" DisplayName="CLSID_WsaClient" />
</com:ExeServer>
<com:ExeServer Executable="WsaClient\WsaClient.exe" LaunchAndActivationPermission="O:SYG:SYD:(A;;9;;;IU)(A;;9;;;S-1-15-2-4120862662-1149765626-4064695116-299589112-4208539117-2961988684-1460418210)S:(ML;;NX;;;ME)">
<com:Class Id="E04AE257-E3B5-4A50-830F-7CFB124A8661" DisplayName="CLSID_WsaClientBindOnly" />
<com:Class Id="A09CE5A1-6194-4387-A6F1-FA4FD1C93AF0" DisplayName="CLSID_WsaTestHooks" />
</com:ExeServer>
<com:ExeServer Executable="WsaSettingsBroker\WsaSettingsBroker.exe" LaunchAndActivationPermission="O:SYG:SYD:(A;;11;;;IU)(A;;11;;;S-1-15-2-4120862662-1149765626-4064695116-299589112-4208539117-2961988684-1460418210)S:(ML;;NX;;;ME)">
<com:Class Id="92E5D48B-DD18-4339-884F-D6087F81E797" DisplayName="CLSID_WsaSettingsBroker" />
</com:ExeServer>
</com2:ComServer>
</com2:Extension>
<com2:Extension Category="windows.comInterface">
<com2:ComInterface>
<com:Interface Id="02754A08-9A4F-48DA-8209-51238D00278A" ProxyStubClsid="76913B52-F9EB-4FAE-8DE7-24C20BDCF37B" />
<com:Interface Id="04A4E322-4148-44AF-9053-A7BEDD09178C" ProxyStubClsid="76913B52-F9EB-4FAE-8DE7-24C20BDCF37B" />
<com:Interface Id="6A0E8133-9C70-4193-821F-A6FF231D5665" ProxyStubClsid="76913B52-F9EB-4FAE-8DE7-24C20BDCF37B" />
<com:Interface Id="3C80B0C2-966E-4AC8-BA88-793970E0650B" ProxyStubClsid="76913B52-F9EB-4FAE-8DE7-24C20BDCF37B" />
<com:Interface Id="E080792C-6458-49A4-AA35-D77EE2C6B1C9" ProxyStubClsid="76913B52-F9EB-4FAE-8DE7-24C20BDCF37B" />
<com:Interface Id="D5873B8F-2048-4877-83A2-473DBA08ABD2" ProxyStubClsid="76913B52-F9EB-4FAE-8DE7-24C20BDCF37B" />
<com:Interface Id="A2FD4EB6-587F-4646-A548-E245BDDF6FEB" ProxyStubClsid="76913B52-F9EB-4FAE-8DE7-24C20BDCF37B" />
<com:ProxyStub Id="76913B52-F9EB-4FAE-8DE7-24C20BDCF37B" Path="WsaProxy\WsaProxy.dll" />
</com2:ComInterface>
</com2:Extension>
<uap3:Extension Category="windows.appUriHandler" uap10:Parameters="/appuri %1">
<uap3:AppUriHandler uap7:Name="WsaAppUriHandler">
<uap3:Host Name="WindowsSubsystemForAndroid.microsoft.com" />
</uap3:AppUriHandler>
</uap3:Extension>
</Extensions>
</Application>
<Application Id="SettingsApp" Executable="WsaSettings.exe" EntryPoint="WsaSettings.App">
<uap:VisualElements DisplayName="ms-resource:WsaSettingsDisplayName" Description="ms-resource:WsaSettingsDescription" Square150x150Logo="Images\MedTile.png" Square44x44Logo="Images\AppList.png" BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Images\WideTile.png" Square71x71Logo="Images\SmallTile.png" Square310x310Logo="Images\LargeTile.png" />
<uap:SplashScreen Image="Images\SplashScreen.png" />
</uap:VisualElements>
<Extensions>
<uap:Extension Category="windows.protocol">
<uap3:Protocol Name="wsa-settings" />
</uap:Extension>
</Extensions>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
<Capability Name="internetClientServer" />
<Capability Name="privateNetworkClientServer" />
<rescap:Capability Name="runFullTrust" />
<rescap:Capability Name="unvirtualizedResources" />
<rescap:Capability Name="packagedServices" />
<rescap:Capability Name="localSystemServices" />
<rescap:Capability Name="packageManagement" />
<rescap:Capability Name="packageQuery" />
<rescap:Capability Name="customInstallActions" />
<uap4:CustomCapability Name="Microsoft.classicAppInstaller_8wekyb3d8bbwe" />
<uap4:CustomCapability Name="Microsoft.delegatedWebFeatures_8wekyb3d8bbwe" />
<DeviceCapability Name="webcam" />
<DeviceCapability Name="microphone" />
<DeviceCapability Name="location" />
</Capabilities>
<Extensions>
<desktop6:Extension Category="windows.customInstall">
<desktop6:CustomInstall Folder="CustomInstall" desktop8:RunAsUser="true">
<desktop6:RepairActions>
<desktop6:RepairAction File="WSARepair.exe" Name="Repair" Arguments="repair" />
</desktop6:RepairActions>
<desktop6:UninstallActions>
<desktop6:UninstallAction File="WSARepair.exe" Name="Uninstall" Arguments="uninstall" />
</desktop6:UninstallActions>
</desktop6:CustomInstall>
</desktop6:Extension>
<Extension Category="windows.activatableClass.proxyStub">
<ProxyStub ClassId="76913B52-F9EB-4FAE-8DE7-24C20BDCF37B">
<Path>WsaProxy\WsaProxy.dll</Path>
<Interface Name="IWsaClient" InterfaceId="BC35C837-7915-45DE-AC1B-7A743AAD7188" />
</ProxyStub>
</Extension>
<desktop2:Extension Category="windows.firewallRules">
<desktop2:FirewallRules Executable="WsaClient\WsaClient.exe">
<desktop2:Rule Direction="in" IPProtocol="TCP" LocalPortMin="58526" LocalPortMax="58526" Profile="private" />
</desktop2:FirewallRules>
</desktop2:Extension>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>Microsoft.Web.WebView2.Core.dll</Path>
<ActivatableClass ActivatableClassId="Microsoft.Web.WebView2.Core.CoreWebView2Controller" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Web.WebView2.Core.CoreWebView2ControllerWindowReference" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Web.WebView2.Core.CoreWebView2EnvironmentOptions" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Web.WebView2.Core.CoreWebView2CompositionController" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Web.WebView2.Core.CoreWebView2Environment" ThreadingModel="both" />
</InProcessServer>
</Extension>
</Extensions>
<build:Metadata>
<build:Item Name="cl.exe" Version="19.42.34433.0" />
<build:Item Name="CodeSharingProject" Value="248F659F-DAC5-46E8-AC09-60EC9FC95053" />
<build:Item Name="VisualStudio" Version="17.0" />
<build:Item Name="OperatingSystem" Version="10.0.20348.1 (WinBuild.160101.0800)" />
<build:Item Name="Microsoft.Build.AppxPackage.dll" Version="17.12.40391.52126" />
<build:Item Name="ProjectGUID" Value="a2be7e6a-792a-4530-8614-bc091a63d7bb" />
<build:Item Name="OptimizingToolset" Value="None" />
<build:Item Name="TargetRuntime" Value="Native" />
<build:Item Name="Microsoft.Windows.UI.Xaml.Build.Tasks.dll" Version="0.0.0.0" />
<build:Item Name="WindowsDesktop" Version="10.0.22000.0" />
<build:Item Name="MakePri.exe" Version="10.0.22000.832 (WinBuild.160101.0800)" />
<build:Item Name="Microsoft.Build.DesktopBridge.Tasks.dll" Version="17.12.40308.65294" />
<build:Item Name="TargetFrameworkMoniker" Value=".NETFramework,Version=v4.5.1" />
</build:Metadata>
<mp:PhoneIdentity PhoneProductId="dd5d7f57-f9ab-4533-8aa3-8b7325addf8a" PhonePublisherId="d949d1ab-24a8-4463-9586-acee62f6de38" />
</Package>
+33
View File
@@ -0,0 +1,33 @@
:: This file is part of MagiskOnWSALocal.
::
:: MagiskOnWSALocal is free software: you can redistribute it and/or modify
:: it under the terms of the GNU Affero General Public License as
:: published by the Free Software Foundation, either version 3 of the
:: License, or (at your option) any later version.
::
:: MagiskOnWSALocal is distributed in the hope that it will be useful,
:: but WITHOUT ANY WARRANTY; without even the implied warranty of
:: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
:: GNU Affero General Public License for more details.
::
:: You should have received a copy of the GNU Affero General Public License
:: along with MagiskOnWSALocal. If not, see <https://www.gnu.org/licenses/>.
::
:: Copyright (C) 2023 LSPosed Contributors
::
@echo off
%~d0
cd "%~dp0"
if not exist Install.ps1 (
echo "Install.ps1" is not found.
echo Press any key to exit
pause>nul
exit 1
) else (
powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File ".\Install.ps1"
exit
)
Binary file not shown.
+101
View File
@@ -0,0 +1,101 @@
# -*- mode: python ; coding: utf-8 -*-
# WSA_Installer_Download_onedir.spec
# --onedir mode
from PyInstaller.utils.hooks import collect_submodules
import os
# SPECPATH in PyInstaller 6.x is already the directory containing the .spec file
# (from os.path.split in build_main.py:1140), so use it directly.
_project_root = os.path.abspath(SPECPATH)
_venv_site = os.path.join(_project_root, 'venv', 'Lib', 'site-packages')
# Resolve base Python DLLs from venv's pyvenv.cfg (portable, no hardcoded user path)
_dlls_dir = os.path.join(_project_root, 'venv', 'DLLs')
if not os.path.isdir(_dlls_dir):
_pyvenv_cfg = os.path.join(_project_root, 'venv', 'pyvenv.cfg')
if os.path.isfile(_pyvenv_cfg):
with open(_pyvenv_cfg) as _f:
for _line in _f:
if _line.strip().startswith('home = '):
_dlls_dir = os.path.join(_line.split('=', 1)[1].strip(), 'DLLs')
break
a = Analysis(
['run.py'],
pathex=[_venv_site],
binaries=[
('widget_ui.pyd', '.'),
('playstore_patcher_mem.pyd', '.'),
('*.pyd', '.'),
(os.path.join(_dlls_dir, 'sqlite3.dll'), '.'),
(os.path.join(_dlls_dir, '_sqlite3.pyd'), '.'),
],
datas=[('assets', 'assets')],
hiddenimports=[
'requests',
'flet',
'pyautogui',
'pyperclip',
'pywinauto',
'PyQt6',
]
+ collect_submodules('requests')
+ collect_submodules('flet')
+ collect_submodules('pyautogui')
+ collect_submodules('pywinauto')
+ collect_submodules('PyQt6')
+ [
'six',
'flet_desktop', 'flet.utils',
'email', 'email.message', 'email.mime',
'http.client', 'widget_ui',
'sqlite3', '_sqlite3',
],
hookspath=['hooks'],
hooksconfig={},
runtime_hooks=[],
excludes=[
'tkinter', 'unittest',
'PySide6', 'rich', 'pygments', 'markdown_it',
'yaml', 'cryptography', 'cffi', 'pycparser',
'dateutil', 'arrow', 'tzdata', 'zstandard',
'pyarmor', 'nuitka', 'PyInstaller',
'altgraph', 'pefile', 'pywin32_ctypes', 'Cython', 'maturin',
'chardet', 'click', 'colorama', 'jinja2', 'markupsafe',
'slugify', 'cookiecutter', 'qrcode', 'watchdog',
'setuptools', 'pip', 'flet_cli',
],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='WSA Installer',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
uac_admin=True,
icon='assets\\icon.ico',
)
coll = COLLECT(
exe,
a.binaries,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='WSA Installer',
)
+309
View File
@@ -0,0 +1,309 @@
; ============================================================
; WSA_Installer_Setup.nsi — NSIS Installer Script
; Modified for MR CYBER with Social Buttons & Branding
; ============================================================
!include "MUI2.nsh"
!include "LogicLib.nsh"
!include "WinVer.nsh"
!include "nsDialogs.nsh"
!include "FileFunc.nsh"
!include "StrFunc.nsh"
${StrLoc}
; ── App Info ─────────────────────────────────────────────────
!define APP_NAME "WSA Installer"
!ifndef APP_VERSION
!define APP_VERSION "1.0"
!endif
!define APP_PUBLISHER "MR CYBER"
!define APP_EXE "WSA Installer.exe"
!define APP_ICON "assets\icon.ico"
!define SOURCE_DIR "dist\WSA Installer"
!define INSTALL_DIR "$PROGRAMFILES64\WSA Installer"
!define UNINSTALL_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\WSAInstaller"
!define MUTEX_NAME "WSAInstallerSetupMutex"
; ── Social Links ─────────────────────────────────────────────
!define YT_URL "https://www.youtube.com/@AT_Tech_Zone"
!define COFFEE_URL "https://buymeacoffee.com/mrcyberdev"
; ── Output ───────────────────────────────────────────────────
Name "${APP_NAME}"
OutFile "dist\WSA_Installer_Setup.exe"
InstallDir "${INSTALL_DIR}"
InstallDirRegKey HKLM "${UNINSTALL_KEY}" "InstallLocation"
BrandingText "WSA Installer | Developed by AT Tech Zone & MR CYBER"
RequestExecutionLevel admin ; Must run as admin
SetCompressor /SOLID lzma ; Best compression
SilentInstall normal ; Enable /S silent mode for auto-update
; ── MUI Settings ─────────────────────────────────────────────
!define MUI_ICON "${APP_ICON}"
!define MUI_UNICON "${APP_ICON}"
!define MUI_WELCOMEPAGE_TITLE "Welcome to ${APP_NAME} Setup"
!define MUI_WELCOMEPAGE_TEXT "This professional installer will set up Windows Subsystem for Android (WSA) with Google Play Store support on your Windows 11 PC.$\n$\nFeatures:$\n - One-click installation of WSA$\n - Full Google Play Store integration$\n - Optimized for performance and stability$\n - Developed by AT Tech Zone & MR CYBER$\n$\nClick Next to start the installation process."
; --- Branding Images ---
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "assets\header.bmp"
!define MUI_WELCOMEFINISHPAGE_BITMAP "assets\sidebar.bmp"
!define MUI_UNWELCOMEFINISHPAGE_BITMAP "assets\sidebar.bmp"
; --- Light Mode (Default) ---
; White background and standard text colors
!define MUI_BGCOLOR "FFFFFF"
!define MUI_TEXTCOLOR "000000"
!define MUI_FINISHPAGE_RUN "$INSTDIR\${APP_EXE}"
!define MUI_FINISHPAGE_RUN_TEXT "Launch ${APP_NAME} now"
!define MUI_ABORTWARNING
; ── MUI Pages ────────────────────────────────────────────────
!insertmacro MUI_PAGE_WELCOME
; Maintenance / Repair Gate (Page 2)
Page custom MaintenancePage
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
; Custom Socials Page (Page 3) - Moved to after installation
Page custom SocialsPage
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English"
; ── Version Info ─────────────────────────────────────────────
VIProductVersion "${APP_VERSION}.0.0"
VIAddVersionKey "ProductName" "${APP_NAME}"
VIAddVersionKey "ProductVersion" "${APP_VERSION}"
VIAddVersionKey "CompanyName" "AT Tech Zone / MR CYBER"
VIAddVersionKey "FileDescription" "WSA Installer Download Edition - Easy Android on Windows"
VIAddVersionKey "FileVersion" "${APP_VERSION}"
VIAddVersionKey "LegalCopyright" "© 2026 AT Tech Zone. All rights reserved."
; ── Maintenance Page ──────────────────────────────────────────
Var ButtonRepair
Var ButtonUninstall
Var MaintenanceDialog
Var RepairMode
Function MaintenancePage
; Skip in silent/repair mode (from Windows Settings)
${If} $RepairMode == 1
Return
${EndIf}
; Check if app is installed
ReadRegStr $R0 HKLM "${UNINSTALL_KEY}" "UninstallString"
${If} $R0 == ""
Return ; Skip page if not installed
${EndIf}
nsDialogs::Create 1018
Pop $MaintenanceDialog
${If} $MaintenanceDialog == "error"
Abort
${EndIf}
${NSD_CreateLabel} 0 0 100% 24u "${APP_NAME} is already installed.$\nSelect an action below to manage your installation:"
Pop $0
${NSD_CreateButton} 25% 45u 50% 25u "Repair / Reinstall"
Pop $ButtonRepair
${NSD_OnClick} $ButtonRepair OnClickRepair
${NSD_CreateButton} 25% 75u 50% 25u "Uninstall"
Pop $ButtonUninstall
${NSD_OnClick} $ButtonUninstall OnClickUninstall
nsDialogs::Show
FunctionEnd
Function OnClickRepair
; Pre-fill install directory from existing installation
ReadRegStr $INSTDIR HKLM "${UNINSTALL_KEY}" "InstallLocation"
${If} $INSTDIR == ""
StrCpy $INSTDIR "${INSTALL_DIR}"
${EndIf}
; Move to the next page (Directory)
SendMessage $HWNDPARENT ${WM_COMMAND} 1 0
FunctionEnd
Function OnClickUninstall
; Perform silent uninstall and then exit
ExecWait '"$INSTDIR\Uninstall.exe" /S _?=$INSTDIR'
Quit
FunctionEnd
; ── Custom Socials Page ──────────────────────────────────────
Var Dialog
Var Label
Var ButtonYT
Var ButtonCoffee
Function SocialsPage
; Skip in silent/repair mode (from Windows Settings)
${If} $RepairMode == 1
Return
${EndIf}
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == "error"
Abort
${EndIf}
${NSD_CreateLabel} 0 0 100% 24u "We hope you find this tool useful! $\nIf you'd like to support future development, consider subscribing or donating."
Pop $Label
${NSD_CreateButton} 25% 45u 50% 25u "Subscribe on YouTube"
Pop $ButtonYT
${NSD_OnClick} $ButtonYT OnClickYT
${NSD_CreateButton} 25% 75u 50% 25u "Buy Me a Coffee"
Pop $ButtonCoffee
${NSD_OnClick} $ButtonCoffee OnClickCoffee
nsDialogs::Show
FunctionEnd
Function OnClickYT
ExecShell "open" "${YT_URL}"
FunctionEnd
Function OnClickCoffee
ExecShell "open" "${COFFEE_URL}"
FunctionEnd
; ── Installer Functions ───────────────────────────────────────
Function .onInit
; Prevent multiple instances of setup
System::Call 'kernel32::CreateMutex(p 0, i 1, t "${MUTEX_NAME}") p .r0 ?e'
Pop $0
${If} $0 != 0
MessageBox MB_OK|MB_ICONEXCLAMATION "Setup is already running."
Abort
${EndIf}
${IfNot} ${AtLeastWin10}
MessageBox MB_OK|MB_ICONSTOP "WSA Installer requires Windows 11 (22H2 or later).$\nSetup will now exit."
Abort
${EndIf}
; Detect /repair flag (from Windows Settings "Modify" / "Repair" buttons)
${GetParameters} $R0
${StrLoc} $R0 $R0 "/repair" ">"
${If} $R0 != ""
StrCpy $RepairMode 1
SetSilent silent
${EndIf}
FunctionEnd
Function .onInstSuccess
ExecShell "open" "${YT_URL}"
FunctionEnd
; ── Main Install Section ─────────────────────────────────────
Section "WSA Installer (Required)" SecMain
SectionIn RO
; Detect repair vs fresh install
${If} $RepairMode == 1
DetailPrint "Repairing ${APP_NAME} installation..."
${Else}
DetailPrint "Installing ${APP_NAME}..."
${EndIf}
; ── Kill old server before install ───────────────────────────
DetailPrint "Stopping old WSA Background Service..."
ExecWait 'sc stop WSABackgroundService'
Sleep 2000
ExecWait 'sc delete WSABackgroundService'
DetailPrint "Closing any running WSA Installer instance..."
ExecWait 'taskkill /F /IM "${APP_EXE}" /T'
Sleep 1000
SetOutPath "$INSTDIR"
SetOverwrite on
; Copy ALL files from PyInstaller output
File /r "${SOURCE_DIR}\*.*"
; Save running installer inside install folder (for Windows Settings Repair)
; NSIS extracts to temp dir, so original EXE is NOT locked — safe to copy
CreateDirectory "$INSTDIR\out_asset"
CopyFiles "$EXEPATH" "$INSTDIR\out_asset\WSA_Installer_Setup.exe"
; Registry keys
WriteRegStr HKLM "${UNINSTALL_KEY}" "DisplayName" "${APP_NAME}"
WriteRegStr HKLM "${UNINSTALL_KEY}" "DisplayVersion" "${APP_VERSION}"
WriteRegStr HKLM "${UNINSTALL_KEY}" "Publisher" "${APP_PUBLISHER}"
WriteRegStr HKLM "${UNINSTALL_KEY}" "InstallLocation" "$INSTDIR"
WriteRegStr HKLM "${UNINSTALL_KEY}" "UninstallString" "$INSTDIR\Uninstall.exe"
WriteRegStr HKLM "${UNINSTALL_KEY}" "QuietUninstallString" '"$INSTDIR\Uninstall.exe" /S'
WriteRegStr HKLM "${UNINSTALL_KEY}" "DisplayIcon" "$INSTDIR\${APP_EXE}"
WriteRegDWORD HKLM "${UNINSTALL_KEY}" "NoModify" 0
WriteRegStr HKLM "${UNINSTALL_KEY}" "ModifyPath" '"$INSTDIR\out_asset\WSA_Installer_Setup.exe" /S /repair'
WriteRegStr HKLM "${UNINSTALL_KEY}" "Repair" '"$INSTDIR\out_asset\WSA_Installer_Setup.exe" /S /repair'
WriteRegDWORD HKLM "${UNINSTALL_KEY}" "EstimatedSize" 52000
WriteUninstaller "$INSTDIR\Uninstall.exe"
; Shortcuts
CreateShortCut "$DESKTOP\${APP_NAME}.lnk" "$INSTDIR\${APP_EXE}" "" "$INSTDIR\${APP_EXE}" 0
CreateDirectory "$SMPROGRAMS\${APP_NAME}"
CreateShortCut "$SMPROGRAMS\${APP_NAME}\${APP_NAME}.lnk" "$INSTDIR\${APP_EXE}" "" "$INSTDIR\${APP_EXE}" 0
CreateShortCut "$SMPROGRAMS\${APP_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
; Install and start Windows service
DetailPrint "Installing Windows background service..."
ExecWait 'sc create WSABackgroundService binPath= "$INSTDIR\${APP_EXE} --bg-service" start= auto'
ExecWait 'sc failure WSABackgroundService reset=86400 actions=restart/10000/restart/15000/restart/30000'
ExecWait 'sc description WSABackgroundService "Monitors Windows Subsystem for Android and manages Play Store patcher SDK. Auto-restarts on failure."'
ExecWait 'sc start WSABackgroundService'
DetailPrint "Service started."
SectionEnd
; ── Uninstaller ───────────────────────────────────────────────
Section "Uninstall"
; Stop and delete the Windows service FIRST (prevents SCM auto-restart)
ExecWait 'sc stop WSABackgroundService'
Sleep 2000
ExecWait 'sc delete WSABackgroundService'
Sleep 500
; Ensure the application is not running
ExecWait 'taskkill /F /IM "${APP_EXE}" /T'
; Run Python uninstaller to clean WSA and related data
; We capture the exit code in $0. 0 = Success, 1 = Cancel/Error
ExecWait '"$INSTDIR\${APP_EXE}" --uninstall' $0
${If} $0 != 0
MessageBox MB_OK|MB_ICONINFORMATION "Uninstallation was cancelled or interrupted. The installation directory will not be removed."
Abort
${EndIf}
; If we reach here, uninstallation was successful
DetailPrint "WSA Uninstalled successfully. Removing remaining files..."
; Safety delay to release file handles
Sleep 1000
RMDir /r "$INSTDIR"
Delete "$DESKTOP\${APP_NAME}.lnk"
Delete "$SMPROGRAMS\${APP_NAME}\${APP_NAME}.lnk"
Delete "$SMPROGRAMS\${APP_NAME}\Uninstall.lnk"
RMDir "$SMPROGRAMS\${APP_NAME}"
DeleteRegKey HKLM "${UNINSTALL_KEY}"
SectionEnd
Function un.onUninstSuccess
ExecShell "open" "${YT_URL}"
FunctionEnd
+285
View File
@@ -0,0 +1,285 @@
@echo off
chcp 65001 >nul 2>nul
setlocal enabledelayedexpansion
cd /d "%~dp0"
:: ═══════════════════════════════════════════════════════════════
:: VERSION — Change this to update app.py, file_version_info,
:: and NSIS installer version in one shot.
:: ═══════════════════════════════════════════════════════════════
SET VERSION=1.2
:: -------- Step 0: Activate Virtual Environment --------
if exist "venv\Scripts\activate.bat" (
echo [+] Activating virtual environment...
call venv\Scripts\activate.bat
)
title WSA Installer Build Script
echo ============================================
echo WSA Installer Build Script
echo 1. Clean
echo 2. Check dependencies
echo 3. Nuitka module (app.py -^> app.pyd)
echo 4. PyInstaller onedir
echo 5. Patch Flet client (icon + metadata)
echo 6. (optional) bundle.wsa
echo 7. NSIS installer
echo ============================================
echo.
:: -------- Step 1: Clean --------
echo [1/7] Cleaning previous build...
if exist "dist" rmdir /s /q "dist"
if exist "build" rmdir /s /q "build"
if exist "app.pyd" del /f /q "app.pyd"
if exist "app.pyi" del /f /q "app.pyi"
for /d %%d in (*.build) do rmdir /s /q "%%d" 2>nul
echo [+] Clean complete.
echo.
:: -------- Step 2: Dependencies --------
echo [2/7] Checking dependencies...
venv\Scripts\python.exe -c "import requests, flet, pyautogui, pyperclip, pywinauto, PyQt6" >nul 2>nul
if %errorlevel% neq 0 (
echo [!] Missing dependencies — installing...
venv\Scripts\python.exe -m pip install -r requirements.txt
if !errorlevel! neq 0 (
echo [!] PIP INSTALL FAILED.
pause
exit /b 1
)
echo [+] Dependencies installed.
) else (
echo [+] All dependencies OK.
)
echo.
:: -------- Step 2.5: Update version across all files --------
echo [2.5/7] Setting version to %VERSION%...
:: app.py: APP_ID suffix
powershell -Command "$c = Get-Content 'app.py' -Raw; $c = $c -replace 'mrcyber\.wsainstaller\.download\.\d+\.\d+', 'mrcyber.wsainstaller.download.%VERSION%'; Set-Content 'app.py' -Value $c -Encoding UTF8 -NoNewline"
:: file_version_info.txt: string versions (1.0.0.0 -> X.Y.0.0) and tuple versions (1, 0, 0, 0)
for /f "tokens=1,2 delims=." %%a in ("%VERSION%") do (
set MAJOR=%%a
set MINOR=%%b
)
powershell -Command "$c = Get-Content 'file_version_info.txt' -Raw; $c = $c -replace '\d+\.\d+\.\d+\.\d+', '%VERSION%.0.0'; $c = $c -replace '\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*,\s*\d+\s*\)', '(!MAJOR!, !MINOR!, 0, 0)'; Set-Content 'file_version_info.txt' -Value $c -Encoding UTF8 -NoNewline"
echo [+] Version updated to %VERSION%
echo - app.py APP_ID = mrcyber.wsainstaller.download.%VERSION%
echo - file_version_info FileVersion = %VERSION%.0.0
echo - NSIS will use /DAPP_VERSION=%VERSION%
echo.
:: -------- Step 3: Nuitka module (Protect source code) --------
echo [3/7] Compiling app.pyd with Nuitka...
:: Backup app.py before compilation
copy /y app.py app.py.backup >nul
echo [+] Backup created: app.py.backup
:: Compile app.py directly (keeps PyInit_app export correct)
python -m nuitka --module --remove-output app.py
if %errorlevel% neq 0 (
echo [!] NUITKA MODULE COMPILATION FAILED.
copy /y app.py.backup app.py >nul
del app.py.backup
pause
exit /b 1
)
:: Find the compiled .pyd (ABI-tagged: app.cp314-win_amd64.pyd)
if exist app.*.pyd (
for %%f in (app.*.pyd) do (
ren "%%f" "app.pyd"
goto :pyd_renamed
)
)
echo [!] No .pyd file found after Nuitka compilation.
copy /y app.py.backup app.py >nul
del app.py.backup
pause
exit /b 1
:pyd_renamed
:: Verify app.pyd exists
if not exist "app.pyd" (
echo [!] app.pyd not found after rename.
copy /y app.py.backup app.py >nul
del app.py.backup
pause
exit /b 1
)
echo [+] app.pyd created successfully (PyInit_app export intact).
:: Delete interface file (exposes function signatures)
if exist "app.pyi" (
del /f /q "app.pyi"
echo [+] app.pyi deleted.
)
:: Rename app.py to wsa.py — hides source from PyInstaller, forces it to bundle app.pyd
ren app.py wsa.py
echo [+] app.py renamed to wsa.py — source hidden from PyInstaller.
:: Backup no longer needed
echo.
:: -------- Step 3.5: Compile WSARepair.py to WSARepair.exe --------
echo [3.5/7] Compiling WSARepair.exe...
venv\Scripts\pyinstaller.exe --onefile --name WSARepair --distpath assets --workpath build_tmp --specpath build_tmp --noconfirm WSARepair.py
if %errorlevel% neq 0 (
echo [!] WSARepair.py compilation failed — skipping.
) else (
echo [+] WSARepair.exe compiled to assets\
)
:: Clean up build artifacts
if exist "build_tmp" rmdir /s /q "build_tmp"
echo.
:: -------- Step 4: PyInstaller onedir --------
echo [4/7] Running PyInstaller (onedir)...
echo Spec: WSA_Installer_Download_onedir.spec
echo.
venv\Scripts\pyinstaller.exe --noconfirm "WSA_Installer_Download_onedir.spec"
if %errorlevel% neq 0 (
echo [!] PyInstaller failed, trying python -m PyInstaller...
venv\Scripts\python.exe -m PyInstaller "WSA_Installer_Download_onedir.spec"
if %errorlevel% neq 0 (
echo [!] PYINSTALLER FAILED.
if exist "wsa.py" (
ren wsa.py app.py
)
pause
exit /b 1
)
)
echo [+] PyInstaller onedir build complete.
echo.
:: -------- Restore app.py from wsa.py --------
echo [4.5/7] Restoring app.py...
if exist "wsa.py" (
ren wsa.py app.py
echo [+] app.py restored from wsa.py.
)
echo.
:: -------- Step 4.6 removed: clean_venv replaced by embedded Python in .pyd --------
:: -------- Step 5: Patch Flet client EXE --------
echo [5/7] Patching Flet client EXE (icon + metadata)...
set FLET_EXE=dist\WSA Installer\_internal\flet_desktop\app\flet\flet.exe
if not exist "patch_flet" mkdir "patch_flet"
if exist "!FLET_EXE!" (
:: Backup original
copy /y "!FLET_EXE!" "patch_flet\flet.exe.bak" >nul
echo [+] Backed up original flet.exe
venv\Scripts\python.exe patch_flet.py "!FLET_EXE!" "assets\icon.ico" "file_version_info.txt"
if !errorlevel! equ 0 (
echo [+] Flet client patched successfully
copy /y "!FLET_EXE!" "patch_flet\flet.exe" >nul
echo [+] Patched copy saved to patch_flet\flet.exe
) else (
echo [!] Patch FAILED — restoring backup...
copy /y "patch_flet\flet.exe.bak" "!FLET_EXE!" >nul
)
:: Also patch the cached Flet client for immediate effect
for /d %%d in ("%USERPROFILE%\.flet\client\flet-desktop-full-*") do (
if exist "%%d\flet.exe" (
echo [~] Patching cached Flet client at %%d...
copy /y "%%d\flet.exe" "%%d\flet.exe.bak" >nul 2>nul
venv\Scripts\python.exe patch_flet.py "%%d\flet.exe" "assets\icon.ico" "file_version_info.txt"
)
)
:: Create patched flet-windows.zip so client machines extract patched version
:: instead of downloading original from GitHub
set FLET_APP_DIR=dist\WSA Installer\_internal\flet_desktop\app
if exist "!FLET_APP_DIR!\flet" (
echo [~] Creating patched flet-windows.zip...
del /f /q "!FLET_APP_DIR!\flet-windows.zip" >nul 2>nul
powershell -Command "Compress-Archive -Path '!FLET_APP_DIR!\flet' -DestinationPath '!FLET_APP_DIR!\flet-windows.zip' -Force"
if !errorlevel! equ 0 (
echo [+] Patched flet-windows.zip created for client cache extraction
) else (
echo [!] Failed to create flet-windows.zip
)
)
) else (
echo [~] flet.exe not found at !FLET_EXE! — skipping patch
)
echo.
:: -------- Step 6: Bundle prompt (bundle.wsa) --------
echo [6/7] PyInstaller build done.
echo Output folder: dist\WSA Installer\
echo ========================================
echo.
echo Enter path to bundle.wsa file (or leave empty to skip):
set /p BUNDLE_PATH="bundle.wsa path: "
if not "!BUNDLE_PATH!"=="" (
if exist "!BUNDLE_PATH!" (
echo Copying bundle.wsa to dist\WSA Installer\out_asset\...
if not exist "dist\WSA Installer\out_asset" mkdir "dist\WSA Installer\out_asset"
copy /y "!BUNDLE_PATH!" "dist\WSA Installer\out_asset\bundle.wsa" >nul
echo [+] bundle.wsa copied.
) else (
echo [~] File not found: !BUNDLE_PATH!
)
) else (
echo Skipping bundle copy.
)
echo.
:: -------- Step 7: NSIS --------
echo [7/7] Building NSIS installer...
if not exist "WSA_Installer_Setup.nsi" (
echo [!] WSA_Installer_Setup.nsi not found - skipping NSIS.
goto :finish
)
makensis /DAPP_VERSION=%VERSION% "WSA_Installer_Setup.nsi"
if %errorlevel% equ 0 (
echo [+] NSIS installer created: dist\WSA_Installer_Setup.exe
) else (
echo [~] makensis not in PATH, trying default path...
if exist "C:\Program Files (x86)\NSIS\makensis.exe" (
"C:\Program Files (x86)\NSIS\makensis.exe" /DAPP_VERSION=%VERSION% "WSA_Installer_Setup.nsi"
if !errorlevel! equ 0 (
echo [+] NSIS installer created: dist\WSA_Installer_Setup.exe
) else (
echo [!] NSIS failed. Install NSIS from https://nsis.sourceforge.io/
)
) else (
echo [!] NSIS not found. Install NSIS from https://nsis.sourceforge.io/
)
)
:finish
:: Safety: restore app.py if wsa.py still exists
if exist "wsa.py" (
echo [~] Restoring app.py from wsa.py...
ren wsa.py app.py
)
echo.
echo ========================================
echo ALL DONE
echo ========================================
echo EXE + deps : dist\WSA Installer\
echo Installer : dist\WSA_Installer_Setup.exe
echo ========================================
echo.
pause
+168
View File
@@ -0,0 +1,168 @@
@echo off
chcp 65001 >nul 2>nul
setlocal enabledelayedexpansion
cd /d "%~dp0"
:: -------- Step 0: Activate Virtual Environment --------
if exist "venv\Scripts\activate.bat" (
echo [+] Activating virtual environment...
call venv\Scripts\activate.bat
)
title WSA Installer Build Script (Nuitka Standalone)
set DIST_FINAL=dist\WSA Installer
echo ============================================
echo WSA Installer Build Script
echo 1. Clean + Check dependencies
echo 2. Nuitka --standalone app
echo 3. Restructure into _internal\ layout
echo 4. Compile launcher (C# via PowerShell)
echo 5. Copy assets + bundle.wsa
echo 6. NSIS installer
echo ============================================
echo.
:: -------- Step 1: Clean + Dependencies --------
echo [1/6] Cleaning previous build...
if exist "dist" rmdir /s /q "dist"
if exist "*.build" for /d %%d in (*.build) do rmdir /s /q "%%d" 2>nul
if exist "app.build_src_backup" del /f /q "app.build_src_backup"
echo [+] Clean complete.
echo.
echo [1/6] Checking dependencies...
venv\Scripts\python.exe -c "import py7zr, requests, flet, pyautogui, pyperclip, pywinauto, PyQt6" >nul 2>nul
if %errorlevel% neq 0 (
echo [!] Missing dependencies — installing...
venv\Scripts\pip.exe install -r requirements.txt
if !errorlevel! neq 0 (
echo [!] PIP INSTALL FAILED.
pause
exit /b 1
)
echo [+] Dependencies installed.
) else (
echo [+] All dependencies OK.
)
echo.
:: -------- Step 2: Nuitka --standalone --------
echo [2/6] Compiling run.py to standalone EXE with Nuitka...
echo This may take 30-60 minutes.
echo.
python -m nuitka --standalone ^
--remove-output ^
--windows-uac-admin ^
--windows-icon-from-ico=assets\icon.ico ^
--output-dir=tmp_nuitka ^
run.py
if %errorlevel% neq 0 (
echo [!] NUITKA COMPILATION FAILED (errorlevel=%errorlevel%^)
pause
exit /b 1
)
echo [+] Nuitka build complete.
echo.
:: -------- Step 3: Restructure into _internal\ layout --------
echo [3/6] Restructuring output (PyInstaller-style _internal\)...
:: Create final directory structure
if not exist "%DIST_FINAL%\_internal" mkdir "%DIST_FINAL%\_internal"
:: Rename run.exe -> WSA Installer.exe
ren "tmp_nuitka\run.dist\run.exe" "WSA Installer.exe"
:: Move everything into _internal\ (including the real EXE)
xcopy /e /i /y "tmp_nuitka\run.dist\*.*" "%DIST_FINAL%\_internal\" >nul
:: Clean up Nuitka temp
rmdir /s /q "tmp_nuitka"
:: Copy assets into _internal\
if exist "assets" (
xcopy /e /i /y "assets" "%DIST_FINAL%\_internal\assets" >nul
)
echo [+] Restructure done. _internal\ has the real EXE + all deps.
echo.
:: -------- Step 4: Compile launcher (C# -> WSA Installer.exe) --------
echo [4/6] Compiling launcher EXE (C# via PowerShell)...
if not exist "launcher.cs" (
echo [!] launcher.cs not found — creating batch launcher instead...
echo @start "" /D "%%~dp0_internal" "%%~dp0_internal\WSA Installer.exe" %%* > "%DIST_FINAL%\WSA Installer.cmd"
echo [+] Created batch launcher: WSA Installer.cmd
echo [~] NSIS and shortcuts will still work.
) else (
:: Compile launcher.cs to GUI EXE at root level
powershell -Command "Add-Type -TypeDefinition (Get-Content 'launcher.cs' -Raw) -OutputAssembly '%DIST_FINAL%\WSA Installer.exe' -OutputType WindowsApplication" >nul 2>nul
if %errorlevel% neq 0 (
echo [!] LAUNCHER COMPILATION FAILED.
echo Trying alternative: batch launcher...
echo @start "" /D "%%~dp0_internal" "%%~dp0_internal\WSA Installer.exe" %%* > "%DIST_FINAL%\WSA Installer.cmd"
echo [+] Created batch launcher instead: WSA Installer.cmd
echo [~] NSIS and shortcuts will still work.
)
)
echo.
:: -------- Step 5: Bundle prompt (bundle.wsa) --------
echo [5/6] Build done.
echo Output folder: %DIST_FINAL%
echo Executable : %DIST_FINAL%\WSA Installer.exe
echo.
echo Enter path to bundle.wsa file (or leave empty to skip):
set /p BUNDLE_PATH="bundle.wsa path: "
if not "!BUNDLE_PATH!"=="" (
if exist "!BUNDLE_PATH!" (
echo Copying bundle.wsa to %DIST_FINAL%\out_asset\...
if not exist "%DIST_FINAL%\out_asset" mkdir "%DIST_FINAL%\out_asset"
copy /y "!BUNDLE_PATH!" "%DIST_FINAL%\out_asset\bundle.wsa" >nul
echo [+] bundle.wsa copied.
) else (
echo [~] File not found: !BUNDLE_PATH!
)
) else (
echo Skipping bundle copy.
)
echo.
:: -------- Step 6: NSIS --------
echo [6/6] Building NSIS installer...
if not exist "WSA_Installer_Setup.nsi" (
echo [~] WSA_Installer_Setup.nsi not found - skipping NSIS.
goto :finish
)
makensis "WSA_Installer_Setup.nsi"
if %errorlevel% equ 0 (
echo [+] NSIS installer created: dist\WSA_Installer_Setup.exe
) else (
echo [~] makensis not in PATH, trying default path...
if exist "C:\Program Files (x86)\NSIS\makensis.exe" (
"C:\Program Files (x86)\NSIS\makensis.exe" "WSA_Installer_Setup.nsi"
if !errorlevel! equ 0 (
echo [+] NSIS installer created: dist\WSA_Installer_Setup.exe
) else (
echo [!] NSIS failed. Install NSIS from https://nsis.sourceforge.io/
)
) else (
echo [!] NSIS not found. Install NSIS from https://nsis.sourceforge.io/
)
)
:finish
echo.
echo ========================================
echo ALL DONE
echo ========================================
echo Launcher : %DIST_FINAL%\WSA Installer.exe
echo App + deps : %DIST_FINAL%\_internal\
echo Installer : dist\WSA_Installer_Setup.exe
echo ========================================
echo.
pause
+33
View File
@@ -0,0 +1,33 @@
@echo off
chcp 65001 >nul 2>nul
setlocal
cd /d "%~dp0"
:: -------- Create venv if missing --------
if not exist "venv\Scripts\python.exe" (
echo [+] Creating virtual environment...
python -m venv venv
if %errorlevel% neq 0 (
echo [!] Failed to create venv. Make sure Python is installed and in PATH.
pause
exit /b 1
)
echo [+] venv created.
)
:: -------- Install requirements if flet is missing --------
venv\Scripts\python.exe -c "import flet" >nul 2>nul
if %errorlevel% neq 0 (
echo [+] Installing dependencies...
venv\Scripts\python.exe -m pip install -r requirements.txt
if %errorlevel% neq 0 (
echo [!] pip install failed.
pause
exit /b 1
)
echo [+] Dependencies installed.
)
:: -------- Run --------
echo [+] Starting WSA Installer...
venv\Scripts\python.exe run.py %*
+36
View File
@@ -0,0 +1,36 @@
# UTF-8
#
# For more details about fixed file info 'ffi' see:
# https://learn.microsoft.com/en-us/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo
VSVersionInfo(
ffi=FixedFileInfo(
filevers=(1, 2, 0, 0),
prodvers=(1, 2, 0, 0),
mask=0x3f,
flags=0x0,
OS=0x40004,
fileType=0x1,
subtype=0x0,
date=(0, 0)
),
kids=[
StringFileInfo(
[
StringTable(
'040904B0',
[
StringStruct('CompanyName', 'MR CYBER'),
StringStruct('FileDescription', 'WSA Installer Download Edition - Easy Android on Windows'),
StringStruct('FileVersion', '1.2.0.0'),
StringStruct('InternalName', 'WSA Installer'),
StringStruct('LegalCopyright', '(C) 2026 AT Tech Zone. All rights reserved.'),
StringStruct('OriginalFilename', 'WSA Installer.exe'),
StringStruct('ProductName', 'WSA Installer'),
StringStruct('ProductVersion', '1.2.0.0')
]
)
]
),
VarFileInfo([VarStruct('Translation', [1033, 1200])])
]
)
+19
View File
@@ -0,0 +1,19 @@
requests
flet
pyautogui
pyperclip
pywinauto
PyQt6
PyQt6-WebEngine
pycryptodomex
pillow
comtypes
psutil
brotli
inflate64
multivolumefile
pybcj
pyppmd
texttable
pywin32
packaging
+80
View File
@@ -0,0 +1,80 @@
"""WSARepair.exe --- proxy for Windows Settings Repair/Uninstall buttons."""
import sys, os, subprocess, time, winreg
def log(msg):
print(f"""[WSARepair {time.strftime("%H:%M:%S")}] {msg}""", flush=True)
def _find_installer():
log("Looking for WSA Installer...")
# Method 1: NSIS uninstaller registry InstallLocation + DisplayIcon
nsus_key = r"Software\Microsoft\Windows\CurrentVersion\Uninstall\WSAInstaller"
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, nsus_key, 0,
winreg.KEY_READ | winreg.KEY_WOW64_64KEY)
install_dir, _ = winreg.QueryValueEx(key, "InstallLocation")
winreg.CloseKey(key)
if install_dir:
exe = os.path.join(install_dir, "WSA Installer.exe")
log(f"NSIS InstallLocation: {exe}")
if os.path.exists(exe):
log(f"Found: {exe}"); return exe
log("Not on disk, trying DisplayIcon...")
except FileNotFoundError:
log("NSIS uninstall key not found")
except Exception as e:
log(f"NSIS registry error: {e}")
# Method 2: NSIS DisplayIcon
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, nsus_key, 0,
winreg.KEY_READ | winreg.KEY_WOW64_64KEY)
icon_path, _ = winreg.QueryValueEx(key, "DisplayIcon")
winreg.CloseKey(key)
log(f"NSIS DisplayIcon: {icon_path}")
if icon_path and os.path.exists(icon_path):
log(f"Found: {icon_path}"); return icon_path
except Exception as e:
log(f"DisplayIcon error: {e}")
# Method 3: HKLM\SOFTWARE\WSAInstaller\InstallerPath (custom, backup)
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\WSAInstaller", 0,
winreg.KEY_READ | winreg.KEY_WOW64_64KEY)
exe_path, _ = winreg.QueryValueEx(key, "InstallerPath")
winreg.CloseKey(key)
log(f"Custom registry: {exe_path}")
if exe_path and os.path.exists(exe_path):
log(f"Found: {exe_path}"); return exe_path
except Exception:
log("Custom registry key not found")
# Method 4: Hardcoded Program Files path
fixed = r"C:\Program Files\WSA Installer\WSA Installer.exe"
log(f"Hardcoded: {fixed}")
if os.path.exists(fixed):
log(f"Found: {fixed}"); return fixed
log("ERROR: No installer found"); return ""
def main():
log("Started")
log(f"Args: {sys.argv}")
a = sys.argv[1].lower() if len(sys.argv) > 1 else ""
log(f"Action: {a}")
if a not in ("repair", "uninstall"):
log(f"Bad action: {a}"); return 1
exe = _find_installer()
if not exe or not os.path.exists(exe):
log("Cannot proceed - not found"); return 1
f = "--repair-wsa" if a == "repair" else "--uninstall"
log(f"Launch: {exe} {f}")
try:
subprocess.Popen([exe, f], creationflags=subprocess.DETACHED_PROCESS,
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
log("Launched OK"); return 0
except Exception as e:
log(f"Launch failed: {e}"); return 1
if __name__ == "__main__":
sys.exit(main())
+10996
View File
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
using System;
using System.Diagnostics;
using System.IO;
class Launcher
{
static void Main()
{
var dir = Path.GetDirectoryName(typeof(Launcher).Assembly.Location);
var exePath = Path.Combine(dir, "_internal", "WSA Installer.exe");
var proc = new Process();
proc.StartInfo.FileName = exePath;
proc.StartInfo.WorkingDirectory = Path.Combine(dir, "_internal");
proc.Start();
proc.WaitForExit();
Environment.Exit(proc.ExitCode);
}
}
+162
View File
@@ -0,0 +1,162 @@
import os
import sys
import struct
import win32api
from PyInstaller.utils.win32 import versioninfo as _vi
RT_ICON = 3
RT_GROUP_ICON = 14
LOAD_LIBRARY_AS_DATAFILE = 0x00000002
def read_ico(ico_path):
with open(ico_path, 'rb') as f:
data = f.read()
if data[:4] != b'\x00\x00\x01\x00':
raise ValueError(f"Not a valid .ico file: {ico_path}")
count = struct.unpack_from('<H', data, 4)[0]
entries = []
for i in range(count):
w, h, colors, reserved, planes, bpp, size, offset = \
struct.unpack_from('<BBBBHHII', data, 6 + i * 16)
icon_data = data[offset:offset + size]
entries.append({
'w': w if w else 256,
'h': h if h else 256,
'colors': colors,
'planes': planes,
'bpp': bpp,
'size': size,
'data': icon_data,
})
return entries
def build_group_icon(entries):
group = struct.pack('<HHH', 0, 1, len(entries))
for i, e in enumerate(entries):
w = e['w'] if e['w'] < 256 else 0
h = e['h'] if e['h'] < 256 else 0
group += struct.pack(
'<BBBBHHIH',
w, h, e['colors'], 0, e['planes'], e['bpp'], e['size'], i + 1,
)
return group
def discover_ids(exe_path):
icon_ids = set()
group_ids = set()
try:
h_mod = win32api.LoadLibraryEx(exe_path, 0, LOAD_LIBRARY_AS_DATAFILE)
for res_type in (RT_ICON, RT_GROUP_ICON):
try:
names = win32api.EnumResourceNames(h_mod, res_type)
for name in names:
if res_type == RT_ICON:
icon_ids.add(name)
elif res_type == RT_GROUP_ICON:
group_ids.add(name)
except win32api.error:
pass
win32api.FreeLibrary(h_mod)
except Exception as e:
print(f" [~] Discovery error: {e}")
return set(), set()
return icon_ids, group_ids
def patch_icons(exe_path, ico_path):
entries = read_ico(ico_path)
icon_ids, group_ids = discover_ids(exe_path)
if not group_ids:
group_ids.add(1)
handle = win32api.BeginUpdateResource(exe_path, 0)
group_data = build_group_icon(entries)
for gid in group_ids:
win32api.UpdateResource(handle, RT_GROUP_ICON, gid, group_data)
print(f" [+] Updated RT_GROUP_ICON ID={gid}")
for i, e in enumerate(entries):
res_id = i + 1
win32api.UpdateResource(handle, RT_ICON, res_id, e['data'])
sz = f"{e['w']}x{e['h']}"
print(f" [+] Updated RT_ICON ID={res_id} ({sz})")
win32api.EndUpdateResource(handle, 0)
return True
def patch_version_info(exe_path, version_info_path):
info = _vi.load_version_info_from_text_file(version_info_path)
_vi.write_version_info_to_executable(exe_path, info)
print(f" [+] Updated version info from {version_info_path}")
def patch_embedded_string(exe_path, old_str, new_str):
with open(exe_path, 'rb') as f:
data = bytearray(f.read())
old_utf16 = old_str.encode('utf-16-le')
new_utf16 = new_str.encode('utf-16-le')
if len(new_utf16) > len(old_utf16):
print(f" [~] New string ({len(new_utf16)} bytes) longer than old ({len(old_utf16)} bytes) — skipping")
return False
idx = data.find(old_utf16)
if idx < 0:
print(f" [~] String '{old_str}' not found in binary — skipping")
return False
padded = new_utf16 + b'\x00' * (len(old_utf16) - len(new_utf16))
data[idx:idx + len(old_utf16)] = padded
with open(exe_path, 'wb') as f:
f.write(data)
print(f" [+] Replaced '{old_str}' -> '{new_str}' at offset 0x{idx:X}")
return True
def main():
if len(sys.argv) < 2:
print("Usage: patch_flet.py <exe_path> [icon.ico] [file_version_info.txt]")
sys.exit(1)
exe_path = os.path.abspath(sys.argv[1])
if not os.path.exists(exe_path):
print(f"Error: {exe_path} not found")
sys.exit(1)
print(f" Patcher: {exe_path}")
ico_path = sys.argv[2] if len(sys.argv) > 2 else None
ver_path = sys.argv[3] if len(sys.argv) > 3 else None
if ico_path:
ico_path = os.path.abspath(ico_path)
if os.path.exists(ico_path):
patch_icons(exe_path, ico_path)
else:
print(f" [~] Icon not found: {ico_path}")
if ver_path:
ver_path = os.path.abspath(ver_path)
if os.path.exists(ver_path):
patch_version_info(exe_path, ver_path)
else:
print(f" [~] Version info not found: {ver_path}")
patch_embedded_string(exe_path, 'Flet description', 'WSA Installer')
print(f" [+] Done: {exe_path}")
if __name__ == '__main__':
main()
+2
View File
@@ -0,0 +1,2 @@
import app
app.start()