├── ApkShellext2
├── Resources
│ ├── Apple.png
│ ├── apkm.png
│ ├── logo.png
│ ├── logo1.png
│ ├── play.png
│ ├── Amazon.png
│ ├── Android.png
│ ├── GitHub.png
│ ├── QR-Scan.png
│ ├── Windows.png
│ ├── output.png
│ ├── rename.png
│ ├── restart.png
│ ├── udpate.png
│ ├── telegram_s.png
│ ├── App-store-icon.png
│ ├── msft store icon.png
│ ├── net_cloud_drive.png
│ ├── Patreon_Mark_Coral.jpg
│ ├── Apkshellext_icons
│ │ ├── apkshell.psd
│ │ ├── apkshell_b.png
│ │ ├── apkshell_w.png
│ │ ├── apkshell_b32.png
│ │ ├── apkshell_b64.png
│ │ ├── apkshell_nc.png
│ │ ├── apkshell_w32.png
│ │ └── apkshell_w64.png
│ ├── restart_explorer.bat
│ ├── uninstall.bat
│ ├── install.bat
│ └── debug.bat
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Settings.cs
│ ├── Settings.settings
│ ├── Resources.my-MM.resx
│ ├── Resources.he-IL.resx
│ ├── Resources.el-GR.resx
│ ├── Resources.ko-KR.resx
│ ├── Resources.ja-JP.resx
│ ├── Settings.Designer.cs
│ ├── Resources.zh-TW.resx
│ └── NonLocalizeResources.resx
├── ApkShellext2.csproj.user
├── ApkInfoTipHandler.cs
├── app.config
├── AppPackageReader.cs
├── AppxbundleReader.cs
├── ApkThumbnailHandler.cs
├── AppxReader.cs
├── Preferences.resx
├── ApkIconHandler.cs
└── IpaReader.cs
├── ApkShellextService
├── App.config
├── Properties
│ └── AssemblyInfo.cs
├── apkShellextServiceInstaller.cs
├── apkShellextService.csproj
└── apkShellextService.cs
├── apkshellextTest
├── App.config
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Program.cs
├── Form1.cs
├── apkshellextTest.csproj
├── Form1.resx
└── Form1.Designer.cs
├── .gitattributes
├── .github
└── FUNDING.yml
├── .gitmodules
├── LICENSE
├── ApkShellext2.sln
├── README.md
└── .gitignore
/ApkShellext2/Resources/Apple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/Apple.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/apkm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/apkm.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/logo.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/logo1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/logo1.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/play.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/Amazon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/Amazon.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/Android.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/Android.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/GitHub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/GitHub.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/QR-Scan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/QR-Scan.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/Windows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/Windows.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/output.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/rename.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/rename.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/restart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/restart.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/udpate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/udpate.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/telegram_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/telegram_s.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/App-store-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/App-store-icon.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/msft store icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/msft store icon.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/net_cloud_drive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/net_cloud_drive.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/Patreon_Mark_Coral.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/Patreon_Mark_Coral.jpg
--------------------------------------------------------------------------------
/ApkShellext2/Resources/Apkshellext_icons/apkshell.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/Apkshellext_icons/apkshell.psd
--------------------------------------------------------------------------------
/ApkShellext2/Resources/Apkshellext_icons/apkshell_b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/Apkshellext_icons/apkshell_b.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/Apkshellext_icons/apkshell_w.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/Apkshellext_icons/apkshell_w.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/Apkshellext_icons/apkshell_b32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/Apkshellext_icons/apkshell_b32.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/Apkshellext_icons/apkshell_b64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/Apkshellext_icons/apkshell_b64.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/Apkshellext_icons/apkshell_nc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/Apkshellext_icons/apkshell_nc.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/Apkshellext_icons/apkshell_w32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/Apkshellext_icons/apkshell_w32.png
--------------------------------------------------------------------------------
/ApkShellext2/Resources/Apkshellext_icons/apkshell_w64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kkguo/apkshellext/HEAD/ApkShellext2/Resources/Apkshellext_icons/apkshell_w64.png
--------------------------------------------------------------------------------
/ApkShellextService/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/apkshellextTest/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ApkShellext2/Resources/restart_explorer.bat:
--------------------------------------------------------------------------------
1 | REM CHOICE /M "Restart explorer process?"
2 | REM IF %ERRORLEVEL%==1 (
3 | TASKKILL /F /IM explorer.exe
4 | TASKKILL /F /IM dllhost.exe
5 | REM pause
6 | START %WINDIR%\explorer.exe
7 | REM )
--------------------------------------------------------------------------------
/apkshellextTest/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/apkshellextTest/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Windows.Forms;
6 |
7 | namespace apkshellextTest
8 | {
9 | static class Program
10 | {
11 | ///
12 | /// The main entry point for the application.
13 | ///
14 | [STAThread]
15 | static void Main()
16 | {
17 | Application.EnableVisualStyles();
18 | Application.SetCompatibleTextRenderingDefault(false);
19 | Application.Run(new Form1());
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: kkguo # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "ApkShellext2/SharpZipLib"]
2 | path = ApkShellext2/SharpZipLib
3 | url = https://github.com/kkguo/SharpZipLib.git
4 | [submodule "ApkShellext2/SharpShell"]
5 | path = ApkShellext2/SharpShell
6 | url = https://github.com/kkguo/sharpshell.git
7 | [submodule "ApkShellext2/PlistCS"]
8 | path = ApkShellext2/PlistCS
9 | url = https://github.com/kkguo/PlistCS.git
10 | [submodule "ApkShellext2/PNGDecrush"]
11 | path = ApkShellext2/PNGDecrush
12 | url = https://github.com/kkguo/PNGDecrush.git
13 | [submodule "ApkShellext2/Ionic.Zlib"]
14 | path = ApkShellext2/Ionic.Zlib
15 | url = https://github.com/kkguo/Ionic.Zlib.git
16 | [submodule "QRCoder"]
17 | path = QRCoder
18 | url = https://github.com/kkguo/QRCoder.git
19 | [submodule "ApkShellext2/QRCoder"]
20 | path = ApkShellext2/QRCoder
21 | url = https://github.com/codebude/QRCoder.git
22 | [submodule "ApkShellext2/SVG"]
23 | path = ApkShellext2/SVG
24 | url = https://github.com/vvvv/SVG.git
25 | [submodule "ApkShellext2/WebP-wrapper"]
26 | path = ApkShellext2/WebP-wrapper
27 | url = https://github.com/JosePineiro/WebP-wrapper.git
28 |
--------------------------------------------------------------------------------
/ApkShellextService/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的常规信息通过以下
6 | // 特性集控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("apkShellextService")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("KK")]
12 | [assembly: AssemblyProduct("apkShellext")]
13 | [assembly: AssemblyCopyright("Copyright © Microsoft 2015")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 使此程序集中的类型
18 | // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
19 | // 则将该类型上的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("caa5fbf9-1ae8-4f71-8a7a-3eeb312c0fc4")]
24 |
25 | // 程序集的版本信息由下面四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
33 | // 方法是按如下所示使用“*”:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Jingang Guo, KK
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/apkshellextTest/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace apkshellextTest.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ApkShellext2/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Resources;
2 | using System.Reflection;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 |
6 | // 有关程序集的常规信息通过以下
7 | // 特性集控制。更改这些特性值可修改
8 | // 与程序集关联的信息。
9 | [assembly: AssemblyTitle("ApkShellext2")]
10 | [assembly: AssemblyDescription("Windows shell plugin enabling showing app package file icon on windows.")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("KKHOMEBREW")]
13 | [assembly: AssemblyProduct("ApkShellext2")]
14 | [assembly: AssemblyCopyright("Copyright © KK 2019")]
15 | [assembly: AssemblyTrademark("ApkShellExt")]
16 |
17 | // 将 ComVisible 设置为 false 使此程序集中的类型
18 | // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
19 | // 则将该类型上的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(true)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("1F869CEE-4FDA-35D9-896F-43975A87D1F5")]
24 |
25 | // 程序集的版本信息由下面四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | // 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
33 | // 方法是按如下所示使用“*”:
34 | [assembly: AssemblyVersion("0.2.0.7")]
35 | [assembly: NeutralResourcesLanguage("en-US")]
36 | //[assembly: AssemblyVersion("0.1.2.*")]
37 | //[assembly: AssemblyFileVersion("0.1.0")]
38 |
--------------------------------------------------------------------------------
/ApkShellextService/apkShellextServiceInstaller.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Configuration.Install;
3 | using System.ServiceProcess;
4 |
5 | namespace ApkShellext2 {
6 | [RunInstaller(true)]
7 | public class apkShellextServiceInstaller : Installer {
8 |
9 | public apkShellextServiceInstaller() {
10 | ServiceProcessInstaller serviceProcessInstaller =
11 | new ServiceProcessInstaller();
12 | ServiceInstaller serviceInstaller = new ServiceInstaller();
13 |
14 | //# Service Account Information
15 | serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
16 | serviceProcessInstaller.Username = null;
17 | serviceProcessInstaller.Password = null;
18 |
19 | //# Service Information
20 | serviceInstaller.DisplayName = "ApkShellext Service";
21 | serviceInstaller.StartType = ServiceStartMode.Automatic;
22 |
23 | //# This must be identical to the WindowsService.ServiceBase name
24 | //# set in the constructor of WindowsService.cs
25 | serviceInstaller.ServiceName = "apkShellext Service";
26 |
27 | this.Installers.Add(serviceProcessInstaller);
28 | this.Installers.Add(serviceInstaller);
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ApkShellext2/Properties/Settings.cs:
--------------------------------------------------------------------------------
1 | namespace ApkShellext2.Properties {
2 |
3 |
4 | // This class allows you to handle specific events on the settings class:
5 | // The SettingChanging event is raised before a setting's value is changed.
6 | // The PropertyChanged event is raised after a setting's value is changed.
7 | // The SettingsLoaded event is raised after the setting values are loaded.
8 | // The SettingsSaving event is raised before the setting values are saved.
9 | internal sealed partial class Settings {
10 |
11 | public Settings() {
12 | // // To add event handlers for saving and changing settings, uncomment the lines below:
13 | //
14 | // this.SettingChanging += this.SettingChangingEventHandler;
15 | //
16 | // this.SettingsSaving += this.SettingsSavingEventHandler;
17 | //
18 | }
19 |
20 | private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
21 | // Add code to handle the SettingChangingEvent event here.
22 | }
23 |
24 | private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
25 | // Add code to handle the SettingsSaving event here.
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/apkshellextTest/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("apkshellextTest")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("apkshellextTest")]
13 | [assembly: AssemblyCopyright("Copyright © 2019")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("6853ddbc-05ea-476a-b1ca-47f6e64ff795")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/ApkShellext2/ApkShellext2.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 |
6 | Program
7 | C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe
8 | C:\Users\guojin\Documents\Brews\ApkShellext2\ApkShellext2\bin\Debug\
9 | /codebase apkshellext2.dll
10 |
16 |
17 |
18 | C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe
19 | C:\Users\guojin\Documents\Brews\ApkShellext2\ApkShellext2\bin\Debug\
20 | /codebase apkshellext2.dll
21 | Program
22 |
23 |
--------------------------------------------------------------------------------
/ApkShellext2/Resources/uninstall.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | ECHO #######################################################
3 | ECHO ## APK Shell Extension 2 ##
4 | ECHO ## ##
5 | ECHO ## http://apkshellext.com s ##
6 | ECHO #######################################################
7 |
8 | REM === check and get the UAC for administrator privilege ===
9 | REM === code from https://sites.google.com/site/eneerge/scripts/batchgotadmin
10 | REM ===
11 | :: BatchGotAdmin
12 | :-------------------------------------
13 | REM --> Check for permissions
14 | >nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
15 |
16 | REM --> If error flag set, we do not have admin.
17 | if '%errorlevel%' NEQ '0' (
18 | echo Requesting administrative privileges...
19 | goto UACPrompt
20 | ) else ( goto gotAdmin )
21 |
22 | :UACPrompt
23 | echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
24 | echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs"
25 |
26 | "%temp%\getadmin.vbs"
27 | exit /B
28 |
29 | :gotAdmin
30 | if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
31 | pushd "%CD%"
32 | CD /D "%~dp0"
33 | :--------------------------------------
34 |
35 | REM SYSTEMINFO | FIND /i "x64-based pc"
36 | echo %PROCESSOR_IDENTIFIER% | FIND /i "x86"
37 |
38 | set FRAMEWORK=%windir%\Microsoft.NET\Framework
39 | set DOTNETVERSION=v4.0.30319
40 | IF %ERRORLEVEL%==1 (
41 | set FRAMEWORK=%FRAMEWORK%64
42 | )
43 | set REGASM="%FRAMEWORK%\%DOTNETVERSION%\regasm.exe"
44 | %REGASM% /unregister "%~dp0\apkshellext2.dll"
45 |
46 | ECHO.
47 | REM ECHO The apkshellext.dll may can't be deleted before explorer restart.
48 |
49 | ECHO.
50 | ECHO /-------------------------------------------------------------------\
51 | ECHO apkshellext is an open-source project,
52 | ECHO Please visit http://apkshellext.com for more information
53 | ECHO \-------------------------------------------------------------------/
54 |
55 | PAUSE
56 | @ECHO ON
57 |
--------------------------------------------------------------------------------
/ApkShellext2/Resources/install.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | ECHO #######################################################
3 | ECHO ## APK Shell Extension 2 ##
4 | ECHO ## ##
5 | ECHO ## http://www.apkshellext.com ##
6 | ECHO #######################################################
7 |
8 | REM === check and get the UAC for administrator privilege ===
9 | REM === code from https://sites.google.com/site/eneerge/scripts/batchgotadmin
10 | :: BatchGotAdmin
11 | :-------------------------------------
12 | REM --> Check for permissions
13 | >nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
14 |
15 | REM --> If error flag set, we do not have admin.
16 | if '%errorlevel%' NEQ '0' (
17 | if '%1' EQU '1' (
18 | echo Cannot elevate administrator privilege
19 | echo Please try again with "Run as Administrator"
20 | echo Installation failed.
21 | pause
22 | exit /B
23 | ) else (
24 | echo Requesting administrative privileges...
25 | goto UACPrompt
26 | )
27 | ) else ( goto gotAdmin )
28 |
29 | :UACPrompt
30 | echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
31 | echo UAC.ShellExecute "%~s0", "1", "", "runas", 1 >> "%temp%\getadmin.vbs"
32 |
33 | "%temp%\getadmin.vbs"
34 | exit /B
35 |
36 | :gotAdmin
37 | if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
38 | pushd "%CD%"
39 | CD /D "%~dp0"
40 | :--------------------------------------
41 |
42 | REM SYSTEMINFO | FIND /i "x64-based pc"
43 | echo %PROCESSOR_IDENTIFIER% | FIND /i "x86"
44 |
45 | set FRAMEWORK=%windir%\Microsoft.NET\Framework
46 | set DOTNETVERSION=v4.0.30319
47 | IF %ERRORLEVEL%==1 (
48 | set FRAMEWORK=%FRAMEWORK%64
49 | )
50 | set REGASM="%FRAMEWORK%\%DOTNETVERSION%\regasm.exe"
51 | %REGASM% /codebase "%~dp0\apkshellext2.dll"
52 |
53 | ECHO Done!
54 | ECHO.
55 | ECHO /-------------------------------------------------------------------\
56 | ECHO apkshellext is an open-source project,
57 | ECHO Please visit http://www.apkshellext.com for more information
58 | ECHO \-------------------------------------------------------------------/
59 |
60 | PAUSE
61 | @ECHO ON
62 |
--------------------------------------------------------------------------------
/ApkShellext2/Resources/debug.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | ECHO #######################################################
3 | ECHO ## APK Shell Extension 2 ##
4 | ECHO ## ##
5 | ECHO ## http://www.apkshellext.com ##
6 | ECHO #######################################################
7 |
8 | REM === check and get the UAC for administrator privilege ===
9 | REM === code from https://sites.google.com/site/eneerge/scripts/batchgotadmin
10 | :: BatchGotAdmin
11 | :-------------------------------------
12 | REM --> Check for permissions
13 | >nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
14 |
15 | REM --> If error flag set, we do not have admin.
16 | if '%errorlevel%' NEQ '0' (
17 | if '%1' EQU '1' (
18 | echo Cannot elevate administrator privilege
19 | echo Please try again with "Run as Administrator"
20 | echo Installation failed.
21 | pause
22 | exit /B
23 | ) else (
24 | echo Requesting administrative privileges...
25 | goto UACPrompt
26 | )
27 | ) else ( goto gotAdmin )
28 |
29 | :UACPrompt
30 | echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
31 | echo UAC.ShellExecute "%~s0", "1", "", "runas", 1 >> "%temp%\getadmin.vbs"
32 |
33 | "%temp%\getadmin.vbs"
34 | exit /B
35 |
36 | :gotAdmin
37 | if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
38 | pushd "%CD%"
39 | CD /D "%~dp0"
40 | :--------------------------------------
41 |
42 | REM SYSTEMINFO | FIND /i "x64-based pc"
43 | echo %PROCESSOR_IDENTIFIER% | FIND /i "x86"
44 |
45 | set FRAMEWORK=%windir%\Microsoft.NET\Framework
46 | set DOTNETVERSION=v4.0.30319
47 | IF %ERRORLEVEL%==1 (
48 | set FRAMEWORK=%FRAMEWORK%64
49 | )
50 | set REGASM="%FRAMEWORK%\%DOTNETVERSION%\regasm.exe"
51 | %REGASM% /codebase "%~dp0\apkshellext2.dll"
52 |
53 | ECHO Done!
54 | ECHO.
55 | ECHO /-------------------------------------------------------------------\
56 | ECHO apkshellext is an open-source project,
57 | ECHO Please visit http://www.apkshellext.com for more information
58 | ECHO \-------------------------------------------------------------------/
59 |
60 | TASKKILL /F /IM explorer.exe
61 | TASKKILL /F /IM dllhost.exe
62 | REM pause
63 | START %WINDIR%\explorer.exe
64 | @ECHO ON
65 |
66 | start C:\Users\guojin\Desktop\project\apk
67 |
--------------------------------------------------------------------------------
/ApkShellext2.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.28803.352
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApkShellext2", "ApkShellext2\ApkShellext2.csproj", "{091659BA-A36B-45D5-AAF2-3CE764453FF2}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "apkShellextService", "apkShellextService\apkShellextService.csproj", "{3F77E975-68ED-4083-B8F8-56EB56372889}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "apkshellextTest", "apkshellextTest\apkshellextTest.csproj", "{6853DDBC-05EA-476A-B1CA-47F6E64FF795}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Debug2|Any CPU = Debug2|Any CPU
16 | Release|Any CPU = Release|Any CPU
17 | EndGlobalSection
18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
19 | {091659BA-A36B-45D5-AAF2-3CE764453FF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
20 | {091659BA-A36B-45D5-AAF2-3CE764453FF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
21 | {091659BA-A36B-45D5-AAF2-3CE764453FF2}.Debug2|Any CPU.ActiveCfg = Debug2|Any CPU
22 | {091659BA-A36B-45D5-AAF2-3CE764453FF2}.Debug2|Any CPU.Build.0 = Debug2|Any CPU
23 | {091659BA-A36B-45D5-AAF2-3CE764453FF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
24 | {091659BA-A36B-45D5-AAF2-3CE764453FF2}.Release|Any CPU.Build.0 = Release|Any CPU
25 | {3F77E975-68ED-4083-B8F8-56EB56372889}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26 | {3F77E975-68ED-4083-B8F8-56EB56372889}.Debug2|Any CPU.ActiveCfg = Debug2|Any CPU
27 | {3F77E975-68ED-4083-B8F8-56EB56372889}.Release|Any CPU.ActiveCfg = Release|Any CPU
28 | {6853DDBC-05EA-476A-B1CA-47F6E64FF795}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {6853DDBC-05EA-476A-B1CA-47F6E64FF795}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {6853DDBC-05EA-476A-B1CA-47F6E64FF795}.Debug2|Any CPU.ActiveCfg = Debug2|Any CPU
31 | {6853DDBC-05EA-476A-B1CA-47F6E64FF795}.Debug2|Any CPU.Build.0 = Debug2|Any CPU
32 | {6853DDBC-05EA-476A-B1CA-47F6E64FF795}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {6853DDBC-05EA-476A-B1CA-47F6E64FF795}.Release|Any CPU.Build.0 = Release|Any CPU
34 | EndGlobalSection
35 | GlobalSection(SolutionProperties) = preSolution
36 | HideSolutionNode = FALSE
37 | EndGlobalSection
38 | GlobalSection(ExtensibilityGlobals) = postSolution
39 | SolutionGuid = {0A438C55-B459-43B6-999D-11D7A8991B0F}
40 | EndGlobalSection
41 | EndGlobal
42 |
--------------------------------------------------------------------------------
/apkshellextTest/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace apkshellextTest.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("apkshellextTest.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/ApkShellext2/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | False
7 |
8 |
9 | True
10 |
11 |
12 | True
13 |
14 |
15 | False
16 |
17 |
18 | True
19 |
20 |
21 | True
22 |
23 |
24 | True
25 |
26 |
27 | True
28 |
29 |
30 | True
31 |
32 |
33 | True
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | -1
43 |
44 |
45 | True
46 |
47 |
48 | 0
49 |
50 |
51 | 2014-12-31
52 |
53 |
54 | False
55 |
56 |
57 |
58 |
59 |
60 | True
61 |
62 |
63 | True
64 |
65 |
66 | True
67 |
68 |
69 | False
70 |
71 |
72 |
--------------------------------------------------------------------------------
/ApkShellext2/ApkInfoTipHandler.cs:
--------------------------------------------------------------------------------
1 | using ApkQuickReader;
2 | using Microsoft.Win32;
3 | using SharpShell.Attributes;
4 | using SharpShell.Diagnostics;
5 | using SharpShell.Extensions;
6 | using SharpShell.ServerRegistration;
7 | using SharpShell.SharpInfoTipHandler;
8 | using System;
9 | using System.IO;
10 | using System.Linq;
11 | using System.Runtime.InteropServices;
12 | using ApkShellext2.Properties;
13 |
14 | namespace ApkShellext2 {
15 |
16 | [Guid("946435a5-fe96-416d-99db-e94ee9fb46c8")]
17 | [ComVisible(true)]
18 | [ClassInterface(ClassInterfaceType.None)]
19 | [COMServerAssociation(AssociationType.ClassOfExtension, ".apk")]
20 | [COMServerAssociation(AssociationType.ClassOfExtension, ".ipa")]
21 | [COMServerAssociation(AssociationType.ClassOfExtension, ".appxbundle")]
22 | [COMServerAssociation(AssociationType.ClassOfExtension, ".appx")]
23 | public class ApkInfoTipHandler : SharpInfoTipHandler {
24 | ///
25 | /// Gets info for the selected item (SelectedItemPath).
26 | ///
27 | /// Type of info to return.
28 | /// if set to true, put the info in a single line.
29 | ///
30 | /// Specified info for the selected file.
31 | ///
32 | protected override string GetInfo(RequestedInfoType infoType, bool singleLine) {
33 | try {
34 | Utility.Localize();
35 | string TipPattern = Utility.GetSetting("ToolTipPattern", NonLocalizeResources.strInfoTipDefault);
36 | bool isapk = SelectedItemPath.EndsWith(".apk");
37 | bool isipa = SelectedItemPath.EndsWith(".ipa");
38 |
39 | using (AppPackageReader reader = AppPackageReader.Read(SelectedItemPath)) {
40 | return ApkContextMenu.ReplaceVariables(TipPattern, reader);
41 | }
42 | } catch (Exception ex) {
43 | Log("Error happend during GetInfo : " + ex.Message);
44 | return Properties.Resources.strReadFileFailed;
45 | }
46 | }
47 |
48 | [CustomRegisterFunction]
49 | public static void postDoRegister(Type type, RegistrationType registrationType) {
50 | Console.WriteLine("Registering " + type.FullName);
51 |
52 | #region Clean up older versions registry
53 | try {
54 | using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(@"\CLSID\" +
55 | type.GUID.ToRegistryString() + @"\InprocServer32")) {
56 | if (key != null && key.GetSubKeyNames().Count() != 0) {
57 | Console.WriteLine("Found old version in registry, cleaning up ...");
58 | foreach (var k in key.GetSubKeyNames()) {
59 | if (k != type.Assembly.GetName().Version.ToString()) {
60 | Registry.ClassesRoot.DeleteSubKeyTree(@"\CLSID\" +
61 | type.GUID.ToRegistryString() + @"\InprocServer32\" + k);
62 | }
63 | }
64 | }
65 | }
66 | } catch (Exception e) {
67 | Logging.Error("Cleaning up older version but see exception. "
68 | + e.Message);
69 | }
70 | #endregion
71 | }
72 |
73 | protected override void Log(string message){
74 | Utility.Log(this, Path.GetFileName(SelectedItemPath), message);
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/ApkShellext2/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | False
12 |
13 |
14 | True
15 |
16 |
17 | True
18 |
19 |
20 | False
21 |
22 |
23 | True
24 |
25 |
26 | True
27 |
28 |
29 | True
30 |
31 |
32 | True
33 |
34 |
35 | True
36 |
37 |
38 | True
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | -1
48 |
49 |
50 | True
51 |
52 |
53 | 0
54 |
55 |
56 | 2014-12-31
57 |
58 |
59 | False
60 |
61 |
62 |
63 |
64 |
65 | True
66 |
67 |
68 | True
69 |
70 |
71 | True
72 |
73 |
74 | False
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ApkShellext2
2 | [](http://translate.apkshellext.com/)
3 |
4 | A Windows shell extension supporting icon for files of
5 | * .apk (android package)
6 | * .ipa (iOS app package)
7 | * .appx .appxbundle (Windows phone 8.1/10 app package, .xap is not supported)
8 |
9 | This is the code repository, please visit the project page http://apkshellext.com or go to [release](https://github.com/kkguo/apkshellext/releases) for download.
10 |
11 | #### Help this project
12 | * Become a Sponsor, I will be more glad to update your request.
13 | * Translators please read this first : [Translate Wiki page](https://github.com/kkguo/apkshellext/wiki/Translation-and-Multi-language-support#1-translate)
14 | * Project pages needs web people to maintain.
15 | * Become a beta testers, join [Telegram group](https://t.me/ApkShellExt2)
16 | * Pull request is always welcome.
17 |
18 | #### Have issue?
19 | * Check the [Known issue list](https://github.com/kkguo/apkshellext/wiki/Known-issues-and-solution) first.
20 | * Look for help on [Telegram group](https://t.me/ApkShellExt2) (Preferred)
21 | * Go raise [Issues](https://github.com/kkguo/apkshellext/issues) (Preferred)
22 | * Send to :email: issue@apkshellext.com
23 |
24 | #### [Features]
25 | - [x] Display app icon in Windows File Explorer with best resolution. __DOES NOT work with other file manager due to .NET restriction__
26 | - [x] Customize-able Info-Tip for showing package information.
27 | - [x] Context menu for batch renaming, use customize-able patterns.
28 | - [x] Go to app store from context menu.
29 | - [x] Auto-check new version.
30 | - [x] Show overlay icon for different type of apps.
31 | - [x] Support multiple languages: Thanks to contributors on https://crowdin.com/project/apkshellext
32 |
33 | #### [Todo]
34 | - [X] Adaptive-icon support (Beta)
35 | - [ ] protobuf support
36 | - [ ] support .NET 4.0??
37 | - [ ] QR code to download to phone
38 | - [ ] Hook up adb function with namespace extension.
39 | - [ ] drag-drop to install / uninstall to phone
40 |
41 | #### Check [Wiki](https://github.com/kkguo/apkshellext/wiki) for how to build from source code
42 |
43 | #### Credit :
44 | |||
45 | | --- | --- |
46 | | [SharpShell](https://github.com/dwmkerr/sharpshell) | Shell extension library |
47 | | [SharpZip](https://github.com/icsharpcode/SharpZipLib) | Zip function implementation in C# |
48 | | [Iteedee.ApkReader](https://github.com/hylander0/Iteedee.ApkReader) | the original APK reader, not in use currently |
49 | | [PlistCS](https://github.com/animetrics/PlistCS) | iOS plist file reader |
50 | | [PNGDecrush](https://github.com/MikeWeller/PNGDecrush) | PNG decrush lib |
51 | | [Ionic.Zlib](https://github.com/jstedfast/Ionic.Zlib) | Another Zip implementation, used by PNGDecrush |
52 | | [QRCoder](https://github.com/codebude/QRCoder) | QR code generator |
53 | | [Ultimate Social](https://www.iconfinder.com/iconsets/ultimate-social) | A free icon set for social medias |
54 | | [SVG](https://github.com/vvvv/SVG) | SVG format renderer |
55 | | [WebP-Wrapper](https://github.com/JosePineiro/WebP-wrapper) | WebP format renderer
56 | | [Thanasis Georgiou](https://github.com/sakisds) | Project web page |
57 | --------------
58 | Originally this project hosted on [GoogleCode](code.google.com/p/apkshellext), now moved to [:octocat:Github](https://github.com/kkguo/apkshellext) and fully re-writen with a native apk reader. The active developing code is on [ApkShellext2 branch](https://github.com/kkguo/apkshellext/tree/ApkShellext2). The obsolete code is on [master branch](https://github.com/kkguo/apkshellext/tree/master)
59 |
--------------------------------------------------------------------------------
/apkshellextTest/Form1.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.IO;
9 | using System.Threading.Tasks;
10 | using System.Windows.Forms;
11 | using ApkShellext2;
12 | using ApkQuickReader;
13 | using ICSharpCode.SharpZipLib.Zip;
14 | using ApkShellext2.ApkChunk;
15 | using System.Drawing.Drawing2D;
16 | using System.Text.RegularExpressions;
17 |
18 | namespace apkshellextTest
19 | {
20 | public partial class Form1 : Form
21 | {
22 | public Form1()
23 | {
24 | InitializeComponent();
25 | }
26 |
27 | private void Button1_Click(object sender, EventArgs e)
28 | {
29 | OpenFileDialog dialog = new OpenFileDialog();
30 | dialog.Filter = "apkfile|*.apk";
31 | dialog.ShowDialog();
32 | textBox1.Text = dialog.FileName;
33 | //parseapk();
34 | }
35 |
36 | private void Button2_Click(object sender, EventArgs e) {
37 |
38 | //string TipPattern = @"Magisk Manager\r\ncom.topjohnwu.magisk\r\nVersion: 7.2.0 213\r\n%Attr(manifest/uses-sdk,minSdkVersion)%";// @"%Attr(mainifest/application,icon)%";
39 | //textBox1.Text = TipPattern;
40 | string TipPattern = textBox1.Text;
41 | Regex rx = new Regex(textBox3.Text);
42 | Match m = rx.Match(TipPattern);
43 | textBox4.Text = m.Success.ToString();
44 | if (m.Success) {
45 | foreach (Group c in m.Groups) {
46 | textBox4.Text = textBox4.Text + "||" + c.Value;
47 | }
48 | }
49 |
50 | //textBox4.Text = ApkContextMenu.ReplaceVariables(TipPattern, reader);
51 |
52 | return;
53 | AppPackageReader reader = AppPackageReader.Read(textBox1.Text);
54 | reader.setFlag("ImageSize", 48);
55 | pictureBox2.Image = reader.Icon;
56 |
57 | //parseapk();
58 |
59 | Bitmap b = new Bitmap(1000, 1000);
60 | using (Graphics g = Graphics.FromImage(b)) {
61 | //g.DrawPath(new Pen(Color.Black,1), VectorDrawableRender.Convert2Path("M 100 100 L 300 100 L 200 300 z"));
62 | g.FillPath(new SolidBrush(Color.Brown), VectorDrawableRender.Convert2Path("M0,0h108v108h-108z"));
63 | //g.FillPath(new SolidBrush(Color.Green), VectorDrawableRender.Convert2Path("M100,200 C100,100 250,100 250,200S400,300 400,200"));
64 | //g.FillPath(new SolidBrush(Color.Red), VectorDrawableRender.Convert2Path("M200,300 Q400,50 600,300 T1000,300"));
65 | //g.DrawPath(new Pen(Color.Purple, 2), VectorDrawableRender.Convert2Path("M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33V9h4.93L13,7v2h4V5.33C17,4.6 16.4,4 15.67,4z"));
66 | //g.DrawPath(new Pen(Color.Purple, 2), VectorDrawableRender.Convert2Path("M600,350 l 50,-25 a25, 25 -30 0, 1 50, -25 l 50, -25 a25, 50 -30 0, 1 50, -25 l 50, -25 a25, 75 -30 0, 1 50, -25 l 50, -25 a25, 100 -30 0, 1 50, -25 l 50, -25"));
67 | if (textBox1.Text != "") {
68 | g.DrawPath(new Pen(Color.Brown, 2),
69 | VectorDrawableRender.Convert2Path(textBox1.Text));
70 | }
71 |
72 | }
73 | pictureBox1.Size = b.Size;
74 | pictureBox1.Image = b;
75 | pictureBox1.Size = new Size(100, 100);
76 | }
77 |
78 | private void parseapk() {
79 | if (File.Exists(textBox1.Text.Trim())) {
80 | ZipFile zip = new ZipFile(textBox1.Text);
81 | ZipEntry en = zip.GetEntry("androidmanifest.xml");
82 | BinaryReader s = new BinaryReader(zip.GetInputStream(en));
83 | byte[] bytes = s.ReadBytes((int)en.Size);
84 | ApkXMLChunk ck = new ApkXMLChunk(bytes);
85 | textBox2.Text = ck.OutputXML();
86 |
87 | //AppPackageReader reader = AppPackageReader.Read(textBox1.Text);
88 | s.Close();
89 | zip.Close();
90 | }
91 | }
92 |
93 | private void Form1_Load(object sender, EventArgs e) {
94 |
95 | }
96 |
97 |
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | #*.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # Build results
11 | [Dd]ebug/
12 | [Dd]ebugPublic/
13 | [Rr]elease/
14 | [Rr]eleases/
15 | x64/
16 | x86/
17 | build/
18 | bld/
19 | [Bb]in/
20 | [Oo]bj/
21 |
22 | # Roslyn cache directories
23 | *.ide/
24 |
25 | # MSTest test Results
26 | [Tt]est[Rr]esult*/
27 | [Bb]uild[Ll]og.*
28 |
29 | #NUNIT
30 | *.VisualState.xml
31 | TestResult.xml
32 |
33 | # Build Results of an ATL Project
34 | [Dd]ebugPS/
35 | [Rr]eleasePS/
36 | dlldata.c
37 |
38 | *_i.c
39 | *_p.c
40 | *_i.h
41 | *.ilk
42 | *.meta
43 | *.obj
44 | *.pch
45 | *.pdb
46 | *.pgc
47 | *.pgd
48 | *.rsp
49 | *.sbr
50 | *.tlb
51 | *.tli
52 | *.tlh
53 | *.tmp
54 | *.tmp_proj
55 | *.log
56 | *.vspscc
57 | *.vssscc
58 | .builds
59 | *.pidb
60 | *.svclog
61 | *.scc
62 |
63 | # Chutzpah Test files
64 | _Chutzpah*
65 |
66 | # Visual C++ cache files
67 | ipch/
68 | *.aps
69 | *.ncb
70 | *.opensdf
71 | *.sdf
72 | *.cachefile
73 |
74 | # Visual Studio profiler
75 | *.psess
76 | *.vsp
77 | *.vspx
78 |
79 | # TFS 2012 Local Workspace
80 | $tf/
81 |
82 | # Guidance Automation Toolkit
83 | *.gpState
84 |
85 | # ReSharper is a .NET coding add-in
86 | _ReSharper*/
87 | *.[Rr]e[Ss]harper
88 | *.DotSettings.user
89 |
90 | # JustCode is a .NET coding addin-in
91 | .JustCode
92 |
93 | # TeamCity is a build add-in
94 | _TeamCity*
95 |
96 | # DotCover is a Code Coverage Tool
97 | *.dotCover
98 |
99 | # NCrunch
100 | _NCrunch_*
101 | .*crunch*.local.xml
102 |
103 | # MightyMoose
104 | *.mm.*
105 | AutoTest.Net/
106 |
107 | # Web workbench (sass)
108 | .sass-cache/
109 |
110 | # Installshield output folder
111 | [Ee]xpress/
112 |
113 | # DocProject is a documentation generator add-in
114 | DocProject/buildhelp/
115 | DocProject/Help/*.HxT
116 | DocProject/Help/*.HxC
117 | DocProject/Help/*.hhc
118 | DocProject/Help/*.hhk
119 | DocProject/Help/*.hhp
120 | DocProject/Help/Html2
121 | DocProject/Help/html
122 |
123 | # Click-Once directory
124 | publish/
125 |
126 | # Publish Web Output
127 | *.[Pp]ublish.xml
128 | *.azurePubxml
129 | # TODO: Comment the next line if you want to checkin your web deploy settings
130 | # but database connection strings (with potential passwords) will be unencrypted
131 | *.pubxml
132 | *.publishproj
133 |
134 | # NuGet Packages
135 | *.nupkg
136 | # The packages folder can be ignored because of Package Restore
137 | **/packages/*
138 | # except build/, which is used as an MSBuild target.
139 | !**/packages/build/
140 | # If using the old MSBuild-Integrated Package Restore, uncomment this:
141 | #!**/packages/repositories.config
142 |
143 | # Windows Azure Build Output
144 | csx/
145 | *.build.csdef
146 |
147 | # Windows Store app package directory
148 | AppPackages/
149 |
150 | # Others
151 | sql/
152 | *.Cache
153 | ClientBin/
154 | [Ss]tyle[Cc]op.*
155 | ~$*
156 | *~
157 | *.dbmdl
158 | *.dbproj.schemaview
159 | *.pfx
160 | *.publishsettings
161 | node_modules/
162 |
163 | # RIA/Silverlight projects
164 | Generated_Code/
165 |
166 | # Backup & report files from converting an old project file
167 | # to a newer Visual Studio version. Backup files are not needed,
168 | # because we have git ;-)
169 | _UpgradeReport_Files/
170 | Backup*/
171 | UpgradeLog*.XML
172 | UpgradeLog*.htm
173 |
174 | # SQL Server files
175 | *.mdf
176 | *.ldf
177 |
178 | # Business Intelligence projects
179 | *.rdl.data
180 | *.bim.layout
181 | *.bim_*.settings
182 |
183 | # Microsoft Fakes
184 | FakesAssemblies/
185 |
186 | # =========================
187 | # Operating System Files
188 | # =========================
189 |
190 | # OSX
191 | # =========================
192 |
193 | .DS_Store
194 | .AppleDouble
195 | .LSOverride
196 |
197 | # Thumbnails
198 | ._*
199 |
200 | # Files that might appear on external disk
201 | .Spotlight-V100
202 | .Trashes
203 |
204 | # Directories potentially created on remote AFP share
205 | .AppleDB
206 | .AppleDesktop
207 | Network Trash Folder
208 | Temporary Items
209 | .apdisk
210 |
211 | # Windows
212 | # =========================
213 |
214 | # Windows image file caches
215 | Thumbs.db
216 | ehthumbs.db
217 |
218 | # Folder config file
219 | Desktop.ini
220 |
221 | # Recycle Bin used on file shares
222 | $RECYCLE.BIN/
223 |
224 | # Windows Installer files
225 | *.cab
226 | *.msi
227 | *.msm
228 | *.msp
229 |
230 | # Windows shortcuts
231 | *.lnk
232 | /.vs
233 | /ApkShellext2/Properties/apkshellext/mv.bat
234 | /ApkShellext2/Properties/apkshellext
235 |
--------------------------------------------------------------------------------
/ApkShellext2/AppPackageReader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Drawing;
7 | using System.Globalization;
8 | using ApkQuickReader;
9 | using System.IO;
10 |
11 | namespace ApkShellext2 {
12 | ///
13 | /// This is the base class for package reader
14 | /// defines common method a package reader should have
15 | /// for reusing and simplify in the code
16 | ///
17 | public class AppPackageReader : IDisposable{
18 | public const string extAPK = ".apk";
19 | public const string extIPA = ".ipa";
20 | public const string extAPPX = ".appx";
21 | public const string extAPPXBUNDLE = ".appxbundle";
22 |
23 | public enum AppType {
24 | AndroidApp,
25 | iOSApp,
26 | WindowsPhoneAppBundle,
27 | WindowsPhoneApp
28 | }
29 | private Dictionary Flags;
30 |
31 | public virtual string FileName { get; protected set; }
32 | // App name
33 | public virtual string AppName { get { return ""; } }
34 | // Package Name
35 | public virtual string PackageName { get { return ""; } }
36 |
37 | // App version
38 | public virtual string Version { get { return ""; } }
39 | // Sub version
40 | public virtual string Revision { get { return ""; } }
41 |
42 | public virtual CultureInfo Culture { get; set; }
43 |
44 | // Publisher
45 | public virtual string Publisher { get { return ""; } }
46 |
47 | public virtual Bitmap Icon { get { return null; } }
48 |
49 | public virtual string AppID { get { return ""; } }
50 |
51 | public virtual AppType Type { get { return AppType.AndroidApp; } }
52 |
53 | // use for other information, or file type specific info
54 | public virtual void setFlag(string flag, object value) {
55 | if (Flags == null)
56 | Flags = new Dictionary();
57 | Flags[flag] = value;
58 | }
59 |
60 | public virtual object getFlag(string flag) {
61 | if (Flags != null && Flags.ContainsKey(flag))
62 | return Flags[flag];
63 | else
64 | return null;
65 | }
66 |
67 | public virtual Bitmap getIcon(Size size) {
68 | return Utility.ResizeBitmap(Icon, size);
69 | }
70 |
71 | // Public implementation of Dispose pattern callable by consumers.
72 | public void Dispose() {
73 | Dispose(true);
74 | GC.SuppressFinalize(this);
75 | }
76 |
77 | bool disposed;
78 | // Protected implementation of Dispose pattern.
79 | protected virtual void Dispose(bool disposing) {
80 | if (disposed)
81 | return;
82 | if (Flags != null)
83 | Flags.Clear();
84 | Flags = null;
85 | disposed = true;
86 | }
87 |
88 | public static AppType getAppType(string path) {
89 | string suffix = Path.GetExtension(path);
90 | if (suffix == extAPK) {
91 | return AppType.AndroidApp;
92 | } else if (suffix == extIPA) {
93 | return AppType.iOSApp;
94 | } else if (suffix == extAPPXBUNDLE) {
95 | return AppType.WindowsPhoneAppBundle;
96 | } else if (suffix == extAPPX) {
97 | return AppType.WindowsPhoneApp;
98 | } else {
99 | throw new NotSupportedException(suffix + " type is not supported.");
100 | }
101 | }
102 |
103 | public static AppPackageReader Read(string path) {
104 | switch (getAppType(path)) {
105 | case AppType.AndroidApp:
106 | return new ApkReader(path);
107 | case AppType.iOSApp:
108 | return new IpaReader(path);
109 | case AppType.WindowsPhoneAppBundle:
110 | return new AppxBundleReader(path);
111 | case AppType.WindowsPhoneApp:
112 | return new AppxReader(path);
113 | default :
114 | throw new NotSupportedException("File type is not supported.");
115 | }
116 | }
117 |
118 | protected void Log(string message) {
119 | Utility.Log(this, Path.GetFileName(FileName), message);
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ApkShellext2/AppxbundleReader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using ICSharpCode.SharpZipLib.Zip;
7 | using System.Xml;
8 | using System.IO;
9 | using System.Drawing;
10 |
11 | namespace ApkShellext2 {
12 | ///
13 | /// Read AppxBundle
14 | ///
15 | public class AppxBundleReader :AppPackageReader {
16 | private ZipFile zip;
17 | private AppxReader appxReader= null;
18 |
19 | private const string AppxBundleManifestXml = @"AppxMetadata/AppxBundleManifest.xml";
20 | private const string ElemIdentity = @"Identity";
21 | //private const string ElemProperties = @"Properties";
22 | //private const string ElemDisplayName = @"DisplayName";
23 | private const string ElemPackage = @"Package";
24 | //private const string AttrVersion = @"Version";
25 | private const string AttrName = @"Name";
26 | //private const string AttrPublisher = @"Publisher";
27 | private const string AttrType = @"Type";
28 | private const string ValApplication = @"application";
29 | private const string AttrFileName = @"FileName";
30 |
31 | public AppxBundleReader(Stream stream) {
32 | FileName = "";
33 | openFile(stream);
34 | }
35 |
36 | public AppxBundleReader(string path) {
37 | FileName = path;
38 | openFile(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read));
39 | }
40 |
41 | private void openFile(Stream stream) {
42 | string appxFileName = "";
43 | zip = new ZipFile(stream);
44 | ZipEntry en = zip.GetEntry(AppxBundleManifestXml);
45 | if (en == null)
46 | throw new EntryPointNotFoundException("cannot find " + AppxBundleManifestXml);
47 |
48 | using (XmlReader reader = XmlReader.Create(zip.GetInputStream(en))) {
49 | reader.ReadToFollowing(ElemIdentity);
50 | reader.MoveToAttribute(AttrName);
51 |
52 | do {
53 | reader.ReadToFollowing(ElemPackage);
54 | reader.MoveToAttribute(AttrType);
55 | } while (reader.Value != ValApplication || reader.EOF);
56 |
57 | if (reader.EOF)
58 | throw new Exception("Cannot find application in " + AppxBundleManifestXml);
59 |
60 | reader.MoveToAttribute(AttrFileName);
61 | appxFileName = reader.Value;
62 | }
63 |
64 | en = zip.GetEntry(appxFileName);
65 | if (en == null)
66 | throw new EntryPointNotFoundException("cannot find appx " + appxFileName);
67 |
68 | appxReader = new AppxReader(zip.GetInputStream(en));
69 | }
70 |
71 | public override AppPackageReader.AppType Type {
72 | get {
73 | return AppType.WindowsPhoneAppBundle;
74 | }
75 | }
76 |
77 | public override Bitmap Icon {
78 | get {
79 | return appxReader.Icon;
80 | }
81 | }
82 |
83 | public override string AppName {
84 | get {
85 | return appxReader.AppName;
86 | }
87 | }
88 |
89 | public override string PackageName {
90 | get {
91 | return appxReader.PackageName;
92 | }
93 | }
94 |
95 | public override string Version {
96 | get {
97 | return appxReader.Version;
98 | }
99 | }
100 |
101 | public override string Publisher {
102 | get {
103 | return appxReader.Publisher;
104 | }
105 | }
106 |
107 | public override string AppID {
108 | get {
109 | return appxReader.AppID;
110 | }
111 | }
112 | private bool disposed = false;
113 | protected override void Dispose(bool disposing) {
114 | if (disposed) return;
115 | if (disposing) {
116 | if (appxReader != null) {
117 | appxReader.Close();
118 | }
119 | if (zip != null)
120 | zip.Close();
121 | }
122 | disposed = true;
123 | base.Dispose(disposing);
124 | }
125 |
126 | public void Close() {
127 | Dispose(true);
128 | }
129 |
130 | ~AppxBundleReader() {
131 | Dispose(true);
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/ApkShellextService/apkShellextService.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {3F77E975-68ED-4083-B8F8-56EB56372889}
8 | Exe
9 | Properties
10 | ApkShellext2
11 | apkShellextService
12 | v4.5
13 | 512
14 |
15 |
16 |
17 |
18 | AnyCPU
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 | true
38 | bin\Debug2\
39 | DEBUG;TRACE
40 | full
41 | AnyCPU
42 | prompt
43 | MinimumRecommendedRules.ruleset
44 | true
45 |
46 |
47 |
48 | ..\packages\Google.Protobuf.3.8.0\lib\net45\Google.Protobuf.dll
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | Component
65 |
66 |
67 | Component
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | net stop "apkshellext service"
77 |
78 |
79 |
80 |
81 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
82 |
83 |
84 |
85 |
92 |
--------------------------------------------------------------------------------
/ApkShellext2/ApkThumbnailHandler.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using SharpShell.Attributes;
3 | using SharpShell.Diagnostics;
4 | using SharpShell.SharpThumbnailHandler;
5 | using System;
6 | using System.Drawing;
7 | using System.Linq;
8 | using System.Runtime.InteropServices;
9 | using SharpShell.Extensions;
10 | using SharpShell.ServerRegistration;
11 | using System.IO;
12 | using ApkShellext2.Properties;
13 | using ApkQuickReader;
14 | using System.Configuration;
15 |
16 | namespace ApkShellext2 {
17 | [Guid("d747c5a7-2f66-4b7d-8301-8531838e4ed3")]
18 | [ComVisible(true)]
19 | [ClassInterface(ClassInterfaceType.None)]
20 | [COMServerAssociation(AssociationType.ClassOfExtension, ".apk")]
21 | public class ApkThumbnailHandler : SharpThumbnailHandler {
22 | protected override Bitmap GetThumbnailImage(uint width) {
23 | Bitmap m_icon = null;
24 |
25 | //Log("Thumbnail is using setting file from: " + ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath);
26 |
27 | //if (!Settings.Default.EnableThumbnail) {
28 | // return null;
29 | //}
30 | if (Utility.GetSetting("EnableThumbnail") != "True") {
31 | return null;
32 | }
33 |
34 | try {
35 | int outputSize = (int) width;
36 | using (AppPackageReader reader = new ApkReader(SelectedItemStream)) {
37 | Log("Reading stream from " + reader.AppName);
38 | m_icon = reader.Icon;
39 | }
40 |
41 | if (m_icon == null)
42 | throw new Exception("Cannot find Icon from Stream, draw default");
43 | if (m_icon.Height < outputSize &&
44 | //!Settings.Default.StretchThumbnail)
45 | (Utility.GetSetting("StretchThumbnail","True")!="True"))
46 | outputSize = m_icon.Height;
47 |
48 | Log("Got icon, resizing...");
49 | //if (Settings.Default.ShowOverLayIcon) {
50 | if (Utility.GetSetting("ShowOverlayIcon")=="True") {
51 | Log("Draw overlay");
52 | m_icon = Utility.CombineBitmap(m_icon,
53 | Utility.AppTypeIcon(AppPackageReader.AppType.AndroidApp),
54 | new Rectangle(0, 0, outputSize , outputSize),
55 | new Rectangle(0, (int)outputSize / 2, (int)outputSize / 2, (int)outputSize / 2),
56 | new Size(outputSize, outputSize));
57 | } else {
58 | m_icon = Utility.ResizeBitmap(m_icon, outputSize);
59 | }
60 | #if DEBUG
61 | string p = Path.GetTempFileName();
62 | m_icon.Save(p);
63 | Log("Save m_icon to " + p);
64 | #endif
65 | return m_icon;
66 | } catch (Exception ex){
67 | Log("Error in reading icon from stream, draw default");
68 | Log(ex.Message);
69 | // read error, draw the default icon
70 | //m_icon = Utility.AppTypeIcon(AppPackageReader.AppType.AndroidApp);
71 | return null;
72 | }
73 | }
74 |
75 | [CustomRegisterFunction]
76 | public static void postDoRegister(Type type, RegistrationType registrationType) {
77 | Console.WriteLine("Registering " + type.FullName );
78 |
79 | using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(@"\CLSID\.apk")) {
80 | if (key != null) {
81 | // disable the shadow under thumbnail, make it more looks like an icon
82 | key.SetValue("Treatment", 0);
83 | }
84 | }
85 |
86 | #region Clean up older versions registry
87 | try {
88 | using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(@"\CLSID\" +
89 | type.GUID.ToRegistryString() + @"\InprocServer32")) {
90 | if (key != null && key.GetSubKeyNames().Count() != 0) {
91 | Console.WriteLine("Found old version in registry, cleaning up ...");
92 | foreach (var k in key.GetSubKeyNames()) {
93 | if (k != type.Assembly.GetName().Version.ToString()) {
94 | Registry.ClassesRoot.DeleteSubKeyTree(@"\CLSID\" +
95 | type.GUID.ToRegistryString() + @"\InprocServer32\" + k);
96 | }
97 | }
98 | }
99 | }
100 | } catch (Exception e) {
101 | Logging.Error("Cleaning up older version but see exception. "
102 | + e.Message);
103 | }
104 | #endregion
105 | }
106 |
107 | protected override void Log(string message) {
108 | Utility.Log(this, "", message);
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/apkshellextTest/apkshellextTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {6853DDBC-05EA-476A-B1CA-47F6E64FF795}
8 | WinExe
9 | apkshellextTest
10 | apkshellextTest
11 | v4.7.2
12 | 512
13 | true
14 | true
15 |
16 |
17 |
18 |
19 | AnyCPU
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 |
28 |
29 | AnyCPU
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 | true
39 | bin\Debug2\
40 | DEBUG;TRACE
41 | full
42 | AnyCPU
43 | prompt
44 | MinimumRecommendedRules.ruleset
45 | true
46 |
47 |
48 |
49 | ..\packages\Google.Protobuf.3.8.0\lib\net45\Google.Protobuf.dll
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | Form
66 |
67 |
68 | Form1.cs
69 |
70 |
71 |
72 |
73 | Form1.cs
74 |
75 |
76 | ResXFileCodeGenerator
77 | Resources.Designer.cs
78 | Designer
79 |
80 |
81 | True
82 | Resources.resx
83 |
84 |
85 | SettingsSingleFileGenerator
86 | Settings.Designer.cs
87 |
88 |
89 | True
90 | Settings.settings
91 | True
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | {091659ba-a36b-45d5-aaf2-3ce764453ff2}
100 | ApkShellext2
101 |
102 |
103 |
104 |
105 |
106 |
107 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/apkshellextTest/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/apkshellextTest/Form1.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/ApkShellext2/AppxReader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.IO;
7 | using ICSharpCode.SharpZipLib.Zip;
8 | using System.Xml;
9 | using System.Drawing;
10 | using System.Text.RegularExpressions;
11 |
12 | namespace ApkShellext2 {
13 | ///
14 | ///
15 | ///
16 | public class AppxReader : AppPackageReader {
17 | private const string AppxManifestXml = @"AppxManifest.xml";
18 | //private const string elemPackage = @"Package";
19 | private const string elemIdentity = @"Identity";
20 | private const string elemProperties = @"Properties";
21 | private const string elemDisplayName = @"DisplayName";
22 | private const string elemLogo = @"Logo";
23 | private const string elemPhoneIdentity = @"mp:PhoneIdentity";
24 |
25 | private const string attrVersion = @"Version";
26 | private const string attrName = @"Name";
27 | private const string attrPublisher = @"Publisher";
28 | private const string attrPhoneProductID = @"PhoneProductId";
29 |
30 | private ZipFile zip;
31 | private string iconPath;
32 |
33 | private string version;
34 | private string appname;
35 | private string packageName;
36 | private string publisher;
37 | private string productid;
38 |
39 | public AppxReader(Stream stream) {
40 | FileName = "";
41 | zip = new ZipFile(stream);
42 | Extract();
43 | }
44 |
45 | public AppxReader(string path) {
46 | FileName = path;
47 | zip = new ZipFile(FileName);
48 | Extract();
49 | }
50 |
51 | public void Extract() {
52 | ZipEntry en = zip.GetEntry(AppxManifestXml);
53 | if (en == null)
54 | throw new EntryPointNotFoundException("cannot find " + AppxManifestXml);
55 | byte[] xmlbytes = new byte[en.Size];
56 | zip.GetInputStream(en).Read(xmlbytes, 0, (int)en.Size);
57 |
58 | XmlDocument xml = new XmlDocument();
59 | xml.XmlResolver = null;
60 | xml.Load(zip.GetInputStream(en));
61 |
62 | XmlElement packageNode = xml.DocumentElement;
63 | XmlElement Identity = packageNode[elemIdentity];
64 | version = Identity.Attributes[attrVersion].Value.ToString();
65 | packageName = Identity.Attributes[attrName].Value.ToString();
66 | publisher = Identity.Attributes[attrPublisher].Value.ToString();
67 | Match m = Regex.Match(publisher,@"CN=([^,]*),?");
68 | if (m.Success) {
69 | publisher = m.Groups[1].Value;
70 | }
71 |
72 | XmlElement DisplayName = packageNode[elemProperties][elemDisplayName];
73 | appname = DisplayName.FirstChild.Value.ToString();
74 | XmlElement Logo = packageNode[elemProperties][elemLogo];
75 | iconPath = Logo.FirstChild.Value.ToString().Replace(@"\",@"/");
76 | XmlElement PhoneIdentity = packageNode[elemPhoneIdentity];
77 | productid = PhoneIdentity.Attributes[attrPhoneProductID].Value.ToString();
78 | }
79 |
80 | public override AppPackageReader.AppType Type {
81 | get {
82 | return AppType.WindowsPhoneApp;
83 | }
84 | }
85 |
86 | public override string AppName {
87 | get {
88 | return appname;
89 | }
90 | }
91 |
92 | public override string Version {
93 | get {
94 | return version;
95 | }
96 | }
97 |
98 | public override string Publisher {
99 | get {
100 | return publisher;
101 | }
102 | }
103 |
104 | public override string PackageName {
105 | get {
106 | return packageName;
107 | }
108 | }
109 |
110 | public override string AppID {
111 | get {
112 | return productid;
113 | }
114 | }
115 |
116 | public override Bitmap Icon {
117 | get {
118 | if (iconPath == "")
119 | throw new Exception("Cannot find logo path");
120 | int dot = iconPath.LastIndexOf(".");
121 | string name = iconPath.Substring(0, dot);
122 | string extension = iconPath.Substring(dot + 1);
123 | ZipEntry logo = null;
124 | int scale = -1;
125 | foreach (ZipEntry en in zip) {
126 | Match m = Regex.Match(en.Name, name + @"(\.scale\-(\d+))?" + @"\." + extension);
127 | if (m.Success) {
128 | if (m.Groups[1].Value == "") { // exactly matching, no scale
129 | logo = en;
130 | break;
131 | } else { // find the biggest scale
132 | int newScale = int.Parse(m.Groups[2].Value); if (newScale > scale) {
133 | logo = en;
134 | scale = newScale;
135 | }
136 | }
137 | }
138 | }
139 | if (logo != null) {
140 | //byte[] imageBytes = new byte[logo.Size];
141 | //zip.GetInputStream(logo).Read(imageBytes, 0, (int)logo.Size);
142 | return new Bitmap(zip.GetInputStream(logo));
143 | } else {
144 | throw new EntryPointNotFoundException("Cannot find Logo file: " + iconPath);
145 | }
146 | }
147 | }
148 |
149 | private bool disposed = false;
150 | protected override void Dispose(bool disposing) {
151 | if (disposed) return;
152 | if (disposing) {
153 | if (zip != null)
154 | zip.Close();
155 | }
156 | disposed = true;
157 | base.Dispose(disposing);
158 | }
159 |
160 | public void Close() {
161 | Dispose(true);
162 | }
163 |
164 | ~AppxReader() {
165 | Dispose(true);
166 | }
167 |
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/ApkShellext2/Preferences.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 21, 16
122 |
123 |
124 | 118
125 |
126 |
--------------------------------------------------------------------------------
/apkshellextTest/Form1.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace apkshellextTest
2 | {
3 | partial class Form1
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.pictureBox1 = new System.Windows.Forms.PictureBox();
32 | this.textBox1 = new System.Windows.Forms.TextBox();
33 | this.button1 = new System.Windows.Forms.Button();
34 | this.textBox2 = new System.Windows.Forms.TextBox();
35 | this.button2 = new System.Windows.Forms.Button();
36 | this.pictureBox2 = new System.Windows.Forms.PictureBox();
37 | this.textBox3 = new System.Windows.Forms.TextBox();
38 | this.textBox4 = new System.Windows.Forms.TextBox();
39 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
40 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit();
41 | this.SuspendLayout();
42 | //
43 | // pictureBox1
44 | //
45 | this.pictureBox1.Location = new System.Drawing.Point(59, 321);
46 | this.pictureBox1.Name = "pictureBox1";
47 | this.pictureBox1.Size = new System.Drawing.Size(72, 62);
48 | this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
49 | this.pictureBox1.TabIndex = 0;
50 | this.pictureBox1.TabStop = false;
51 | //
52 | // textBox1
53 | //
54 | this.textBox1.Location = new System.Drawing.Point(59, 85);
55 | this.textBox1.Name = "textBox1";
56 | this.textBox1.Size = new System.Drawing.Size(212, 20);
57 | this.textBox1.TabIndex = 1;
58 | //
59 | // button1
60 | //
61 | this.button1.Location = new System.Drawing.Point(277, 83);
62 | this.button1.Name = "button1";
63 | this.button1.Size = new System.Drawing.Size(75, 23);
64 | this.button1.TabIndex = 2;
65 | this.button1.Text = "Browse";
66 | this.button1.UseVisualStyleBackColor = true;
67 | this.button1.Click += new System.EventHandler(this.Button1_Click);
68 | //
69 | // textBox2
70 | //
71 | this.textBox2.Location = new System.Drawing.Point(381, 83);
72 | this.textBox2.Multiline = true;
73 | this.textBox2.Name = "textBox2";
74 | this.textBox2.Size = new System.Drawing.Size(293, 50);
75 | this.textBox2.TabIndex = 3;
76 | //
77 | // button2
78 | //
79 | this.button2.Location = new System.Drawing.Point(59, 247);
80 | this.button2.Name = "button2";
81 | this.button2.Size = new System.Drawing.Size(75, 23);
82 | this.button2.TabIndex = 4;
83 | this.button2.Text = "Test";
84 | this.button2.UseVisualStyleBackColor = true;
85 | this.button2.Click += new System.EventHandler(this.Button2_Click);
86 | //
87 | // pictureBox2
88 | //
89 | this.pictureBox2.Location = new System.Drawing.Point(59, 153);
90 | this.pictureBox2.Name = "pictureBox2";
91 | this.pictureBox2.Size = new System.Drawing.Size(85, 73);
92 | this.pictureBox2.TabIndex = 5;
93 | this.pictureBox2.TabStop = false;
94 | //
95 | // textBox3
96 | //
97 | this.textBox3.Location = new System.Drawing.Point(265, 166);
98 | this.textBox3.Name = "textBox3";
99 | this.textBox3.Size = new System.Drawing.Size(359, 20);
100 | this.textBox3.TabIndex = 6;
101 | //
102 | // textBox4
103 | //
104 | this.textBox4.Location = new System.Drawing.Point(265, 206);
105 | this.textBox4.Name = "textBox4";
106 | this.textBox4.Size = new System.Drawing.Size(359, 20);
107 | this.textBox4.TabIndex = 7;
108 | //
109 | // Form1
110 | //
111 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
112 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
113 | this.ClientSize = new System.Drawing.Size(710, 559);
114 | this.Controls.Add(this.textBox4);
115 | this.Controls.Add(this.textBox3);
116 | this.Controls.Add(this.pictureBox2);
117 | this.Controls.Add(this.button2);
118 | this.Controls.Add(this.textBox2);
119 | this.Controls.Add(this.button1);
120 | this.Controls.Add(this.textBox1);
121 | this.Controls.Add(this.pictureBox1);
122 | this.Name = "Form1";
123 | this.Text = "Form1";
124 | this.Load += new System.EventHandler(this.Form1_Load);
125 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
126 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit();
127 | this.ResumeLayout(false);
128 | this.PerformLayout();
129 |
130 | }
131 |
132 | #endregion
133 |
134 | private System.Windows.Forms.PictureBox pictureBox1;
135 | private System.Windows.Forms.TextBox textBox1;
136 | private System.Windows.Forms.Button button1;
137 | private System.Windows.Forms.TextBox textBox2;
138 | private System.Windows.Forms.Button button2;
139 | private System.Windows.Forms.PictureBox pictureBox2;
140 | private System.Windows.Forms.TextBox textBox3;
141 | private System.Windows.Forms.TextBox textBox4;
142 | }
143 | }
144 |
145 |
--------------------------------------------------------------------------------
/ApkShellext2/Properties/Resources.my-MM.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | အိုကေ
122 |
123 |
124 | GitHub ေပါ်ရှိ တရားဝင်စာမျက်နှာ
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
--------------------------------------------------------------------------------
/ApkShellextService/apkShellextService.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Net;
6 | using System.ServiceProcess;
7 | using System.Threading;
8 | using System.Collections.Generic;
9 |
10 | namespace ApkShellext2 {
11 | class apkShellextService : ServiceBase {
12 | public apkShellextService() {
13 | ServiceName = "ApkShellext Service";
14 | EventLog.Log = "Application";
15 |
16 | CanHandlePowerEvent = false;
17 | CanHandleSessionChangeEvent = false;
18 | CanPauseAndContinue = false;
19 | CanShutdown = false;
20 | CanStop = true;
21 | }
22 |
23 | static void Main() {
24 | ServiceBase.Run(new apkShellextService());
25 | }
26 |
27 | protected override void Dispose(bool disposing) {
28 | base.Dispose(disposing);
29 | }
30 |
31 | private WebServer ws;
32 |
33 | private static string LocalIPAddress() {
34 | var card = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()[0];
35 | var str = card.GetIPProperties().GatewayAddresses;
36 |
37 | IPHostEntry host;
38 | string localIP = "";
39 | host = Dns.GetHostEntry(Dns.GetHostName());
40 | foreach (IPAddress ip in host.AddressList) {
41 | if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) {
42 | localIP = ip.ToString();
43 | break;
44 | }
45 | }
46 | return localIP;
47 | }
48 |
49 | protected override void OnStart(string[] args) {
50 | base.OnStart(args);
51 |
52 | string[] prefixes = new string[] {
53 | @"http://*:42728",
54 | @"http://localhost:42728/",
55 | @"http://"+LocalIPAddress()+@":42728/",
56 | @"http://127.0.0.1:42728/"
57 | };
58 |
59 | ws = new WebServer(SendResponse, prefixes);
60 | ws.Run();
61 | }
62 |
63 | protected override void OnStop() {
64 | base.OnStop();
65 | ws.Stop();
66 | }
67 |
68 | ///
69 | /// OnCustomCommand(): If you need to send a command to your
70 | /// service without the need for Remoting or Sockets, use
71 | /// this method to do custom methods.
72 | ///
73 | /// Arbitrary Integer between 128 & 256
74 | protected override void OnCustomCommand(int command) {
75 | // A custom command can be sent to a service by using this method:
76 | //# int command = 128; //Some Arbitrary number between 128 & 256
77 | //# ServiceController sc = new ServiceController("NameOfService");
78 | //# sc.ExecuteCommand(command);
79 |
80 | base.OnCustomCommand(command);
81 | }
82 |
83 | Dictionary pathList = new Dictionary();
84 |
85 | public string SendResponse(HttpListenerRequest request) {
86 | if (request.QueryString["md5"] != null) {
87 | if (!pathList.ContainsKey(request.QueryString["md5"])) {
88 | pathList.Add(request.QueryString["md5"], request.QueryString["path"]);
89 | }
90 | return "";
91 | } else {
92 | string md5 = request.RawUrl.Replace(@"/", "");
93 | if (pathList.ContainsKey(md5))
94 | return pathList[md5];
95 | return "";
96 | }
97 | }
98 | }
99 |
100 |
101 | public class WebServer
102 | {
103 | private readonly HttpListener _listener = new HttpListener();
104 | private readonly Func _responderMethod;
105 |
106 | public WebServer(string[] prefixes, Func method)
107 | {
108 | if (!HttpListener.IsSupported)
109 | throw new NotSupportedException(
110 | "Needs Windows XP SP2, Server 2003 or later.");
111 |
112 | if (prefixes == null || prefixes.Length == 0)
113 | throw new ArgumentException("prefixes");
114 |
115 | // A responder method is required
116 | if (method == null)
117 | throw new ArgumentException("method");
118 |
119 | foreach (string s in prefixes)
120 | _listener.Prefixes.Add(s);
121 |
122 | _responderMethod = method;
123 | _listener.Start();
124 | }
125 |
126 | public WebServer(Func method, params string[] prefixes)
127 | : this(prefixes, method) { }
128 |
129 | public void Run()
130 | {
131 | ThreadPool.QueueUserWorkItem((o) =>
132 | {
133 | Console.WriteLine("Webserver running...");
134 | try
135 | {
136 | while (_listener.IsListening)
137 | {
138 | ThreadPool.QueueUserWorkItem((c) =>
139 | {
140 | var ctx = c as HttpListenerContext;
141 | try
142 | {
143 | string rstr = _responderMethod(ctx.Request);
144 | if (rstr != "") {
145 | string filename = Path.GetFileName(rstr);
146 | using (FileStream fs = new FileStream(rstr, FileMode.Open)) {
147 | using (BinaryReader sr = new BinaryReader(fs)) {
148 | byte[] buf = sr.ReadBytes((int)sr.BaseStream.Length);
149 | ctx.Response.ContentType = "application/octet-stream";
150 | ctx.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
151 | ctx.Response.ContentLength64 = buf.Length;
152 | ctx.Response.OutputStream.Write(buf, 0, buf.Length);
153 | }
154 | }
155 | }
156 | }
157 | catch (Exception ex){
158 | EventLog log = new EventLog();
159 | log.WriteEntry(ex.Message);
160 | } // suppress any exceptions
161 | finally
162 | {
163 | // always close the stream
164 | ctx.Response.OutputStream.Close();
165 | }
166 | }, _listener.GetContext());
167 | }
168 | }
169 | catch { } // suppress any exceptions
170 | });
171 | }
172 |
173 | public void Stop()
174 | {
175 | _listener.Stop();
176 | _listener.Close();
177 | }
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/ApkShellext2/Properties/Resources.he-IL.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 |
123 | עדכון
124 |
125 |
126 | לך לאתר הפרוייקט כדי לעדכן
127 |
128 |
129 | החלף דפוס
130 |
131 |
132 |
133 |
134 | בדוק ב-GooglePlay
135 |
136 |
137 |
138 | הרחבת מעטפת APK
139 |
140 |
141 | העדפות ועדכון
142 |
143 |
144 | שינוי שם ל {0}
145 |
146 |
147 |
148 |
149 | בדיקת גירסה חדשה...
150 |
151 |
152 |
153 | הגירסה הנוכחית: {0}
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
--------------------------------------------------------------------------------
/ApkShellext2/Properties/Resources.el-GR.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | ΟΚ
122 |
123 |
124 | Επίσημη σελίδα στο GitHub
125 |
126 |
127 |
128 | Πηγαίνετε στην σελίδα του project για ενημέρωση
129 |
130 |
131 |
132 | Δείτε το {0} στο Amazon Appstore
133 |
134 |
135 | Δείτε το {0} στο Appstore της Apple
136 |
137 |
138 | Δείτε το {0} στο Google Play
139 |
140 |
141 | Δείτε το {0} στο Microsoft Store
142 |
143 |
144 | APK Shell Extension
145 |
146 |
147 | Προτιμήσεις && Ενημέρωση
148 |
149 |
150 | Μετονομάστε σε {0}
151 |
152 |
153 | Εμφάνιση συντομέυσεων για app stores όταν έχουν επιλεχθεί πολλά αρχεία
154 |
155 |
156 |
157 | Έλεγχος για νέα έκδοση...
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 | Μεγέθυνση εικονιδίου αν τα Windows ζητήσουν για μεγαλύτερο μέγεθος
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
--------------------------------------------------------------------------------
/ApkShellext2/ApkIconHandler.cs:
--------------------------------------------------------------------------------
1 | using ApkQuickReader;
2 | using Microsoft.Win32;
3 | using SharpShell.Attributes;
4 | using SharpShell.Diagnostics;
5 | using SharpShell.Extensions;
6 | using SharpShell.ServerRegistration;
7 | using SharpShell.SharpIconHandler;
8 | using System;
9 | using System.Drawing;
10 | using System.IO;
11 | using System.Linq;
12 | using System.Runtime.InteropServices;
13 | using ApkShellext2.Properties;
14 | using System.Threading;
15 | using System.Text.RegularExpressions;
16 |
17 | namespace ApkShellext2 {
18 | ///
19 | /// This is the icon handler, not only supporting apk, but also other type of apps.
20 | ///
21 | [Guid("1F869CEE-4FDA-35D9-896F-43975A87D1F6")]
22 | [ComVisible(true)]
23 | [ClassInterface(ClassInterfaceType.None)]
24 | [COMServerAssociation(AssociationType.ClassOfExtension, ".apk")]
25 | [COMServerAssociation(AssociationType.ClassOfExtension, ".ipa")]
26 | [COMServerAssociation(AssociationType.ClassOfExtension, ".appxbundle")]
27 | [COMServerAssociation(AssociationType.ClassOfExtension, ".appx")]
28 | public class ApkIconHandler : SharpIconHandler {
29 | private Bitmap m_icon = null;
30 | protected override Icon GetIcon(bool smallIcon, uint iconSize) {
31 | if (m_icon == null) {
32 | try {
33 | using (AppPackageReader reader = AppPackageReader.Read(SelectedItemPath)) {
34 | if (reader.Type == AppPackageReader.AppType.iOSApp && Utility.GetSetting("ShowIpaIcon", "True") != "True") {
35 | m_icon = Utility.AppTypeIcon(reader.Type);
36 | } else if ((reader.Type == AppPackageReader.AppType.WindowsPhoneApp ||
37 | reader.Type == AppPackageReader.AppType.WindowsPhoneAppBundle) &&
38 | Utility.GetSetting("ShowAppxIcon", "False") != "True") {
39 | m_icon = Utility.AppTypeIcon(reader.Type);
40 | } else {
41 | m_icon = reader.getIcon(new Size((int)iconSize, (int)iconSize));
42 | }
43 | if (m_icon == null)
44 | throw new Exception("Cannot find Icon for " + Path.GetFileName(SelectedItemPath) + ", draw default");
45 | }
46 | if (Utility.GetSetting("ShowOverLayIcon") == "True")
47 | m_icon = Utility.CombineBitmap(m_icon,
48 | Utility.AppTypeIcon(AppPackageReader.getAppType(SelectedItemPath)),
49 | new Rectangle((int)(m_icon.Width * 0.05), 0, (int)(m_icon.Width * 0.95), (int)(m_icon.Height * 0.95)),
50 | new Rectangle(0, (int)m_icon.Height / 2, (int)m_icon.Width / 2, (int)m_icon.Height / 2),
51 | new Size((int)m_icon.Width, (int)m_icon.Height));
52 | } catch (Exception ex) {
53 | Log("Error in reading icon for " + Path.GetFileName(SelectedItemPath) + ", draw default : " + ex.Message);
54 | // read error, draw the default icon
55 | m_icon = Utility.AppTypeIcon(AppPackageReader.getAppType(SelectedItemPath));
56 | }
57 | }
58 |
59 | return Icon.FromHandle(Utility.ResizeBitmap(m_icon, new Size((int)iconSize, (int)iconSize)).GetHicon());
60 | }
61 |
62 | [CustomRegisterFunction]
63 | public static void postDoRegister(Type type, RegistrationType registrationType) {
64 | Console.WriteLine("Registering " + type.FullName + " Version " + type.Assembly.GetName().Version.ToString());
65 |
66 | // Todo: clean other icon handler as they were integrated
67 | //"d5ff6172-1ae5-4c4a-a207-5a2dd100891e"
68 | //"a0ac4758-12d3-4dcf-9d12-03faaa3c0a9d"
69 |
70 | #region Clean up apkshellext registry
71 | try {
72 | string oldVersionClassName = @"KKHomeProj.ApkShellExt.ApkShellExt";
73 | string oldVersionCLID = "";
74 | using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(oldVersionClassName + @"\CLSID")) {
75 | if (key != null) {
76 | Console.WriteLine("Found old version in registry, cleaning up ...");
77 | oldVersionCLID = (string)key.GetValue(null);
78 | key.Close();
79 | Registry.ClassesRoot.DeleteSubKeyTree(oldVersionClassName);
80 | }
81 | }
82 | if (oldVersionCLID != "") {
83 | using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Classes\CLSID\" + oldVersionCLID)) {
84 | if (key != null) {
85 | key.Close();
86 | Registry.LocalMachine.DeleteSubKeyTree(@"SOFTWARE\Classes\CLSID\" + oldVersionCLID);
87 | }
88 | }
89 | using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved\" + oldVersionCLID)) {
90 | if (key != null) {
91 | key.Close();
92 | Registry.LocalMachine.DeleteSubKeyTree(@"Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved\" + oldVersionCLID);
93 | }
94 | }
95 | }
96 | } catch (Exception e) {
97 | Logging.Error("Cleaning up apkshellext remaining registry items but see exception" +
98 | e.Message);
99 | }
100 | #endregion
101 |
102 | #region Clean up older versions registry
103 | try {
104 | using (RegistryKey key = Registry.ClassesRoot.OpenSubKey(@"\CLSID\" +
105 | type.GUID.ToRegistryString() + @"\InprocServer32")) {
106 | if (key != null && key.GetSubKeyNames().Count() != 0) {
107 | Console.WriteLine("Found old version in registry, cleaning up ...");
108 | foreach (var k in key.GetSubKeyNames()) {
109 | if (k != type.Assembly.GetName().Version.ToString()) {
110 | Registry.ClassesRoot.DeleteSubKeyTree(@"\CLSID\" +
111 | type.GUID.ToRegistryString() + @"\InprocServer32\" + k);
112 | }
113 | }
114 | }
115 | }
116 | } catch (Exception e) {
117 | Logging.Error("Cleaning up older version but see exception. "
118 | + e.Message);
119 | }
120 |
121 | #endregion
122 |
123 | #region restore the old settings from registry
124 | // This is not possible as at this time, the user is admin, which is different when running explorer, so comment this out for now.
125 | //Settings.Default.ShowAppStoreWhenMultiSelected = Utility.getRegistrySetting(Utility.keyMultiSelectShowStore) == 1;
126 | //Settings.Default.ShowGooglePlay = Utility.getRegistrySetting(Utility.keyShowGooglePlay) == 1;
127 | //Settings.Default.ShowOverLayIcon = Utility.getRegistrySetting(Utility.keyShowOverlay) == 1;
128 | //Settings.Default.ShowIpaIcon = Utility.getRegistrySetting(Utility.keyShowIpaIcon) == 1;
129 | //Settings.Default.ShowAppxIcon = Utility.getRegistrySetting(Utility.keyShowAppxIcon) == 1;
130 | //Settings.Default.ShowMenuIcon = Utility.getRegistrySetting(Utility.keyShowMenuIcon) == 1;
131 |
132 | //if (Utility.getRegistrySetting(Utility.keyRenameWithVersionCode) == 1) {
133 | // Settings.Default.RenamePattern = Resources.strRenamePatternDefault + "_" + Resources.varRevision;
134 | //}
135 |
136 | //int lang = Utility.getRegistrySetting(Utility.keyLanguage, -1);
137 | //if (lang != -1) {
138 | // Settings.Default.Language = lang;
139 | //}
140 | //Settings.Default.Save();
141 | #endregion
142 |
143 | #region Enable debug log
144 | #if DEBUG
145 | using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE", true).CreateSubKey(@"SharpShell", RegistryKeyPermissionCheck.ReadWriteSubTree)) {
146 | key.SetValue("LoggingMode", 4);
147 | key.SetValue("LogPath", @"%AppData%\apkshellext.log",RegistryValueKind.ExpandString);
148 | }
149 | #endif
150 | #endregion
151 | }
152 |
153 | protected override void Log(string message) {
154 | Utility.Log(this, Path.GetFileName(SelectedItemPath), message);
155 | }
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/ApkShellext2/IpaReader.cs:
--------------------------------------------------------------------------------
1 | using PlistCS;
2 | using PNGDecrush;
3 | using SharpShell.Attributes;
4 | using SharpShell.Extensions;
5 | using SharpShell.Diagnostics;
6 | using SharpShell.Exceptions;
7 | using SharpShell.ServerRegistration;
8 | using SharpShell.SharpIconHandler;
9 | using System;
10 | using System.Collections.Generic;
11 | using System.Drawing;
12 | using System.IO;
13 | using System.Linq;
14 | using System.Runtime.InteropServices;
15 | using System.Text;
16 | using System.Threading.Tasks;
17 | using ICSharpCode.SharpZipLib.Zip;
18 | using Microsoft.Win32;
19 | using System.Text.RegularExpressions;
20 | using Ionic.Zlib;
21 |
22 | namespace ApkShellext2
23 | {
24 | public class IpaReader : AppPackageReader
25 | {
26 | private string strAppRoot;
27 | private Dictionary infoPlistDic;
28 | private Dictionary itunesMetadataDic;
29 | private ZipFile zip;
30 |
31 | private const string iTunesMetadataPath = @"iTunesMetadata.plist";
32 | private const string infoPlistPath = @"(Payload/.*\.app/)Info\.plist";
33 | private const string CFBundleIcons = @"CFBundleIcons";
34 | private const string CFBundlePrimaryIcon = @"CFBundlePrimaryIcon";
35 | private const string CFBundleIconFile = @"CFBundleIconFile";
36 | private const string CFBundleIconFiles = @"CFBundleIconFiles";
37 | private const string CFBundleDisplayName = @"CFBundleDisplayName";
38 | private const string FacebookDisplayName = @"FacebookDisplayName";
39 | private const string CFBundleIdentifier = @"CFBundleIdentifier";
40 | private const string CFBundleShortVersionString = @"CFBundleShortVersionString";
41 | private const string CFBundleVersion = @"CFBundleVersion";
42 | private const string CFBundleResourceSpecification = @"CFBundleResourceSpecification";
43 |
44 | public const string flagAppId = @"itemId";
45 | public const string flagCopyright = @"copyright";
46 |
47 | public IpaReader(string path) {
48 | FileName = path;
49 | openStream(new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read));
50 | }
51 |
52 | public IpaReader(Stream stream) {
53 | openStream(stream);
54 | }
55 |
56 | private void openStream(Stream stream) {
57 | zip = new ZipFile(stream);
58 | ZipEntry infoPlist = null;
59 | foreach (ZipEntry en in zip) {
60 | Match m = Regex.Match(en.Name, infoPlistPath);
61 | if (m.Success) {
62 | strAppRoot = m.Groups[1].Value;
63 | infoPlist = en;
64 | break;
65 | }
66 | }
67 |
68 | if (infoPlist == null) {
69 | throw new EntryPointNotFoundException("cannot find info.plist");
70 | }
71 |
72 | byte[] infoBytes = new byte[infoPlist.Size];
73 | zip.GetInputStream(infoPlist).Read(infoBytes, 0, (int)infoPlist.Size);
74 |
75 | infoPlistDic = (Dictionary)Plist.readPlist(infoBytes);
76 | }
77 |
78 | public string[] getStrings(Dictionary dic, string[] keys) {
79 | for (int i = 0; i < keys.Length - 1; i++) {
80 | if (dic.ContainsKey(keys[i])) {
81 | dic = (Dictionary)dic[keys[i]];
82 | } else {
83 | return new string[] { };
84 | //throw new Exception("Given ID is not valid");
85 | }
86 | }
87 | if (dic.ContainsKey(keys[keys.Length - 1])) {
88 | if (dic[keys[keys.Length - 1]] is string) {
89 | return new string[] { dic[keys[keys.Length - 1]] as string };
90 | }
91 | if (dic[keys[keys.Length - 1]] is int) {
92 | return new string[] { dic[keys[keys.Length - 1]].ToString() };
93 | } else { // is list
94 | object[] arr = ((List