mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-12 02:07:19 +10:00
Compare commits
132 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32a48c5e41 | ||
|
|
ed0920b21b | ||
|
|
5378e3d54b | ||
|
|
87beb7af51 | ||
|
|
4993fd9968 | ||
|
|
1df420c437 | ||
|
|
994a53a00b | ||
|
|
179ae49d20 | ||
|
|
c0dac1ac7f | ||
|
|
687e18b80c | ||
|
|
598007f177 | ||
|
|
7552ffed35 | ||
|
|
8227689e6a | ||
|
|
d170a9196d | ||
|
|
f5edaf2f23 | ||
|
|
1ef31d54c8 | ||
|
|
0cabf43e17 | ||
|
|
f98c57ef3a | ||
|
|
84f89f3464 | ||
|
|
f36351c009 | ||
|
|
f44589009c | ||
|
|
868fb8b3e8 | ||
|
|
e1d89a022e | ||
|
|
10aa419e98 | ||
|
|
db20b3bc4e | ||
|
|
de33c438b6 | ||
|
|
1f9635255e | ||
|
|
3329058840 | ||
|
|
ee5854c5a1 | ||
|
|
471ce85cdf | ||
|
|
f28e3fe24c | ||
|
|
169815e88a | ||
|
|
2c6391804e | ||
|
|
fa65d40f3e | ||
|
|
2fd73eab85 | ||
|
|
9111c019ff | ||
|
|
200262d3ca | ||
|
|
0f7c4be17e | ||
|
|
ded9ea9293 | ||
|
|
b131251a3b | ||
|
|
f563f97f12 | ||
|
|
19757502ae | ||
|
|
c28c09973e | ||
|
|
8dd01a67e9 | ||
|
|
84a28db8cf | ||
|
|
b315782df6 | ||
|
|
9ba3b875da | ||
|
|
9ae2e886bd | ||
|
|
0926da3f27 | ||
|
|
4355ce4d13 | ||
|
|
90d16151f4 | ||
|
|
4bddb96052 | ||
|
|
368efeb2f0 | ||
|
|
8e8a0453c4 | ||
|
|
e58b47926c | ||
|
|
6d40668c1a | ||
|
|
71c8d76593 | ||
|
|
76ce97370f | ||
|
|
c4eaa4ad45 | ||
|
|
9edccede4e | ||
|
|
1d7359ebdd | ||
|
|
fafff1bc5c | ||
|
|
be599991b8 | ||
|
|
48954e5206 | ||
|
|
a7c22adc05 | ||
|
|
be643a9935 | ||
|
|
64f3958d7f | ||
|
|
b562d5b5ba | ||
|
|
bf54d5a531 | ||
|
|
f9f4db3f6c | ||
|
|
880a834296 | ||
|
|
e47813765a | ||
|
|
2f0d1dc27f | ||
|
|
3c35a8acaa | ||
|
|
27e604892d | ||
|
|
1c05d8a379 | ||
|
|
43983a2c87 | ||
|
|
df0d14e282 | ||
|
|
419498bef8 | ||
|
|
4118efa4b6 | ||
|
|
300b1ba55a | ||
|
|
ecde1c8d80 | ||
|
|
79674b639b | ||
|
|
0073da9c8e | ||
|
|
a472ddba73 | ||
|
|
b2633b37e5 | ||
|
|
fe6a9a186b | ||
|
|
2e45bb1cd9 | ||
|
|
ccf6cfd66c | ||
|
|
34895b9edd | ||
|
|
745a89fa9c | ||
|
|
a3ff273405 | ||
|
|
ca0b7dbcbb | ||
|
|
e49f9db426 | ||
|
|
2cdc310598 | ||
|
|
fe19eaf169 | ||
|
|
d85fbb8de8 | ||
|
|
d91948eaff | ||
|
|
0c87a2cdcd | ||
|
|
5a404a55e3 | ||
|
|
503ece1c64 | ||
|
|
75cb72964d | ||
|
|
7483ed6930 | ||
|
|
5b7b41a40c | ||
|
|
2e6214a35a | ||
|
|
3ab9761705 | ||
|
|
521b13563e | ||
|
|
319d13c2b1 | ||
|
|
4d10da5630 | ||
|
|
621c6fcfd3 | ||
|
|
4cf0a0a55d | ||
|
|
470cbedde1 | ||
|
|
4668f09dac | ||
|
|
a40ff21fe6 | ||
|
|
052042132f | ||
|
|
5518101cfc | ||
|
|
086dc5cd45 | ||
|
|
975c8ee9e3 | ||
|
|
1c831854b3 | ||
|
|
7c10123c8f | ||
|
|
fc66b6de72 | ||
|
|
85b0d2b5b9 | ||
|
|
0e8bc66ddf | ||
|
|
5c18f75cb6 | ||
|
|
46e9083f90 | ||
|
|
6b59bdcf17 | ||
|
|
15ca1f928c | ||
|
|
8e7a241b98 | ||
|
|
c0c39b9379 | ||
|
|
1bed599fae | ||
|
|
6cc3aa9e16 | ||
|
|
d1813637c5 |
10
.gitignore
vendored
10
.gitignore
vendored
@@ -240,3 +240,13 @@ ModelManifest.xml
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# Generated Setup
|
||||
[Gg]enerated/
|
||||
|
||||
# Setup Build Files
|
||||
[Oo]thers/
|
||||
|
||||
# Arm Build Files
|
||||
package.zip
|
||||
ArmPackage.zip
|
||||
@@ -1,15 +1,10 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.14.37012.4 d17.14
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pkgread", "pkgread\pkgread.vcxproj", "{A7753282-AA16-43D9-8ACA-7065239DD702}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "priformatcli", "..\priformatcli\priformatcli\priformatcli.vcxproj", "{33D91B58-1981-4A3C-B4D1-86EE406CDE12}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D} = {EF4012D4-EF08-499C-B803-177739350B2D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pkgmgr", "pkgmgr\pkgmgr.vcxproj", "{8EAC0230-4990-4E41-8E0F-D641D1561396}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "notice", "notice\notice.vcxproj", "{798ED492-EECE-457D-8FD8-129DA93CE126}"
|
||||
@@ -20,16 +15,19 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "certmgr", "certmgr\certmgr.
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "appinstaller", "appinstaller\appinstaller.vcxproj", "{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396} = {8EAC0230-4990-4E41-8E0F-D641D1561396}
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12} = {33D91B58-1981-4A3C-B4D1-86EE406CDE12}
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702} = {A7753282-AA16-43D9-8ACA-7065239DD702}
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126} = {798ED492-EECE-457D-8FD8-129DA93CE126}
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396} = {8EAC0230-4990-4E41-8E0F-D641D1561396}
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702} = {A7753282-AA16-43D9-8ACA-7065239DD702}
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C} = {B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0} = {E04CCAB9-35DB-495C-A279-5B483C707CD0}
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D} = {EF4012D4-EF08-499C-B803-177739350B2D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "settings", "settings\settings.vcxproj", "{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00} = {3AE2A022-ED83-41F1-948A-12A7593CBD00}
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C} = {B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reslib", "reslib\reslib.vcxproj", "{3AE2A022-ED83-41F1-948A-12A7593CBD00}"
|
||||
@@ -39,116 +37,257 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shortcut", "shortcut\shortc
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126} = {798ED492-EECE-457D-8FD8-129DA93CE126}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "desktopini", "desktopini\desktopini.vcxproj", "{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "priformatcli", "priformatcli\priformatcli.vcxproj", "{33D91B58-1981-4A3C-B4D1-86EE406CDE12}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D} = {EF4012D4-EF08-499C-B803-177739350B2D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Update", "Update\Update.csproj", "{512BF866-1AA0-4169-A7D6-D2776B5D731E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrivateInit", "PrivateInit\PrivateInit.csproj", "{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppxPackage", "AppxPackage\AppxPackage.csproj", "{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12} = {33D91B58-1981-4A3C-B4D1-86EE406CDE12}
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396} = {8EAC0230-4990-4E41-8E0F-D641D1561396}
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702} = {A7753282-AA16-43D9-8ACA-7065239DD702}
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D} = {EF4012D4-EF08-499C-B803-177739350B2D}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataUtils", "DataUtils\DataUtils.csproj", "{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bridge", "Bridge\Bridge.csproj", "{3C2F5446-33F0-41D5-813A-64A94AA474AF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WAShell", "WAShell\WAShell.csproj", "{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Manager", "Manager\Manager.csproj", "{DC074727-72E4-43C5-BAAF-E0D548104797}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00} = {3AE2A022-ED83-41F1-948A-12A7593CBD00}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IEHelper", "IEHelper\IEHelper.vcxproj", "{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernNotice", "ModernNotice\ModernNotice.csproj", "{C5587B6E-19C4-4484-AA97-5C20FBB07E43}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Launch", "Launch\Launch.csproj", "{F0288B24-7B84-42A5-9A92-2E16A012E4DE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reader", "Reader\Reader.csproj", "{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pugixml", "pugixml\pugixml.vcxproj", "{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PkgCLI", "PkgCLI\PkgCLI.csproj", "{8D333AF6-E901-4301-B3EE-923088E81062}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|ARM = Release|ARM
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|x64.Build.0 = Debug|x64
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|x86.Build.0 = Debug|Win32
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x64.ActiveCfg = Release|x64
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x64.Build.0 = Release|x64
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|ARM.Build.0 = Release|ARM
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x86.ActiveCfg = Release|Win32
|
||||
{A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x86.Build.0 = Release|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x64.Build.0 = Debug|x64
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x86.Build.0 = Debug|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x64.ActiveCfg = Release|x64
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x64.Build.0 = Release|x64
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x86.ActiveCfg = Release|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x86.Build.0 = Release|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|x64.ActiveCfg = Debug|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|x86.Build.0 = Debug|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|x64.ActiveCfg = Release|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|ARM.Build.0 = Release|ARM
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|x86.ActiveCfg = Release|Win32
|
||||
{8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|x86.Build.0 = Release|Win32
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|x64.ActiveCfg = Debug|Win32
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|x86.Build.0 = Debug|Win32
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Release|x64.ActiveCfg = Release|Win32
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Release|ARM.Build.0 = Release|ARM
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Release|x86.ActiveCfg = Release|Win32
|
||||
{798ED492-EECE-457D-8FD8-129DA93CE126}.Release|x86.Build.0 = Release|Win32
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Debug|x64.Build.0 = Debug|x64
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Debug|x86.Build.0 = Debug|x86
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|x86.ActiveCfg = Release|x86
|
||||
{EF4012D4-EF08-499C-B803-177739350B2D}.Release|x86.Build.0 = Release|x86
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Debug|x86.Build.0 = Debug|Win32
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Release|x64.ActiveCfg = Release|x64
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Release|x64.Build.0 = Release|x64
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Release|ARM.Build.0 = Release|ARM
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Release|x86.ActiveCfg = Release|Win32
|
||||
{E04CCAB9-35DB-495C-A279-5B483C707CD0}.Release|x86.Build.0 = Release|Win32
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Debug|x64.Build.0 = Debug|x64
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Debug|x86.Build.0 = Debug|Win32
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Release|x64.ActiveCfg = Release|x64
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Release|x64.Build.0 = Release|x64
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Release|ARM.Build.0 = Release|ARM
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Release|x86.ActiveCfg = Release|Win32
|
||||
{F0C84812-0CDF-4AA0-A0F8-F37AC833F39B}.Release|x86.Build.0 = Release|Win32
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Debug|x64.Build.0 = Debug|x64
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Debug|x86.Build.0 = Debug|Win32
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|x64.ActiveCfg = Release|x64
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|x64.Build.0 = Release|x64
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|ARM.Build.0 = Release|ARM
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|x86.ActiveCfg = Release|Win32
|
||||
{AD25497F-A15F-4DFF-AC7A-B8ABF5F411D6}.Release|x86.Build.0 = Release|Win32
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|x64.Build.0 = Debug|x64
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Debug|x86.Build.0 = Debug|Win32
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|x64.ActiveCfg = Release|x64
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|x64.Build.0 = Release|x64
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|ARM.Build.0 = Release|ARM
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|x86.ActiveCfg = Release|Win32
|
||||
{3AE2A022-ED83-41F1-948A-12A7593CBD00}.Release|x86.Build.0 = Release|Win32
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Debug|x64.Build.0 = Debug|x64
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Debug|x86.Build.0 = Debug|Win32
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|x64.ActiveCfg = Release|x64
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|x64.Build.0 = Release|x64
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|ARM.Build.0 = Release|ARM
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|x86.ActiveCfg = Release|Win32
|
||||
{18E0189B-F3F1-4CB2-A3AF-5606ADD5E279}.Release|x86.Build.0 = Release|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Debug|x86.Build.0 = Debug|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Release|ARM.Build.0 = Release|ARM
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Release|x86.ActiveCfg = Release|Win32
|
||||
{7A05E943-6E0A-4F57-8BD7-BE90F44DCAD7}.Release|x86.Build.0 = Release|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Debug|x86.Build.0 = Debug|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|ARM.Build.0 = Release|ARM
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x86.ActiveCfg = Release|Win32
|
||||
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x86.Build.0 = Release|Win32
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Debug|x86.Build.0 = Debug|x86
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Release|x86.ActiveCfg = Release|x86
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Release|x86.Build.0 = Release|x86
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|x86.Build.0 = Debug|x86
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|x86.ActiveCfg = Release|x86
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|x86.Build.0 = Release|x86
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Debug|x86.Build.0 = Debug|x86
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Release|x86.ActiveCfg = Release|x86
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Release|x86.Build.0 = Release|x86
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|x86.Build.0 = Debug|x86
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|x86.ActiveCfg = Release|x86
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|x86.Build.0 = Release|x86
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|x86.Build.0 = Debug|x86
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|x86.ActiveCfg = Release|x86
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|x86.Build.0 = Release|x86
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|x86.Build.0 = Debug|x86
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|x86.ActiveCfg = Release|x86
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|x86.Build.0 = Release|x86
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Debug|x86.Build.0 = Debug|x86
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Release|x86.ActiveCfg = Release|x86
|
||||
{DC074727-72E4-43C5-BAAF-E0D548104797}.Release|x86.Build.0 = Release|x86
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Debug|x86.Build.0 = Debug|Win32
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Release|ARM.Build.0 = Release|ARM
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Release|x86.ActiveCfg = Release|Win32
|
||||
{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}.Release|x86.Build.0 = Release|Win32
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Debug|x86.Build.0 = Debug|x86
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Release|x86.ActiveCfg = Release|x86
|
||||
{C5587B6E-19C4-4484-AA97-5C20FBB07E43}.Release|x86.Build.0 = Release|x86
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Debug|x86.Build.0 = Debug|x86
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Release|x86.ActiveCfg = Release|x86
|
||||
{F0288B24-7B84-42A5-9A92-2E16A012E4DE}.Release|x86.Build.0 = Release|x86
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Debug|x86.Build.0 = Debug|x86
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Release|x86.ActiveCfg = Release|x86
|
||||
{26B3C19D-6182-4DB5-8B69-EE098A0FD3BB}.Release|x86.Build.0 = Release|x86
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Debug|x86.Build.0 = Debug|Win32
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Release|ARM.Build.0 = Release|ARM
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{B1DF139F-CEF1-404F-8255-31EF4BF0EC4C}.Release|x86.Build.0 = Release|Win32
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Debug|x86.Build.0 = Debug|x86
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Release|x86.ActiveCfg = Release|x86
|
||||
{8D333AF6-E901-4301-B3EE-923088E81062}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5FAD9D1A-D291-492A-956A-94422761AA8E}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
96
AppxPackage/AppxPackage.csproj
Normal file
96
AppxPackage/AppxPackage.csproj
Normal file
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>AppxPackage</RootNamespace>
|
||||
<AssemblyName>AppxPackage</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="DataInterface.cs" />
|
||||
<Compile Include="ManifestReader.cs" />
|
||||
<Compile Include="PackageManager.cs" />
|
||||
<Compile Include="PackageReader.cs" />
|
||||
<Compile Include="PkgMgrNative.cs" />
|
||||
<Compile Include="PkgReadNative.cs" />
|
||||
<Compile Include="PriFileNative.cs" />
|
||||
<Compile Include="PriReader.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Utils.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DataUtils\DataUtils.csproj">
|
||||
<Project>{ffd3fd52-37a8-4f43-883c-de8d996cb0e0}</Project>
|
||||
<Name>DataUtils</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
261
AppxPackage/DataInterface.cs
Normal file
261
AppxPackage/DataInterface.cs
Normal file
@@ -0,0 +1,261 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
|
||||
namespace AppxPackage
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class Ref<T>
|
||||
{
|
||||
private T _value;
|
||||
public Ref ()
|
||||
{
|
||||
_value = default (T);
|
||||
}
|
||||
public Ref (T value)
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
/// <summary>
|
||||
/// 模拟 & 引用访问
|
||||
/// </summary>
|
||||
public T Value
|
||||
{
|
||||
get { return _value; }
|
||||
set { _value = value; }
|
||||
}
|
||||
/// <summary>
|
||||
/// 直接赋值(像 *ref = value)
|
||||
/// </summary>
|
||||
public void Set (T value)
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
/// <summary>
|
||||
/// 取值(像 value = *ref)
|
||||
/// </summary>
|
||||
public T Get ()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
public override string ToString ()
|
||||
{
|
||||
return _value == null ? string.Empty : _value.ToString ();
|
||||
}
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
return _value == null ? 0 : _value.GetHashCode ();
|
||||
}
|
||||
public override bool Equals (object obj)
|
||||
{
|
||||
if (ReferenceEquals (this, obj)) return true;
|
||||
if (obj is Ref<T>) return Equals (_value, ((Ref<T>)obj)._value);
|
||||
return Equals (_value, obj);
|
||||
}
|
||||
public static implicit operator T (Ref<T> r)
|
||||
{
|
||||
return r == null ? default (T) : r._value;
|
||||
}
|
||||
public static implicit operator Ref<T>(T value)
|
||||
{
|
||||
return new Ref<T> (value);
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace AppxPackage.Info
|
||||
{
|
||||
public enum Architecture
|
||||
{
|
||||
x86 = 0,
|
||||
ARM = 5,
|
||||
x64 = 9,
|
||||
Neutral = 11,
|
||||
ARM64 = 12,
|
||||
Unknown = ushort.MaxValue
|
||||
};
|
||||
public enum PackageType
|
||||
{
|
||||
Unknown = 0,
|
||||
Appx = 1,
|
||||
Bundle = 2
|
||||
};
|
||||
public enum PackageRole
|
||||
{
|
||||
Unknown = 0,
|
||||
Application = 1,
|
||||
Framework = 2,
|
||||
Resource = 3
|
||||
};
|
||||
public interface IIdentity
|
||||
{
|
||||
string Name { get; }
|
||||
string Publisher { get; }
|
||||
string FamilyName { get; }
|
||||
string FullName { get; }
|
||||
string ResourceId { get; }
|
||||
DataUtils.Version Version { get; }
|
||||
List<Architecture> ProcessArchitecture { get; }
|
||||
}
|
||||
public interface IProperties
|
||||
{
|
||||
string DisplayName { get; }
|
||||
string Description { get; }
|
||||
string Publisher { get; }
|
||||
string Logo { get; }
|
||||
string LogoBase64 { get; }
|
||||
bool Framework { get; }
|
||||
bool ResourcePackage { get; }
|
||||
}
|
||||
public interface ICapabilities
|
||||
{
|
||||
List<string> Capabilities { get; }
|
||||
List<string> DeviceCapabilities { get; }
|
||||
}
|
||||
public class DependencyInfo
|
||||
{
|
||||
public string Name { get; private set; } = "";
|
||||
public string Publisher { get; private set; } = "";
|
||||
public DataUtils.Version Version { get; private set; } = new DataUtils.Version ();
|
||||
public DependencyInfo (string name, string publisher, DataUtils.Version ver)
|
||||
{
|
||||
Name = name;
|
||||
Publisher = publisher;
|
||||
Version = ver;
|
||||
}
|
||||
public DependencyInfo (string name, DataUtils.Version ver): this (name, "", ver) { }
|
||||
public DependencyInfo () { }
|
||||
}
|
||||
public enum DXFeatureLevel
|
||||
{
|
||||
Unspecified = 0,
|
||||
Level9 = 0x1,
|
||||
Level10 = 0x2,
|
||||
Level11 = 0x4,
|
||||
Level12 = 0x8
|
||||
}
|
||||
public interface IResources
|
||||
{
|
||||
List <string> Languages { get; }
|
||||
List <int> Languages_LCID { get; }
|
||||
List <int> Scales { get; }
|
||||
List <DXFeatureLevel> DXFeatures { get; }
|
||||
}
|
||||
public interface IPrerequisites
|
||||
{
|
||||
DataUtils.Version OSMinVersion { get; }
|
||||
DataUtils.Version OSMaxVersionTested { get; }
|
||||
string OSMinVersionDescription { get; }
|
||||
string OSMaxVersionDescription { get; }
|
||||
}
|
||||
[Serializable]
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
public struct HRESULT: IEquatable<HRESULT>
|
||||
{
|
||||
private readonly int _value;
|
||||
public HRESULT (int value)
|
||||
{
|
||||
_value = value;
|
||||
}
|
||||
public int Value
|
||||
{
|
||||
get { return _value; }
|
||||
}
|
||||
public bool Succeeded
|
||||
{
|
||||
get { return _value >= 0; }
|
||||
}
|
||||
public bool Failed
|
||||
{
|
||||
get { return _value < 0; }
|
||||
}
|
||||
public void ThrowIfFailed ()
|
||||
{
|
||||
if (Failed)
|
||||
Marshal.ThrowExceptionForHR (_value);
|
||||
}
|
||||
public Exception GetException ()
|
||||
{
|
||||
return Failed ? Marshal.GetExceptionForHR (_value) : null;
|
||||
}
|
||||
public override string ToString ()
|
||||
{
|
||||
return string.Format ("HRESULT 0x{0:X8}", _value);
|
||||
}
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
public override bool Equals (object obj)
|
||||
{
|
||||
if (obj is HRESULT) return Equals ((HRESULT)obj);
|
||||
return false;
|
||||
}
|
||||
public bool Equals (HRESULT other)
|
||||
{
|
||||
return _value == other._value;
|
||||
}
|
||||
public static implicit operator int (HRESULT hr)
|
||||
{
|
||||
return hr._value;
|
||||
}
|
||||
public static implicit operator HRESULT (int value)
|
||||
{
|
||||
return new HRESULT (value);
|
||||
}
|
||||
public static bool operator == (HRESULT a, HRESULT b)
|
||||
{
|
||||
return a._value == b._value;
|
||||
}
|
||||
public static bool operator != (HRESULT a, HRESULT b)
|
||||
{
|
||||
return a._value != b._value;
|
||||
}
|
||||
public static bool operator >= (HRESULT a, int value)
|
||||
{
|
||||
return a._value >= value;
|
||||
}
|
||||
public static bool operator <= (HRESULT a, int value)
|
||||
{
|
||||
return a._value <= value;
|
||||
}
|
||||
public static bool operator > (HRESULT a, int value)
|
||||
{
|
||||
return a._value > value;
|
||||
}
|
||||
public static bool operator < (HRESULT a, int value)
|
||||
{
|
||||
return a._value < value;
|
||||
}
|
||||
}
|
||||
public static class JSHelper
|
||||
{
|
||||
public static void CallJS (object jsFunc, params object [] args)
|
||||
{
|
||||
if (jsFunc == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
// 这里固定第一个参数为 thisArg(比如 1)
|
||||
object [] realArgs = new object [args.Length + 1];
|
||||
realArgs [0] = jsFunc; // thisArg
|
||||
Array.Copy (args, 0, realArgs, 1, args.Length);
|
||||
|
||||
jsFunc.GetType ().InvokeMember (
|
||||
"call",
|
||||
BindingFlags.InvokeMethod,
|
||||
null,
|
||||
jsFunc,
|
||||
realArgs
|
||||
);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore errors in callback invocation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1026
AppxPackage/ManifestReader.cs
Normal file
1026
AppxPackage/ManifestReader.cs
Normal file
File diff suppressed because it is too large
Load Diff
619
AppxPackage/PackageManager.cs
Normal file
619
AppxPackage/PackageManager.cs
Normal file
@@ -0,0 +1,619 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using AppxPackage.Info;
|
||||
using NativeWrappers;
|
||||
using System.Runtime.InteropServices;
|
||||
using DataUtils;
|
||||
using System.Net;
|
||||
using System.IO;
|
||||
|
||||
namespace AppxPackage
|
||||
{
|
||||
public enum DeploymentOptions
|
||||
{
|
||||
None = 0,
|
||||
ForceAppShutdown = 0x00000001,
|
||||
DevelopmentMode = 0x00000002,
|
||||
InstallAllResources = 0x00000020
|
||||
};
|
||||
public enum PackageStatus
|
||||
{
|
||||
Normal = 0,
|
||||
LicenseInvalid = 1,
|
||||
Modified = 2,
|
||||
Tampered = 3
|
||||
};
|
||||
public static class ImageUriToBase64
|
||||
{
|
||||
public static string ConvertToDataUri (string uriString)
|
||||
{
|
||||
if (string.IsNullOrEmpty (uriString)) throw new ArgumentNullException ("uriString");
|
||||
Uri uri = new Uri (uriString, UriKind.Absolute);
|
||||
byte [] data;
|
||||
string mime;
|
||||
if (uri.IsFile)
|
||||
{
|
||||
string path = uri.LocalPath;
|
||||
data = File.ReadAllBytes (path);
|
||||
mime = GetMimeFromExtension (Path.GetExtension (path));
|
||||
}
|
||||
else
|
||||
{
|
||||
using (WebClient wc = new WebClient ())
|
||||
{
|
||||
data = wc.DownloadData (uri);
|
||||
mime = GetMimeFromExtension (Path.GetExtension (uri.AbsolutePath));
|
||||
}
|
||||
}
|
||||
string base64 = Convert.ToBase64String (data);
|
||||
return "data:" + mime + ";base64," + base64;
|
||||
}
|
||||
private static string GetMimeFromExtension (string ext)
|
||||
{
|
||||
if (string.IsNullOrEmpty (ext)) return "application/octet-stream";
|
||||
switch (ext.ToLowerInvariant ())
|
||||
{
|
||||
case ".png": return "image/png";
|
||||
case ".jpg":
|
||||
case ".jpeg": return "image/jpeg";
|
||||
case ".gif": return "image/gif";
|
||||
case ".bmp": return "image/bmp";
|
||||
case ".webp": return "image/webp";
|
||||
case ".svg": return "image/svg+xml";
|
||||
default: return "application/octet-stream";
|
||||
}
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class PMIdentity: IIdentity
|
||||
{
|
||||
private string name = "";
|
||||
private string publisher = "";
|
||||
private DataUtils.Version version = new DataUtils.Version ();
|
||||
private IEnumerable<Architecture> archs;
|
||||
private string familyName = "";
|
||||
private string fullName = "";
|
||||
private string resourceId = "";
|
||||
private string publisherId = "";
|
||||
public PMIdentity (string _name, string _publisher, DataUtils.Version _ver, IEnumerable<Architecture> _archs, string _family, string _full, string _resid, string _publisherId)
|
||||
{
|
||||
name = _name;
|
||||
publisher = _publisher;
|
||||
version = _ver;
|
||||
archs = _archs ?? new List<Architecture> ();
|
||||
familyName = _family;
|
||||
fullName = _full;
|
||||
resourceId = _resid;
|
||||
publisherId = _publisherId;
|
||||
}
|
||||
public PMIdentity (PackageManageHelper.FIND_PACKAGE_ID pkgId) :
|
||||
this (
|
||||
Marshal.PtrToStringUni (pkgId.lpName),
|
||||
Marshal.PtrToStringUni (pkgId.lpPublisher),
|
||||
new DataUtils.Version (pkgId.qwVersion),
|
||||
new Architecture [] { (Architecture)pkgId.wProcessArchitecture },
|
||||
Marshal.PtrToStringUni (pkgId.lpFamilyName),
|
||||
Marshal.PtrToStringUni (pkgId.lpFullName),
|
||||
Marshal.PtrToStringUni (pkgId.lpResourceId),
|
||||
Marshal.PtrToStringUni (pkgId.lpPublisherId)
|
||||
)
|
||||
{ }
|
||||
public string FamilyName => familyName;
|
||||
public string FullName => fullName;
|
||||
public string Name => name;
|
||||
public List<Architecture> ProcessArchitecture => archs.ToList ();
|
||||
public string Publisher => publisher;
|
||||
public string PublisherId => publisherId;
|
||||
public string ResourceId => resourceId;
|
||||
public DataUtils.Version Version => version;
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class PMProperties: IProperties
|
||||
{
|
||||
private string desc = "";
|
||||
private string displayName = "";
|
||||
private bool framework = false;
|
||||
private string logo = "";
|
||||
private string publisher = "";
|
||||
private bool isres = false;
|
||||
public PMProperties (string _name, string _pub, string _desc, string _logo, bool _fw, bool _res)
|
||||
{
|
||||
desc = _desc;
|
||||
displayName = _name;
|
||||
framework = _fw;
|
||||
logo = _logo;
|
||||
publisher = _pub;
|
||||
isres = _res;
|
||||
}
|
||||
public PMProperties (PackageManageHelper.FIND_PACKAGE_PROPERTIES prop) :
|
||||
this (
|
||||
Marshal.PtrToStringUni (prop.lpDisplayName),
|
||||
Marshal.PtrToStringUni (prop.lpPublisher),
|
||||
Marshal.PtrToStringUni (prop.lpDescription),
|
||||
Marshal.PtrToStringUni (prop.lpLogoUri),
|
||||
prop.bIsFramework,
|
||||
prop.bIsResourcePackage
|
||||
)
|
||||
{ }
|
||||
public string Description => desc;
|
||||
public string DisplayName => displayName;
|
||||
public bool Framework => framework;
|
||||
public string Logo => logo;
|
||||
public string LogoBase64
|
||||
{
|
||||
get
|
||||
{
|
||||
try { return ImageUriToBase64.ConvertToDataUri (Logo); }
|
||||
catch (Exception) { }
|
||||
return "";
|
||||
}
|
||||
}
|
||||
public string Publisher => publisher;
|
||||
public bool ResourcePackage => isres;
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class PMPackageInfo
|
||||
{
|
||||
public PMIdentity Identity { get; private set; }
|
||||
public PMProperties Properties { get; private set; }
|
||||
public bool IsBundle { get; private set; }
|
||||
public bool DevelopmentMode { get; private set; }
|
||||
public string InstallLocation { get; private set; }
|
||||
public List<string> Users { get; private set; }
|
||||
public List<string> SIDs { get; private set; }
|
||||
public PMPackageInfo (PackageManageHelper.FIND_PACKAGE_INFO info)
|
||||
{
|
||||
Identity = new PMIdentity (info.piIdentity);
|
||||
Properties = new PMProperties (info.piProperties);
|
||||
IsBundle = info.piProperties.bIsBundle;
|
||||
DevelopmentMode = info.piProperties.bIsDevelopmentMode;
|
||||
InstallLocation = Marshal.PtrToStringUni (info.lpInstallLocation);
|
||||
Users = (Marshal.PtrToStringUni (info.lpUsers) ?? "").Split (';').ToList ();
|
||||
SIDs = (Marshal.PtrToStringUni (info.lpSIDs) ?? "").Split (';').ToList ();
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public static class PackageManager
|
||||
{
|
||||
private static DataUtils._I_HResult FromNative (int hr,IntPtr pErrorCode,IntPtr pDetailMsg)
|
||||
{
|
||||
string errCode = null;
|
||||
string detail = null;
|
||||
try
|
||||
{
|
||||
if (pErrorCode != IntPtr.Zero) errCode = Marshal.PtrToStringUni (pErrorCode);
|
||||
if (pDetailMsg != IntPtr.Zero) detail = Marshal.PtrToStringUni (pDetailMsg);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pErrorCode != IntPtr.Zero) PackageManageHelper.PackageManagerFreeString (pErrorCode);
|
||||
if (pDetailMsg != IntPtr.Zero) PackageManageHelper.PackageManagerFreeString (pDetailMsg);
|
||||
}
|
||||
return new DataUtils._I_HResult (hr, errCode, detail);
|
||||
}
|
||||
public delegate void PackageProgressCallback (uint progress);
|
||||
internal sealed class ProgressCallbackHolder
|
||||
{
|
||||
private readonly PackageProgressCallback _callback;
|
||||
public ProgressCallbackHolder (PackageProgressCallback cb)
|
||||
{
|
||||
_callback = cb;
|
||||
Native = new PackageManageHelper.PKGMRR_PROGRESSCALLBACK (OnNative);
|
||||
}
|
||||
public PackageManageHelper.PKGMRR_PROGRESSCALLBACK Native { get; private set; }
|
||||
private void OnNative (uint progress, IntPtr custom)
|
||||
{
|
||||
if (_callback != null)
|
||||
_callback (progress);
|
||||
}
|
||||
}
|
||||
internal sealed class ResultCallbackHolder
|
||||
{
|
||||
public readonly List<PMPackageInfo> RetList = new List<PMPackageInfo> ();
|
||||
public PackageManageHelper.PKGMGR_FINDENUMCALLBACK Callback;
|
||||
public ResultCallbackHolder ()
|
||||
{
|
||||
Callback = OnResult;
|
||||
}
|
||||
private void OnResult (
|
||||
IntPtr nativeInfo,
|
||||
IntPtr pCustom)
|
||||
{
|
||||
RetList.Add (new PMPackageInfo (PackageManageHelper.PtrToFindPackageInfo (nativeInfo)));
|
||||
}
|
||||
}
|
||||
public static DataUtils._I_HResult AddPackage (Uri fileUri, IEnumerable<Uri> depUris, DeploymentOptions options, PackageProgressCallback progress = null)
|
||||
{
|
||||
if (fileUri == null) throw new ArgumentNullException ("Required File URI");
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
var depList = depUris == null ? new List<string> () : depUris.Select (u => u.AbsoluteUri).ToList ();
|
||||
ProgressCallbackHolder holder = null;
|
||||
try
|
||||
{
|
||||
depArray = NativeUtil.AllocStringArray (depList);
|
||||
PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null;
|
||||
if (progress != null)
|
||||
{
|
||||
holder = new ProgressCallbackHolder (progress);
|
||||
nativeCb = holder.Native;
|
||||
}
|
||||
int hr = PackageManageHelper.AddAppxPackageFromURI (fileUri.AbsoluteUri, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return FromNative (hr, pErrCode, pDetail);
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeUtil.FreeStringArray (depArray, depList.Count);
|
||||
GC.KeepAlive (holder);
|
||||
}
|
||||
}
|
||||
public static DataUtils._I_HResult AddPackage (string filePath, IEnumerable<string> depUris, DeploymentOptions options, PackageProgressCallback progress = null)
|
||||
{
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
var depList = depUris == null ? new List<string> () : depUris.ToList ();
|
||||
ProgressCallbackHolder holder = null;
|
||||
try
|
||||
{
|
||||
depArray = NativeUtil.AllocStringArray (depList);
|
||||
PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null;
|
||||
if (progress != null)
|
||||
{
|
||||
holder = new ProgressCallbackHolder (progress);
|
||||
nativeCb = holder.Native;
|
||||
}
|
||||
int hr = PackageManageHelper.AddAppxPackageFromPath (filePath, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return FromNative (hr, pErrCode, pDetail);
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeUtil.FreeStringArray (depArray, depList.Count);
|
||||
GC.KeepAlive (holder);
|
||||
}
|
||||
}
|
||||
public static Tuple <DataUtils._I_HResult, List <PMPackageInfo>> GetPackages ()
|
||||
{
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
ResultCallbackHolder callback = null;
|
||||
try
|
||||
{
|
||||
callback = new ResultCallbackHolder ();
|
||||
int hr = PackageManageHelper.GetAppxPackages (callback.Callback, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return Tuple.Create (FromNative (hr, pErrCode, pDetail), callback.RetList);
|
||||
}
|
||||
finally
|
||||
{
|
||||
GC.KeepAlive (callback);
|
||||
}
|
||||
}
|
||||
public static DataUtils._I_HResult RemovePackage (string packageFullName, PackageProgressCallback progress = null)
|
||||
{
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
ProgressCallbackHolder holder = null;
|
||||
try
|
||||
{
|
||||
PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null;
|
||||
if (progress != null)
|
||||
{
|
||||
holder = new ProgressCallbackHolder (progress);
|
||||
nativeCb = holder.Native;
|
||||
}
|
||||
int hr = PackageManageHelper.RemoveAppxPackage (packageFullName, nativeCb, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return FromNative (hr, pErrCode, pDetail);
|
||||
}
|
||||
finally
|
||||
{
|
||||
GC.KeepAlive (holder);
|
||||
}
|
||||
}
|
||||
public static DataUtils._I_HResult ClearupPackage (string packageName, string userSID, PackageProgressCallback progress = null)
|
||||
{
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
ProgressCallbackHolder holder = null;
|
||||
try
|
||||
{
|
||||
PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null;
|
||||
if (progress != null)
|
||||
{
|
||||
holder = new ProgressCallbackHolder (progress);
|
||||
nativeCb = holder.Native;
|
||||
}
|
||||
int hr = PackageManageHelper.CleanupAppxPackage (packageName, userSID, nativeCb, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return FromNative (hr, pErrCode, pDetail);
|
||||
}
|
||||
finally
|
||||
{
|
||||
GC.KeepAlive (holder);
|
||||
}
|
||||
}
|
||||
public static DataUtils._I_HResult RegisterPackage (Uri manifestUri, IEnumerable<Uri> depUris, DeploymentOptions options, PackageProgressCallback progress = null)
|
||||
{
|
||||
if (manifestUri == null) throw new ArgumentNullException ("Required File URI");
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
var depList = depUris == null ? new List<string> () : depUris.Select (u => u.AbsoluteUri).ToList ();
|
||||
ProgressCallbackHolder holder = null;
|
||||
try
|
||||
{
|
||||
depArray = NativeUtil.AllocStringArray (depList);
|
||||
PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null;
|
||||
if (progress != null)
|
||||
{
|
||||
holder = new ProgressCallbackHolder (progress);
|
||||
nativeCb = holder.Native;
|
||||
}
|
||||
int hr = PackageManageHelper.RegisterAppxPackageByUri (manifestUri.AbsoluteUri, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return FromNative (hr, pErrCode, pDetail);
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeUtil.FreeStringArray (depArray, depList.Count);
|
||||
GC.KeepAlive (holder);
|
||||
}
|
||||
}
|
||||
public static DataUtils._I_HResult RegisterPackage (string manifestPath, IEnumerable<string> depUris, DeploymentOptions options, PackageProgressCallback progress = null)
|
||||
{
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
var depList = depUris == null ? new List<string> () : depUris.ToList ();
|
||||
ProgressCallbackHolder holder = null;
|
||||
try
|
||||
{
|
||||
depArray = NativeUtil.AllocStringArray (depList);
|
||||
PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null;
|
||||
if (progress != null)
|
||||
{
|
||||
holder = new ProgressCallbackHolder (progress);
|
||||
nativeCb = holder.Native;
|
||||
}
|
||||
int hr = PackageManageHelper.RegisterAppxPackageByUri (manifestPath, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return FromNative (hr, pErrCode, pDetail);
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeUtil.FreeStringArray (depArray, depList.Count);
|
||||
GC.KeepAlive (holder);
|
||||
}
|
||||
}
|
||||
public static DataUtils._I_HResult RegisterPackageByFullName (string pkgFullName, IEnumerable<string> depFullNames, DeploymentOptions options, PackageProgressCallback progress = null)
|
||||
{
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
var depList = depFullNames == null ? new List<string> () : depFullNames.ToList ();
|
||||
ProgressCallbackHolder holder = null;
|
||||
try
|
||||
{
|
||||
depArray = NativeUtil.AllocStringArray (depList);
|
||||
PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null;
|
||||
if (progress != null)
|
||||
{
|
||||
holder = new ProgressCallbackHolder (progress);
|
||||
nativeCb = holder.Native;
|
||||
}
|
||||
int hr = PackageManageHelper.RegisterAppxPackageByFullName (pkgFullName, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return FromNative (hr, pErrCode, pDetail);
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeUtil.FreeStringArray (depArray, depList.Count);
|
||||
GC.KeepAlive (holder);
|
||||
}
|
||||
}
|
||||
public static DataUtils._I_HResult SetPackageStatus (string packageFullName, PackageStatus status)
|
||||
{
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
int hr = PackageManageHelper.SetAppxPackageStatus (packageFullName, (uint)status, out pErrCode, out pDetail);
|
||||
return FromNative (hr, pErrCode, pDetail);
|
||||
}
|
||||
finally { }
|
||||
}
|
||||
public static DataUtils._I_HResult StagePackage (Uri fileUri, IEnumerable<Uri> depUris, DeploymentOptions options, PackageProgressCallback progress = null)
|
||||
{
|
||||
if (fileUri == null) throw new ArgumentNullException ("Required File URI");
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
var depList = depUris == null ? new List<string> () : depUris.Select (u => u.AbsoluteUri).ToList ();
|
||||
ProgressCallbackHolder holder = null;
|
||||
try
|
||||
{
|
||||
depArray = NativeUtil.AllocStringArray (depList);
|
||||
PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null;
|
||||
if (progress != null)
|
||||
{
|
||||
holder = new ProgressCallbackHolder (progress);
|
||||
nativeCb = holder.Native;
|
||||
}
|
||||
int hr = PackageManageHelper.StageAppxPackageFromURI (fileUri.AbsoluteUri, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return FromNative (hr, pErrCode, pDetail);
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeUtil.FreeStringArray (depArray, depList.Count);
|
||||
GC.KeepAlive (holder);
|
||||
}
|
||||
}
|
||||
public static DataUtils._I_HResult StagePackage (string filePath, IEnumerable<string> depUris, DeploymentOptions options, PackageProgressCallback progress = null)
|
||||
{
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
var depList = depUris == null ? new List<string> () : depUris.ToList ();
|
||||
ProgressCallbackHolder holder = null;
|
||||
try
|
||||
{
|
||||
depArray = NativeUtil.AllocStringArray (depList);
|
||||
PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null;
|
||||
if (progress != null)
|
||||
{
|
||||
holder = new ProgressCallbackHolder (progress);
|
||||
nativeCb = holder.Native;
|
||||
}
|
||||
int hr = PackageManageHelper.StageAppxPackageFromPath (filePath, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return FromNative (hr, pErrCode, pDetail);
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeUtil.FreeStringArray (depArray, depList.Count);
|
||||
GC.KeepAlive (holder);
|
||||
}
|
||||
}
|
||||
public static DataUtils._I_HResult StageUserData (string packageFullName, PackageProgressCallback progress = null)
|
||||
{
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
ProgressCallbackHolder holder = null;
|
||||
try
|
||||
{
|
||||
PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null;
|
||||
if (progress != null)
|
||||
{
|
||||
holder = new ProgressCallbackHolder (progress);
|
||||
nativeCb = holder.Native;
|
||||
}
|
||||
int hr = PackageManageHelper.StageAppxUserData (packageFullName, nativeCb, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return FromNative (hr, pErrCode, pDetail);
|
||||
}
|
||||
finally
|
||||
{
|
||||
GC.KeepAlive (holder);
|
||||
}
|
||||
}
|
||||
public static DataUtils._I_HResult UpdatePackage (Uri fileUri, IEnumerable<Uri> depUris, DeploymentOptions options, PackageProgressCallback progress = null)
|
||||
{
|
||||
if (fileUri == null) throw new ArgumentNullException ("Required File URI");
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
var depList = depUris == null ? new List<string> () : depUris.Select (u => u.AbsoluteUri).ToList ();
|
||||
ProgressCallbackHolder holder = null;
|
||||
try
|
||||
{
|
||||
depArray = NativeUtil.AllocStringArray (depList);
|
||||
PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null;
|
||||
if (progress != null)
|
||||
{
|
||||
holder = new ProgressCallbackHolder (progress);
|
||||
nativeCb = holder.Native;
|
||||
}
|
||||
int hr = PackageManageHelper.UpdateAppxPackageFromURI (fileUri.AbsoluteUri, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return FromNative (hr, pErrCode, pDetail);
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeUtil.FreeStringArray (depArray, depList.Count);
|
||||
GC.KeepAlive (holder);
|
||||
}
|
||||
}
|
||||
public static DataUtils._I_HResult UpdatePackage (string filePath, IEnumerable<string> depUris, DeploymentOptions options, PackageProgressCallback progress = null)
|
||||
{
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
var depList = depUris == null ? new List<string> () : depUris.ToList ();
|
||||
ProgressCallbackHolder holder = null;
|
||||
try
|
||||
{
|
||||
depArray = NativeUtil.AllocStringArray (depList);
|
||||
PackageManageHelper.PKGMRR_PROGRESSCALLBACK nativeCb = null;
|
||||
if (progress != null)
|
||||
{
|
||||
holder = new ProgressCallbackHolder (progress);
|
||||
nativeCb = holder.Native;
|
||||
}
|
||||
int hr = PackageManageHelper.UpdateAppxPackageFromPath (filePath, depArray, (uint)options, nativeCb, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return FromNative (hr, pErrCode, pDetail);
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeUtil.FreeStringArray (depArray, depList.Count);
|
||||
GC.KeepAlive (holder);
|
||||
}
|
||||
}
|
||||
public static Tuple<DataUtils._I_HResult, List<PMPackageInfo>> FindPackage (string packageName, string packagePublisher)
|
||||
{
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
ResultCallbackHolder callback = null;
|
||||
try
|
||||
{
|
||||
callback = new ResultCallbackHolder ();
|
||||
int hr = PackageManageHelper.FindAppxPackagesByIdentity (packageName, packagePublisher, callback.Callback, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return Tuple.Create (FromNative (hr, pErrCode, pDetail), callback.RetList);
|
||||
}
|
||||
finally
|
||||
{
|
||||
GC.KeepAlive (callback);
|
||||
}
|
||||
}
|
||||
public static Tuple<DataUtils._I_HResult, List<PMPackageInfo>> FindPackage (string packageFamilyName)
|
||||
{
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
ResultCallbackHolder callback = null;
|
||||
try
|
||||
{
|
||||
callback = new ResultCallbackHolder ();
|
||||
int hr = PackageManageHelper.FindAppxPackagesByFamilyName (packageFamilyName, callback.Callback, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return Tuple.Create (FromNative (hr, pErrCode, pDetail), callback.RetList);
|
||||
}
|
||||
finally
|
||||
{
|
||||
GC.KeepAlive (callback);
|
||||
}
|
||||
}
|
||||
public static Tuple<DataUtils._I_HResult, List<PMPackageInfo>> FindPackageByFullName (string packageFullName)
|
||||
{
|
||||
IntPtr depArray = IntPtr.Zero;
|
||||
IntPtr pErrCode = IntPtr.Zero;
|
||||
IntPtr pDetail = IntPtr.Zero;
|
||||
ResultCallbackHolder callback = null;
|
||||
try
|
||||
{
|
||||
callback = new ResultCallbackHolder ();
|
||||
int hr = PackageManageHelper.FindAppxPackage (packageFullName, callback.Callback, IntPtr.Zero, out pErrCode, out pDetail);
|
||||
return Tuple.Create (FromNative (hr, pErrCode, pDetail), callback.RetList);
|
||||
}
|
||||
finally
|
||||
{
|
||||
GC.KeepAlive (callback);
|
||||
}
|
||||
}
|
||||
public static DataUtils._I_HResult ActiveApp (string appUserId)
|
||||
{
|
||||
uint processId;
|
||||
var hr = PackageManageHelper.ActivateAppxApplication (appUserId, out processId);
|
||||
return new DataUtils._I_HResult (hr);
|
||||
}
|
||||
public static DataUtils._I_HResult ActiveApp (string appUserId, string cmdargs)
|
||||
{
|
||||
uint processId;
|
||||
var hr = PackageManageHelper.ActivateAppxApplicationWithArgs (appUserId, cmdargs, out processId);
|
||||
return new DataUtils._I_HResult (hr);
|
||||
}
|
||||
}
|
||||
}
|
||||
3324
AppxPackage/PackageReader.cs
Normal file
3324
AppxPackage/PackageReader.cs
Normal file
File diff suppressed because it is too large
Load Diff
230
AppxPackage/PkgMgrNative.cs
Normal file
230
AppxPackage/PkgMgrNative.cs
Normal file
@@ -0,0 +1,230 @@
|
||||
// PackageManageHelper.cs
|
||||
// P/Invoke wrapper for pkgmgr.dll (x86).
|
||||
//
|
||||
// 说明:此文件兼容 .NET Framework 4。
|
||||
// - 将项目 Platform target 设置为 x86。
|
||||
// - pkgmgr.dll 提供 PackageManagerFreeString 来释放它返回的字符串,请务必使用它释放由 pkgmgr 返回的 LPWSTR。
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NativeWrappers
|
||||
{
|
||||
using DWORD = System.UInt32;
|
||||
using HRESULT = System.Int32;
|
||||
using BOOL = System.Int32;
|
||||
using UINT64 = System.UInt64;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public static class PackageManageHelper
|
||||
{
|
||||
private const string DllName = "pkgmgr.dll";
|
||||
private const CallingConvention CallConv = CallingConvention.Cdecl;
|
||||
|
||||
[UnmanagedFunctionPointer (CallConv)]
|
||||
public delegate void PKGMRR_PROGRESSCALLBACK (DWORD dwProgress, IntPtr pCustom);
|
||||
|
||||
[UnmanagedFunctionPointer (CallConv)]
|
||||
public delegate void PKGMGR_FINDENUMCALLBACK (IntPtr pNowItem, IntPtr pCustom);
|
||||
|
||||
[StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct REGISTER_PACKAGE_DEFENDENCIES
|
||||
{
|
||||
public DWORD dwSize;
|
||||
public IntPtr alpDepUris; // tail array
|
||||
}
|
||||
|
||||
[StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct FIND_PACKAGE_ID
|
||||
{
|
||||
public UINT64 qwVersion;
|
||||
public ushort wProcessArchitecture;
|
||||
[MarshalAs (UnmanagedType.ByValArray, SizeConst = 3)]
|
||||
public ushort [] wPadding;
|
||||
public IntPtr lpName;
|
||||
public IntPtr lpFullName;
|
||||
public IntPtr lpFamilyName;
|
||||
public IntPtr lpPublisher;
|
||||
public IntPtr lpPublisherId;
|
||||
public IntPtr lpResourceId;
|
||||
}
|
||||
|
||||
[StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct FIND_PACKAGE_PROPERTIES
|
||||
{
|
||||
public IntPtr lpDisplayName;
|
||||
public IntPtr lpDescription;
|
||||
public IntPtr lpPublisher;
|
||||
public IntPtr lpLogoUri;
|
||||
[MarshalAs (UnmanagedType.Bool)]
|
||||
public bool bIsFramework;
|
||||
[MarshalAs (UnmanagedType.Bool)]
|
||||
public bool bIsResourcePackage;
|
||||
[MarshalAs (UnmanagedType.Bool)]
|
||||
public bool bIsBundle;
|
||||
[MarshalAs (UnmanagedType.Bool)]
|
||||
public bool bIsDevelopmentMode;
|
||||
}
|
||||
|
||||
[StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct FIND_PACKAGE_INFO
|
||||
{
|
||||
public FIND_PACKAGE_ID piIdentity;
|
||||
public FIND_PACKAGE_PROPERTIES piProperties;
|
||||
public IntPtr lpInstallLocation;
|
||||
public IntPtr lpUsers;
|
||||
public IntPtr lpSIDs;
|
||||
public DWORD dwDependencesSize;
|
||||
public DWORD dwPadding;
|
||||
public UINT64 ullBuffer;
|
||||
}
|
||||
|
||||
// ========== Functions ==========
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT AddAppxPackageFromPath (string lpPkgPath, IntPtr alpDepUrlList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT AddAppxPackageFromURI (string lpFileUri, IntPtr alpDepFullNameList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT GetAppxPackages (PKGMGR_FINDENUMCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT RemoveAppxPackage (string lpPkgFullName, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT CleanupAppxPackage (string lpPkgName, string lpUserSID, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT RegisterAppxPackageByPath (string lpManifestPath, IntPtr alpDependencyUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT RegisterAppxPackageByUri (string lpManifestUri, IntPtr alpDependencyUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT RegisterAppxPackageByFullName (string lpPackageFullName, IntPtr alpDepFullNameList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT SetAppxPackageStatus (string lpPackageFullName, DWORD dwStatus, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT StageAppxPackageFromURI (string lpFileUri, IntPtr alpDepUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT StageAppxPackageFromPath (string lpFileUri, IntPtr alpDepUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT StageAppxUserData (string lpPackageFullName, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT UpdateAppxPackageFromPath (string lpPkgPath, IntPtr alpDepUrlList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT UpdateAppxPackageFromURI (string lpFileUri, IntPtr alpDepFullNameList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT FindAppxPackage (string lpPackageFullName, PKGMGR_FINDENUMCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetPackageManagerLastErrorCode ();
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetPackageManagerLastErrorDetailMessage ();
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT ActivateAppxApplication (string lpAppUserId, out DWORD pdwProcessId);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT FindAppxPackagesByIdentity (string lpPkgName, string lpPkgPublisher, PKGMGR_FINDENUMCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT FindAppxPackagesByFamilyName (string lpPkgFamilyName, PKGMGR_FINDENUMCALLBACK pfCallback, IntPtr pCustom, out IntPtr pErrorCode, out IntPtr pDetailMsg);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void PackageManagerFreeString (IntPtr lpString);
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode, ExactSpelling = true)]
|
||||
public static extern HRESULT ActivateAppxApplicationWithArgs ([MarshalAs (UnmanagedType.LPWStr)] string lpAppUserId, [MarshalAs (UnmanagedType.LPWStr)] string lpArguments, out DWORD pdwProcessId);
|
||||
|
||||
// ========== 托管辅助 ==========
|
||||
public static string PtrToStringAndFree (IntPtr nativePtr)
|
||||
{
|
||||
if (nativePtr == IntPtr.Zero) return null;
|
||||
string s = Marshal.PtrToStringUni (nativePtr);
|
||||
try
|
||||
{
|
||||
PackageManagerFreeString (nativePtr);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public static FIND_PACKAGE_INFO PtrToFindPackageInfo (IntPtr pInfo)
|
||||
{
|
||||
if (pInfo == IntPtr.Zero) return default (FIND_PACKAGE_INFO);
|
||||
object boxed = Marshal.PtrToStructure (pInfo, typeof (FIND_PACKAGE_INFO));
|
||||
return (FIND_PACKAGE_INFO)boxed;
|
||||
}
|
||||
|
||||
public static string GetDisplayNameFromFindPackageInfo (IntPtr pInfo)
|
||||
{
|
||||
FIND_PACKAGE_INFO info = PtrToFindPackageInfo (pInfo);
|
||||
if (info.piProperties.lpDisplayName == IntPtr.Zero) return null;
|
||||
return Marshal.PtrToStringUni (info.piProperties.lpDisplayName);
|
||||
}
|
||||
|
||||
public static string [] ReadRegisterPackageDependencies (IntPtr pReg)
|
||||
{
|
||||
if (pReg == IntPtr.Zero) return new string [0];
|
||||
uint size = (uint)Marshal.ReadInt32 (pReg);
|
||||
if (size == 0) return new string [0];
|
||||
string [] result = new string [size];
|
||||
int offset = Marshal.SizeOf (typeof (uint));
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
IntPtr pStr = Marshal.ReadIntPtr (pReg, offset + i * IntPtr.Size);
|
||||
result [i] = pStr == IntPtr.Zero ? null : Marshal.PtrToStringUni (pStr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
internal static class NativeUtil
|
||||
{
|
||||
public static string ToAbsoluteUriString (Uri uri)
|
||||
{
|
||||
if (uri == null) return null;
|
||||
return uri.AbsoluteUri;
|
||||
}
|
||||
|
||||
public static IntPtr AllocStringArray (IEnumerable<string> values)
|
||||
{
|
||||
if (values == null) return IntPtr.Zero;
|
||||
|
||||
var list = values.Where (s => !string.IsNullOrEmpty (s)).ToList ();
|
||||
if (list.Count == 0) return IntPtr.Zero;
|
||||
|
||||
IntPtr mem = Marshal.AllocHGlobal (IntPtr.Size * list.Count);
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
IntPtr pStr = Marshal.StringToHGlobalUni (list [i]);
|
||||
Marshal.WriteIntPtr (mem, i * IntPtr.Size, pStr);
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
public static void FreeStringArray (IntPtr array, int count)
|
||||
{
|
||||
if (array == IntPtr.Zero) return;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
IntPtr p = Marshal.ReadIntPtr (array, i * IntPtr.Size);
|
||||
if (p != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal (p);
|
||||
}
|
||||
Marshal.FreeHGlobal (array);
|
||||
}
|
||||
}
|
||||
}
|
||||
566
AppxPackage/PkgReadNative.cs
Normal file
566
AppxPackage/PkgReadNative.cs
Normal file
@@ -0,0 +1,566 @@
|
||||
// PackageReadHelper.cs
|
||||
// P/Invoke wrapper for pkgread.dll (x86).
|
||||
//
|
||||
// 说明:此文件兼容 .NET Framework 4。
|
||||
// - 将项目 Platform target 设置为 x86(因为你只编译了 x86 的本机 DLL)。
|
||||
// - pkgread.dll 返回了很多需由调用者释放的 LPWSTR 指针;header 中未提供通用释放函数,示例中调用 CRT 的 free(msvcrt.dll)来释放。
|
||||
// 如果能修改 pkgread.dll 并导出专用释放函数(如 PackageReadFreeString),那是更安全的做法。
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace NativeWrappers
|
||||
{
|
||||
// 本机类型别名(便于阅读)
|
||||
using BOOL = System.Int32;
|
||||
using WORD = System.UInt16;
|
||||
using DWORD = System.UInt32;
|
||||
using UINT16 = System.UInt16;
|
||||
using UINT64 = System.UInt64;
|
||||
using HRESULT = System.Int32;
|
||||
using ULONG = System.UInt32;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public static class PackageReadHelper
|
||||
{
|
||||
private const string DllName = "pkgread.dll";
|
||||
private const CallingConvention CallConv = CallingConvention.Cdecl;
|
||||
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
public struct VERSION
|
||||
{
|
||||
public ushort major;
|
||||
public ushort minor;
|
||||
public ushort build;
|
||||
public ushort revision;
|
||||
}
|
||||
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
public struct PAIR_PVOID
|
||||
{
|
||||
public IntPtr lpKey;
|
||||
public IntPtr lpValue;
|
||||
}
|
||||
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
public struct DEPENDENCY_INFO
|
||||
{
|
||||
public VERSION verMin;
|
||||
public IntPtr lpName; // LPWSTR
|
||||
public IntPtr lpPublisher; // LPWSTR
|
||||
}
|
||||
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
public struct LIST_DEPINFO
|
||||
{
|
||||
public DWORD dwSize;
|
||||
public IntPtr aDepInfo; // tail array
|
||||
}
|
||||
|
||||
// Delegates
|
||||
[UnmanagedFunctionPointer (CallConv)]
|
||||
public delegate void PKGMRR_PROGRESSCALLBACK (DWORD dwProgress, IntPtr pCustom);
|
||||
|
||||
// ========== P/Invoke ==========
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr CreatePackageReader ();
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool LoadPackageFromFile (IntPtr hReader, string lpFilePath);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void DestroyPackageReader (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern ushort GetPackageType (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool IsPackageValid (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern ushort GetPackageRole (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetPackageIdentityStringValue (IntPtr hReader, uint dwName);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool GetPackageIdentityVersion (IntPtr hReader, out VERSION pVersion, [MarshalAs (UnmanagedType.Bool)] bool bGetSubPkgVer);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool GetPackageIdentityArchitecture (IntPtr hReader, out DWORD pdwArchi);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetPackagePropertiesStringValue (IntPtr hReader, string lpName);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT GetPackagePropertiesBoolValue (IntPtr hReader, string lpName, out BOOL pRet);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool AddPackageApplicationItemGetName (string lpName);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool RemovePackageApplicationItemGetName (string lpName);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetAllApplicationItemsName ();
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void DestroyApplicationItemsName (IntPtr hList);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetPackageApplications (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr ApplicationsToMap (IntPtr hEnumerator);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void DestroyApplicationsMap (IntPtr hEnumerator);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void DestroyPackageApplications (IntPtr hEnumerator);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetResourcesLanguages (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetResourcesLanguagesToLcid (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetResourcesScales (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern DWORD GetResourcesDxFeatureLevels (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void DestroyResourcesLanguagesList (IntPtr hList);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void DestroyResourcesLanguagesLcidList (IntPtr hList);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void DestroyUInt32List (IntPtr hList);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetDependencesInfoList (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void DestroyDependencesInfoList (IntPtr hList);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetCapabilitiesList (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetDeviceCapabilitiesList (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void DestroyWStringList (IntPtr hList);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool GetPackagePrerequisite (IntPtr hReader, string lpName, out VERSION pVerRet);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetPackagePrerequistieSystemVersionName (IntPtr hReader, string lpName);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetAppxFileFromAppxPackage (IntPtr hReader, string lpFileName);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetAppxBundlePayloadPackageFile (IntPtr hReader, string lpFileName);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetAppxPriFileStream (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetFileFromPayloadPackage (IntPtr hPackageStream, string lpFileName);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetPriFileFromPayloadPackage (IntPtr hPackageStream);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool GetSuitablePackageFromBundle (IntPtr hReader, out IntPtr pStreamForLang, out IntPtr pStreamForScale);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern ULONG DestroyAppxFileStream (IntPtr hFileStream);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr StreamToBase64W (IntPtr hFileStream, StringBuilder lpMimeBuf, DWORD dwCharCount, out IntPtr lpBase64Head);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetAppxBundleApplicationPackageFile (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetPackageCapabilityDisplayName (string lpCapabilityName);
|
||||
|
||||
// CRT free(当 header 指示用 free 释放)
|
||||
[DllImport ("msvcrt.dll", CallingConvention = CallConv, EntryPoint = "free")]
|
||||
private static extern void crt_free (IntPtr ptr);
|
||||
|
||||
// ========== 托管辅助方法 ==========
|
||||
public static string GetStringAndFreeFromPkgRead (IntPtr nativePtr)
|
||||
{
|
||||
if (nativePtr == IntPtr.Zero) return null;
|
||||
string s = Marshal.PtrToStringUni (nativePtr);
|
||||
try
|
||||
{
|
||||
PackageReaderFreeString (nativePtr);
|
||||
nativePtr = IntPtr.Zero;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 忽略释放失败(注意可能的 CRT 不匹配风险)
|
||||
}
|
||||
return s;
|
||||
}
|
||||
public static string GetStringFromPkgRead (IntPtr nativePtr)
|
||||
{
|
||||
if (nativePtr == IntPtr.Zero) return null;
|
||||
string s = Marshal.PtrToStringUni (nativePtr);
|
||||
return s;
|
||||
}
|
||||
|
||||
public static string PtrToStringNoFree (IntPtr nativePtr)
|
||||
{
|
||||
if (nativePtr == IntPtr.Zero) return null;
|
||||
return Marshal.PtrToStringUni (nativePtr);
|
||||
}
|
||||
|
||||
// 解析 HLIST_PVOID (字符串列表)
|
||||
public static string [] ReadWStringList (IntPtr hList)
|
||||
{
|
||||
if (hList == IntPtr.Zero) return new string [0];
|
||||
uint size = (uint)Marshal.ReadInt32 (hList);
|
||||
if (size == 0) return new string [0];
|
||||
string [] result = new string [size];
|
||||
int offset = Marshal.SizeOf (typeof (uint)); // typically 4 on x86
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
IntPtr pSlot = Marshal.ReadIntPtr (hList, offset + i * IntPtr.Size);
|
||||
result [i] = pSlot == IntPtr.Zero ? null : Marshal.PtrToStringUni (pSlot);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static uint [] ReadUInt32List (IntPtr hList)
|
||||
{
|
||||
if (hList == IntPtr.Zero) return new uint [0];
|
||||
uint size = (uint)Marshal.ReadInt32 (hList);
|
||||
if (size == 0) return new uint [0];
|
||||
uint [] result = new uint [size];
|
||||
int offset = Marshal.SizeOf (typeof (uint));
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
result [i] = (uint)Marshal.ReadInt32 (hList, offset + i * 4);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int [] ReadLcidList (IntPtr hList)
|
||||
{
|
||||
if (hList == IntPtr.Zero) return new int [0];
|
||||
uint size = (uint)Marshal.ReadInt32 (hList);
|
||||
if (size == 0) return new int [0];
|
||||
int [] result = new int [size];
|
||||
int offset = Marshal.SizeOf (typeof (uint));
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
result [i] = Marshal.ReadInt32 (hList, offset + i * 4);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static DEPENDENCY_INFO [] ReadDependencyInfoList (IntPtr hList)
|
||||
{
|
||||
if (hList == IntPtr.Zero) return new DEPENDENCY_INFO [0];
|
||||
uint size = (uint)Marshal.ReadInt32 (hList);
|
||||
if (size == 0) return new DEPENDENCY_INFO [0];
|
||||
DEPENDENCY_INFO [] result = new DEPENDENCY_INFO [size];
|
||||
int baseOffset = Marshal.SizeOf (typeof (uint));
|
||||
int structSize = Marshal.SizeOf (typeof (DEPENDENCY_INFO));
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
IntPtr pItem = IntPtr.Add (hList, baseOffset + i * structSize);
|
||||
object boxed = Marshal.PtrToStructure (pItem, typeof (DEPENDENCY_INFO));
|
||||
result [i] = (DEPENDENCY_INFO)boxed;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void FreePkgReadMemory (IntPtr nativePtr)
|
||||
{
|
||||
if (nativePtr == IntPtr.Zero) return;
|
||||
try
|
||||
{
|
||||
crt_free (nativePtr);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
// ================= Manifest Reader =================
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr CreateManifestReader ();
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool LoadManifestFromFile (
|
||||
IntPtr hReader,
|
||||
string lpFilePath
|
||||
);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void DestroyManifestReader (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
public static extern ushort GetManifestType (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool IsManifestValid (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
public static extern ushort GetManifestRole (IntPtr hReader);
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetManifestIdentityStringValue (
|
||||
IntPtr hReader,
|
||||
uint dwName
|
||||
);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool GetManifestIdentityVersion (
|
||||
IntPtr hReader,
|
||||
out VERSION pVersion
|
||||
);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool GetManifestIdentityArchitecture (
|
||||
IntPtr hReader,
|
||||
out DWORD pdwArchi
|
||||
);
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetManifestPropertiesStringValue (
|
||||
IntPtr hReader,
|
||||
string lpName
|
||||
);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT GetManifestPropertiesBoolValue (
|
||||
IntPtr hReader,
|
||||
string lpName,
|
||||
out BOOL pRet
|
||||
);
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool AddManifestApplicationItemGetName (string lpName);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool RemoveManifestApplicationItemGetName (string lpName);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
public static extern IntPtr GetManifestApplications (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
public static extern void DestroyManifestApplications (IntPtr hEnumerator);
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
public static extern IntPtr GetManifestResourcesLanguages (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
public static extern IntPtr GetManifestResourcesLanguagesToLcid (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
public static extern IntPtr GetManifestResourcesScales (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
public static extern DWORD GetManifestResourcesDxFeatureLevels (IntPtr hReader);
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
public static extern IntPtr GetManifestDependencesInfoList (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
public static extern IntPtr GetManifestCapabilitiesList (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
public static extern IntPtr GetManifestDeviceCapabilitiesList (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool GetManifestPrerequisite (
|
||||
IntPtr hReader,
|
||||
string lpName,
|
||||
out VERSION pVerRet
|
||||
);
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
public static extern void PackageReaderFreeString (IntPtr p);
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern IntPtr GetManifestPrerequistieSystemVersionName (IntPtr hReader, string lpName);
|
||||
|
||||
// ========== Appx Bundle Resource Packages ==========
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
private static extern IntPtr GetAppxBundleAllResourcePackageFileNames (IntPtr hReader);
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
private static extern void FreeAppxBundlePayloadsFileNameList (IntPtr hStringList);
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Bundle 包中所有资源包的文件名列表。
|
||||
/// </summary>
|
||||
/// <param name="hReader">由 CreatePackageReader 创建的读取器句柄</param>
|
||||
/// <returns>资源包文件名数组,若无资源包或非 bundle 类型则返回空数组</returns>
|
||||
public static string [] GetAppxBundleAllResourcePackageFileNameList (IntPtr hReader)
|
||||
{
|
||||
IntPtr hList = GetAppxBundleAllResourcePackageFileNames (hReader);
|
||||
if (hList == IntPtr.Zero)
|
||||
return new string [0];
|
||||
|
||||
try
|
||||
{
|
||||
return ReadWStringList (hList);
|
||||
}
|
||||
finally
|
||||
{
|
||||
FreeAppxBundlePayloadsFileNameList (hList);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
private static extern IntPtr GetAppxBundleAllLocaleResourcePackageFileNames (IntPtr hReader);
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Bundle 包中所有区域设置资源包的文件名列表。
|
||||
/// </summary>
|
||||
/// <param name="hReader">由 CreatePackageReader 创建的读取器句柄</param>
|
||||
/// <returns>区域设置资源包文件名数组,若无则返回空数组</returns>
|
||||
public static string [] GetAppxBundleAllLocaleResourcePackageFileNameList (IntPtr hReader)
|
||||
{
|
||||
IntPtr hList = GetAppxBundleAllLocaleResourcePackageFileNames (hReader);
|
||||
if (hList == IntPtr.Zero)
|
||||
return new string [0];
|
||||
|
||||
try
|
||||
{
|
||||
return ReadWStringList (hList);
|
||||
}
|
||||
finally
|
||||
{
|
||||
FreeAppxBundlePayloadsFileNameList (hList);
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport (DllName, CallingConvention = CallConv)]
|
||||
private static extern IntPtr GetAppxBundleAllFileResourcePackageFileNames (IntPtr hReader);
|
||||
|
||||
/// <summary>
|
||||
/// 获取 Bundle 包中所有文件资源包的文件名列表。
|
||||
/// </summary>
|
||||
/// <param name="hReader">由 CreatePackageReader 创建的读取器句柄</param>
|
||||
/// <returns>文件资源包文件名数组,若无则返回空数组</returns>
|
||||
public static string [] GetAppxBundleAllFileResourcePackageFileNameList (IntPtr hReader)
|
||||
{
|
||||
IntPtr hList = GetAppxBundleAllFileResourcePackageFileNames (hReader);
|
||||
if (hList == IntPtr.Zero)
|
||||
return new string [0];
|
||||
|
||||
try
|
||||
{
|
||||
return ReadWStringList (hList);
|
||||
}
|
||||
finally
|
||||
{
|
||||
FreeAppxBundlePayloadsFileNameList (hList);
|
||||
}
|
||||
}
|
||||
|
||||
// 用于更新应用项名称列表(设置要查询的项)
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void UpdatePackageApplicationItemGetName (
|
||||
[In] IntPtr [] lpNames, // 传入一个 IntPtr 数组,每个元素指向一个 Unicode 字符串
|
||||
uint dwArrLen
|
||||
);
|
||||
|
||||
// 回调委托声明
|
||||
[UnmanagedFunctionPointer (CallConv)]
|
||||
public delegate void IterWStringCallback ([MarshalAs (UnmanagedType.LPWStr)] string lpString);
|
||||
|
||||
// 枚举当前列表中的项(通过回调逐个返回)
|
||||
[DllImport (DllName, CallingConvention = CallConv, CharSet = CharSet.Unicode)]
|
||||
public static extern void GetPackageApplicationItemGetNameList (
|
||||
IterWStringCallback pfCallback // 回调函数指针
|
||||
);
|
||||
/// <summary>
|
||||
/// 更新内部的应用项名称列表(设置要查询的项)
|
||||
/// </summary>
|
||||
/// <param name="names">要设置的项名称集合</param>
|
||||
public static void SetApplicationItemNames (IEnumerable<string> names)
|
||||
{
|
||||
if (names == null)
|
||||
{
|
||||
// 传入空数组,清空列表
|
||||
UpdatePackageApplicationItemGetName (new IntPtr [0], 0);
|
||||
return;
|
||||
}
|
||||
|
||||
var nameList = names.ToList ();
|
||||
if (nameList.Count == 0)
|
||||
{
|
||||
UpdatePackageApplicationItemGetName (new IntPtr [0], 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// 为每个字符串分配非托管内存
|
||||
IntPtr [] ptrs = new IntPtr [nameList.Count];
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < nameList.Count; i++)
|
||||
{
|
||||
ptrs [i] = Marshal.StringToHGlobalUni (nameList [i]);
|
||||
}
|
||||
|
||||
UpdatePackageApplicationItemGetName (ptrs, (uint)nameList.Count);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// 释放分配的内存
|
||||
foreach (var ptr in ptrs)
|
||||
{
|
||||
if (ptr != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal (ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取当前内部的应用项名称列表(通过回调收集所有项)
|
||||
/// </summary>
|
||||
/// <returns>应用项名称数组</returns>
|
||||
public static string [] GetApplicationItemNames ()
|
||||
{
|
||||
var result = new List<string> ();
|
||||
|
||||
// 定义回调:将收到的字符串添加到列表
|
||||
IterWStringCallback callback = (str) =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty (str))
|
||||
result.Add (str);
|
||||
};
|
||||
|
||||
// 调用本机函数,传入委托
|
||||
GetPackageApplicationItemGetNameList (callback);
|
||||
|
||||
// 注意:GC 需要保持 callback 的存活直到本机调用结束,这里通过局部变量引用即可,
|
||||
// 因为本机函数是同步调用的,不会在函数返回后继续使用回调。
|
||||
return result.ToArray ();
|
||||
}
|
||||
}
|
||||
}
|
||||
247
AppxPackage/PriFileNative.cs
Normal file
247
AppxPackage/PriFileNative.cs
Normal file
@@ -0,0 +1,247 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using PCSPRIFILE = System.IntPtr;
|
||||
using PCOISTREAM = System.IntPtr;
|
||||
|
||||
namespace AppxPackage
|
||||
{
|
||||
public static class PriFileHelper
|
||||
{
|
||||
private const string DLL = "PriFormatCli.dll"; // 改成你的 DLL 名称
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern PCSPRIFILE CreatePriFileInstanceFromStream (PCOISTREAM pStream);
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void DestroyPriFileInstance (PCSPRIFILE pFilePri);
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr GetPriStringResource (PCSPRIFILE pFilePri, [MarshalAs (UnmanagedType.LPWStr)] string lpswUri);
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr GetPriPathResource (PCSPRIFILE pFilePri, [MarshalAs (UnmanagedType.LPWStr)] string lpswFilePath);
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern PCSPRIFILE CreatePriFileInstanceFromPath ([MarshalAs (UnmanagedType.LPWStr)] string lpswFilePath);
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs (UnmanagedType.LPWStr)]
|
||||
public static extern string PriFileGetLastError ();
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void FindPriStringResource (PCSPRIFILE pFilePri, IntPtr hUriList);
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void FindPriPathResource (PCSPRIFILE pFilePri, IntPtr hPathList);
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void ClearPriCacheData ();
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr GetPriResource (PCSPRIFILE pFilePri, [MarshalAs (UnmanagedType.LPWStr)] string lpswResId);
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void FindPriResource (PCSPRIFILE pFilePri, IntPtr hUriList);
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool IsMsResourcePrefix ([MarshalAs (UnmanagedType.LPWStr)] string pResName);
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool IsMsResourceUriFull ([MarshalAs (UnmanagedType.LPWStr)] string pResUri);
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
public static extern bool IsMsResourceUri ([MarshalAs (UnmanagedType.LPWStr)] string pResUri);
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
private static extern void PriFormatFreeString (IntPtr ptr);
|
||||
public static string PtrToString (IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero) return null;
|
||||
string s = Marshal.PtrToStringUni (ptr);
|
||||
PriFormatFreeString (ptr); // 如果 DLL 返回的内存要求 free
|
||||
return s;
|
||||
}
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
internal struct DWORDWSTRPAIR
|
||||
{
|
||||
public uint dwKey;
|
||||
public IntPtr lpValue; // LPWSTR
|
||||
}
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
internal struct DWSPAIRLIST
|
||||
{
|
||||
public uint dwLength;
|
||||
public DWORDWSTRPAIR lpArray; // 第一个元素(柔性数组起点)
|
||||
}
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
internal struct WSDSPAIR
|
||||
{
|
||||
public IntPtr lpKey; // LPWSTR
|
||||
public IntPtr lpValue; // HDWSPAIRLIST
|
||||
}
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
internal struct WSDSPAIRLIST
|
||||
{
|
||||
public uint dwLength;
|
||||
public WSDSPAIR lpArray; // 第一个元素
|
||||
}
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr GetPriResourceAllValueList (PCSPRIFILE pFilePri, [MarshalAs (UnmanagedType.LPWStr)] string resName);
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void DestroyPriResourceAllValueList (IntPtr list);
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr GetPriResourcesAllValuesList (PCSPRIFILE pFilePri, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string [] lpResNames, uint dwCount);
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void DestroyResourcesAllValuesList (IntPtr list);
|
||||
public static Dictionary<uint, string> ParseDWSPAIRLIST (IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
var result = new Dictionary<uint, string> ();
|
||||
|
||||
// 读取数量
|
||||
uint count = (uint)Marshal.ReadInt32 (ptr);
|
||||
|
||||
// 跳过 dwLength
|
||||
IntPtr pFirst = IntPtr.Add (ptr, sizeof (uint));
|
||||
|
||||
int elementSize = Marshal.SizeOf (typeof (DWORDWSTRPAIR));
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
IntPtr pItem = IntPtr.Add (pFirst, i * elementSize);
|
||||
|
||||
object boxed =
|
||||
Marshal.PtrToStructure (pItem, typeof (DWORDWSTRPAIR));
|
||||
|
||||
DWORDWSTRPAIR item = (DWORDWSTRPAIR)boxed;
|
||||
|
||||
string value = null;
|
||||
|
||||
if (item.lpValue != IntPtr.Zero)
|
||||
value = Marshal.PtrToStringUni (item.lpValue);
|
||||
|
||||
result [item.dwKey] = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
public static Dictionary<string, Dictionary<uint, string>> ParseWSDSPAIRLIST (IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
var result =
|
||||
new Dictionary<string, Dictionary<uint, string>> ();
|
||||
|
||||
uint count = (uint)Marshal.ReadInt32 (ptr);
|
||||
|
||||
IntPtr pFirst = IntPtr.Add (ptr, sizeof (uint));
|
||||
|
||||
int elementSize = Marshal.SizeOf (typeof (WSDSPAIR));
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
IntPtr pItem = IntPtr.Add (pFirst, i * elementSize);
|
||||
|
||||
object boxed =
|
||||
Marshal.PtrToStructure (pItem, typeof (WSDSPAIR));
|
||||
|
||||
WSDSPAIR item = (WSDSPAIR)boxed;
|
||||
|
||||
string key = null;
|
||||
|
||||
if (item.lpKey != IntPtr.Zero)
|
||||
key = Marshal.PtrToStringUni (item.lpKey);
|
||||
|
||||
Dictionary<uint, string> valueDict =
|
||||
ParseDWSPAIRLIST (item.lpValue);
|
||||
|
||||
result [key] = valueDict;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
internal struct WSTRWSTRPAIR
|
||||
{
|
||||
public IntPtr lpKey; // LPWSTR
|
||||
public IntPtr lpValue; // LPWSTR
|
||||
}
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr GetPriLocaleResourceAllValuesList (
|
||||
PCSPRIFILE pFilePri,
|
||||
[MarshalAs (UnmanagedType.LPWStr)] string lpResName);
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void DestroyLocaleResourceAllValuesList (IntPtr list);
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern IntPtr GetPriFileResourceAllValuesList (
|
||||
PCSPRIFILE pFilePri,
|
||||
[MarshalAs (UnmanagedType.LPWStr)] string lpResName);
|
||||
/// <summary>
|
||||
/// 将 HWSWSPAIRLIST 解析为 Dictionary<string, string>(语言代码 → 字符串值)
|
||||
/// </summary>
|
||||
public static Dictionary<string, string> ParseWSWSPAIRLIST (IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero) return null;
|
||||
|
||||
uint count = (uint)Marshal.ReadInt32 (ptr); // dwLength
|
||||
IntPtr pFirst = IntPtr.Add (ptr, sizeof (uint)); // 跳过 dwLength
|
||||
int elementSize = Marshal.SizeOf (typeof (WSTRWSTRPAIR));
|
||||
|
||||
var dict = new Dictionary<string, string> ((int)count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
IntPtr pItem = IntPtr.Add (pFirst, i * elementSize);
|
||||
var item = (WSTRWSTRPAIR)Marshal.PtrToStructure (pItem, typeof (WSTRWSTRPAIR));
|
||||
|
||||
string key = item.lpKey != IntPtr.Zero ? Marshal.PtrToStringUni (item.lpKey) : null;
|
||||
string value = item.lpValue != IntPtr.Zero ? Marshal.PtrToStringUni (item.lpValue) : null;
|
||||
if (key != null)
|
||||
dict [key] = value;
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
public static class LpcwstrListHelper
|
||||
{
|
||||
public static IntPtr Create (IEnumerable<string> strings)
|
||||
{
|
||||
if (strings == null) return IntPtr.Zero;
|
||||
var list = new List<string> (strings);
|
||||
int count = list.Count;
|
||||
int size = sizeof (uint) + IntPtr.Size * count;
|
||||
IntPtr pMem = Marshal.AllocHGlobal (size);
|
||||
Marshal.WriteInt32 (pMem, count);
|
||||
IntPtr pArray = pMem + sizeof (uint);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
IntPtr pStr = Marshal.StringToHGlobalUni (list [i]);
|
||||
Marshal.WriteIntPtr (pArray, i * IntPtr.Size, pStr);
|
||||
}
|
||||
return pMem;
|
||||
}
|
||||
public static void Destroy (IntPtr pList)
|
||||
{
|
||||
if (pList == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
int count = Marshal.ReadInt32 (pList);
|
||||
IntPtr pArray = pList + sizeof (uint);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
IntPtr pStr = Marshal.ReadIntPtr (pArray, i * IntPtr.Size);
|
||||
if (pStr != IntPtr.Zero)
|
||||
Marshal.FreeHGlobal (pStr);
|
||||
}
|
||||
Marshal.FreeHGlobal (pList);
|
||||
}
|
||||
}
|
||||
}
|
||||
454
AppxPackage/PriReader.cs
Normal file
454
AppxPackage/PriReader.cs
Normal file
@@ -0,0 +1,454 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AppxPackage
|
||||
{
|
||||
public struct PriResourceKey
|
||||
{
|
||||
public enum PriResourceType: byte
|
||||
{
|
||||
Scale = 0,
|
||||
TargetSize = 1,
|
||||
String = 2
|
||||
}
|
||||
public enum PriContrast: byte
|
||||
{
|
||||
None = 0,
|
||||
White = 1,
|
||||
Black = 2,
|
||||
High = 3,
|
||||
Low = 4
|
||||
}
|
||||
public readonly PriResourceType Type;
|
||||
public readonly PriContrast Contrast;
|
||||
public readonly ushort Value;
|
||||
public uint Raw { get; }
|
||||
public PriResourceKey (uint raw)
|
||||
{
|
||||
Raw = raw;
|
||||
Type = (PriResourceType)((raw >> 28) & 0xF);
|
||||
Contrast = (PriContrast)((raw >> 24) & 0xF);
|
||||
Value = (ushort)(raw & 0xFFFF);
|
||||
}
|
||||
public bool IsScale => Type == PriResourceType.Scale;
|
||||
public bool IsTargetSize => Type == PriResourceType.TargetSize;
|
||||
public bool IsString => Type == PriResourceType.String;
|
||||
public override string ToString ()
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case PriResourceType.Scale:
|
||||
return $"Scale={Value}, Contrast={Contrast}";
|
||||
case PriResourceType.TargetSize:
|
||||
return $"TargetSize={Value}, Contrast={Contrast}";
|
||||
case PriResourceType.String:
|
||||
return $"LCID=0x{Value:X4}";
|
||||
default:
|
||||
return $"Unknown(0x{Raw:X8})";
|
||||
}
|
||||
}
|
||||
}
|
||||
public class PriReader: IDisposable
|
||||
{
|
||||
private IntPtr m_hPriFile = IntPtr.Zero;
|
||||
public bool Valid { get { return m_hPriFile != IntPtr.Zero; } }
|
||||
public void Dispose ()
|
||||
{
|
||||
if (Valid)
|
||||
{
|
||||
PriFileHelper.DestroyPriFileInstance (m_hPriFile);
|
||||
m_hPriFile = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
~PriReader () { Dispose (); }
|
||||
public bool Create (IStream isfile)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose ();
|
||||
if (isfile == null) return false;
|
||||
var pStream = Marshal.GetComInterfaceForObject (isfile, typeof (IStream));
|
||||
m_hPriFile = PriFileHelper.CreatePriFileInstanceFromStream (pStream);
|
||||
}
|
||||
catch (Exception) { m_hPriFile = IntPtr.Zero; }
|
||||
return Valid;
|
||||
}
|
||||
public bool Create (IntPtr pStream)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose ();
|
||||
if (pStream == IntPtr.Zero) return false;
|
||||
m_hPriFile = PriFileHelper.CreatePriFileInstanceFromStream (pStream);
|
||||
}
|
||||
catch (Exception) { m_hPriFile = IntPtr.Zero; }
|
||||
return Valid;
|
||||
}
|
||||
public bool Create ([MarshalAs (UnmanagedType.LPWStr)] string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispose ();
|
||||
if (string.IsNullOrWhiteSpace (filePath)) return false;
|
||||
m_hPriFile = PriFileHelper.CreatePriFileInstanceFromPath (filePath);
|
||||
}
|
||||
catch (Exception) { m_hPriFile = IntPtr.Zero; }
|
||||
return Valid;
|
||||
}
|
||||
public PriReader (IStream isfile) { Create (isfile); }
|
||||
public PriReader (IntPtr pStream) { Create (pStream); }
|
||||
public PriReader ([MarshalAs (UnmanagedType.LPWStr)] string fileName) { Create (fileName); }
|
||||
public PriReader () { }
|
||||
public void AddSearch (IEnumerable<string> arr)
|
||||
{
|
||||
IntPtr buf = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
if (arr == null) return;
|
||||
buf = LpcwstrListHelper.Create (arr);
|
||||
PriFileHelper.FindPriResource (m_hPriFile, buf);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (buf != IntPtr.Zero) LpcwstrListHelper.Destroy (buf);
|
||||
}
|
||||
}
|
||||
public void AddSearch (string uri) { AddSearch (new string [] { uri }); }
|
||||
public string Resource (string resName)
|
||||
{
|
||||
var task = Task.Factory.StartNew (() => {
|
||||
IntPtr ret = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
ret = PriFileHelper.GetPriResource (m_hPriFile, resName);
|
||||
if (ret == IntPtr.Zero) return string.Empty;
|
||||
return PriFileHelper.PtrToString (ret);
|
||||
}
|
||||
finally
|
||||
{
|
||||
//if (ret != IntPtr.Zero) PriFileHelper.FreePriString(ret);
|
||||
}
|
||||
});
|
||||
return task.Result;
|
||||
}
|
||||
public Dictionary<string, string> Resources (IEnumerable<string> resnames)
|
||||
{
|
||||
if (resnames == null) throw new ArgumentNullException (nameof (resnames));
|
||||
var result = new Dictionary<string, string> ();
|
||||
AddSearch (resnames);
|
||||
foreach (var name in resnames) result [name] = Resource (name);
|
||||
return result;
|
||||
}
|
||||
public static string LastError { get { return PriFileHelper.PriFileGetLastError (); } }
|
||||
public string Path (string resName) { return Resource (resName); }
|
||||
public Dictionary<string, string> Paths (IEnumerable<string> resNames) { return Resources (resNames); }
|
||||
public string String (string resName) { return Resource (resName); }
|
||||
public Dictionary<string, string> Strings (IEnumerable<string> resNames) { return Resources (resNames); }
|
||||
public Dictionary<PriResourceKey, string> ResourceAllValues (string resName)
|
||||
{
|
||||
var task = Task.Factory.StartNew (() => {
|
||||
IntPtr ptr = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
ptr = PriFileHelper.GetPriResourceAllValueList (
|
||||
m_hPriFile, resName);
|
||||
|
||||
if (ptr == IntPtr.Zero)
|
||||
return new Dictionary<PriResourceKey, string> ();
|
||||
|
||||
var raw =
|
||||
PriFileHelper.ParseDWSPAIRLIST (ptr);
|
||||
|
||||
var result =
|
||||
new Dictionary<PriResourceKey, string> ();
|
||||
|
||||
foreach (var kv in raw)
|
||||
{
|
||||
var key = new PriResourceKey (kv.Key);
|
||||
result [key] = kv.Value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (ptr != IntPtr.Zero) PriFileHelper.DestroyPriResourceAllValueList (ptr);
|
||||
}
|
||||
});
|
||||
return task.Result;
|
||||
}
|
||||
public Dictionary<string, Dictionary<PriResourceKey, string>> ResourcesAllValues (IEnumerable<string> resNames)
|
||||
{
|
||||
var task = Task.Factory.StartNew (() => {
|
||||
IntPtr ptr = IntPtr.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
var list = resNames?.ToList ();
|
||||
|
||||
if (list == null || list.Count == 0)
|
||||
return new Dictionary<string,
|
||||
Dictionary<PriResourceKey, string>> ();
|
||||
|
||||
ptr = PriFileHelper.GetPriResourcesAllValuesList (
|
||||
m_hPriFile,
|
||||
list.ToArray (),
|
||||
(uint)list.Count);
|
||||
|
||||
if (ptr == IntPtr.Zero)
|
||||
return new Dictionary<string,
|
||||
Dictionary<PriResourceKey, string>> ();
|
||||
|
||||
var raw =
|
||||
PriFileHelper.ParseWSDSPAIRLIST (ptr);
|
||||
|
||||
var result =
|
||||
new Dictionary<string,
|
||||
Dictionary<PriResourceKey, string>> ();
|
||||
|
||||
foreach (var outer in raw)
|
||||
{
|
||||
var innerDict =
|
||||
new Dictionary<PriResourceKey, string> ();
|
||||
|
||||
foreach (var inner in outer.Value)
|
||||
{
|
||||
var key =
|
||||
new PriResourceKey (inner.Key);
|
||||
|
||||
innerDict [key] = inner.Value;
|
||||
}
|
||||
|
||||
result [outer.Key] = innerDict;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (ptr != IntPtr.Zero)
|
||||
PriFileHelper.DestroyResourcesAllValuesList (ptr);
|
||||
}
|
||||
});
|
||||
|
||||
return task.Result;
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取指定字符串资源的所有语言变体(语言代码 → 字符串值)
|
||||
/// </summary>
|
||||
public Dictionary<string, string> LocaleResourceAllValue (string resName)
|
||||
{
|
||||
var task = Task.Factory.StartNew (() =>
|
||||
{
|
||||
IntPtr ptr = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
// 修正:第一个参数应为 m_hPriFile,而不是 ptr
|
||||
ptr = PriFileHelper.GetPriLocaleResourceAllValuesList (m_hPriFile, resName);
|
||||
if (ptr == IntPtr.Zero)
|
||||
return new Dictionary<string, string> ();
|
||||
|
||||
// 解析 HWSWSPAIRLIST 为 Dictionary<string, string>
|
||||
var raw = PriFileHelper.ParseWSWSPAIRLIST (ptr);
|
||||
return raw ?? new Dictionary<string, string> ();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (ptr != IntPtr.Zero)
|
||||
PriFileHelper.DestroyLocaleResourceAllValuesList (ptr);
|
||||
}
|
||||
});
|
||||
return task.Result;
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取指定文件资源的所有缩放/对比度/目标大小变体(PriResourceKey → 文件路径)
|
||||
/// </summary>
|
||||
public Dictionary<PriResourceKey, string> PathResourceAllValue (string resName)
|
||||
{
|
||||
var task = Task.Factory.StartNew (() =>
|
||||
{
|
||||
IntPtr ptr = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
ptr = PriFileHelper.GetPriFileResourceAllValuesList (m_hPriFile, resName);
|
||||
if (ptr == IntPtr.Zero)
|
||||
return new Dictionary<PriResourceKey, string> ();
|
||||
|
||||
// 解析 HDWSPAIRLIST 为 Dictionary<uint, string>
|
||||
var raw = PriFileHelper.ParseDWSPAIRLIST (ptr);
|
||||
if (raw == null)
|
||||
return new Dictionary<PriResourceKey, string> ();
|
||||
|
||||
// 将 uint 键转换为 PriResourceKey
|
||||
var result = new Dictionary<PriResourceKey, string> ();
|
||||
foreach (var kv in raw)
|
||||
{
|
||||
var key = new PriResourceKey (kv.Key);
|
||||
result [key] = kv.Value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (ptr != IntPtr.Zero)
|
||||
PriFileHelper.DestroyPriResourceAllValueList (ptr); // 注意:使用对应的释放函数
|
||||
}
|
||||
});
|
||||
return task.Result;
|
||||
}
|
||||
}
|
||||
public class PriReaderBundle: IDisposable
|
||||
{
|
||||
private class PriInst
|
||||
{
|
||||
public byte Type; // 0b01 lang, 0b10 scale, 0b11 both
|
||||
public PriReader Reader;
|
||||
public PriInst (byte type, IStream stream)
|
||||
{
|
||||
Type = (byte)(type & 0x03);
|
||||
Reader = new PriReader (stream);
|
||||
}
|
||||
public PriInst (byte type, IntPtr stream)
|
||||
{
|
||||
Type = (byte)(type & 0x03);
|
||||
Reader = new PriReader (stream);
|
||||
}
|
||||
public bool IsValid
|
||||
{
|
||||
get { return (Type & 0x03) != 0; }
|
||||
}
|
||||
}
|
||||
private readonly List<PriInst> _priFiles = new List<PriInst> (3);
|
||||
private readonly Dictionary<byte, PriInst> _mapPri = new Dictionary<byte, PriInst> ();
|
||||
// type: 1 language, 2 scale, 3 both
|
||||
public bool Set (byte type, IStream priStream)
|
||||
{
|
||||
byte realType = (byte)(type & 0x03);
|
||||
if (realType == 0) return false;
|
||||
PriInst inst;
|
||||
if (_mapPri.TryGetValue (realType, out inst))
|
||||
{
|
||||
inst.Reader.Dispose ();
|
||||
if (priStream != null) inst.Reader.Create (priStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (priStream == null) return false;
|
||||
inst = new PriInst (realType, priStream);
|
||||
_priFiles.Add (inst);
|
||||
_mapPri [realType] = inst;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public bool Set (byte type, IntPtr priStream)
|
||||
{
|
||||
byte realType = (byte)(type & 0x03);
|
||||
if (realType == 0) return false;
|
||||
PriInst inst;
|
||||
if (_mapPri.TryGetValue (realType, out inst))
|
||||
{
|
||||
inst.Reader.Dispose ();
|
||||
if (priStream != IntPtr.Zero) inst.Reader.Create (priStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (priStream == IntPtr.Zero) return false;
|
||||
inst = new PriInst (realType, priStream);
|
||||
_priFiles.Add (inst);
|
||||
_mapPri [realType] = inst;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private PriReader Get (byte type, bool mustReturn)
|
||||
{
|
||||
type = (byte)(type & 0x03);
|
||||
PriInst inst;
|
||||
if (_mapPri.TryGetValue (type, out inst)) return inst.Reader;
|
||||
if (type != 0x03 && _mapPri.TryGetValue (0x03, out inst)) return inst.Reader;
|
||||
if (_priFiles.Count > 0 && mustReturn) return _priFiles [0].Reader;
|
||||
return null;
|
||||
}
|
||||
private static bool IsMsResourcePrefix (string s)
|
||||
{
|
||||
return PriFileHelper.IsMsResourcePrefix (s);
|
||||
}
|
||||
public void AddSearch (IEnumerable<string> arr)
|
||||
{
|
||||
if (arr == null) return;
|
||||
List<string> strRes = new List<string> ();
|
||||
List<string> pathRes = new List<string> ();
|
||||
foreach (string it in arr)
|
||||
{
|
||||
if (IsMsResourcePrefix (it)) strRes.Add (it);
|
||||
else pathRes.Add (it);
|
||||
}
|
||||
PriReader langPri = Get (1, true);
|
||||
PriReader scalePri = Get (2, true);
|
||||
if (langPri != null && strRes.Count > 0) langPri.AddSearch (strRes);
|
||||
if (scalePri != null && pathRes.Count > 0) scalePri.AddSearch (pathRes);
|
||||
}
|
||||
public void AddSearch (string resName)
|
||||
{
|
||||
if (IsMsResourcePrefix (resName))
|
||||
{
|
||||
PriReader langPri = Get (1, true);
|
||||
if (langPri != null) langPri.AddSearch (resName);
|
||||
}
|
||||
else
|
||||
{
|
||||
PriReader scalePri = Get (2, true);
|
||||
if (scalePri != null) scalePri.AddSearch (resName);
|
||||
}
|
||||
}
|
||||
public string Resource (string resName)
|
||||
{
|
||||
if (IsMsResourcePrefix (resName))
|
||||
{
|
||||
PriReader langPri = Get (1, true);
|
||||
return langPri != null ? langPri.Resource (resName) : string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
PriReader scalePri = Get (2, true);
|
||||
return scalePri != null ? scalePri.Resource (resName) : string.Empty;
|
||||
}
|
||||
}
|
||||
public Dictionary<string, string> Resources (IEnumerable<string> resNames)
|
||||
{
|
||||
if (resNames == null) throw new ArgumentNullException ("resNames");
|
||||
Dictionary<string, string> result = new Dictionary<string, string> ();
|
||||
AddSearch (resNames);
|
||||
foreach (string name in resNames) result [name] = Resource (name);
|
||||
return result;
|
||||
}
|
||||
public string Path (string resName)
|
||||
{
|
||||
return Resource (resName);
|
||||
}
|
||||
public Dictionary<string, string> Paths (IEnumerable<string> resNames)
|
||||
{
|
||||
return Resources (resNames);
|
||||
}
|
||||
public string String (string resName)
|
||||
{
|
||||
return Resource (resName);
|
||||
}
|
||||
public Dictionary<string, string> Strings (IEnumerable<string> resNames)
|
||||
{
|
||||
return Resources (resNames);
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
foreach (PriInst it in _priFiles) it.Reader.Dispose ();
|
||||
_mapPri.Clear ();
|
||||
_priFiles.Clear ();
|
||||
}
|
||||
}
|
||||
}
|
||||
36
AppxPackage/Properties/AssemblyInfo.cs
Normal file
36
AppxPackage/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("AppxPackage")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("AppxPackage")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2026")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//将 ComVisible 设置为 false 将使此程序集中的类型
|
||||
//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible (true)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("bd681a4f-eb60-4bb8-90b5-65968fc7da59")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
|
||||
// 方法是按如下所示使用“*”: :
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
67
AppxPackage/Utils.cs
Normal file
67
AppxPackage/Utils.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
internal static class Utils
|
||||
{
|
||||
public static string PascalToCamel (string pascalCase)
|
||||
{
|
||||
if (string.IsNullOrEmpty (pascalCase))
|
||||
return pascalCase;
|
||||
|
||||
// 已经是小驼峰或首字母小写,直接返回
|
||||
if (char.IsLower (pascalCase [0]))
|
||||
return pascalCase;
|
||||
|
||||
// 按大写字母边界拆分单词(处理连续大写字母作为一个单词)
|
||||
// 正则解释:
|
||||
// (?<=[a-z])(?=[A-Z]) 小写后跟大写 -> 分割
|
||||
// | 或
|
||||
// (?<=[A-Z])(?=[A-Z][a-z]) 大写后跟大写+小写(如 XMLR 中的 X 和 MLR)-> 分割
|
||||
string [] words = Regex.Split (pascalCase, @"(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])");
|
||||
|
||||
StringBuilder result = new StringBuilder ();
|
||||
|
||||
for (int i = 0; i < words.Length; i++)
|
||||
{
|
||||
string word = words [i];
|
||||
if (string.IsNullOrEmpty (word))
|
||||
continue;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
// 第一个单词:全部转为小写
|
||||
result.Append (word.ToLowerInvariant ());
|
||||
}
|
||||
else
|
||||
{
|
||||
// 后续单词:首字母大写,其余小写
|
||||
result.Append (char.ToUpperInvariant (word [0]));
|
||||
if (word.Length > 1)
|
||||
result.Append (word.Substring (1).ToLowerInvariant ());
|
||||
}
|
||||
}
|
||||
|
||||
return result.ToString ();
|
||||
}
|
||||
/// <summary>
|
||||
/// 表示应用清单中用于定义文件/资源路径的属性名称
|
||||
/// </summary>
|
||||
public static readonly List<string> AppFileProperties = new List<string>
|
||||
{
|
||||
"Executable",
|
||||
"LockScreenLogo",
|
||||
"Logo",
|
||||
"SmallLogo",
|
||||
"Square150x150Logo",
|
||||
"Square30x30Logo",
|
||||
"Square310x310Logo",
|
||||
"Square44x44Logo",
|
||||
"Square70x70Logo",
|
||||
"Square71x71Logo",
|
||||
"StartPage",
|
||||
"Tall150x310Logo",
|
||||
"WideLogo",
|
||||
"Wide310x150Logo"
|
||||
};
|
||||
}
|
||||
5
AppxPackage/packages.config
Normal file
5
AppxPackage/packages.config
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="13.0.4" targetFramework="net40" />
|
||||
<package id="SharpZipLib" version="0.86.0" targetFramework="net40" />
|
||||
</packages>
|
||||
62
ArmBuild.ps1
Normal file
62
ArmBuild.ps1
Normal file
@@ -0,0 +1,62 @@
|
||||
# ArmBuild.ps1
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$root = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$staging = Join-Path $root "_staging"
|
||||
$outZip = Join-Path $root "ArmPackage.zip"
|
||||
$packageFolderName = "Desktop App Installer"
|
||||
$destRoot = Join-Path $staging $packageFolderName
|
||||
|
||||
function Copy-Binaries-ToDest($src, $dest)
|
||||
{
|
||||
if (!(Test-Path $src)) { return }
|
||||
|
||||
Get-ChildItem $src -File | Where-Object {
|
||||
$_.Extension -in ".exe", ".dll"
|
||||
} | ForEach-Object {
|
||||
Copy-Item -Path $_.FullName -Destination $dest -Force
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Preparing staging..."
|
||||
# 清理旧的 staging
|
||||
if (Test-Path $staging) { Remove-Item $staging -Recurse -Force }
|
||||
New-Item $destRoot -ItemType Directory | Out-Null
|
||||
|
||||
# ① 先放 Release
|
||||
Copy-Binaries-ToDest (Join-Path $root "Release") $destRoot
|
||||
|
||||
# ② 再放 ARM\Release(覆盖同名)
|
||||
Copy-Binaries-ToDest (Join-Path $root "ARM\Release") $destRoot
|
||||
|
||||
# ③ shared 全部铺到 Desktop App Installer 里
|
||||
$shared = Join-Path $root "shared"
|
||||
if (Test-Path $shared) {
|
||||
Get-ChildItem $shared -Recurse | ForEach-Object {
|
||||
$relativePath = $_.FullName.Substring($shared.Length).TrimStart('\')
|
||||
$destinationPath = Join-Path $destRoot $relativePath
|
||||
|
||||
if ($_.PSIsContainer) {
|
||||
if (!(Test-Path $destinationPath)) {
|
||||
New-Item -Path $destinationPath -ItemType Directory | Out-Null
|
||||
}
|
||||
} else {
|
||||
$parentDir = Split-Path $destinationPath -Parent
|
||||
if (!(Test-Path $parentDir)) {
|
||||
New-Item -Path $parentDir -ItemType Directory | Out-Null
|
||||
}
|
||||
Copy-Item -Path $_.FullName -Destination $destinationPath -Force
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Creating ZIP..."
|
||||
if (Test-Path $outZip) { Remove-Item $outZip -Force }
|
||||
|
||||
# 压缩 _staging 下的 Desktop App Installer 文件夹
|
||||
Compress-Archive -Path $destRoot -DestinationPath $outZip -CompressionLevel Optimal
|
||||
|
||||
# 清理 staging
|
||||
Remove-Item $staging -Recurse -Force
|
||||
|
||||
Write-Host "Done: $outZip"
|
||||
10
ArmDesktopSdk.props
Normal file
10
ArmDesktopSdk.props
Normal file
@@ -0,0 +1,10 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemDefinitionGroup Condition="'$(Platform)'=='ARM'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM'">
|
||||
<WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
102
Bridge/Bridge.csproj
Normal file
102
Bridge/Bridge.csproj
Normal file
@@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{3C2F5446-33F0-41D5-813A-64A94AA474AF}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Bridge</RootNamespace>
|
||||
<AssemblyName>Bridge</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<LangVersion>default</LangVersion>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<LangVersion>default</LangVersion>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="SysInit.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AppxPackage\AppxPackage.csproj">
|
||||
<Project>{bd681a4f-eb60-4bb8-90b5-65968fc7da59}</Project>
|
||||
<Name>AppxPackage</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\DataUtils\DataUtils.csproj">
|
||||
<Project>{ffd3fd52-37a8-4f43-883c-de8d996cb0e0}</Project>
|
||||
<Name>DataUtils</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\ModernNotice\ModernNotice.csproj">
|
||||
<Project>{c5587b6e-19c4-4484-aa97-5c20fbb07e43}</Project>
|
||||
<Name>ModernNotice</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\PrivateInit\PrivateInit.csproj">
|
||||
<Project>{8e708d9a-6325-4aa9-b5a5-d1b5eca8eef7}</Project>
|
||||
<Name>PrivateInit</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.manifest" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
36
Bridge/Properties/AssemblyInfo.cs
Normal file
36
Bridge/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("Bridge")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Bridge")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2026")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//将 ComVisible 设置为 false 将使此程序集中的类型
|
||||
//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible (true)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("3c2f5446-33f0-41d5-813a-64a94aa474af")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
|
||||
// 方法是按如下所示使用“*”: :
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
966
Bridge/SysInit.cs
Normal file
966
Bridge/SysInit.cs
Normal file
@@ -0,0 +1,966 @@
|
||||
using System;
|
||||
using Win32;
|
||||
using DataUtils;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using Newtonsoft.Json;
|
||||
using AppxPackage;
|
||||
using ModernNotice;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Bridge
|
||||
{
|
||||
public static class InitFileStore
|
||||
{
|
||||
public static readonly InitConfig Config;
|
||||
static InitFileStore ()
|
||||
{
|
||||
try
|
||||
{
|
||||
string programRoot = GetProgramRootDirectory ();
|
||||
string manifestPath = Path.Combine (programRoot, "config.ini");
|
||||
Config = new InitConfig (manifestPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Config = new InitConfig ();
|
||||
}
|
||||
}
|
||||
public static string GetProgramRootDirectory ()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Prefer the directory of the executing assembly
|
||||
string codeBase = Assembly.GetExecutingAssembly ().Location;
|
||||
if (!string.IsNullOrEmpty (codeBase))
|
||||
{
|
||||
string dir = Path.GetDirectoryName (codeBase);
|
||||
if (!string.IsNullOrEmpty (dir)) return dir;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
return AppDomain.CurrentDomain.BaseDirectory ?? Environment.CurrentDirectory;
|
||||
}
|
||||
catch { }
|
||||
|
||||
return Environment.CurrentDirectory;
|
||||
}
|
||||
}
|
||||
public static class ResXmlStore
|
||||
{
|
||||
public static readonly StringResXmlDoc StringRes;
|
||||
static ResXmlStore ()
|
||||
{
|
||||
try
|
||||
{
|
||||
string programRoot = InitFileStore.GetProgramRootDirectory ();
|
||||
string manifestPath = Path.Combine (programRoot, "locale\\resources.xml");
|
||||
StringRes = new StringResXmlDoc (manifestPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
StringRes = new StringResXmlDoc ();
|
||||
}
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_InitConfig
|
||||
{
|
||||
public InitConfig Create (string filepath) => new InitConfig (filepath);
|
||||
public InitConfig GetConfig () => InitFileStore.Config;
|
||||
public InitConfig Current => InitFileStore.Config;
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_System
|
||||
{
|
||||
private readonly _I_Resources ires = new _I_Resources ();
|
||||
private readonly _I_Locale ilocale = new _I_Locale ();
|
||||
private readonly _I_UI ui;
|
||||
public _I_Resources Resources { get { return ires; } }
|
||||
public _I_Locale Locale { get { return ilocale; } }
|
||||
public _I_UI UI => ui;
|
||||
// Determines if the OS major version is 10 or greater.
|
||||
// Uses RtlGetVersion for a reliable OS version.
|
||||
public bool IsWindows10
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
OSVERSIONINFOEX info = new OSVERSIONINFOEX ();
|
||||
info.dwOSVersionInfoSize = Marshal.SizeOf (typeof (OSVERSIONINFOEX));
|
||||
int status = RtlGetVersion (ref info);
|
||||
if (status == 0) // STATUS_SUCCESS
|
||||
{
|
||||
return info.dwMajorVersion >= 10;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// fallback below
|
||||
}
|
||||
|
||||
// Fallback: Environment.OSVersion (may be unreliable on some systems)
|
||||
try
|
||||
{
|
||||
return Environment.OSVersion.Version.Major >= 10;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#region Native interop (RtlGetVersion)
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
private struct OSVERSIONINFOEX
|
||||
{
|
||||
public int dwOSVersionInfoSize;
|
||||
public int dwMajorVersion;
|
||||
public int dwMinorVersion;
|
||||
public int dwBuildNumber;
|
||||
public int dwPlatformId;
|
||||
[MarshalAs (UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string szCSDVersion;
|
||||
public ushort wServicePackMajor;
|
||||
public ushort wServicePackMinor;
|
||||
public ushort wSuiteMask;
|
||||
public byte wProductType;
|
||||
public byte wReserved;
|
||||
}
|
||||
// RtlGetVersion returns NTSTATUS (0 = STATUS_SUCCESS)
|
||||
[DllImport ("ntdll.dll", SetLastError = false)]
|
||||
private static extern int RtlGetVersion (ref OSVERSIONINFOEX versionInfo);
|
||||
#endregion
|
||||
public _I_System (Form mainWnd)
|
||||
{
|
||||
ui = new _I_UI (mainWnd);
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_PackageManager
|
||||
{
|
||||
public enum JsAsyncResultKind
|
||||
{
|
||||
Success,
|
||||
Failed,
|
||||
None // 什么都不回调(极少数情况)
|
||||
}
|
||||
public sealed class JsAsyncResult
|
||||
{
|
||||
public JsAsyncResultKind Kind { get; private set; }
|
||||
public object Value { get; private set; }
|
||||
private JsAsyncResult (JsAsyncResultKind kind, object value)
|
||||
{
|
||||
Kind = kind;
|
||||
Value = value;
|
||||
}
|
||||
public static JsAsyncResult Success (object value = null)
|
||||
{
|
||||
return new JsAsyncResult (JsAsyncResultKind.Success, value);
|
||||
}
|
||||
public static JsAsyncResult Failed (object value = null)
|
||||
{
|
||||
return new JsAsyncResult (JsAsyncResultKind.Failed, value);
|
||||
}
|
||||
public static JsAsyncResult None ()
|
||||
{
|
||||
return new JsAsyncResult (JsAsyncResultKind.None, null);
|
||||
}
|
||||
}
|
||||
internal static class JsAsyncRunner
|
||||
{
|
||||
private static readonly int MaxConcurrency =
|
||||
Math.Min (8, Environment.ProcessorCount * 2);
|
||||
|
||||
private static readonly SemaphoreSlim _semaphore =
|
||||
new SemaphoreSlim (MaxConcurrency);
|
||||
|
||||
private static CancellationTokenSource _cts =
|
||||
new CancellationTokenSource ();
|
||||
|
||||
public static Task Run (
|
||||
Func<CancellationToken, Action<object>, JsAsyncResult> work,
|
||||
object jsSuccess,
|
||||
object jsFailed,
|
||||
object jsProgress)
|
||||
{
|
||||
var success = jsSuccess;
|
||||
var failed = jsFailed;
|
||||
var progress = jsProgress;
|
||||
var token = _cts.Token;
|
||||
|
||||
return Task.Factory.StartNew (() =>
|
||||
{
|
||||
bool entered = false;
|
||||
|
||||
try
|
||||
{
|
||||
_semaphore.Wait (token);
|
||||
entered = true;
|
||||
|
||||
token.ThrowIfCancellationRequested ();
|
||||
|
||||
Action<object> reportProgress = p =>
|
||||
{
|
||||
if (!token.IsCancellationRequested && progress != null)
|
||||
CallJS (progress, p);
|
||||
};
|
||||
|
||||
var result = work (token, reportProgress);
|
||||
|
||||
if (token.IsCancellationRequested || result == null)
|
||||
return;
|
||||
|
||||
switch (result.Kind)
|
||||
{
|
||||
case JsAsyncResultKind.Success:
|
||||
CallJS (success, result.Value);
|
||||
break;
|
||||
|
||||
case JsAsyncResultKind.Failed:
|
||||
CallJS (failed, result.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// 只对“已进入执行态”的任务回调取消
|
||||
if (!entered)
|
||||
return;
|
||||
|
||||
var cancelObj = new
|
||||
{
|
||||
status = false,
|
||||
canceled = true,
|
||||
message = "Operation canceled",
|
||||
jsontext = ""
|
||||
};
|
||||
|
||||
CallJS (failed,
|
||||
Newtonsoft.Json.JsonConvert.SerializeObject (cancelObj));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errObj = new
|
||||
{
|
||||
status = false,
|
||||
message = ex.Message,
|
||||
jsontext = ""
|
||||
};
|
||||
|
||||
CallJS (failed,
|
||||
Newtonsoft.Json.JsonConvert.SerializeObject (errObj));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (entered)
|
||||
_semaphore.Release ();
|
||||
}
|
||||
},
|
||||
token,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Default);
|
||||
}
|
||||
|
||||
private static void CallJS (object jsFunc, params object [] args)
|
||||
{
|
||||
if (jsFunc == null) return;
|
||||
try
|
||||
{
|
||||
object [] invokeArgs = new object [(args?.Length ?? 0) + 1];
|
||||
invokeArgs [0] = 1;
|
||||
if (args != null)
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
invokeArgs [i + 1] = args [i];
|
||||
|
||||
jsFunc.GetType ().InvokeMember (
|
||||
"call",
|
||||
BindingFlags.InvokeMethod,
|
||||
null,
|
||||
jsFunc,
|
||||
invokeArgs);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
// 兼容旧版:只有 reportProgress 的写法
|
||||
public static Task Run (
|
||||
Func<Action<object>, JsAsyncResult> work,
|
||||
object jsSuccess,
|
||||
object jsFailed,
|
||||
object jsProgress)
|
||||
{
|
||||
return Run (
|
||||
(token, report) => {
|
||||
token.ThrowIfCancellationRequested ();
|
||||
return work (report);
|
||||
},
|
||||
jsSuccess,
|
||||
jsFailed,
|
||||
jsProgress
|
||||
);
|
||||
}
|
||||
|
||||
public static void CancelAll ()
|
||||
{
|
||||
var old = _cts;
|
||||
_cts = new CancellationTokenSource ();
|
||||
old.Cancel ();
|
||||
old.Dispose ();
|
||||
}
|
||||
}
|
||||
private string BuildJsonText (object obj)
|
||||
{
|
||||
return Newtonsoft.Json.JsonConvert.SerializeObject (
|
||||
obj,
|
||||
Newtonsoft.Json.Formatting.Indented
|
||||
);
|
||||
}
|
||||
public void AddPackage (string path, int options, object success, object failed, object progress)
|
||||
{
|
||||
JsAsyncRunner.Run (
|
||||
report => {
|
||||
var hr = PackageManager.AddPackage (
|
||||
path,
|
||||
null,
|
||||
(DeploymentOptions)options,
|
||||
e => report (e)
|
||||
);
|
||||
if (hr == null) return JsAsyncResult.Failed ("Unknown error");
|
||||
return hr.Succeeded ? JsAsyncResult.Success (hr) : JsAsyncResult.Failed (hr);
|
||||
},
|
||||
success,
|
||||
failed,
|
||||
progress
|
||||
);
|
||||
}
|
||||
public void GetPackages (object success, object failed)
|
||||
{
|
||||
JsAsyncRunner.Run (
|
||||
report => {
|
||||
var res = PackageManager.GetPackages ();
|
||||
var hr = res.Item1;
|
||||
var jsstr = "";
|
||||
{
|
||||
var ret = new
|
||||
{
|
||||
result = res.Item1,
|
||||
list = res.Item2
|
||||
};
|
||||
jsstr = BuildJsonText (ret);
|
||||
}
|
||||
if (hr == null) return JsAsyncResult.Failed (jsstr);
|
||||
return hr.Succeeded ? JsAsyncResult.Success (jsstr) : JsAsyncResult.Failed (jsstr);
|
||||
},
|
||||
success,
|
||||
failed,
|
||||
null
|
||||
);
|
||||
}
|
||||
public void RemovePackage (string packageFullName, object success, object failed, object progress)
|
||||
{
|
||||
JsAsyncRunner.Run (
|
||||
report => {
|
||||
var hr = PackageManager.RemovePackage (
|
||||
packageFullName,
|
||||
e => report (e)
|
||||
);
|
||||
if (hr == null) return JsAsyncResult.Failed ("Unknown error");
|
||||
return hr.Succeeded ? JsAsyncResult.Success (hr) : JsAsyncResult.Failed (hr);
|
||||
},
|
||||
success,
|
||||
failed,
|
||||
progress
|
||||
);
|
||||
}
|
||||
public void ClearupPackage (string packageName, string userSID, object success, object failed, object progress)
|
||||
{
|
||||
JsAsyncRunner.Run (
|
||||
report => {
|
||||
var hr = PackageManager.ClearupPackage (
|
||||
packageName,
|
||||
userSID,
|
||||
e => report (e)
|
||||
);
|
||||
if (hr == null) return JsAsyncResult.Failed ("Unknown error");
|
||||
return hr.Succeeded ? JsAsyncResult.Success (hr) : JsAsyncResult.Failed (hr);
|
||||
},
|
||||
success,
|
||||
failed,
|
||||
progress
|
||||
);
|
||||
}
|
||||
public void RegisterPackage (string path, int options, object success, object failed, object progress)
|
||||
{
|
||||
JsAsyncRunner.Run (
|
||||
report => {
|
||||
var hr = PackageManager.RegisterPackage (
|
||||
path,
|
||||
null,
|
||||
(DeploymentOptions)options,
|
||||
e => report (e)
|
||||
);
|
||||
if (hr == null) return JsAsyncResult.Failed ("Unknown error");
|
||||
return hr.Succeeded ? JsAsyncResult.Success (hr) : JsAsyncResult.Failed (hr);
|
||||
},
|
||||
success,
|
||||
failed,
|
||||
progress
|
||||
);
|
||||
}
|
||||
public void RegisterPackageByFullName (string packageFullName, int options, object success, object failed, object progress)
|
||||
{
|
||||
JsAsyncRunner.Run (
|
||||
report => {
|
||||
var hr = PackageManager.RegisterPackageByFullName (
|
||||
packageFullName,
|
||||
null,
|
||||
(DeploymentOptions)options,
|
||||
e => report (e)
|
||||
);
|
||||
if (hr == null) return JsAsyncResult.Failed ("Unknown error");
|
||||
return hr.Succeeded ? JsAsyncResult.Success (hr) : JsAsyncResult.Failed (hr);
|
||||
},
|
||||
success,
|
||||
failed,
|
||||
progress
|
||||
);
|
||||
}
|
||||
public _I_HResult SetPackageStatus (string packageFullName, int status)
|
||||
{
|
||||
return PackageManager.SetPackageStatus (packageFullName, (PackageStatus)status);
|
||||
}
|
||||
public void StagePackage (string path, int options, object success, object failed, object progress)
|
||||
{
|
||||
JsAsyncRunner.Run (
|
||||
report => {
|
||||
var hr = PackageManager.StagePackage (
|
||||
path,
|
||||
null,
|
||||
(DeploymentOptions)options,
|
||||
e => report (e)
|
||||
);
|
||||
if (hr == null) return JsAsyncResult.Failed ("Unknown error");
|
||||
return hr.Succeeded ? JsAsyncResult.Success (hr) : JsAsyncResult.Failed (hr);
|
||||
},
|
||||
success,
|
||||
failed,
|
||||
progress
|
||||
);
|
||||
}
|
||||
public void StageUserData (string packageFullName, object success, object failed, object progress)
|
||||
{
|
||||
JsAsyncRunner.Run (
|
||||
report => {
|
||||
var hr = PackageManager.StageUserData (
|
||||
packageFullName,
|
||||
e => report (e)
|
||||
);
|
||||
if (hr == null) return JsAsyncResult.Failed ("Unknown error");
|
||||
return hr.Succeeded ? JsAsyncResult.Success (hr) : JsAsyncResult.Failed (hr);
|
||||
},
|
||||
success,
|
||||
failed,
|
||||
progress
|
||||
);
|
||||
}
|
||||
public void UpdatePackage (string path, int options, object success, object failed, object progress)
|
||||
{
|
||||
JsAsyncRunner.Run (
|
||||
report => {
|
||||
var hr = PackageManager.UpdatePackage (
|
||||
path,
|
||||
null,
|
||||
(DeploymentOptions)options,
|
||||
e => report (e)
|
||||
);
|
||||
if (hr == null) return JsAsyncResult.Failed ("Unknown error");
|
||||
return hr.Succeeded ? JsAsyncResult.Success (hr) : JsAsyncResult.Failed (hr);
|
||||
},
|
||||
success,
|
||||
failed,
|
||||
progress
|
||||
);
|
||||
}
|
||||
public void FindPackageByIdentity (string packageName, string packagePublisher, object success, object failed)
|
||||
{
|
||||
JsAsyncRunner.Run (
|
||||
report => {
|
||||
var res = PackageManager.FindPackage (packageName, packagePublisher);
|
||||
var hr = res.Item1;
|
||||
var jsstr = "";
|
||||
{
|
||||
var ret = new
|
||||
{
|
||||
result = res.Item1,
|
||||
list = res.Item2
|
||||
};
|
||||
jsstr = BuildJsonText (ret);
|
||||
}
|
||||
if (hr == null) return JsAsyncResult.Failed (jsstr);
|
||||
return hr.Succeeded ? JsAsyncResult.Success (jsstr) : JsAsyncResult.Failed (jsstr);
|
||||
},
|
||||
success,
|
||||
failed,
|
||||
null
|
||||
);
|
||||
}
|
||||
public void FindPackageByFamilyName (string packageFamilyName, object success, object failed)
|
||||
{
|
||||
JsAsyncRunner.Run (
|
||||
report => {
|
||||
var res = PackageManager.FindPackage (packageFamilyName);
|
||||
var hr = res.Item1;
|
||||
var jsstr = "";
|
||||
{
|
||||
var ret = new
|
||||
{
|
||||
result = res.Item1,
|
||||
list = res.Item2
|
||||
};
|
||||
jsstr = BuildJsonText (ret);
|
||||
}
|
||||
if (hr == null) return JsAsyncResult.Failed (jsstr);
|
||||
return hr.Succeeded ? JsAsyncResult.Success (jsstr) : JsAsyncResult.Failed (jsstr);
|
||||
},
|
||||
success,
|
||||
failed,
|
||||
null
|
||||
);
|
||||
}
|
||||
public void FindPackageByFullName (string packageFullName, object success, object failed)
|
||||
{
|
||||
JsAsyncRunner.Run (
|
||||
report => {
|
||||
var res = PackageManager.FindPackageByFullName (packageFullName);
|
||||
var hr = res.Item1;
|
||||
var jsstr = "";
|
||||
{
|
||||
var ret = new
|
||||
{
|
||||
result = res.Item1,
|
||||
list = res.Item2
|
||||
};
|
||||
jsstr = BuildJsonText (ret);
|
||||
}
|
||||
if (hr == null) return JsAsyncResult.Failed (jsstr);
|
||||
return hr.Succeeded ? JsAsyncResult.Success (jsstr) : JsAsyncResult.Failed (jsstr);
|
||||
},
|
||||
success,
|
||||
failed,
|
||||
null
|
||||
);
|
||||
}
|
||||
public _I_HResult ActiveApp (string appUserId, string args) { return PackageManager.ActiveApp (appUserId, args); }
|
||||
public _I_HResult ActiveAppByIdentity (string idName, string appId, string args) { return ActiveApp ($"{idName?.Trim ()}!{appId?.Trim ()}", args); }
|
||||
public void CancelAll () { JsAsyncRunner.CancelAll (); }
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_PackageReader
|
||||
{
|
||||
private static readonly int MaxConcurrency = Math.Min (8, Environment.ProcessorCount * 2);
|
||||
private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim (MaxConcurrency);
|
||||
private static CancellationTokenSource _cts = new CancellationTokenSource ();
|
||||
private static void CallJS (object jsFunc, params object [] args)
|
||||
{
|
||||
if (jsFunc == null) return;
|
||||
try
|
||||
{
|
||||
// 这里固定第一个参数为 thisArg(比如 1)
|
||||
object [] realArgs = new object [args.Length + 1];
|
||||
realArgs [0] = jsFunc; // thisArg
|
||||
Array.Copy (args, 0, realArgs, 1, args.Length);
|
||||
|
||||
jsFunc.GetType ().InvokeMember (
|
||||
"call",
|
||||
BindingFlags.InvokeMethod,
|
||||
null,
|
||||
jsFunc,
|
||||
realArgs
|
||||
);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore errors in callback invocation
|
||||
}
|
||||
}
|
||||
private static Task RunAsync (Action<CancellationToken> work, object successCallback, object failedCallback)
|
||||
{
|
||||
var token = _cts.Token;
|
||||
return Task.Factory.StartNew (() => {
|
||||
_semaphore.Wait (token);
|
||||
try
|
||||
{
|
||||
token.ThrowIfCancellationRequested ();
|
||||
work (token);
|
||||
}
|
||||
catch (OperationCanceledException oce)
|
||||
{
|
||||
var errObj = new
|
||||
{
|
||||
status = false,
|
||||
message = "Task is canceled. Message: " + oce.Message,
|
||||
jsontext = ""
|
||||
};
|
||||
string errJson = Newtonsoft.Json.JsonConvert.SerializeObject (errObj);
|
||||
if (failedCallback != null) CallJS (failedCallback, errJson);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errObj = new
|
||||
{
|
||||
status = false,
|
||||
message = ex.Message,
|
||||
jsontext = ""
|
||||
};
|
||||
string errJson = Newtonsoft.Json.JsonConvert.SerializeObject (errObj);
|
||||
if (failedCallback != null) CallJS (failedCallback, errJson);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_semaphore.Release ();
|
||||
}
|
||||
},
|
||||
token,
|
||||
TaskCreationOptions.LongRunning,
|
||||
TaskScheduler.Default);
|
||||
}
|
||||
public AppxPackage.PackageReader Package (string packagePath) { return new AppxPackage.PackageReader (packagePath); }
|
||||
public AppxPackage.ManifestReader Manifest (string manifestPath) { return new AppxPackage.ManifestReader (manifestPath); }
|
||||
public AppxPackage.ManifestReader FromInstallLocation (string installLocation) { return Manifest (Path.Combine (installLocation, "AppxManifest.xml")); }
|
||||
public Task ReadFromPackageAsync (string packagePath, bool enablePri, object successCallback, object failedCallback)
|
||||
{
|
||||
return RunAsync (token => {
|
||||
string cacheKey = BuildCacheKey (packagePath, enablePri, ReadKind.Package);
|
||||
if (TryHitCache (cacheKey, successCallback)) return;
|
||||
using (var reader = Package (packagePath))
|
||||
{
|
||||
if (enablePri)
|
||||
{
|
||||
reader.EnablePri = true;
|
||||
reader.UsePri = true;
|
||||
}
|
||||
token.ThrowIfCancellationRequested ();
|
||||
if (!reader.IsValid)
|
||||
{
|
||||
var failObj = new
|
||||
{
|
||||
status = false,
|
||||
message = "Reader invalid",
|
||||
jsontext = ""
|
||||
};
|
||||
string failJson = Newtonsoft.Json.JsonConvert.SerializeObject (failObj);
|
||||
if (failedCallback != null) CallJS (failedCallback, failJson);
|
||||
return;
|
||||
}
|
||||
var obj = new
|
||||
{
|
||||
status = true,
|
||||
message = "ok",
|
||||
jsontext = reader.BuildJsonText ()
|
||||
};
|
||||
string json = Newtonsoft.Json.JsonConvert.SerializeObject (obj);
|
||||
if (!token.IsCancellationRequested && successCallback != null) CallJS (successCallback, json);
|
||||
SaveCache (cacheKey, json);
|
||||
}
|
||||
}, successCallback, failedCallback);
|
||||
}
|
||||
public Task ReadFromManifestAsync (string manifestPath, bool enablePri, object successCallback, object failedCallback)
|
||||
{
|
||||
return RunAsync (token => {
|
||||
string cacheKey = BuildCacheKey (manifestPath, enablePri, ReadKind.Manifest);
|
||||
if (TryHitCache (cacheKey, successCallback)) return;
|
||||
using (var reader = Manifest (manifestPath))
|
||||
{
|
||||
if (enablePri)
|
||||
{
|
||||
reader.EnablePri = true;
|
||||
reader.UsePri = true;
|
||||
}
|
||||
token.ThrowIfCancellationRequested ();
|
||||
if (!reader.IsValid)
|
||||
{
|
||||
var failObj = new
|
||||
{
|
||||
status = false,
|
||||
message = "Reader invalid",
|
||||
jsontext = ""
|
||||
};
|
||||
string failJson = Newtonsoft.Json.JsonConvert.SerializeObject (failObj);
|
||||
if (failedCallback != null) CallJS (failedCallback, failJson);
|
||||
return;
|
||||
}
|
||||
var obj = new
|
||||
{
|
||||
status = true,
|
||||
message = "ok",
|
||||
jsontext = reader.BuildJsonText ()
|
||||
};
|
||||
string json = Newtonsoft.Json.JsonConvert.SerializeObject (obj);
|
||||
if (!token.IsCancellationRequested && successCallback != null) CallJS (successCallback, json);
|
||||
SaveCache (cacheKey, json);
|
||||
}
|
||||
}, successCallback, failedCallback);
|
||||
}
|
||||
public Task ReadFromInstallLocationAsync (string installLocation, bool enablePri, object successCallback, object failedCallback)
|
||||
{
|
||||
return RunAsync (token => {
|
||||
var manifestpath = Path.Combine (installLocation, "AppxManifest.xml");
|
||||
string cacheKey = BuildCacheKey (manifestpath, enablePri, ReadKind.Manifest);
|
||||
if (TryHitCache (cacheKey, successCallback)) return;
|
||||
using (var reader = FromInstallLocation (installLocation))
|
||||
{
|
||||
if (enablePri)
|
||||
{
|
||||
reader.EnablePri = true;
|
||||
reader.UsePri = true;
|
||||
}
|
||||
token.ThrowIfCancellationRequested ();
|
||||
if (!reader.IsValid)
|
||||
{
|
||||
var failObj = new
|
||||
{
|
||||
status = false,
|
||||
message = "Reader invalid",
|
||||
jsontext = ""
|
||||
};
|
||||
string failJson = Newtonsoft.Json.JsonConvert.SerializeObject (failObj);
|
||||
if (failedCallback != null) CallJS (failedCallback, failJson);
|
||||
return;
|
||||
}
|
||||
var obj = new
|
||||
{
|
||||
status = true,
|
||||
message = "ok",
|
||||
jsontext = reader.BuildJsonText ()
|
||||
};
|
||||
string json = Newtonsoft.Json.JsonConvert.SerializeObject (obj);
|
||||
if (!token.IsCancellationRequested && successCallback != null) CallJS (successCallback, json);
|
||||
SaveCache (cacheKey, json);
|
||||
}
|
||||
}, successCallback, failedCallback);
|
||||
}
|
||||
public void CancelAll ()
|
||||
{
|
||||
var old = _cts;
|
||||
_cts = new CancellationTokenSource ();
|
||||
old.Cancel ();
|
||||
old.Dispose ();
|
||||
}
|
||||
public bool AddApplicationItem (string itemName) => PackageReader.AddApplicationItem (itemName);
|
||||
public bool RemoveApplicationItem (string itemName) => PackageReader.RemoveApplicationItem (itemName);
|
||||
private List<object> JsArrayToList (object jsArray)
|
||||
{
|
||||
var result = new List<object> ();
|
||||
|
||||
if (jsArray == null)
|
||||
return result;
|
||||
|
||||
// JS Array 有 length 属性和数字索引器
|
||||
var type = jsArray.GetType ();
|
||||
|
||||
int length = (int)type.InvokeMember (
|
||||
"length",
|
||||
BindingFlags.GetProperty,
|
||||
null,
|
||||
jsArray,
|
||||
null);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
object value = type.InvokeMember (
|
||||
i.ToString (),
|
||||
BindingFlags.GetProperty,
|
||||
null,
|
||||
jsArray,
|
||||
null);
|
||||
|
||||
result.Add (value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
public void UpdateApplicationItems (object items)
|
||||
{
|
||||
lock (_I_PackageReader._cacheCleanupLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
_I_PackageReader._cache?.Clear ();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
var stritems = JsArrayToList (items).Select (e => e?.ToString ()).ToList ();
|
||||
PackageReader.UpdateApplicationItems (stritems);
|
||||
}
|
||||
public string [] GetApplicationItems () => PackageReader.GetApplicationItems ();
|
||||
public string GetApplicationItemsToJson () => JsonConvert.SerializeObject (GetApplicationItems ());
|
||||
// Cache about
|
||||
private const int MaxCacheItems = 64; // 最大缓存数量
|
||||
private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes (30);
|
||||
internal sealed class CacheEntry
|
||||
{
|
||||
public string Json { get; private set; }
|
||||
public DateTime ExpireAt { get; private set; }
|
||||
public DateTime LastAccessUtc { get; private set; }
|
||||
public CacheEntry (string json, DateTime expireAt)
|
||||
{
|
||||
Json = json;
|
||||
ExpireAt = expireAt;
|
||||
LastAccessUtc = DateTime.UtcNow;
|
||||
}
|
||||
public bool IsExpired { get { return DateTime.UtcNow > ExpireAt; } }
|
||||
public void Touch () { LastAccessUtc = DateTime.UtcNow; }
|
||||
}
|
||||
private static readonly ConcurrentDictionary<string, CacheEntry> _cache = new ConcurrentDictionary<string, CacheEntry> ();
|
||||
private static readonly object _cacheCleanupLock = new object ();
|
||||
private static bool TryHitCache (string cacheKey, object successCallback)
|
||||
{
|
||||
CacheEntry entry;
|
||||
if (_cache.TryGetValue (cacheKey, out entry))
|
||||
{
|
||||
if (!entry.IsExpired)
|
||||
{
|
||||
entry.Touch ();
|
||||
if (successCallback != null) CallJS (successCallback, entry.Json);
|
||||
return true;
|
||||
}
|
||||
CacheEntry removed;
|
||||
_cache.TryRemove (cacheKey, out removed);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private static void SaveCache (string cacheKey, string json)
|
||||
{
|
||||
var entry = new CacheEntry (
|
||||
json,
|
||||
DateTime.UtcNow.Add (CacheDuration)
|
||||
);
|
||||
_cache [cacheKey] = entry;
|
||||
EnsureCacheSize ();
|
||||
}
|
||||
private static void EnsureCacheSize ()
|
||||
{
|
||||
if (_cache.Count <= MaxCacheItems) return;
|
||||
lock (_cacheCleanupLock)
|
||||
{
|
||||
if (_cache.Count <= MaxCacheItems) return;
|
||||
foreach (var kv in _cache)
|
||||
{
|
||||
if (kv.Value.IsExpired)
|
||||
{
|
||||
CacheEntry removed;
|
||||
_cache.TryRemove (kv.Key, out removed);
|
||||
}
|
||||
}
|
||||
if (_cache.Count <= MaxCacheItems) return;
|
||||
while (_cache.Count > MaxCacheItems)
|
||||
{
|
||||
string oldestKey = null;
|
||||
DateTime oldest = DateTime.MaxValue;
|
||||
foreach (var kv in _cache)
|
||||
{
|
||||
if (kv.Value.LastAccessUtc < oldest)
|
||||
{
|
||||
oldest = kv.Value.LastAccessUtc;
|
||||
oldestKey = kv.Key;
|
||||
}
|
||||
}
|
||||
if (oldestKey == null) break;
|
||||
CacheEntry removed;
|
||||
_cache.TryRemove (oldestKey, out removed);
|
||||
}
|
||||
}
|
||||
}
|
||||
private static string NormalizePath (string path)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace (path)) return string.Empty;
|
||||
path = path.Trim ();
|
||||
while (path.EndsWith ("\\") || path.EndsWith ("/")) path = path.Substring (0, path.Length - 1);
|
||||
return path.ToLowerInvariant ();
|
||||
}
|
||||
private enum ReadKind { Package, Manifest }
|
||||
private static string BuildCacheKey (string path, bool enablePri, ReadKind kind)
|
||||
{
|
||||
return NormalizePath (path) + "|" + enablePri.ToString () + "|" + kind.ToString ();
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Package
|
||||
{
|
||||
public _I_PackageReader Reader => new _I_PackageReader ();
|
||||
public _I_PackageManager Manager => new _I_PackageManager ();
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Notice
|
||||
{
|
||||
public string TemplateXml (string templateName) { return Notice.GetTemplateString (templateName); }
|
||||
public string SimpleTemplateXml (string text, string imgPath = null) { return Notice.GetSimpleTemplateString (text, imgPath); }
|
||||
public string SimpleTemplateXml2 (string title, string text = null, string imgPath = null) { return Notice.GetSimpleTemplateString2 (title, text, imgPath); }
|
||||
public _I_HResult NoticeByXml (string appId, string xmlstr) { return Notice.Create (appId, xmlstr); }
|
||||
public _I_HResult NoticeSimply (string appId, string text, string imgPath = null) { return Notice.Create (appId, text, imgPath); }
|
||||
public _I_HResult NoticeSimply2 (string appId, string title, string text = null, string imgPath = null) { return Notice.Create (appId, title, text, imgPath); }
|
||||
public _I_HResult NoticeSimplyByBase64 (string appId, string text, string imgBase64 = null) { return Notice.CreateWithImgBase64 (appId, text, imgBase64); }
|
||||
public _I_HResult NoticeSimply2ByBase64 (string appId, string title, string text = null, string imgBase64 = null) { return Notice.CreateWithImgBase64 (appId, title, text, imgBase64); }
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_BridgeBase
|
||||
{
|
||||
protected readonly _I_String str = new _I_String ();
|
||||
protected readonly _I_InitConfig conf = new _I_InitConfig ();
|
||||
protected readonly _I_Storage stog = new _I_Storage ();
|
||||
protected readonly _I_Window window;
|
||||
protected readonly _I_System system;
|
||||
protected readonly _I_IEFrame ieframe;
|
||||
protected readonly _I_Process proc = new _I_Process ();
|
||||
public _I_String String => str;
|
||||
public _I_InitConfig Config => conf;
|
||||
public _I_Storage Storage => stog;
|
||||
public _I_Window Window => window;
|
||||
public _I_IEFrame IEFrame => ieframe;
|
||||
public _I_VisualElements VisualElements => new _I_VisualElements ();
|
||||
public StringResXmlDoc StringResources => ResXmlStore.StringRes;
|
||||
public _I_Package Package => new _I_Package ();
|
||||
public _I_Taskbar Taskbar { get; private set; } = null;
|
||||
public _I_System System => system;
|
||||
public _I_Notice Notice => new _I_Notice ();
|
||||
public _I_Process Process => proc;
|
||||
public _I_Web Web => new _I_Web ();
|
||||
public _I_Utilities Utilities => new _I_Utilities ();
|
||||
public string CmdArgs
|
||||
{
|
||||
get
|
||||
{
|
||||
return JsonConvert.SerializeObject (
|
||||
Environment.GetCommandLineArgs ()
|
||||
);
|
||||
}
|
||||
}
|
||||
public _I_BridgeBase (Form wnd, IScriptBridge isc, IWebBrowserPageScale iwbps, ITaskbarProgress itp)
|
||||
{
|
||||
window = new _I_Window (isc);
|
||||
system = new _I_System (wnd);
|
||||
ieframe = new _I_IEFrame (iwbps);
|
||||
Taskbar = new _I_Taskbar (itp);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
75
Bridge/app.manifest
Normal file
75
Bridge/app.manifest
Normal file
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<!-- UAC 清单选项
|
||||
如果想要更改 Windows 用户帐户控制级别,请使用
|
||||
以下节点之一替换 requestedExecutionLevel 节点。n
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
|
||||
|
||||
指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
|
||||
如果你的应用程序需要此虚拟化来实现向后兼容性,则删除此
|
||||
元素。
|
||||
-->
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的
|
||||
Windows 版本的列表。取消评论适当的元素,Windows 将
|
||||
自动选择最兼容的环境。 -->
|
||||
|
||||
<!-- Windows Vista -->
|
||||
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
|
||||
|
||||
<!-- Windows 7 -->
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
|
||||
|
||||
<!-- Windows 8 -->
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
|
||||
|
||||
<!-- Windows 8.1 -->
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
|
||||
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
|
||||
</application>
|
||||
</compatibility>
|
||||
|
||||
<!-- 指示该应用程序可以感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
|
||||
自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
|
||||
选择加入。选择加入此设置的 Windows 窗体应用程序(目标设定为 .NET Framework 4.6 )还应
|
||||
在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。-->
|
||||
<!--
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
-->
|
||||
|
||||
<!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->
|
||||
<!--
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
</assembly>
|
||||
4
Bridge/packages.config
Normal file
4
Bridge/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="13.0.4" targetFramework="net40" />
|
||||
</packages>
|
||||
816
DataUtils/Calendar.cs
Normal file
816
DataUtils/Calendar.cs
Normal file
@@ -0,0 +1,816 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Calendar
|
||||
{
|
||||
private DateTime _utcDateTime; // 存储 UTC 时间(所有算术的基础)
|
||||
private Calendar _calendar; // 当前日历系统
|
||||
private TimeZoneInfo _timeZone; // 当前时区
|
||||
private bool _is24HourClock; // true = 24小时制,false = 12小时制
|
||||
private List<string> _languages; // 语言优先级列表
|
||||
private string _numeralSystem = "Latn"; // 数字系统(简化实现,仅存储)
|
||||
private const long TicksPerNanosecond = 100; // 1 tick = 100 ns
|
||||
|
||||
// 缓存的本地时间(根据时区从 _utcDateTime 转换得到)
|
||||
private DateTime _localDateTime;
|
||||
|
||||
// 更新本地时间(当 UTC 时间或时区改变时调用)
|
||||
private void UpdateLocalDateTime ()
|
||||
{
|
||||
_localDateTime = TimeZoneInfo.ConvertTimeFromUtc (_utcDateTime, _timeZone);
|
||||
}
|
||||
|
||||
// 当本地时间被修改后,同步回 UTC 时间
|
||||
private void UpdateUtcDateTime ()
|
||||
{
|
||||
_utcDateTime = TimeZoneInfo.ConvertTimeToUtc (_localDateTime, _timeZone);
|
||||
}
|
||||
|
||||
// 辅助:日历字段的读取
|
||||
private int GetCalendarField (Func<Calendar, DateTime, int> fieldGetter)
|
||||
{
|
||||
return fieldGetter (_calendar, _localDateTime);
|
||||
}
|
||||
|
||||
// 辅助:日历字段的设置(返回新的本地时间)
|
||||
private DateTime SetCalendarField (DateTime currentLocal, Func<Calendar, DateTime, int, DateTime> fieldSetter, int value)
|
||||
{
|
||||
return fieldSetter (_calendar, currentLocal, value);
|
||||
}
|
||||
|
||||
// 根据日历标识符创建日历实例
|
||||
private static Calendar CreateCalendar (string calendarId)
|
||||
{
|
||||
switch (calendarId)
|
||||
{
|
||||
case "GregorianCalendar":
|
||||
return new GregorianCalendar ();
|
||||
case "HebrewCalendar":
|
||||
return new HebrewCalendar ();
|
||||
case "HijriCalendar":
|
||||
return new HijriCalendar ();
|
||||
case "JapaneseCalendar":
|
||||
return new JapaneseCalendar ();
|
||||
case "KoreanCalendar":
|
||||
return new KoreanCalendar ();
|
||||
case "TaiwanCalendar":
|
||||
return new TaiwanCalendar ();
|
||||
case "ThaiBuddhistCalendar":
|
||||
return new ThaiBuddhistCalendar ();
|
||||
case "UmAlQuraCalendar":
|
||||
return new UmAlQuraCalendar ();
|
||||
// 可根据需要增加更多日历
|
||||
default:
|
||||
return new GregorianCalendar ();
|
||||
}
|
||||
}
|
||||
|
||||
private _I_Language GetFormatCulture ()
|
||||
{
|
||||
if (_languages == null || _languages.Count == 0)
|
||||
return new _I_Language (CultureInfo.CurrentCulture.Name);
|
||||
try
|
||||
{
|
||||
return new _I_Language (_languages [0]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new _I_Language (CultureInfo.CurrentCulture.Name);
|
||||
}
|
||||
}
|
||||
|
||||
private List<object> JsArrayToList (object jsArray)
|
||||
{
|
||||
var result = new List<object> ();
|
||||
|
||||
if (jsArray == null)
|
||||
return result;
|
||||
|
||||
// JS Array 有 length 属性和数字索引器
|
||||
var type = jsArray.GetType ();
|
||||
|
||||
int length = (int)type.InvokeMember (
|
||||
"length",
|
||||
BindingFlags.GetProperty,
|
||||
null,
|
||||
jsArray,
|
||||
null);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
object value = type.InvokeMember (
|
||||
i.ToString (),
|
||||
BindingFlags.GetProperty,
|
||||
null,
|
||||
jsArray,
|
||||
null);
|
||||
|
||||
result.Add (value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public _I_Calendar ()
|
||||
: this (new List<string> { CultureInfo.CurrentCulture.Name },
|
||||
"GregorianCalendar", "24HourClock", TimeZoneInfo.Local.Id)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_Calendar (object languages)
|
||||
: this (languages, "GregorianCalendar", "24HourClock", TimeZoneInfo.Local.Id)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_Calendar (object languages, string calendar, string clock)
|
||||
: this (languages, calendar, clock, TimeZoneInfo.Local.Id)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_Calendar (object languages, string calendar, string clock, string timeZoneId)
|
||||
{
|
||||
_languages = languages == null ? new List<string> () : new List<string> (JsArrayToList (languages).Select (e => e as string));
|
||||
if (_languages.Count == 0)
|
||||
_languages.Add (CultureInfo.CurrentCulture.Name);
|
||||
|
||||
_calendar = CreateCalendar (calendar);
|
||||
_is24HourClock = (clock == "24HourClock");
|
||||
_timeZone = TimeZoneInfo.FindSystemTimeZoneById (timeZoneId);
|
||||
_utcDateTime = DateTime.UtcNow;
|
||||
UpdateLocalDateTime ();
|
||||
}
|
||||
|
||||
public int Day
|
||||
{
|
||||
get
|
||||
{
|
||||
return _calendar.GetDayOfMonth (_localDateTime);
|
||||
}
|
||||
set
|
||||
{
|
||||
int currentDay = _calendar.GetDayOfMonth (_localDateTime);
|
||||
if (value == currentDay) return;
|
||||
// 通过加减天数来设置日期
|
||||
DateTime newLocal = _calendar.AddDays (_localDateTime, value - currentDay);
|
||||
_localDateTime = newLocal;
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public int DayOfWeek
|
||||
{
|
||||
get
|
||||
{
|
||||
// 返回 0-6,0 表示星期日
|
||||
return (int)_calendar.GetDayOfWeek (_localDateTime);
|
||||
}
|
||||
}
|
||||
|
||||
public int Era
|
||||
{
|
||||
get
|
||||
{
|
||||
return _calendar.GetEra (_localDateTime);
|
||||
}
|
||||
set
|
||||
{
|
||||
// 更改纪元较复杂,简化:仅当值不同时不做任何操作(可根据需求实现)
|
||||
// 这里忽略设置,或者可以抛出 NotSupportedException
|
||||
if (value != Era)
|
||||
throw new NotSupportedException ("Setting Era directly is not supported in this implementation.");
|
||||
}
|
||||
}
|
||||
|
||||
public int FirstDayInThisMonth
|
||||
{
|
||||
get { return 1; }
|
||||
}
|
||||
|
||||
public int FirstEra
|
||||
{
|
||||
get { return _calendar.GetEra (_calendar.MinSupportedDateTime); }
|
||||
}
|
||||
|
||||
public int FirstHourInThisPeriod
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_is24HourClock)
|
||||
return 0;
|
||||
else
|
||||
return (Period == 0) ? 1 : 13;
|
||||
}
|
||||
}
|
||||
|
||||
public int FirstMinuteInThisHour
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public int FirstMonthInThisYear
|
||||
{
|
||||
get { return 1; }
|
||||
}
|
||||
|
||||
public int FirstPeriodInThisDay
|
||||
{
|
||||
get { return 0; } // 0 = AM
|
||||
}
|
||||
|
||||
public int FirstSecondInThisMinute
|
||||
{
|
||||
get { return 0; }
|
||||
}
|
||||
|
||||
public int FirstYearInThisEra
|
||||
{
|
||||
get
|
||||
{
|
||||
DateTime eraStart = _calendar.MinSupportedDateTime;
|
||||
int targetEra = Era;
|
||||
while (_calendar.GetEra (eraStart) != targetEra && eraStart < DateTime.MaxValue)
|
||||
{
|
||||
eraStart = _calendar.AddYears (eraStart, 1);
|
||||
}
|
||||
return _calendar.GetYear (eraStart);
|
||||
}
|
||||
}
|
||||
|
||||
public int Hour
|
||||
{
|
||||
get
|
||||
{
|
||||
int hour24 = _calendar.GetHour (_localDateTime);
|
||||
if (_is24HourClock)
|
||||
return hour24;
|
||||
int hour12 = hour24 % 12;
|
||||
return (hour12 == 0) ? 12 : hour12;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (_is24HourClock)
|
||||
{
|
||||
if (value < 0 || value > 23)
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Hour must be between 0 and 23 for 24-hour clock.");
|
||||
DateTime newLocal = _localDateTime.Date.AddHours (value).AddMinutes (Minute).AddSeconds (Second);
|
||||
_localDateTime = newLocal;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value < 1 || value > 12)
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Hour must be between 1 and 12 for 12-hour clock.");
|
||||
int hour24 = value % 12;
|
||||
if (Period == 1) hour24 += 12;
|
||||
DateTime newLocal = _localDateTime.Date.AddHours (hour24).AddMinutes (Minute).AddSeconds (Second);
|
||||
_localDateTime = newLocal;
|
||||
}
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDaylightSavingTime
|
||||
{
|
||||
get { return _timeZone.IsDaylightSavingTime (_localDateTime); }
|
||||
}
|
||||
|
||||
public _I_List Languages
|
||||
{
|
||||
get { return new _I_List (_languages.AsReadOnly ().Select (e => (object)e), true) ; }
|
||||
}
|
||||
|
||||
public int LastDayInThisMonth
|
||||
{
|
||||
get { return _calendar.GetDaysInMonth (_calendar.GetYear (_localDateTime), _calendar.GetMonth (_localDateTime)); }
|
||||
}
|
||||
|
||||
public int LastEra
|
||||
{
|
||||
get { return _calendar.GetEra (_calendar.MaxSupportedDateTime); }
|
||||
}
|
||||
|
||||
public int LastHourInThisPeriod
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_is24HourClock)
|
||||
return 23;
|
||||
else
|
||||
return (Period == 0) ? 11 : 23;
|
||||
}
|
||||
}
|
||||
|
||||
public int LastMinuteInThisHour
|
||||
{
|
||||
get { return 59; }
|
||||
}
|
||||
|
||||
public int LastMonthInThisYear
|
||||
{
|
||||
get { return _calendar.GetMonthsInYear (_calendar.GetYear (_localDateTime)); }
|
||||
}
|
||||
|
||||
public int LastPeriodInThisDay
|
||||
{
|
||||
get { return 1; } // 1 = PM
|
||||
}
|
||||
|
||||
public int LastSecondInThisMinute
|
||||
{
|
||||
get { return 59; }
|
||||
}
|
||||
|
||||
public int LastYearInThisEra
|
||||
{
|
||||
get
|
||||
{
|
||||
DateTime eraEnd = _calendar.MaxSupportedDateTime;
|
||||
int targetEra = Era;
|
||||
while (_calendar.GetEra (eraEnd) != targetEra && eraEnd > DateTime.MinValue)
|
||||
{
|
||||
eraEnd = _calendar.AddYears (eraEnd, -1);
|
||||
}
|
||||
return _calendar.GetYear (eraEnd);
|
||||
}
|
||||
}
|
||||
|
||||
public int Minute
|
||||
{
|
||||
get { return _calendar.GetMinute (_localDateTime); }
|
||||
set
|
||||
{
|
||||
if (value < 0 || value > 59)
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Minute must be between 0 and 59.");
|
||||
DateTime newLocal = _localDateTime.AddMinutes (value - _calendar.GetMinute (_localDateTime));
|
||||
_localDateTime = newLocal;
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public int Month
|
||||
{
|
||||
get { return _calendar.GetMonth (_localDateTime); }
|
||||
set
|
||||
{
|
||||
if (value < 1 || value > _calendar.GetMonthsInYear (_calendar.GetYear (_localDateTime)))
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Month is out of range for current year.");
|
||||
DateTime newLocal = SetCalendarField (_localDateTime, (cal, dt, val) => cal.AddMonths (dt, val - cal.GetMonth (dt)), value);
|
||||
_localDateTime = newLocal;
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public int Nanosecond
|
||||
{
|
||||
get
|
||||
{
|
||||
long ticksInSecond = _localDateTime.Ticks % TimeSpan.TicksPerSecond;
|
||||
return (int)(ticksInSecond * 100); // 1 tick = 100 ns
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value < 0 || value > 999999999)
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Nanosecond must be between 0 and 999,999,999.");
|
||||
long ticks = (_localDateTime.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond + (value / 100);
|
||||
_localDateTime = new DateTime (ticks, _localDateTime.Kind);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public int NumberOfDaysInThisMonth
|
||||
{
|
||||
get { return LastDayInThisMonth; }
|
||||
}
|
||||
|
||||
public int NumberOfEras
|
||||
{
|
||||
get { return _calendar.Eras.Length; }
|
||||
}
|
||||
|
||||
public int NumberOfHoursInThisPeriod
|
||||
{
|
||||
get { return _is24HourClock ? 24 : 12; }
|
||||
}
|
||||
|
||||
public int NumberOfMinutesInThisHour
|
||||
{
|
||||
get { return 60; }
|
||||
}
|
||||
|
||||
public int NumberOfMonthsInThisYear
|
||||
{
|
||||
get { return _calendar.GetMonthsInYear (_calendar.GetYear (_localDateTime)); }
|
||||
}
|
||||
|
||||
public int NumberOfPeriodsInThisDay
|
||||
{
|
||||
get { return 2; }
|
||||
}
|
||||
|
||||
public int NumberOfSecondsInThisMinute
|
||||
{
|
||||
get { return 60; }
|
||||
}
|
||||
|
||||
public int NumberOfYearsInThisEra
|
||||
{
|
||||
get { return LastYearInThisEra - FirstYearInThisEra + 1; }
|
||||
}
|
||||
|
||||
public string NumeralSystem
|
||||
{
|
||||
get { return _numeralSystem; }
|
||||
set { _numeralSystem = value; } // 简化:未实现实际数字转换
|
||||
}
|
||||
|
||||
public int Period
|
||||
{
|
||||
get
|
||||
{
|
||||
int hour24 = _calendar.GetHour (_localDateTime);
|
||||
return (hour24 >= 12) ? 1 : 0;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value != 0 && value != 1)
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Period must be 0 (AM) or 1 (PM).");
|
||||
int currentPeriod = Period;
|
||||
if (currentPeriod == value) return;
|
||||
// 切换 AM/PM:加减 12 小时
|
||||
DateTime newLocal = _localDateTime.AddHours (value == 0 ? -12 : 12);
|
||||
_localDateTime = newLocal;
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public string ResolvedLanguage
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_languages != null && _languages.Count > 0)
|
||||
return _languages [0];
|
||||
return CultureInfo.CurrentCulture.Name;
|
||||
}
|
||||
}
|
||||
|
||||
public int Second
|
||||
{
|
||||
get { return _calendar.GetSecond (_localDateTime); }
|
||||
set
|
||||
{
|
||||
if (value < 0 || value > 59)
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Second must be between 0 and 59.");
|
||||
DateTime newLocal = _localDateTime.AddSeconds (value - _calendar.GetSecond (_localDateTime));
|
||||
_localDateTime = newLocal;
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public int Year
|
||||
{
|
||||
get { return _calendar.GetYear (_localDateTime); }
|
||||
set
|
||||
{
|
||||
if (value < _calendar.GetYear (_calendar.MinSupportedDateTime) || value > _calendar.GetYear (_calendar.MaxSupportedDateTime))
|
||||
throw new ArgumentOutOfRangeException (nameof (value), "Year is out of range for this calendar.");
|
||||
DateTime newLocal = SetCalendarField (_localDateTime, (cal, dt, val) => cal.AddYears (dt, val - cal.GetYear (dt)), value);
|
||||
_localDateTime = newLocal;
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddDays (int days)
|
||||
{
|
||||
_localDateTime = _calendar.AddDays (_localDateTime, days);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddEras (int eras)
|
||||
{
|
||||
// 简化:每个纪元按 1000 年估算(实际应基于日历的纪元范围)
|
||||
// 大多数情况下不应频繁使用此方法
|
||||
_localDateTime = _calendar.AddYears (_localDateTime, eras * 1000);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddHours (int hours)
|
||||
{
|
||||
_localDateTime = _localDateTime.AddHours (hours);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddMinutes (int minutes)
|
||||
{
|
||||
_localDateTime = _localDateTime.AddMinutes (minutes);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddMonths (int months)
|
||||
{
|
||||
_localDateTime = _calendar.AddMonths (_localDateTime, months);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddNanoseconds (int nanoseconds)
|
||||
{
|
||||
long ticksToAdd = nanoseconds / 100;
|
||||
_localDateTime = _localDateTime.AddTicks (ticksToAdd);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddPeriods (int periods)
|
||||
{
|
||||
_localDateTime = _localDateTime.AddHours (periods * 12);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddSeconds (int seconds)
|
||||
{
|
||||
_localDateTime = _localDateTime.AddSeconds (seconds);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void AddWeeks (int weeks)
|
||||
{
|
||||
AddDays (weeks * 7);
|
||||
}
|
||||
|
||||
public void AddYears (int years)
|
||||
{
|
||||
_localDateTime = _calendar.AddYears (_localDateTime, years);
|
||||
UpdateUtcDateTime ();
|
||||
}
|
||||
|
||||
public void ChangeCalendarSystem (string calendarId)
|
||||
{
|
||||
Calendar newCalendar = CreateCalendar (calendarId);
|
||||
// 注意:日历改变不会改变绝对时间,但会影响组件(年、月、日等)
|
||||
// 只需替换日历实例,_localDateTime 保持不变(但解释方式变了)
|
||||
_calendar = newCalendar;
|
||||
}
|
||||
|
||||
public void ChangeClock (string clock)
|
||||
{
|
||||
_is24HourClock = (clock == "24HourClock");
|
||||
}
|
||||
|
||||
public void ChangeTimeZone (string timeZoneId)
|
||||
{
|
||||
_timeZone = TimeZoneInfo.FindSystemTimeZoneById (timeZoneId);
|
||||
UpdateLocalDateTime (); // 重新计算本地时间(UTC 不变)
|
||||
}
|
||||
|
||||
public _I_Calendar Clone ()
|
||||
{
|
||||
var clone = new _I_Calendar (_languages, GetCalendarSystem (), GetClock (), GetTimeZone ());
|
||||
clone.SetDateTime (GetDateTime ());
|
||||
return clone;
|
||||
}
|
||||
|
||||
public int Compare (_I_Calendar other)
|
||||
{
|
||||
if (other == null) return 1;
|
||||
return DateTime.Compare (this.GetDateTime (), other.GetDateTime ());
|
||||
}
|
||||
|
||||
public static DateTime JsDateToDateTime (object jsDate)
|
||||
{
|
||||
if (jsDate == null)
|
||||
throw new ArgumentNullException (nameof (jsDate));
|
||||
Type type = jsDate.GetType ();
|
||||
double milliseconds = (double)type.InvokeMember (
|
||||
"getTime",
|
||||
BindingFlags.InvokeMethod,
|
||||
null,
|
||||
jsDate,
|
||||
null);
|
||||
DateTimeOffset epoch = new DateTimeOffset (1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
|
||||
DateTimeOffset dateTimeOffset = epoch.AddMilliseconds (milliseconds);
|
||||
return dateTimeOffset.UtcDateTime;
|
||||
}
|
||||
public int CompareDateTime (object other)
|
||||
{
|
||||
return DateTime.Compare (this.GetDateTime (), JsDateToDateTime (other));
|
||||
}
|
||||
|
||||
public void CopyTo (_I_Calendar other)
|
||||
{
|
||||
if (other == null) throw new ArgumentNullException (nameof (other));
|
||||
other._utcDateTime = this._utcDateTime;
|
||||
other._localDateTime = this._localDateTime;
|
||||
other._calendar = this._calendar;
|
||||
other._timeZone = this._timeZone;
|
||||
other._is24HourClock = this._is24HourClock;
|
||||
other._languages = new List<string> (this._languages);
|
||||
other._numeralSystem = this._numeralSystem;
|
||||
}
|
||||
|
||||
public string DayAsPaddedString (int minDigits)
|
||||
{
|
||||
return Day.ToString ().PadLeft (minDigits, '0');
|
||||
}
|
||||
|
||||
public string DayAsString ()
|
||||
{
|
||||
return Day.ToString ();
|
||||
}
|
||||
|
||||
public string DayOfWeekAsSoloString ()
|
||||
{
|
||||
return DayOfWeekAsString ();
|
||||
}
|
||||
|
||||
public string DayOfWeekAsSoloString (int idealLength)
|
||||
{
|
||||
// 简化:忽略 idealLength
|
||||
return DayOfWeekAsString ();
|
||||
}
|
||||
|
||||
public string DayOfWeekAsString ()
|
||||
{
|
||||
return _localDateTime.ToString ("dddd", GetFormatCulture ());
|
||||
}
|
||||
|
||||
public string DayOfWeekAsString (int idealLength)
|
||||
{
|
||||
return DayOfWeekAsString ();
|
||||
}
|
||||
|
||||
public string EraAsString ()
|
||||
{
|
||||
// 简化:返回纪元索引的字符串
|
||||
return Era.ToString ();
|
||||
}
|
||||
|
||||
public string EraAsString (int idealLength)
|
||||
{
|
||||
return EraAsString ();
|
||||
}
|
||||
|
||||
public string GetCalendarSystem ()
|
||||
{
|
||||
if (_calendar is GregorianCalendar) return "GregorianCalendar";
|
||||
if (_calendar is HebrewCalendar) return "HebrewCalendar";
|
||||
if (_calendar is HijriCalendar) return "HijriCalendar";
|
||||
if (_calendar is JapaneseCalendar) return "JapaneseCalendar";
|
||||
if (_calendar is KoreanCalendar) return "KoreanCalendar";
|
||||
if (_calendar is TaiwanCalendar) return "TaiwanCalendar";
|
||||
if (_calendar is ThaiBuddhistCalendar) return "ThaiBuddhistCalendar";
|
||||
if (_calendar is UmAlQuraCalendar) return "UmAlQuraCalendar";
|
||||
return "GregorianCalendar";
|
||||
}
|
||||
|
||||
public string GetClock ()
|
||||
{
|
||||
return _is24HourClock ? "24HourClock" : "12HourClock";
|
||||
}
|
||||
|
||||
public DateTime GetDateTime ()
|
||||
{
|
||||
// 返回 UTC 时间
|
||||
return _utcDateTime;
|
||||
}
|
||||
|
||||
public string GetTimeZone ()
|
||||
{
|
||||
return _timeZone.Id;
|
||||
}
|
||||
|
||||
public string HourAsPaddedString (int minDigits)
|
||||
{
|
||||
return Hour.ToString ().PadLeft (minDigits, '0');
|
||||
}
|
||||
|
||||
public string HourAsString ()
|
||||
{
|
||||
return Hour.ToString ();
|
||||
}
|
||||
|
||||
public string MinuteAsPaddedString (int minDigits)
|
||||
{
|
||||
return Minute.ToString ().PadLeft (minDigits, '0');
|
||||
}
|
||||
|
||||
public string MinuteAsString ()
|
||||
{
|
||||
return Minute.ToString ();
|
||||
}
|
||||
|
||||
public string MonthAsNumericString ()
|
||||
{
|
||||
return Month.ToString ();
|
||||
}
|
||||
|
||||
public string MonthAsPaddedNumericString (int minDigits)
|
||||
{
|
||||
return Month.ToString ().PadLeft (minDigits, '0');
|
||||
}
|
||||
|
||||
public string MonthAsSoloString ()
|
||||
{
|
||||
return _localDateTime.ToString ("MMMM", GetFormatCulture ());
|
||||
}
|
||||
|
||||
public string MonthAsSoloString (int idealLength)
|
||||
{
|
||||
return MonthAsSoloString ();
|
||||
}
|
||||
|
||||
public string MonthAsString ()
|
||||
{
|
||||
return _localDateTime.ToString ("MMM", GetFormatCulture ());
|
||||
}
|
||||
|
||||
public string MonthAsString (int idealLength)
|
||||
{
|
||||
return MonthAsString ();
|
||||
}
|
||||
|
||||
public string NanosecondAsPaddedString (int minDigits)
|
||||
{
|
||||
return Nanosecond.ToString ().PadLeft (minDigits, '0');
|
||||
}
|
||||
|
||||
public string NanosecondAsString ()
|
||||
{
|
||||
return Nanosecond.ToString ();
|
||||
}
|
||||
|
||||
public string PeriodAsString ()
|
||||
{
|
||||
return PeriodAsString (0);
|
||||
}
|
||||
|
||||
public string PeriodAsString (int idealLength)
|
||||
{
|
||||
return _localDateTime.ToString ("tt", GetFormatCulture ());
|
||||
}
|
||||
|
||||
public string SecondAsPaddedString (int minDigits)
|
||||
{
|
||||
return Second.ToString ().PadLeft (minDigits, '0');
|
||||
}
|
||||
|
||||
public string SecondAsString ()
|
||||
{
|
||||
return Second.ToString ();
|
||||
}
|
||||
|
||||
public void SetDateTime (DateTime value)
|
||||
{
|
||||
_utcDateTime = value.ToUniversalTime ();
|
||||
UpdateLocalDateTime ();
|
||||
}
|
||||
|
||||
public void SetToMax ()
|
||||
{
|
||||
SetDateTime (DateTime.MaxValue);
|
||||
}
|
||||
|
||||
public void SetToMin ()
|
||||
{
|
||||
SetDateTime (DateTime.MinValue);
|
||||
}
|
||||
|
||||
public void SetToNow ()
|
||||
{
|
||||
SetDateTime (DateTime.UtcNow);
|
||||
}
|
||||
|
||||
public string TimeZoneAsString ()
|
||||
{
|
||||
return TimeZoneAsString (0);
|
||||
}
|
||||
|
||||
public string TimeZoneAsString (int idealLength)
|
||||
{
|
||||
// 简化:返回标准显示名称
|
||||
return _timeZone.DisplayName;
|
||||
}
|
||||
|
||||
public string YearAsPaddedString (int minDigits)
|
||||
{
|
||||
return Year.ToString ().PadLeft (minDigits, '0');
|
||||
}
|
||||
|
||||
public string YearAsString ()
|
||||
{
|
||||
return Year.ToString ();
|
||||
}
|
||||
|
||||
public string YearAsTruncatedString (int remainingDigits)
|
||||
{
|
||||
string yearStr = Year.ToString ();
|
||||
if (yearStr.Length <= remainingDigits)
|
||||
return yearStr;
|
||||
return yearStr.Substring (yearStr.Length - remainingDigits);
|
||||
}
|
||||
}
|
||||
}
|
||||
106
DataUtils/DataUtils.csproj
Normal file
106
DataUtils/DataUtils.csproj
Normal file
@@ -0,0 +1,106 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>DataUtils</RootNamespace>
|
||||
<AssemblyName>DataUtils</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<LangVersion>default</LangVersion>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<LangVersion>default</LangVersion>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Calendar.cs" />
|
||||
<Compile Include="DateTimeFormat.cs" />
|
||||
<Compile Include="Download.cs" />
|
||||
<Compile Include="Enumerable.cs" />
|
||||
<Compile Include="HResult.cs" />
|
||||
<Compile Include="IE.cs" />
|
||||
<Compile Include="Locale.cs" />
|
||||
<Compile Include="Process.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Resources.cs" />
|
||||
<Compile Include="ResourceXml.cs" />
|
||||
<Compile Include="Storage.cs" />
|
||||
<Compile Include="String.cs" />
|
||||
<Compile Include="SysInit.cs" />
|
||||
<Compile Include="Taskbar.cs" />
|
||||
<Compile Include="Theme.cs" />
|
||||
<Compile Include="Utils.cs" />
|
||||
<Compile Include="Version.cs" />
|
||||
<Compile Include="VisualElements.cs" />
|
||||
<Compile Include="Web.cs" />
|
||||
<Compile Include="WebBrowser.cs" />
|
||||
<Compile Include="Window.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\IEHelper\IEHelper.vcxproj">
|
||||
<Project>{e4ca78a9-9408-4f5f-add6-730fd501ff8e}</Project>
|
||||
<Name>IEHelper</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
494
DataUtils/DateTimeFormat.cs
Normal file
494
DataUtils/DateTimeFormat.cs
Normal file
@@ -0,0 +1,494 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
public enum YearFormat
|
||||
{
|
||||
None = 0,
|
||||
Default = 1,
|
||||
Abbreviated = 2,
|
||||
Full = 3,
|
||||
}
|
||||
|
||||
public enum MonthFormat
|
||||
{
|
||||
None = 0,
|
||||
Default = 1,
|
||||
Abbreviated = 2,
|
||||
Full = 3,
|
||||
Numeric = 4,
|
||||
}
|
||||
|
||||
public enum DayFormat
|
||||
{
|
||||
None = 0,
|
||||
Default = 1,
|
||||
}
|
||||
|
||||
public enum DayOfWeekFormat
|
||||
{
|
||||
None = 0,
|
||||
Default = 1,
|
||||
Abbreviated = 2,
|
||||
Full = 3,
|
||||
}
|
||||
|
||||
public enum HourFormat
|
||||
{
|
||||
None = 0,
|
||||
Default = 1,
|
||||
}
|
||||
|
||||
public enum MinuteFormat
|
||||
{
|
||||
None = 0,
|
||||
Default = 1,
|
||||
}
|
||||
|
||||
public enum SecondFormat
|
||||
{
|
||||
None = 0,
|
||||
Default = 1,
|
||||
}
|
||||
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_DateTimeFormatter
|
||||
{
|
||||
// ---------- 私有字段 ----------
|
||||
private string _formatTemplate; // 原始模板字符串
|
||||
private string _formatPattern; // 实际用于 .NET 格式化的模式
|
||||
private List<string> _languages; // 语言优先级列表
|
||||
private string _geographicRegion; // 地理区域
|
||||
private string _calendar = "GregorianCalendar";
|
||||
private string _clock = "24HourClock";
|
||||
private string _numeralSystem = "Latn";
|
||||
private CultureInfo _culture; // 解析后的 CultureInfo
|
||||
private string _resolvedLanguage; // 实际使用的语言
|
||||
private string _resolvedGeographicRegion; // 实际使用的区域
|
||||
|
||||
// 存储构造时传入的枚举值(用于 IncludeXXX 属性)
|
||||
private YearFormat _yearFormat = YearFormat.None;
|
||||
private MonthFormat _monthFormat = MonthFormat.None;
|
||||
private DayFormat _dayFormat = DayFormat.None;
|
||||
private DayOfWeekFormat _dayOfWeekFormat = DayOfWeekFormat.None;
|
||||
private HourFormat _hourFormat = HourFormat.None;
|
||||
private MinuteFormat _minuteFormat = MinuteFormat.None;
|
||||
private SecondFormat _secondFormat = SecondFormat.None;
|
||||
|
||||
// ---------- 辅助方法 ----------
|
||||
private static string MapTemplateToPattern (string template, CultureInfo culture, string clock)
|
||||
{
|
||||
if (string.IsNullOrEmpty (template))
|
||||
return string.Empty;
|
||||
|
||||
switch (template.ToLowerInvariant ())
|
||||
{
|
||||
case "longdate":
|
||||
return culture.DateTimeFormat.LongDatePattern;
|
||||
case "shortdate":
|
||||
return culture.DateTimeFormat.ShortDatePattern;
|
||||
case "longtime":
|
||||
return culture.DateTimeFormat.LongTimePattern;
|
||||
case "shorttime":
|
||||
return culture.DateTimeFormat.ShortTimePattern;
|
||||
case "dayofweek":
|
||||
return culture.DateTimeFormat.ShortestDayNames? [0] ?? "dddd"; // 近似
|
||||
case "dayofweek.full":
|
||||
return "dddd";
|
||||
case "dayofweek.abbreviated":
|
||||
return "ddd";
|
||||
case "day":
|
||||
return "dd";
|
||||
case "month":
|
||||
return "MMMM";
|
||||
case "month.full":
|
||||
return "MMMM";
|
||||
case "month.abbreviated":
|
||||
return "MMM";
|
||||
case "month.numeric":
|
||||
return "MM";
|
||||
case "year":
|
||||
return "yyyy";
|
||||
case "year.full":
|
||||
return "yyyy";
|
||||
case "year.abbreviated":
|
||||
return "yy";
|
||||
case "hour":
|
||||
return clock == "24HourClock" ? "HH" : "hh";
|
||||
case "minute":
|
||||
return "mm";
|
||||
case "second":
|
||||
return "ss";
|
||||
case "timezone":
|
||||
return "zzz";
|
||||
default:
|
||||
// 如果不是预定义模板,则当作自定义模式直接返回
|
||||
return template;
|
||||
}
|
||||
}
|
||||
|
||||
// 根据枚举组合构建格式模式
|
||||
private static string BuildPatternFromEnums (YearFormat year, MonthFormat month, DayFormat day, DayOfWeekFormat dayOfWeek,
|
||||
HourFormat hour, MinuteFormat minute, SecondFormat second,
|
||||
string clock, CultureInfo culture)
|
||||
{
|
||||
var parts = new List<string> ();
|
||||
// 日期部分
|
||||
if (dayOfWeek != DayOfWeekFormat.None)
|
||||
{
|
||||
if (dayOfWeek == DayOfWeekFormat.Abbreviated)
|
||||
parts.Add ("ddd");
|
||||
else // Full or Default
|
||||
parts.Add ("dddd");
|
||||
}
|
||||
if (year != YearFormat.None)
|
||||
{
|
||||
if (year == YearFormat.Abbreviated)
|
||||
parts.Add ("yy");
|
||||
else
|
||||
parts.Add ("yyyy");
|
||||
}
|
||||
if (month != MonthFormat.None)
|
||||
{
|
||||
switch (month)
|
||||
{
|
||||
case MonthFormat.Numeric:
|
||||
parts.Add ("MM");
|
||||
break;
|
||||
case MonthFormat.Abbreviated:
|
||||
parts.Add ("MMM");
|
||||
break;
|
||||
case MonthFormat.Full:
|
||||
parts.Add ("MMMM");
|
||||
break;
|
||||
default:
|
||||
parts.Add ("MM");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (day != DayFormat.None)
|
||||
{
|
||||
parts.Add ("dd");
|
||||
}
|
||||
string datePart = string.Join (" ", parts);
|
||||
// 时间部分
|
||||
var timeParts = new List<string> ();
|
||||
if (hour != HourFormat.None)
|
||||
{
|
||||
if (clock == "24HourClock")
|
||||
timeParts.Add ("HH");
|
||||
else
|
||||
timeParts.Add ("hh");
|
||||
}
|
||||
if (minute != MinuteFormat.None)
|
||||
{
|
||||
timeParts.Add ("mm");
|
||||
}
|
||||
if (second != SecondFormat.None)
|
||||
{
|
||||
timeParts.Add ("ss");
|
||||
}
|
||||
string timePart = timeParts.Count > 0 ? string.Join (":", timeParts) : "";
|
||||
if (!string.IsNullOrEmpty (datePart) && !string.IsNullOrEmpty (timePart))
|
||||
return datePart + " " + timePart;
|
||||
if (!string.IsNullOrEmpty (datePart))
|
||||
return datePart;
|
||||
return timePart;
|
||||
}
|
||||
|
||||
// 将 JS Date 对象转换为 DateTime
|
||||
private DateTime ConvertJsDateToDateTime (object jsDate)
|
||||
{
|
||||
if (jsDate == null)
|
||||
throw new ArgumentNullException (nameof (jsDate));
|
||||
|
||||
Type type = jsDate.GetType ();
|
||||
// 调用 getTime() 获取毫秒数 (double)
|
||||
double milliseconds = (double)type.InvokeMember (
|
||||
"getTime",
|
||||
BindingFlags.InvokeMethod,
|
||||
null,
|
||||
jsDate,
|
||||
null);
|
||||
|
||||
// 手动计算 Unix 纪元转换(兼容低版本 .NET)
|
||||
DateTime epoch = new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
DateTime utcDateTime = epoch.AddMilliseconds (milliseconds);
|
||||
// 返回本地时间(可根据需求调整)
|
||||
return utcDateTime.ToLocalTime ();
|
||||
}
|
||||
|
||||
// 初始化文化信息
|
||||
private void InitializeCulture ()
|
||||
{
|
||||
string lang = (_languages != null && _languages.Count > 0) ? _languages [0] : CultureInfo.CurrentCulture.Name;
|
||||
try
|
||||
{
|
||||
_culture = new CultureInfo (lang);
|
||||
_resolvedLanguage = _culture.Name;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_culture = CultureInfo.CurrentCulture;
|
||||
_resolvedLanguage = _culture.Name;
|
||||
}
|
||||
_resolvedGeographicRegion = _geographicRegion ?? _culture.Name;
|
||||
// 根据区域和语言更新格式模式(如果使用模板)
|
||||
if (!string.IsNullOrEmpty (_formatTemplate))
|
||||
{
|
||||
_formatPattern = MapTemplateToPattern (_formatTemplate, _culture, _clock);
|
||||
}
|
||||
else if (_yearFormat != YearFormat.None || _monthFormat != MonthFormat.None ||
|
||||
_dayFormat != DayFormat.None || _dayOfWeekFormat != DayOfWeekFormat.None ||
|
||||
_hourFormat != HourFormat.None || _minuteFormat != MinuteFormat.None ||
|
||||
_secondFormat != SecondFormat.None)
|
||||
{
|
||||
_formatPattern = BuildPatternFromEnums (_yearFormat, _monthFormat, _dayFormat, _dayOfWeekFormat,
|
||||
_hourFormat, _minuteFormat, _secondFormat, _clock, _culture);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- 构造函数 ----------
|
||||
public _I_DateTimeFormatter (string formatTemplate)
|
||||
: this (formatTemplate, null, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_DateTimeFormatter (string formatTemplate, IEnumerable<string> languages)
|
||||
: this (formatTemplate, languages, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_DateTimeFormatter (string formatTemplate, IEnumerable<string> languages, string geographicRegion, string calendar, string clock)
|
||||
{
|
||||
_formatTemplate = formatTemplate;
|
||||
_languages = languages == null ? new List<string> () : new List<string> (languages);
|
||||
_geographicRegion = geographicRegion;
|
||||
if (!string.IsNullOrEmpty (calendar))
|
||||
_calendar = calendar;
|
||||
if (!string.IsNullOrEmpty (clock))
|
||||
_clock = clock;
|
||||
InitializeCulture ();
|
||||
}
|
||||
|
||||
public _I_DateTimeFormatter (YearFormat year, MonthFormat month, DayFormat day, DayOfWeekFormat dayOfWeek)
|
||||
: this (year, month, day, dayOfWeek, HourFormat.None, MinuteFormat.None, SecondFormat.None, null, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_DateTimeFormatter (HourFormat hour, MinuteFormat minute, SecondFormat second)
|
||||
: this (YearFormat.None, MonthFormat.None, DayFormat.None, DayOfWeekFormat.None, hour, minute, second, null, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_DateTimeFormatter (YearFormat year, MonthFormat month, DayFormat day, DayOfWeekFormat dayOfWeek,
|
||||
HourFormat hour, MinuteFormat minute, SecondFormat second,
|
||||
IEnumerable<string> languages)
|
||||
: this (year, month, day, dayOfWeek, hour, minute, second, languages, null, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
public _I_DateTimeFormatter (YearFormat year, MonthFormat month, DayFormat day, DayOfWeekFormat dayOfWeek,
|
||||
HourFormat hour, MinuteFormat minute, SecondFormat second,
|
||||
IEnumerable<string> languages, string geographicRegion, string calendar, string clock)
|
||||
{
|
||||
_yearFormat = year;
|
||||
_monthFormat = month;
|
||||
_dayFormat = day;
|
||||
_dayOfWeekFormat = dayOfWeek;
|
||||
_hourFormat = hour;
|
||||
_minuteFormat = minute;
|
||||
_secondFormat = second;
|
||||
_languages = languages == null ? new List<string> () : new List<string> (languages);
|
||||
_geographicRegion = geographicRegion;
|
||||
if (!string.IsNullOrEmpty (calendar))
|
||||
_calendar = calendar;
|
||||
if (!string.IsNullOrEmpty (clock))
|
||||
_clock = clock;
|
||||
InitializeCulture ();
|
||||
}
|
||||
|
||||
// ---------- 属性 ----------
|
||||
public string Calendar
|
||||
{
|
||||
get { return _calendar; }
|
||||
set
|
||||
{
|
||||
_calendar = value;
|
||||
// 日历更改可能需要重新初始化模式,这里简化处理
|
||||
}
|
||||
}
|
||||
|
||||
public string Clock
|
||||
{
|
||||
get { return _clock; }
|
||||
set
|
||||
{
|
||||
_clock = value;
|
||||
InitializeCulture (); // 重新生成模式(因为小时格式可能变化)
|
||||
}
|
||||
}
|
||||
|
||||
public string GeographicRegion
|
||||
{
|
||||
get { return _geographicRegion; }
|
||||
set
|
||||
{
|
||||
_geographicRegion = value;
|
||||
InitializeCulture ();
|
||||
}
|
||||
}
|
||||
|
||||
public int IncludeDay
|
||||
{
|
||||
get { return (int)_dayFormat; }
|
||||
}
|
||||
|
||||
public int IncludeDayOfWeek
|
||||
{
|
||||
get { return (int)_dayOfWeekFormat; }
|
||||
}
|
||||
|
||||
public int IncludeHour
|
||||
{
|
||||
get { return (int)_hourFormat; }
|
||||
}
|
||||
|
||||
public int IncludeMinute
|
||||
{
|
||||
get { return (int)_minuteFormat; }
|
||||
}
|
||||
|
||||
public int IncludeMonth
|
||||
{
|
||||
get { return (int)_monthFormat; }
|
||||
}
|
||||
|
||||
public int IncludeSecond
|
||||
{
|
||||
get { return (int)_secondFormat; }
|
||||
}
|
||||
|
||||
public int IncludeYear
|
||||
{
|
||||
get { return (int)_yearFormat; }
|
||||
}
|
||||
|
||||
public _I_List Languages
|
||||
{
|
||||
get { return new _I_List (_languages.AsReadOnly ().Select (e => (object)e), true); }
|
||||
}
|
||||
|
||||
public static _I_DateTimeFormatter LongDate
|
||||
{
|
||||
get
|
||||
{
|
||||
return new _I_DateTimeFormatter ("longdate");
|
||||
}
|
||||
}
|
||||
|
||||
public static _I_DateTimeFormatter LongTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return new _I_DateTimeFormatter ("longtime");
|
||||
}
|
||||
}
|
||||
|
||||
public string NumeralSystem
|
||||
{
|
||||
get { return _numeralSystem; }
|
||||
set { _numeralSystem = value; }
|
||||
}
|
||||
|
||||
public _I_List Patterns
|
||||
{
|
||||
get
|
||||
{
|
||||
return new _I_List (new List<string> { _formatPattern }.AsReadOnly ().Select (e => (object)e), true);
|
||||
}
|
||||
}
|
||||
|
||||
public string ResolvedGeographicRegion
|
||||
{
|
||||
get { return _resolvedGeographicRegion; }
|
||||
}
|
||||
|
||||
public string ResolvedLanguage
|
||||
{
|
||||
get { return _resolvedLanguage; }
|
||||
}
|
||||
|
||||
public static _I_DateTimeFormatter ShortDate
|
||||
{
|
||||
get
|
||||
{
|
||||
return new _I_DateTimeFormatter ("shortdate");
|
||||
}
|
||||
}
|
||||
|
||||
public static _I_DateTimeFormatter ShortTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return new _I_DateTimeFormatter ("shorttime");
|
||||
}
|
||||
}
|
||||
|
||||
public string Template
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty (_formatTemplate))
|
||||
return _formatTemplate;
|
||||
// 从枚举组合生成模板描述(简化)
|
||||
return _formatPattern;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- 方法 ----------
|
||||
public string FormatC (DateTime dateTime)
|
||||
{
|
||||
return dateTime.ToString (_formatPattern, _culture);
|
||||
}
|
||||
|
||||
public string FormatC (DateTime dateTime, string timeZoneId)
|
||||
{
|
||||
if (!string.IsNullOrEmpty (timeZoneId))
|
||||
{
|
||||
try
|
||||
{
|
||||
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById (timeZoneId);
|
||||
DateTime targetTime = TimeZoneInfo.ConvertTime (dateTime, tzi);
|
||||
return targetTime.ToString (_formatPattern, _culture);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 时区无效,回退到原始时间
|
||||
return dateTime.ToString (_formatPattern, _culture);
|
||||
}
|
||||
}
|
||||
return dateTime.ToString (_formatPattern, _culture);
|
||||
}
|
||||
|
||||
// 为方便 JS 调用,提供接受 object 的重载(自动识别 JS Date)
|
||||
public string Format (object jsDate)
|
||||
{
|
||||
DateTime dt = ConvertJsDateToDateTime (jsDate);
|
||||
return FormatC (dt);
|
||||
}
|
||||
|
||||
public string FormatWithTimeZone (object jsDate, string timeZoneId)
|
||||
{
|
||||
DateTime dt = ConvertJsDateToDateTime (jsDate);
|
||||
return FormatC (dt, timeZoneId);
|
||||
}
|
||||
}
|
||||
}
|
||||
270
DataUtils/Download.cs
Normal file
270
DataUtils/Download.cs
Normal file
@@ -0,0 +1,270 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Reflection;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
[ComVisible (false)]
|
||||
public sealed class DownloadHelper
|
||||
{
|
||||
private static readonly object s_downloadLock = new object (); // mimic g_download_cs
|
||||
|
||||
// Public static entry (starts background thread)
|
||||
public static void DownloadFile (string httpUrl, string savePath, object onProgress, object onComplete, object onError)
|
||||
{
|
||||
if (string.IsNullOrEmpty (httpUrl)) throw new ArgumentNullException ("httpUrl");
|
||||
if (string.IsNullOrEmpty (savePath)) throw new ArgumentNullException ("savePath");
|
||||
|
||||
var helper = new DownloadHelper (httpUrl, savePath, onProgress, onComplete, onError);
|
||||
Thread th = new Thread (helper.Worker);
|
||||
th.IsBackground = true;
|
||||
th.Start ();
|
||||
}
|
||||
|
||||
// Instance members
|
||||
private readonly string _url;
|
||||
private readonly string _savePath;
|
||||
private readonly object _cbProgress;
|
||||
private readonly object _cbComplete;
|
||||
private readonly object _cbError;
|
||||
|
||||
private DownloadHelper (string url, string savePath, object cbProgress, object cbComplete, object cbError)
|
||||
{
|
||||
_url = url;
|
||||
_savePath = savePath;
|
||||
_cbProgress = cbProgress;
|
||||
_cbComplete = cbComplete;
|
||||
_cbError = cbError;
|
||||
}
|
||||
|
||||
private void Worker ()
|
||||
{
|
||||
// Single download at a time (mimic CreateScopedLock)
|
||||
lock (s_downloadLock)
|
||||
{
|
||||
HttpWebRequest request = null;
|
||||
HttpWebResponse response = null;
|
||||
Stream responseStream = null;
|
||||
FileStream fileStream = null;
|
||||
|
||||
try
|
||||
{
|
||||
request = (HttpWebRequest)WebRequest.Create (_url);
|
||||
request.Method = "GET";
|
||||
request.AllowAutoRedirect = true;
|
||||
request.UserAgent = "Mozilla/5.0 (Windows NT 6.2; Win32; x86) AppInstallerUpdater/1.0";
|
||||
request.Timeout = 60000; // 60s connect timeout
|
||||
request.ReadWriteTimeout = 60000;
|
||||
|
||||
response = (HttpWebResponse)request.GetResponse ();
|
||||
long contentLength = -1;
|
||||
try { contentLength = response.ContentLength; } catch { contentLength = -1; }
|
||||
|
||||
responseStream = response.GetResponseStream ();
|
||||
|
||||
// create directory if needed
|
||||
string dir = Path.GetDirectoryName (_savePath);
|
||||
if (!string.IsNullOrEmpty (dir) && !Directory.Exists (dir))
|
||||
Directory.CreateDirectory (dir);
|
||||
|
||||
fileStream = new FileStream (_savePath, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||||
|
||||
byte [] buffer = new byte [8192];
|
||||
int bytesRead;
|
||||
long received = 0;
|
||||
|
||||
var lastCheck = DateTime.UtcNow;
|
||||
long lastBytes = 0;
|
||||
const double reportIntervalSeconds = 0.5;
|
||||
|
||||
while ((bytesRead = SafeRead (responseStream, buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
fileStream.Write (buffer, 0, bytesRead);
|
||||
received += bytesRead;
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
double interval = (now - lastCheck).TotalSeconds;
|
||||
long speed = -1;
|
||||
if (interval >= reportIntervalSeconds)
|
||||
{
|
||||
long bytesInInterval = received - lastBytes;
|
||||
if (interval > 0)
|
||||
speed = (long)(bytesInInterval / interval); // B/s
|
||||
lastCheck = now;
|
||||
lastBytes = received;
|
||||
}
|
||||
|
||||
ReportProgress (received, contentLength >= 0 ? contentLength : 0, speed);
|
||||
}
|
||||
|
||||
// flush and close file
|
||||
fileStream.Flush ();
|
||||
|
||||
ReportComplete (_savePath, received);
|
||||
}
|
||||
catch (WebException wex)
|
||||
{
|
||||
string reason = BuildWebExceptionReason (wex);
|
||||
ReportError (_savePath, reason);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ReportError (_savePath, ex.Message ?? ex.ToString ());
|
||||
}
|
||||
finally
|
||||
{
|
||||
try { if (responseStream != null) responseStream.Close (); } catch { }
|
||||
try { if (response != null) response.Close (); } catch { }
|
||||
try { if (fileStream != null) fileStream.Close (); } catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Safe read wrapper to handle potential stream interruptions
|
||||
private static int SafeRead (Stream s, byte [] buffer, int offset, int count)
|
||||
{
|
||||
try
|
||||
{
|
||||
return s.Read (buffer, offset, count);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Build a user-friendly reason text from WebException (includes status / inner messages)
|
||||
private static string BuildWebExceptionReason (WebException wex)
|
||||
{
|
||||
try
|
||||
{
|
||||
StringBuilder sb = new StringBuilder ();
|
||||
sb.Append ("WebException: ");
|
||||
sb.Append (wex.Status.ToString ());
|
||||
if (wex.Response != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var resp = (HttpWebResponse)wex.Response;
|
||||
sb.AppendFormat (CultureInfo.InvariantCulture, " (HTTP {0})", (int)resp.StatusCode);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
if (!string.IsNullOrEmpty (wex.Message))
|
||||
{
|
||||
sb.Append (" - ");
|
||||
sb.Append (wex.Message);
|
||||
}
|
||||
return sb.ToString ();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return wex.Message ?? "Unknown WebException";
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- Reporting helpers (use Newtonsoft.Json) ----------
|
||||
|
||||
private void ReportProgress (long received, long total, long speed)
|
||||
{
|
||||
if (_cbProgress == null) return;
|
||||
|
||||
double progress = 0.0;
|
||||
if (total > 0) progress = received / (double)total * 100.0;
|
||||
|
||||
var payload = new
|
||||
{
|
||||
received = received,
|
||||
total = total,
|
||||
speed = FormatSpeed (speed),
|
||||
progress = progress
|
||||
};
|
||||
|
||||
string json = JsonConvert.SerializeObject (payload);
|
||||
CallJS (_cbProgress, json);
|
||||
}
|
||||
|
||||
private void ReportComplete (string file, long size)
|
||||
{
|
||||
if (_cbComplete == null) return;
|
||||
|
||||
var payload = new
|
||||
{
|
||||
file = file ?? string.Empty,
|
||||
status = "ok",
|
||||
size = size
|
||||
};
|
||||
|
||||
string json = JsonConvert.SerializeObject (payload);
|
||||
CallJS (_cbComplete, json);
|
||||
}
|
||||
|
||||
private void ReportError (string file, string reason)
|
||||
{
|
||||
if (_cbError == null) return;
|
||||
|
||||
var payload = new
|
||||
{
|
||||
file = file ?? string.Empty,
|
||||
status = "failed",
|
||||
reason = reason ?? string.Empty
|
||||
};
|
||||
|
||||
string json = JsonConvert.SerializeObject (payload);
|
||||
CallJS (_cbError, json);
|
||||
}
|
||||
|
||||
// Call JS callback object: invoke its "call" method like original code: jsFunc.call(1, arg)
|
||||
private void CallJS (object jsFunc, string arg)
|
||||
{
|
||||
if (jsFunc == null) return;
|
||||
try
|
||||
{
|
||||
// Use reflection to invoke `call` method with (thisArg, arg)
|
||||
jsFunc.GetType ().InvokeMember (
|
||||
"call",
|
||||
BindingFlags.InvokeMethod,
|
||||
null,
|
||||
jsFunc,
|
||||
new object [] { 1, arg });
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore errors in callback invocation
|
||||
}
|
||||
}
|
||||
|
||||
// Format speed like original: B/s, KB/s, MB/s, …
|
||||
private string FormatSpeed (long speed)
|
||||
{
|
||||
if (speed < 0) return "--/s";
|
||||
string [] units = new string [] { "B/s", "KB/s", "MB/s", "GB/s", "TB/s" };
|
||||
double s = (double)speed;
|
||||
int idx = 0;
|
||||
while (s >= 1024.0 && idx < units.Length - 1)
|
||||
{
|
||||
s /= 1024.0;
|
||||
idx++;
|
||||
}
|
||||
return string.Format (CultureInfo.InvariantCulture, "{0:0.##} {1}", s, units [idx]);
|
||||
}
|
||||
}
|
||||
|
||||
// Simple COM-visible wrapper class for JS/COM consumers
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Download
|
||||
{
|
||||
// Keep method order and names similar to your C++/CLI _I_Download.WorkAsync
|
||||
public void WorkAsync (string httpurl, string saveFilePath, object onComplete, object onError, object onProgress)
|
||||
{
|
||||
DownloadHelper.DownloadFile (httpurl, saveFilePath, onProgress, onComplete, onError);
|
||||
}
|
||||
}
|
||||
}
|
||||
173
DataUtils/Enumerable.cs
Normal file
173
DataUtils/Enumerable.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
[ComVisible (true)]
|
||||
[InterfaceType (ComInterfaceType.InterfaceIsDual)]
|
||||
public interface _I_Enumerable: IDisposable
|
||||
{
|
||||
int Length { get; set; }
|
||||
object this [int index] { get; set; }
|
||||
void Add (object value); // push
|
||||
void Push (object value);
|
||||
object Pop (); // 删除并返回末尾元素
|
||||
object Shift (); // 删除并返回开头元素
|
||||
void Unshift (object value); // 在开头插入
|
||||
void RemoveAt (int index); // 删除任意索引
|
||||
void Clear (); // 清空数组
|
||||
_I_Enumerable Slice (int start, int end); // 返回子数组
|
||||
void Splice (int start, int deleteCount, object [] items); // 删除并插入
|
||||
int IndexOf (object value); // 查找索引
|
||||
bool Includes (object value); // 是否包含
|
||||
void ForEach (object callback, bool suppressExceptions = false); // 遍历,callback(item, index)
|
||||
_I_Enumerable Concat (_I_Enumerable other); // 拼接
|
||||
string Join (string separator); // 转字符串
|
||||
object GetItem (int index); // 返回 { key, data } 或直接 data
|
||||
void SetAt (int index, object value); // 替换元素
|
||||
int IndexOfKey (int key); // 按内部 key 查找
|
||||
void Move (int index, int newIndex); // 移动元素
|
||||
void PushAll (object [] items); // 一次性 push 多个
|
||||
object Get (int index);
|
||||
object Set (int index, object value);
|
||||
object At (int index);
|
||||
}
|
||||
public class _I_List: _I_Enumerable, IList
|
||||
{
|
||||
public _I_List (IEnumerable<object> initArr, bool readOnly = false, bool fixedSize = false, bool sync = true)
|
||||
{
|
||||
_list = initArr?.ToList () ?? new List<object> ();
|
||||
IsFixedSize = fixedSize;
|
||||
IsReadOnly = readOnly;
|
||||
IsSynchronized = sync;
|
||||
}
|
||||
public _I_List (bool readOnly = false, bool fixedSize = false, bool sync = true) :
|
||||
this (null, readOnly, fixedSize, sync)
|
||||
{ }
|
||||
protected List<object> _list;
|
||||
protected object _lock = new object ();
|
||||
public object this [int index] { get { return _list [index]; } set { _list [index] = value; } }
|
||||
public int Count => _list.Count;
|
||||
public bool IsFixedSize { get; }
|
||||
public bool IsReadOnly { get; }
|
||||
public bool IsSynchronized { get; }
|
||||
public int Length
|
||||
{
|
||||
get { return _list.Count; }
|
||||
set
|
||||
{
|
||||
if (!IsFixedSize && !IsReadOnly)
|
||||
{
|
||||
_list.Capacity = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
public object SyncRoot => _lock;
|
||||
public void Add (object value) => _list.Add (value);
|
||||
public void Push (object value) => _list.Add (value);
|
||||
public void RemoveAt (int index) => _list.RemoveAt (index);
|
||||
public void Clear () => _list.Clear ();
|
||||
public int IndexOf (object value) => _list.IndexOf (value);
|
||||
int IList.Add (object value)
|
||||
{
|
||||
_list.Add (value);
|
||||
return _list.Count - 1;
|
||||
}
|
||||
public bool Contains (object value) => _list.Contains (value);
|
||||
public void Insert (int index, object value) => _list.Insert (index, value);
|
||||
public void Remove (object value) => _list.Remove (value);
|
||||
public void ForEach (object callback, bool suppressExceptions = false)
|
||||
{
|
||||
for (int i = 0; i < _list.Count; i++)
|
||||
{
|
||||
var item = _list [i];
|
||||
if (suppressExceptions)
|
||||
{
|
||||
try { JsUtils.Call (callback, item, i); } catch { }
|
||||
}
|
||||
else JsUtils.Call (callback, item, i);
|
||||
}
|
||||
}
|
||||
public IEnumerator GetEnumerator () => _list.GetEnumerator ();
|
||||
public _I_Enumerable Slice (int start, int end)
|
||||
{
|
||||
if (end < 0) end = _list.Count + end;
|
||||
start = Math.Max (0, start);
|
||||
end = Math.Min (_list.Count, end);
|
||||
var arr = _list.GetRange (start, Math.Max (0, end - start));
|
||||
return new _I_List (arr);
|
||||
}
|
||||
public void Splice (int start, int deleteCount, object [] items)
|
||||
{
|
||||
if (start < 0) start = Math.Max (0, _list.Count + start);
|
||||
int count = Math.Min (deleteCount, _list.Count - start);
|
||||
_list.RemoveRange (start, count);
|
||||
if (items != null && items.Length > 0)
|
||||
_list.InsertRange (start, items);
|
||||
}
|
||||
public bool Includes (object value) => _list.Contains (value);
|
||||
public _I_Enumerable Concat (_I_Enumerable other)
|
||||
{
|
||||
var newList = new List<object> (_list);
|
||||
if (other is _I_List)
|
||||
newList.AddRange ((other as _I_List)._list);
|
||||
return new _I_List (newList);
|
||||
}
|
||||
public string Join (string separator)
|
||||
{
|
||||
return string.Join (separator ?? ",", _list.Select (x => x?.ToString () ?? ""));
|
||||
}
|
||||
public object GetItem (int index) => _list [index];
|
||||
public void SetAt (int index, object value) => _list [index] = value;
|
||||
public int IndexOfKey (int key)
|
||||
{
|
||||
return key >= 0 && key < _list.Count ? key : -1;
|
||||
}
|
||||
public void Move (int index, int newIndex)
|
||||
{
|
||||
if (index < 0 || index >= _list.Count || newIndex < 0 || newIndex >= _list.Count) return;
|
||||
var item = _list [index];
|
||||
_list.RemoveAt (index);
|
||||
_list.Insert (newIndex, item);
|
||||
}
|
||||
public void PushAll (object [] items)
|
||||
{
|
||||
if (items == null || items.Length == 0) return;
|
||||
_list.AddRange (items);
|
||||
}
|
||||
public void CopyTo (Array array, int index)
|
||||
{
|
||||
if (array == null) throw new ArgumentNullException (nameof (array));
|
||||
for (int i = 0; i < _list.Count && index + i < array.Length; i++)
|
||||
array.SetValue (_list [i], index + i);
|
||||
}
|
||||
public object Pop ()
|
||||
{
|
||||
if (_list.Count == 0) return null;
|
||||
var last = _list [_list.Count - 1];
|
||||
_list.RemoveAt (_list.Count - 1);
|
||||
return last;
|
||||
}
|
||||
public object Shift ()
|
||||
{
|
||||
if (_list.Count == 0) return null;
|
||||
var first = _list [0];
|
||||
_list.RemoveAt (0);
|
||||
return first;
|
||||
}
|
||||
public void Unshift (object value) => _list.Insert (0, value);
|
||||
public void Dispose ()
|
||||
{
|
||||
_list?.Clear ();
|
||||
_list = null;
|
||||
}
|
||||
public object Get (int index) => this [index];
|
||||
public object Set (int index, object value) => this [index] = value;
|
||||
public object At (int index) => this [index];
|
||||
}
|
||||
}
|
||||
101
DataUtils/HResult.cs
Normal file
101
DataUtils/HResult.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_HResult
|
||||
{
|
||||
private int hr;
|
||||
private string errorcode;
|
||||
private string detailmsg;
|
||||
public _I_HResult (int hres)
|
||||
{
|
||||
hr = hres;
|
||||
errorcode = null;
|
||||
detailmsg = HResultToMessage (hr) ?? string.Empty;
|
||||
}
|
||||
public _I_HResult (int hres, string error, string message)
|
||||
{
|
||||
hr = hres;
|
||||
errorcode = error ?? string.Empty;
|
||||
detailmsg = message ?? string.Empty;
|
||||
}
|
||||
// Properties (read-only as in your C++/CLI)
|
||||
public int HResult
|
||||
{
|
||||
get { return hr; }
|
||||
}
|
||||
// If user provided an explicit error code string use it; otherwise return the hex form "0xXXXXXXXX"
|
||||
public string ErrorCode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!string.IsNullOrEmpty (errorcode)) return errorcode;
|
||||
return "0x" + hr.ToString ("X8", System.Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
public string Message
|
||||
{
|
||||
get { return detailmsg; }
|
||||
}
|
||||
public bool Succeeded
|
||||
{
|
||||
get { return hr >= 0; } // SUCCEEDED macro: hr >= 0
|
||||
}
|
||||
public bool Failed
|
||||
{
|
||||
get { return hr < 0; } // FAILED macro: hr < 0
|
||||
}
|
||||
public override string ToString ()
|
||||
{
|
||||
return string.Format (System.Globalization.CultureInfo.InvariantCulture,
|
||||
"HResult={0}, ErrorCode={1}, Message={2}", hr, ErrorCode, Message);
|
||||
}
|
||||
// Try to obtain a user-friendly message for the HRESULT.
|
||||
// First try Marshal.GetExceptionForHR, then fallback to FormatMessage.
|
||||
private static string HResultToMessage (int hresult)
|
||||
{
|
||||
try
|
||||
{
|
||||
Exception ex = Marshal.GetExceptionForHR (hresult);
|
||||
if (ex != null)
|
||||
{
|
||||
string msg = ex.Message;
|
||||
if (!string.IsNullOrEmpty (msg)) return msg;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
string fmt = FormatMessageFromSystem (hresult);
|
||||
if (!string.IsNullOrEmpty (fmt)) return fmt;
|
||||
int win32Code = hresult & 0xFFFF;
|
||||
fmt = FormatMessageFromSystem (win32Code);
|
||||
if (!string.IsNullOrEmpty (fmt)) return fmt;
|
||||
return string.Empty;
|
||||
}
|
||||
private static string FormatMessageFromSystem (int messageId)
|
||||
{
|
||||
const int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
|
||||
const int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
|
||||
const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
|
||||
int flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
|
||||
StringBuilder sb = new StringBuilder (512);
|
||||
|
||||
int res = FormatMessage (flags, IntPtr.Zero, messageId, 0, sb, sb.Capacity, IntPtr.Zero);
|
||||
if (res != 0)
|
||||
{
|
||||
// Trim trailing newlines that FormatMessage often appends
|
||||
return sb.ToString ().TrimEnd ('\r', '\n', ' ');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
private static extern int FormatMessage (int dwFlags, IntPtr lpSource, int dwMessageId, int dwLanguageId, [Out] StringBuilder lpBuffer, int nSize, IntPtr Arguments);
|
||||
}
|
||||
}
|
||||
198
DataUtils/IE.cs
Normal file
198
DataUtils/IE.cs
Normal file
@@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Win32;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
public static class BrowserEmulation
|
||||
{
|
||||
// The emulation value used in original C++ (11001).
|
||||
// 11001 typically corresponds to IE11 in edge mode for most hosts.
|
||||
private const int EmulationValue = 11001;
|
||||
/// <summary>
|
||||
/// Set the browser emulation value for the current user and current executable.
|
||||
/// Writes to HKCU\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION.
|
||||
/// Creates the key if it does not exist.
|
||||
/// </summary>
|
||||
public static void SetWebBrowserEmulation ()
|
||||
{
|
||||
try
|
||||
{
|
||||
string exeName = GetCurrentProcessFileName ();
|
||||
if (string.IsNullOrEmpty (exeName)) return;
|
||||
|
||||
// Registry path under HKCU (per-user setting)
|
||||
const string subKey = @"Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION";
|
||||
|
||||
using (RegistryKey key = Registry.CurrentUser.CreateSubKey (subKey, RegistryKeyPermissionCheck.ReadWriteSubTree))
|
||||
{
|
||||
if (key == null) return;
|
||||
// set DWORD value
|
||||
key.SetValue (exeName, EmulationValue, RegistryValueKind.DWord);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore exceptions to match original "best-effort" behavior
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取系统安装的 Internet Explorer 主版本号(如 8、9、10、11)。
|
||||
/// 会尝试从 64-bit registry view 和 32-bit registry view 读取(HKLM\SOFTWARE\Microsoft\Internet Explorer)。
|
||||
/// 返回 0 表示未能读取到版本信息。
|
||||
/// </summary>
|
||||
public static int GetInternetExplorerVersionMajor ()
|
||||
{
|
||||
const string ieKey = @"SOFTWARE\Microsoft\Internet Explorer";
|
||||
string versionStr = null;
|
||||
|
||||
// Try RegistryView.Registry64 then Registry32 for robustness on WOW64 systems
|
||||
foreach (RegistryView view in new [] { RegistryView.Registry64, RegistryView.Registry32 })
|
||||
{
|
||||
try
|
||||
{
|
||||
using (RegistryKey baseKey = RegistryKey.OpenBaseKey (RegistryHive.LocalMachine, view))
|
||||
using (RegistryKey key = baseKey.OpenSubKey (ieKey))
|
||||
{
|
||||
if (key == null) continue;
|
||||
object svcVersion = key.GetValue ("svcVersion");
|
||||
if (svcVersion is string)
|
||||
{
|
||||
versionStr = (string)svcVersion;
|
||||
}
|
||||
else
|
||||
{
|
||||
object ver = key.GetValue ("Version");
|
||||
if (ver is string) versionStr = (string)ver;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore and continue to next view
|
||||
}
|
||||
if (!string.IsNullOrEmpty (versionStr)) break;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty (versionStr)) return 0;
|
||||
|
||||
// parse major number before first non-digit/dot
|
||||
int major = 0;
|
||||
try
|
||||
{
|
||||
// common version formats: "11.0.9600.16428" etc.
|
||||
string [] parts = versionStr.Split (new char [] { '.' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length > 0 && int.TryParse (parts [0], out major))
|
||||
{
|
||||
return major;
|
||||
}
|
||||
// fallback: try to read first integer found
|
||||
string num = "";
|
||||
foreach (char c in versionStr)
|
||||
{
|
||||
if (char.IsDigit (c)) num += c;
|
||||
else break;
|
||||
}
|
||||
if (!string.IsNullOrEmpty (num) && int.TryParse (num, out major)) return major;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore parsing errors
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
public static int IEVersionMajor => GetInternetExplorerVersionMajor ();
|
||||
public static bool IsInternetExplorer10 ()
|
||||
{
|
||||
return GetInternetExplorerVersionMajor () == 10;
|
||||
}
|
||||
public static bool IE10 => IsInternetExplorer10 ();
|
||||
public static bool IsInternetExplorer11AndLater ()
|
||||
{
|
||||
return GetInternetExplorerVersionMajor () >= 11;
|
||||
}
|
||||
public static bool IE11 => IsInternetExplorer11AndLater ();
|
||||
// Helper: get file name of current process executable, e.g. "myapp.exe"
|
||||
private static string GetCurrentProcessFileName ()
|
||||
{
|
||||
try
|
||||
{
|
||||
string path = null;
|
||||
try
|
||||
{
|
||||
// prefer process main module (may throw in some restricted environments)
|
||||
path = Process.GetCurrentProcess ().MainModule.FileName;
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
var asm = System.Reflection.Assembly.GetEntryAssembly ();
|
||||
if (asm != null) path = asm.Location;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
if (string.IsNullOrEmpty (path))
|
||||
{
|
||||
path = AppDomain.CurrentDomain.FriendlyName;
|
||||
}
|
||||
if (string.IsNullOrEmpty (path)) return string.Empty;
|
||||
return Path.GetFileName (path);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
public interface IScriptBridge
|
||||
{
|
||||
/// <summary>
|
||||
/// 调用程序窗口实例中的事件
|
||||
/// </summary>
|
||||
/// <param name="funcName">函数名</param>
|
||||
/// <param name="e">事件参数</param>
|
||||
/// <returns>调用结果</returns>
|
||||
object CallEvent (string funcName, object e);
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_IEFrame
|
||||
{
|
||||
public int Version => BrowserEmulation.IEVersionMajor;
|
||||
public string ParseHtmlColor (string color)
|
||||
{
|
||||
try
|
||||
{
|
||||
Color dcolor = ColorTranslator.FromHtml (color);
|
||||
var obj = new
|
||||
{
|
||||
r = (ushort)dcolor.R,
|
||||
g = (ushort)dcolor.G,
|
||||
b = (ushort)dcolor.B,
|
||||
a = (ushort)dcolor.A
|
||||
};
|
||||
return JsonConvert.SerializeObject (obj);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "{}";
|
||||
}
|
||||
}
|
||||
private IWebBrowserPageScale iwbps;
|
||||
public _I_IEFrame (IWebBrowserPageScale _iwbps)
|
||||
{
|
||||
iwbps = _iwbps;
|
||||
}
|
||||
public int Scale
|
||||
{
|
||||
get { return iwbps.PageScale; }
|
||||
set { iwbps.PageScale = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
534
DataUtils/Locale.cs
Normal file
534
DataUtils/Locale.cs
Normal file
@@ -0,0 +1,534 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
public const int LOCALE_SSHORTESTSCRIPT = 0x0000004F; // 获取四字母脚本代码
|
||||
public const uint KLF_ACTIVATE = 0x00000001; // 激活键盘布局
|
||||
// GetLocaleInfoW for LCID-based queries
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int GetLocaleInfoW (int Locale, int LCType, [Out] StringBuilder lpLCData, int cchData);
|
||||
// GetLocaleInfoEx for locale name based queries
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int GetLocaleInfoEx (string lpLocaleName, int LCType, [Out] StringBuilder lpLCData, int cchData);
|
||||
// LocaleNameToLCID - available on Vista+; fallback is to use CultureInfo
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int LocaleNameToLCID (string lpName, uint dwFlags);
|
||||
// LCIDToLocaleName (Vista+)
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern int LCIDToLocaleName (int Locale, [Out] StringBuilder lpName, int cchName, uint dwFlags);
|
||||
[DllImport ("user32.dll")]
|
||||
public static extern IntPtr GetKeyboardLayout (uint dwLayout);
|
||||
[DllImport ("user32.dll", CharSet = CharSet.Auto)]
|
||||
public static extern IntPtr LoadKeyboardLayout (string pwszKLID, uint Flags);
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Language: System.Globalization.CultureInfo
|
||||
{
|
||||
public _I_Language (string localeName) : base (localeName) { }
|
||||
public string AbbreviatedName => this.ThreeLetterISOLanguageName;
|
||||
public string LanguageTag => this.IetfLanguageTag ?? this.Name;
|
||||
public int LayoutDirection
|
||||
{
|
||||
get
|
||||
{
|
||||
if (base.TextInfo.IsRightToLeft) return 1;
|
||||
string tag = this.LanguageTag;
|
||||
bool isVerticalCandidate = false;
|
||||
if (tag != null)
|
||||
{
|
||||
var scriptMatch = Regex.Match (tag, @"-([A-Za-z]{4})(?:-|$)");
|
||||
if (scriptMatch.Success)
|
||||
{
|
||||
string script = scriptMatch.Groups [1].Value;
|
||||
if (script == "Hani" || script == "Hira" || script == "Kana" || script == "Jpan" || script == "Kore" || script == "Hans" || script == "Hant")
|
||||
isVerticalCandidate = true;
|
||||
}
|
||||
if (!isVerticalCandidate)
|
||||
{
|
||||
var regionMatch = Regex.Match (tag, @"-([A-Za-z]{2})$");
|
||||
if (regionMatch.Success)
|
||||
{
|
||||
string region = regionMatch.Groups [1].Value.ToUpperInvariant ();
|
||||
if (region == "JP" || region == "CN" || region == "TW" || region == "HK" || region == "MO" || region == "KR")
|
||||
isVerticalCandidate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isVerticalCandidate)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
public string Script
|
||||
{
|
||||
get
|
||||
{
|
||||
StringBuilder sb = new StringBuilder (10);
|
||||
if (NativeMethods.GetLocaleInfoEx (this.Name, NativeMethods.LOCALE_SSHORTESTSCRIPT, sb, sb.Capacity) > 0)
|
||||
return sb.ToString ();
|
||||
|
||||
// 如果失败,尝试从语言标记中解析脚本子标记(如 "zh-Hans-CN" 中的 "Hans")
|
||||
var match = Regex.Match (this.Name, @"-([A-Za-z]{4})(?:-|$)");
|
||||
if (match.Success)
|
||||
return match.Groups [1].Value;
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
public _I_List GetExtensionSubtags (string singleton)
|
||||
{
|
||||
if (string.IsNullOrEmpty (singleton) || singleton.Length != 1)
|
||||
throw new ArgumentException ("Singleton must be a single character", nameof (singleton));
|
||||
var subtags = new List<string> ();
|
||||
string tag = this.LanguageTag;
|
||||
string pattern = $@"-{Regex.Escape (singleton)}-([a-zA-Z0-9](?:-[a-zA-Z0-9]+)*)";
|
||||
var match = Regex.Match (tag, pattern);
|
||||
if (match.Success)
|
||||
{
|
||||
string extPart = match.Groups [1].Value;
|
||||
subtags.AddRange (extPart.Split ('-'));
|
||||
}
|
||||
return new _I_List (subtags.Select (i => (object)i));
|
||||
}
|
||||
public bool TrySetInputMethodLanguageTag (string languageTag)
|
||||
{
|
||||
int lcid = NativeMethods.LocaleNameToLCID (languageTag, 0);
|
||||
if (lcid == 0)
|
||||
return false;
|
||||
string klid = $"{lcid:X8}";
|
||||
IntPtr hkl = NativeMethods.LoadKeyboardLayout (klid, NativeMethods.KLF_ACTIVATE);
|
||||
return hkl != IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Locale
|
||||
{
|
||||
// Current locale name like "en-US"
|
||||
public string CurrentLocale
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
// prefer thread culture name which reflects user culture
|
||||
string name = CultureInfo.CurrentCulture.Name;
|
||||
if (string.IsNullOrEmpty (name))
|
||||
name = CultureInfo.InstalledUICulture.Name;
|
||||
return name ?? string.Empty;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Current LCID (int)
|
||||
public int CurrentLCID
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return CultureInfo.CurrentCulture.LCID;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return CultureInfo.InvariantCulture.LCID;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Convert LCID -> locale name (e.g. 1033 -> "en-US")
|
||||
public string ToLocaleName (int lcid)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Try managed first
|
||||
var ci = new CultureInfo (lcid);
|
||||
if (!string.IsNullOrEmpty (ci.Name))
|
||||
return ci.Name;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// try Win32 LCIDToLocaleName (Vista+)
|
||||
try
|
||||
{
|
||||
StringBuilder sb = new StringBuilder (LOCALE_NAME_MAX_LENGTH);
|
||||
int res = NativeMethods.LCIDToLocaleName (lcid, sb, sb.Capacity, 0);
|
||||
if (res > 0) return sb.ToString ();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
// Convert locale name -> LCID
|
||||
public int ToLCID (string localeName)
|
||||
{
|
||||
if (string.IsNullOrEmpty (localeName)) return CultureInfo.InvariantCulture.LCID;
|
||||
try
|
||||
{
|
||||
// prefer managed creation
|
||||
var ci = new CultureInfo (localeName);
|
||||
return ci.LCID;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// try Win32 LocaleNameToLCID (Vista+)
|
||||
try
|
||||
{
|
||||
int lcid = NativeMethods.LocaleNameToLCID (localeName, 0);
|
||||
if (lcid != 0) return lcid;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
// fallback: invariant culture
|
||||
return CultureInfo.InvariantCulture.LCID;
|
||||
}
|
||||
// Return a locale info string for given LCID and LCTYPE. LCTYPE is the Win32 LOCALE_* constant.
|
||||
// Returns a string (or empty string on failure).
|
||||
public object LocaleInfo (int lcid, int lctype)
|
||||
{
|
||||
try
|
||||
{
|
||||
// First try mapping common LCTYPE values to managed properties for better correctness
|
||||
// Some common LCTYPE values:
|
||||
// LOCALE_SISO639LANGNAME = 0x59 (89) -> Two-letter ISO language name
|
||||
// LOCALE_SISO3166CTRYNAME = 0x5A (90) -> Two-letter country/region name
|
||||
// LOCALE_SNAME = 0x5c (92) -> locale name like "en-US" (Vista+)
|
||||
// But we cannot rely on all values, so we fallback to native GetLocaleInfoW.
|
||||
if (lctype == 0x59) // LOCALE_SISO639LANGNAME
|
||||
{
|
||||
try
|
||||
{
|
||||
var ci = new CultureInfo (lcid);
|
||||
return ci.TwoLetterISOLanguageName ?? string.Empty;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
else if (lctype == 0x5A) // LOCALE_SISO3166CTRYNAME
|
||||
{
|
||||
try
|
||||
{
|
||||
var ci = new CultureInfo (lcid);
|
||||
try
|
||||
{
|
||||
var ri = new RegionInfo (ci.Name);
|
||||
return ri.TwoLetterISORegionName ?? string.Empty;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// some cultures have no region; fallback to parsing name
|
||||
var name = ci.Name;
|
||||
if (!string.IsNullOrEmpty (name) && name.IndexOf ('-') >= 0)
|
||||
{
|
||||
return name.Split ('-') [1];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
else if (lctype == 0x5c) // LOCALE_SNAME
|
||||
{
|
||||
try
|
||||
{
|
||||
var ci = new CultureInfo (lcid);
|
||||
return ci.Name ?? string.Empty;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// Fallback to native GetLocaleInfoW
|
||||
StringBuilder sb = new StringBuilder (256);
|
||||
int ret = NativeMethods.GetLocaleInfoW (lcid, lctype, sb, sb.Capacity);
|
||||
if (ret > 0)
|
||||
return sb.ToString ();
|
||||
return string.Empty;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
// LocaleInfoEx: query by locale name string and LCTYPE
|
||||
// Returns string if available; otherwise returns the integer result code (as int) if string empty (mimic C++ behavior).
|
||||
public object LocaleInfoEx (string localeName, int lctype)
|
||||
{
|
||||
if (string.IsNullOrEmpty (localeName))
|
||||
{
|
||||
// fall back to current culture name
|
||||
localeName = CurrentLocale;
|
||||
if (string.IsNullOrEmpty (localeName)) return 0;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Try managed shortcuts for common types
|
||||
if (lctype == 0x59) // LOCALE_SISO639LANGNAME
|
||||
{
|
||||
try
|
||||
{
|
||||
var ci = new CultureInfo (localeName);
|
||||
return ci.TwoLetterISOLanguageName ?? string.Empty;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
else if (lctype == 0x5A) // LOCALE_SISO3166CTRYNAME
|
||||
{
|
||||
try
|
||||
{
|
||||
var ci = new CultureInfo (localeName);
|
||||
var ri = new RegionInfo (ci.Name);
|
||||
return ri.TwoLetterISORegionName ?? string.Empty;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// try to split
|
||||
var parts = localeName.Split (new char [] { '-', '_' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length >= 2) return parts [1];
|
||||
}
|
||||
}
|
||||
else if (lctype == 0x5c) // LOCALE_SNAME
|
||||
{
|
||||
// localeName is probably already the name
|
||||
return localeName;
|
||||
}
|
||||
|
||||
// Fallback to GetLocaleInfoEx
|
||||
StringBuilder sb = new StringBuilder (LOCALE_NAME_MAX_LENGTH);
|
||||
int res = NativeMethods.GetLocaleInfoEx (localeName, lctype, sb, sb.Capacity);
|
||||
if (res > 0)
|
||||
{
|
||||
string outStr = sb.ToString ();
|
||||
if (!string.IsNullOrEmpty (outStr))
|
||||
return outStr;
|
||||
}
|
||||
// if nothing returned, return the result code
|
||||
return res;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// Helpers similar to the C++: restricted (language) and elaborated (region) codes
|
||||
public string GetLocaleRestrictedCode (string localeName)
|
||||
{
|
||||
if (string.IsNullOrEmpty (localeName)) localeName = CurrentLocale;
|
||||
try
|
||||
{
|
||||
var ci = new CultureInfo (localeName);
|
||||
return ci.TwoLetterISOLanguageName ?? string.Empty;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// fallback: parse name
|
||||
var parts = localeName.Split (new char [] { '-', '_' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length >= 1) return parts [0];
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
public string GetLocaleElaboratedCode (string localeName)
|
||||
{
|
||||
if (string.IsNullOrEmpty (localeName)) localeName = CurrentLocale;
|
||||
try
|
||||
{
|
||||
var ci = new CultureInfo (localeName);
|
||||
// Region part from RegionInfo
|
||||
try
|
||||
{
|
||||
var ri = new RegionInfo (ci.Name);
|
||||
return ri.TwoLetterISORegionName ?? string.Empty;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// fallback: parse
|
||||
var parts = localeName.Split (new char [] { '-', '_' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length >= 2) return parts [1];
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
var parts = localeName.Split (new char [] { '-', '_' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length >= 2) return parts [1];
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
// LCID -> combined code like "en-US" (with configurable separator)
|
||||
public string LcidToLocaleCode (int lcid)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ci = new CultureInfo (lcid);
|
||||
if (!string.IsNullOrEmpty (ci.Name)) return ci.Name;
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
var name = ToLocaleName (lcid);
|
||||
if (!string.IsNullOrEmpty (name)) return name;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
// Get the user default locale name
|
||||
public string GetUserDefaultLocaleName ()
|
||||
{
|
||||
try
|
||||
{
|
||||
// In .NET, CurrentCulture corresponds to user default
|
||||
string name = CultureInfo.CurrentCulture.Name;
|
||||
if (!string.IsNullOrEmpty (name)) return name;
|
||||
}
|
||||
catch { }
|
||||
return LcidToLocaleCode (CultureInfo.CurrentCulture.LCID);
|
||||
}
|
||||
// Get system default locale name (machine)
|
||||
public string GetSystemDefaultLocaleName ()
|
||||
{
|
||||
try
|
||||
{
|
||||
// InstalledUICulture / Invariant fallback
|
||||
string name = CultureInfo.InstalledUICulture.Name;
|
||||
if (!string.IsNullOrEmpty (name)) return name;
|
||||
}
|
||||
catch { }
|
||||
return LcidToLocaleCode (CultureInfo.InstalledUICulture.LCID);
|
||||
}
|
||||
// Get computer locale code similar to C++ approach
|
||||
public string GetComputerLocaleCode ()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Thread culture -> user -> system
|
||||
string threadName = System.Threading.Thread.CurrentThread.CurrentCulture.Name;
|
||||
if (!string.IsNullOrEmpty (threadName)) return threadName;
|
||||
|
||||
string user = GetUserDefaultLocaleName ();
|
||||
if (!string.IsNullOrEmpty (user)) return user;
|
||||
|
||||
string system = GetSystemDefaultLocaleName ();
|
||||
if (!string.IsNullOrEmpty (system)) return system;
|
||||
}
|
||||
catch { }
|
||||
// fallback to invariant
|
||||
return CultureInfo.InvariantCulture.Name ?? string.Empty;
|
||||
}
|
||||
public _I_List RecommendLocaleNames
|
||||
{
|
||||
get
|
||||
{
|
||||
var arr = new string [] {
|
||||
System.Threading.Thread.CurrentThread.CurrentCulture.Name,
|
||||
GetUserDefaultLocaleName (),
|
||||
GetSystemDefaultLocaleName (),
|
||||
LcidToLocaleCode (CurrentLCID),
|
||||
GetLocaleRestrictedCode (System.Threading.Thread.CurrentThread.CurrentCulture.Name),
|
||||
GetLocaleRestrictedCode (GetUserDefaultLocaleName ()),
|
||||
GetLocaleRestrictedCode (GetSystemDefaultLocaleName ()),
|
||||
"en-US",
|
||||
"en"
|
||||
};
|
||||
var list = new _I_List ();
|
||||
foreach (var loc in arr)
|
||||
{
|
||||
var lloc = loc.Trim ().ToLowerInvariant ();
|
||||
var isfind = false;
|
||||
foreach (var item in list)
|
||||
{
|
||||
var str = item as string;
|
||||
if (string.IsNullOrWhiteSpace (str)) isfind = true;
|
||||
isfind = str.Trim ().ToLowerInvariant () == lloc;
|
||||
if (isfind) break;
|
||||
}
|
||||
if (!isfind) list.Add (loc);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
// Compare two locale names; returns true if equal by name or LCID
|
||||
public bool LocaleNameCompare (string left, string right)
|
||||
{
|
||||
if (string.Equals (left, right, StringComparison.OrdinalIgnoreCase)) return true;
|
||||
try
|
||||
{
|
||||
int l = ToLCID (left);
|
||||
int r = ToLCID (right);
|
||||
return l == r && l != CultureInfo.InvariantCulture.LCID;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Constants
|
||||
private const int LOCALE_NAME_MAX_LENGTH = 85; // defined by Windows
|
||||
public _I_Language CreateLanguage (string localeName) => new _I_Language (localeName);
|
||||
public static string CurrentInputMethodLanguageTag
|
||||
{
|
||||
get
|
||||
{
|
||||
IntPtr hkl = NativeMethods.GetKeyboardLayout (0);
|
||||
int lcid = hkl.ToInt32 () & 0xFFFF;
|
||||
|
||||
StringBuilder sb = new StringBuilder (85);
|
||||
int result = NativeMethods.LCIDToLocaleName (lcid, sb, sb.Capacity, 0);
|
||||
if (result > 0)
|
||||
return sb.ToString ();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public static bool IsWellFormed (string languageTag)
|
||||
{
|
||||
if (string.IsNullOrEmpty (languageTag))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
var _ = new CultureInfo (languageTag);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public static _I_List GetMuiCompatibleLanguageListFromLanguageTags (IEnumerable<string> languageTags)
|
||||
{
|
||||
var result = new List<string> ();
|
||||
foreach (string tag in languageTags)
|
||||
{
|
||||
if (string.IsNullOrEmpty (tag))
|
||||
continue;
|
||||
result.Add (tag);
|
||||
try
|
||||
{
|
||||
var ci = new CultureInfo (tag);
|
||||
string parent = ci.Parent.Name;
|
||||
if (!string.IsNullOrEmpty (parent) && parent != tag && !result.Contains (parent))
|
||||
result.Add (parent);
|
||||
}
|
||||
catch { }
|
||||
string neutral = Regex.Replace (tag, @"-.*$", "");
|
||||
if (neutral != tag && !result.Contains (neutral))
|
||||
result.Add (neutral);
|
||||
}
|
||||
if (!result.Contains ("neutral"))
|
||||
result.Add ("neutral");
|
||||
return new _I_List (result.Select (t => (object)t));
|
||||
}
|
||||
}
|
||||
}
|
||||
203
DataUtils/Process.cs
Normal file
203
DataUtils/Process.cs
Normal file
@@ -0,0 +1,203 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
public static class ProcessHelper
|
||||
{
|
||||
public static int ExecuteProgram (
|
||||
string cmdline,
|
||||
string file,
|
||||
int wndShowMode,
|
||||
bool wait,
|
||||
string execDir = "")
|
||||
{
|
||||
try
|
||||
{
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = string.IsNullOrEmpty (file) ? cmdline : file,
|
||||
Arguments = string.IsNullOrEmpty (file) ? "" : cmdline,
|
||||
WorkingDirectory = string.IsNullOrEmpty (execDir) ? null : execDir,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = false,
|
||||
WindowStyle = (ProcessWindowStyle)wndShowMode
|
||||
};
|
||||
using (var p = Process.Start (psi))
|
||||
{
|
||||
if (wait && p != null)
|
||||
p.WaitForExit ();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Marshal.GetHRForException (ex);
|
||||
}
|
||||
}
|
||||
public static bool KillProcessByFilePath (
|
||||
string filepath,
|
||||
bool multiple = false,
|
||||
bool isOnlyName = false)
|
||||
{
|
||||
if (string.IsNullOrEmpty (filepath)) return false;
|
||||
bool killed = false;
|
||||
string targetName = isOnlyName ? Path.GetFileName (filepath) : null;
|
||||
foreach (var p in Process.GetProcesses ())
|
||||
{
|
||||
try
|
||||
{
|
||||
bool match = false;
|
||||
|
||||
if (isOnlyName)
|
||||
{
|
||||
match = string.Equals (p.ProcessName + ".exe", targetName,
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
string fullPath = p.MainModule.FileName;
|
||||
match = string.Equals (fullPath, filepath,
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
if (match)
|
||||
{
|
||||
p.Kill ();
|
||||
killed = true;
|
||||
if (!multiple) break;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
return killed;
|
||||
}
|
||||
public static string GetFileVersionAsJson (string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
var info = FileVersionInfo.GetVersionInfo (filePath);
|
||||
var obj = new
|
||||
{
|
||||
info.CompanyName,
|
||||
info.FileDescription,
|
||||
info.FileVersion,
|
||||
info.InternalName,
|
||||
info.OriginalFilename,
|
||||
info.ProductName,
|
||||
info.ProductVersion,
|
||||
info.LegalCopyright,
|
||||
FileVersionRaw = info.FileMajorPart + "." +
|
||||
info.FileMinorPart + "." +
|
||||
info.FileBuildPart + "." +
|
||||
info.FilePrivatePart
|
||||
};
|
||||
return JsonConvert.SerializeObject (obj);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return JsonConvert.SerializeObject (new { error = ex.Message });
|
||||
}
|
||||
}
|
||||
public static int ExploreSaveFile (
|
||||
IWin32Window owner,
|
||||
List<string> results,
|
||||
string filter = "Windows Store App Package (*.appx; *.appxbundle)|*.appx;*.appxbundle",
|
||||
string defExt = "appx",
|
||||
string title = "Please select the file to save:",
|
||||
string initDir = null)
|
||||
{
|
||||
results.Clear ();
|
||||
using (var dlg = new SaveFileDialog ())
|
||||
{
|
||||
dlg.Filter = filter;
|
||||
dlg.DefaultExt = defExt;
|
||||
dlg.Title = title;
|
||||
dlg.InitialDirectory = initDir;
|
||||
if (dlg.ShowDialog (owner) == DialogResult.OK)
|
||||
{
|
||||
results.Add (dlg.FileName);
|
||||
}
|
||||
}
|
||||
return results.Count;
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Process
|
||||
{
|
||||
public Process Start (string filename, string args) => Process.Start (filename, args);
|
||||
public Process Open (string url) => Process.Start (url);
|
||||
public int Run (
|
||||
string cmdline,
|
||||
string filepath,
|
||||
int wndtype,
|
||||
bool wait,
|
||||
string runpath)
|
||||
{
|
||||
return ProcessHelper.ExecuteProgram (cmdline, filepath, wndtype, wait, runpath);
|
||||
}
|
||||
public void RunAsync (
|
||||
string cmdline,
|
||||
string filepath,
|
||||
int wndtype,
|
||||
string runpath,
|
||||
object callback)
|
||||
{
|
||||
var worker = new ProcessWorker (this)
|
||||
{
|
||||
CmdLine = cmdline,
|
||||
FilePath = filepath,
|
||||
WndType = wndtype,
|
||||
RunPath = runpath,
|
||||
Callback = callback
|
||||
};
|
||||
var th = new Thread (worker.Work)
|
||||
{
|
||||
IsBackground = true
|
||||
};
|
||||
th.Start ();
|
||||
}
|
||||
public bool Kill (string filename, bool allproc, bool onlyname)
|
||||
{
|
||||
return ProcessHelper.KillProcessByFilePath (filename, allproc, onlyname);
|
||||
}
|
||||
private class ProcessWorker
|
||||
{
|
||||
private readonly _I_Process parent;
|
||||
public string CmdLine;
|
||||
public string FilePath;
|
||||
public int WndType;
|
||||
public string RunPath;
|
||||
public object Callback;
|
||||
public ProcessWorker (_I_Process parent)
|
||||
{
|
||||
this.parent = parent;
|
||||
}
|
||||
public void Work ()
|
||||
{
|
||||
int ret = parent.Run (CmdLine, FilePath, WndType, true, RunPath);
|
||||
|
||||
if (Callback != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Callback.GetType ().InvokeMember (
|
||||
"call",
|
||||
System.Reflection.BindingFlags.InvokeMethod,
|
||||
null,
|
||||
Callback,
|
||||
new object [] { 1, ret }
|
||||
);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
36
DataUtils/Properties/AssemblyInfo.cs
Normal file
36
DataUtils/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("DataUtils")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("DataUtils")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2026")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//将 ComVisible 设置为 false 将使此程序集中的类型
|
||||
//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible (true)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("ffd3fd52-37a8-4f43-883c-de8d996cb0e0")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
|
||||
// 方法是按如下所示使用“*”: :
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
273
DataUtils/ResourceXml.cs
Normal file
273
DataUtils/ResourceXml.cs
Normal file
@@ -0,0 +1,273 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
public class FileResXmlDoc: IDisposable
|
||||
{
|
||||
private string _filepath;
|
||||
private XmlDocument _doc;
|
||||
private bool _available;
|
||||
|
||||
public FileResXmlDoc (string xmlpath)
|
||||
{
|
||||
Create (xmlpath);
|
||||
}
|
||||
|
||||
public bool Create (string xmlpath)
|
||||
{
|
||||
Destroy ();
|
||||
if (string.IsNullOrEmpty (xmlpath) || !File.Exists (xmlpath))
|
||||
{
|
||||
_available = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_doc = new XmlDocument ();
|
||||
_doc.Load (xmlpath);
|
||||
_filepath = xmlpath;
|
||||
_available = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_available = false;
|
||||
}
|
||||
return _available;
|
||||
}
|
||||
|
||||
public void Destroy ()
|
||||
{
|
||||
if (!_available) return;
|
||||
_doc = null;
|
||||
_available = false;
|
||||
_filepath = null;
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Destroy ();
|
||||
}
|
||||
|
||||
// Returns the chosen absolute (or resolved) path string or empty if none found
|
||||
public string Get (string id)
|
||||
{
|
||||
if (!_available || _doc == null) return string.Empty;
|
||||
if (string.IsNullOrEmpty (id)) return string.Empty;
|
||||
|
||||
XmlNode root = _doc.DocumentElement;
|
||||
if (root == null) return string.Empty;
|
||||
|
||||
foreach (XmlNode node in root.ChildNodes)
|
||||
{
|
||||
var attr = node.Attributes? ["id"];
|
||||
if (attr == null) continue;
|
||||
if (!string.Equals (attr.Value, id, StringComparison.OrdinalIgnoreCase)) continue;
|
||||
|
||||
// Build dpi -> path map
|
||||
var map = new Dictionary<int, string> ();
|
||||
foreach (XmlNode child in node.ChildNodes)
|
||||
{
|
||||
var dpiAttr = child.Attributes? ["dpi"];
|
||||
string dpiStr = dpiAttr != null ? dpiAttr.Value : "default";
|
||||
string text = child.InnerText ?? string.Empty;
|
||||
int dpiKey = 0;
|
||||
if (string.Equals (dpiStr, "default", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
dpiKey = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int parsed;
|
||||
if (int.TryParse (dpiStr, out parsed)) dpiKey = parsed;
|
||||
else dpiKey = 0;
|
||||
}
|
||||
// Resolve relative path relative to xml file directory
|
||||
string candidate = text;
|
||||
if (!Path.IsPathRooted (candidate) && !string.IsNullOrEmpty (_filepath))
|
||||
{
|
||||
string dir = Path.GetDirectoryName (_filepath);
|
||||
if (!string.IsNullOrEmpty (dir))
|
||||
candidate = Path.Combine (dir, candidate);
|
||||
}
|
||||
// Normalize
|
||||
try { candidate = Path.GetFullPath (candidate); } catch { /* ignore */ }
|
||||
|
||||
// Insert/overwrite by key (keep last if duplicate)
|
||||
map [dpiKey] = candidate;
|
||||
}
|
||||
|
||||
// Convert map to list and sort by string value (to mimic original)
|
||||
var list = map.Select (kv => new KeyValuePair<int, string> (kv.Key, kv.Value)).ToList ();
|
||||
list.Sort ((a, b) => string.CompareOrdinal (a.Value, b.Value));
|
||||
|
||||
// Keep only those whose file exists
|
||||
var existList = new List<KeyValuePair<int, string>> ();
|
||||
foreach (var kv in list)
|
||||
{
|
||||
if (!string.IsNullOrEmpty (kv.Value) && File.Exists (kv.Value))
|
||||
existList.Add (kv);
|
||||
}
|
||||
|
||||
int dpiPercent = UITheme.GetDPI (); // uses earlier helper
|
||||
|
||||
// Find first with dpi >= dpiPercent
|
||||
foreach (var kv in existList)
|
||||
{
|
||||
if (kv.Key >= dpiPercent) return kv.Value;
|
||||
}
|
||||
|
||||
// otherwise return first existing candidate
|
||||
if (existList.Count > 0) return existList [0].Value;
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// Overloads for convenience
|
||||
//public string Get (System.String idAsString) { return Get (idAsString); }
|
||||
}
|
||||
public class StringResXmlDoc: IDisposable
|
||||
{
|
||||
private XmlDocument doc;
|
||||
private bool isValid;
|
||||
|
||||
public bool IsValid
|
||||
{
|
||||
get { return isValid; }
|
||||
}
|
||||
|
||||
public StringResXmlDoc () { }
|
||||
|
||||
public StringResXmlDoc (string filePath)
|
||||
{
|
||||
Create (filePath);
|
||||
}
|
||||
|
||||
public bool Create (string filePath)
|
||||
{
|
||||
Destroy ();
|
||||
|
||||
if (string.IsNullOrEmpty (filePath) || !File.Exists (filePath))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
doc = new XmlDocument ();
|
||||
doc.Load (filePath);
|
||||
isValid = true;
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Destroy ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Destroy ()
|
||||
{
|
||||
doc = null;
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Destroy ();
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
|
||||
public string Get (string id)
|
||||
{
|
||||
if (!isValid || doc == null || string.IsNullOrEmpty (id))
|
||||
return string.Empty;
|
||||
|
||||
XmlElement root = doc.DocumentElement;
|
||||
if (root == null)
|
||||
return string.Empty;
|
||||
|
||||
foreach (XmlNode node in root.ChildNodes)
|
||||
{
|
||||
if (node.Attributes == null)
|
||||
continue;
|
||||
|
||||
XmlAttribute idAttr = node.Attributes ["id"];
|
||||
if (idAttr == null)
|
||||
continue;
|
||||
|
||||
if (!StringEqualsNormalized (idAttr.Value, id))
|
||||
continue;
|
||||
|
||||
Dictionary<string, string> langValues =
|
||||
new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (XmlNode sub in node.ChildNodes)
|
||||
{
|
||||
if (sub.Attributes == null)
|
||||
continue;
|
||||
|
||||
XmlAttribute langAttr = sub.Attributes ["name"];
|
||||
if (langAttr == null)
|
||||
continue;
|
||||
|
||||
string lang = langAttr.Value;
|
||||
if (!string.IsNullOrEmpty (lang))
|
||||
{
|
||||
langValues [lang] = sub.InnerText;
|
||||
}
|
||||
}
|
||||
|
||||
return GetSuitableLanguageValue (langValues);
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
public string GetString (string id) => Get (id);
|
||||
|
||||
public string this [string id]
|
||||
{
|
||||
get { return Get (id); }
|
||||
}
|
||||
|
||||
private static bool StringEqualsNormalized (string a, string b)
|
||||
{
|
||||
return string.Equals (
|
||||
a != null ? a.Trim () : null,
|
||||
b != null ? b.Trim () : null,
|
||||
StringComparison.OrdinalIgnoreCase
|
||||
);
|
||||
}
|
||||
|
||||
private static string GetSuitableLanguageValue (
|
||||
Dictionary<string, string> values)
|
||||
{
|
||||
if (values == null || values.Count == 0)
|
||||
return string.Empty;
|
||||
|
||||
CultureInfo culture = CultureInfo.CurrentUICulture;
|
||||
string val;
|
||||
|
||||
if (values.TryGetValue (culture.Name, out val))
|
||||
return val;
|
||||
|
||||
if (values.TryGetValue (culture.TwoLetterISOLanguageName, out val))
|
||||
return val;
|
||||
|
||||
if (values.TryGetValue ("en", out val))
|
||||
return val;
|
||||
|
||||
foreach (string v in values.Values)
|
||||
return v;
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
84
DataUtils/Resources.cs
Normal file
84
DataUtils/Resources.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Resources
|
||||
{
|
||||
// Flags for LoadLibraryEx
|
||||
private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
|
||||
private const uint LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020;
|
||||
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
private static extern IntPtr LoadLibraryEx (string lpFileName, IntPtr hFile, uint dwFlags);
|
||||
|
||||
[DllImport ("kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs (UnmanagedType.Bool)]
|
||||
private static extern bool FreeLibrary (IntPtr hModule);
|
||||
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
private static extern IntPtr GetModuleHandle (string lpModuleName);
|
||||
|
||||
[DllImport ("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
private static extern int LoadString (IntPtr hInstance, uint uID, StringBuilder lpBuffer, int nBufferMax);
|
||||
|
||||
/// <summary>
|
||||
/// Load a string resource from another module (DLL/EXE) identified by file path, or from the current module if filepath is null/empty.
|
||||
/// </summary>
|
||||
/// <param name="filepath">Path to the module file. If null/empty, use current process module.</param>
|
||||
/// <param name="resid">Resource ID to load.</param>
|
||||
/// <returns>The resource string, or empty string if not found or on error.</returns>
|
||||
public string GetFromOthers (string filepath, uint resid)
|
||||
{
|
||||
IntPtr hModule = IntPtr.Zero;
|
||||
bool needFree = false;
|
||||
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace (filepath))
|
||||
{
|
||||
// Load as datafile + image resource so we can access resources without executing DllMain of the module.
|
||||
hModule = LoadLibraryEx (filepath, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
|
||||
if (hModule == IntPtr.Zero)
|
||||
{
|
||||
// Failed to load; return empty string
|
||||
return string.Empty;
|
||||
}
|
||||
needFree = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get handle of current process module (exe)
|
||||
hModule = GetModuleHandle (null);
|
||||
if (hModule == IntPtr.Zero)
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// Prepare buffer. Typical string resources are not huge; 4096 should be enough.
|
||||
const int BUFFER_SIZE = 4096;
|
||||
StringBuilder sb = new StringBuilder (BUFFER_SIZE);
|
||||
|
||||
int copied = LoadString (hModule, resid, sb, sb.Capacity);
|
||||
if (copied > 0)
|
||||
{
|
||||
// LoadString returns number of characters copied (excluding terminating null)
|
||||
return sb.ToString (0, copied);
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (needFree && hModule != IntPtr.Zero)
|
||||
{
|
||||
try { FreeLibrary (hModule); }
|
||||
catch { /* ignore */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
804
DataUtils/Storage.cs
Normal file
804
DataUtils/Storage.cs
Normal file
@@ -0,0 +1,804 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Path
|
||||
{
|
||||
public string Current
|
||||
{
|
||||
get
|
||||
{
|
||||
try { return Directory.GetCurrentDirectory (); }
|
||||
catch { return string.Empty; }
|
||||
}
|
||||
set
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty (value)) Directory.SetCurrentDirectory (value);
|
||||
}
|
||||
catch { /* ignore */ }
|
||||
}
|
||||
}
|
||||
public string Program
|
||||
{
|
||||
get { return Utilities.GetCurrentProgramPath (); }
|
||||
}
|
||||
public string Root
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
string prog = Utilities.GetCurrentProgramPath ();
|
||||
return Path.GetDirectoryName (prog) ?? string.Empty;
|
||||
}
|
||||
catch { return string.Empty; }
|
||||
}
|
||||
}
|
||||
public string Combine (string l, string r)
|
||||
{
|
||||
if (string.IsNullOrEmpty (l)) return r ?? string.Empty;
|
||||
if (string.IsNullOrEmpty (r)) return l ?? string.Empty;
|
||||
try { return Path.Combine (l, r); }
|
||||
catch { return l + Path.DirectorySeparatorChar + r; }
|
||||
}
|
||||
public string GetName (string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty (path)) return string.Empty;
|
||||
try
|
||||
{
|
||||
return Path.GetFileName (path);
|
||||
}
|
||||
catch { return string.Empty; }
|
||||
}
|
||||
public string GetDirectory (string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty (path)) return string.Empty;
|
||||
try
|
||||
{
|
||||
return Path.GetDirectoryName (path) ?? string.Empty;
|
||||
}
|
||||
catch { return string.Empty; }
|
||||
}
|
||||
public string GetDir (string path) { return GetDirectory (path); }
|
||||
public bool Exist (string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty (path)) return false;
|
||||
return File.Exists (path) || Directory.Exists (path);
|
||||
}
|
||||
public bool FileExist (string filepath)
|
||||
{
|
||||
if (string.IsNullOrEmpty (filepath)) return false;
|
||||
return File.Exists (filepath);
|
||||
}
|
||||
public bool DirectoryExist (string dirpath)
|
||||
{
|
||||
if (string.IsNullOrEmpty (dirpath)) return false;
|
||||
return Directory.Exists (dirpath);
|
||||
}
|
||||
public bool DirExist (string dirpath) { return DirectoryExist (dirpath); }
|
||||
public string GetEnvironmentString (string str)
|
||||
{
|
||||
if (string.IsNullOrEmpty (str)) return string.Empty;
|
||||
try
|
||||
{
|
||||
return Environment.ExpandEnvironmentVariables (str);
|
||||
}
|
||||
catch { return str; }
|
||||
}
|
||||
// Valid Windows filename?
|
||||
public bool ValidName (string filename)
|
||||
{
|
||||
if (string.IsNullOrEmpty (filename)) return false;
|
||||
char [] invalid = Path.GetInvalidFileNameChars ();
|
||||
return filename.IndexOfAny (invalid) < 0;
|
||||
}
|
||||
// filter may be e.g. "*.txt;*.md" or using "\" separators per legacy code
|
||||
public string EnumFilesToJson (string dir, string filter, bool withpath, bool sort, bool includesub)
|
||||
{
|
||||
var arr = EnumFiles (dir, filter, withpath, sort, includesub);
|
||||
return Utilities.StringArrayToJson (arr);
|
||||
}
|
||||
public string EnumDirsToJson (string dir, bool withpath, bool sort, bool includesub)
|
||||
{
|
||||
var arr = EnumDirs (dir, withpath, sort, includesub);
|
||||
return Utilities.StringArrayToJson (arr);
|
||||
}
|
||||
public string EnumSubDirsToJson (string dir, bool withpath)
|
||||
{
|
||||
var arr = EnumSubDirs (dir, withpath);
|
||||
return Utilities.StringArrayToJson (arr);
|
||||
}
|
||||
public string [] EnumFiles (string dir, string filter, bool withpath, bool sort, bool includesub)
|
||||
{
|
||||
if (string.IsNullOrEmpty (dir)) return new string [0];
|
||||
var patterns = Utilities.SplitFilters (filter);
|
||||
var list = new List<string> (100);
|
||||
|
||||
try
|
||||
{
|
||||
var searchOption = includesub ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||||
foreach (var pat in patterns)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var f in Directory.EnumerateFiles (dir, pat, searchOption))
|
||||
{
|
||||
list.Add (withpath ? f : Path.GetFileName (f));
|
||||
}
|
||||
}
|
||||
catch (UnauthorizedAccessException) { /* skip */ }
|
||||
catch (DirectoryNotFoundException) { /* skip */ }
|
||||
catch (IOException) { /* skip */ }
|
||||
}
|
||||
|
||||
if (sort)
|
||||
{
|
||||
list.Sort (StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// fallback: empty
|
||||
}
|
||||
|
||||
return list.ToArray ();
|
||||
}
|
||||
public string [] EnumDirs (string dir, bool withpath, bool sort, bool includesub)
|
||||
{
|
||||
if (string.IsNullOrEmpty (dir)) return new string [0];
|
||||
var list = new List<string> (100);
|
||||
try
|
||||
{
|
||||
var searchOption = includesub ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
|
||||
foreach (var d in Directory.EnumerateDirectories (dir, "*", searchOption))
|
||||
{
|
||||
list.Add (withpath ? d : Path.GetFileName (d));
|
||||
}
|
||||
if (sort) list.Sort (StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
catch { }
|
||||
return list.ToArray ();
|
||||
}
|
||||
public string [] EnumSubDirs (string dir, bool withpath)
|
||||
{
|
||||
return EnumDirs (dir, withpath, true, true);
|
||||
}
|
||||
public string CommonPrefix (string path1, string path2)
|
||||
{
|
||||
if (string.IsNullOrEmpty (path1) || string.IsNullOrEmpty (path2)) return string.Empty;
|
||||
try
|
||||
{
|
||||
string a = Utilities.NormalizeFullPath (path1);
|
||||
string b = Utilities.NormalizeFullPath (path2);
|
||||
string [] asplit = a.Split (new char [] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
|
||||
string [] bsplit = b.Split (new char [] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
|
||||
int min = Math.Min (asplit.Length, bsplit.Length);
|
||||
var sb = new StringBuilder ();
|
||||
for (int i = 0; i < min; i++)
|
||||
{
|
||||
if (!string.Equals (asplit [i], bsplit [i], StringComparison.OrdinalIgnoreCase)) break;
|
||||
sb.Append (asplit [i]);
|
||||
sb.Append (Path.DirectorySeparatorChar);
|
||||
}
|
||||
return sb.ToString ().TrimEnd (Path.DirectorySeparatorChar);
|
||||
}
|
||||
catch { return string.Empty; }
|
||||
}
|
||||
public string EnsureDirSlash (string dir)
|
||||
{
|
||||
if (string.IsNullOrEmpty (dir)) return string.Empty;
|
||||
try
|
||||
{
|
||||
if (!dir.EndsWith (Path.DirectorySeparatorChar.ToString ()))
|
||||
dir += Path.DirectorySeparatorChar;
|
||||
return dir;
|
||||
}
|
||||
catch { return dir; }
|
||||
}
|
||||
public string Normalize (string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty (path)) return string.Empty;
|
||||
try { return Path.GetFullPath (path); }
|
||||
catch { return path; }
|
||||
}
|
||||
public string FullPathName (string path) { return Normalize (path); }
|
||||
public string FullPath (string path) { return FullPathName (path); }
|
||||
public string Expand (string path) { return GetEnvironmentString (path); }
|
||||
// GetFolder via SHGetFolderPath (preserves the original csidl param usage)
|
||||
public string GetFolder (int csidl)
|
||||
{
|
||||
try
|
||||
{
|
||||
// try P/Invoke to SHGetFolderPath
|
||||
return ShellHelpers.GetFolderPath (csidl);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
// KnownFolder by GUID string (wraps SHGetKnownFolderPath)
|
||||
public string KnownFolder (string guidString)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace (guidString)) return string.Empty;
|
||||
Guid guid;
|
||||
try
|
||||
{
|
||||
guid = new Guid (guidString);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return ShellHelpers.GetKnownFolderPath (guid);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
public bool PEquals (string l, string r)
|
||||
{
|
||||
if (l == null && r == null) return true;
|
||||
if (l == null || r == null) return false;
|
||||
string a = Utilities.NormalizeFullPath (l);
|
||||
string b = Utilities.NormalizeFullPath (r);
|
||||
return string.Equals (a, b, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
public bool Open (string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty (path)) return false;
|
||||
try
|
||||
{
|
||||
if (File.Exists (path))
|
||||
{
|
||||
Process.Start (path);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Directory.Exists (path))
|
||||
{
|
||||
Process.Start ("explorer.exe", path);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Basic entry object
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Entry
|
||||
{
|
||||
protected string path;
|
||||
public _I_Entry (string path)
|
||||
{
|
||||
this.path = path ?? string.Empty;
|
||||
}
|
||||
public _I_Entry ()
|
||||
{
|
||||
this.path = string.Empty;
|
||||
}
|
||||
public virtual string Path
|
||||
{
|
||||
get { return path; }
|
||||
set { path = value ?? string.Empty; }
|
||||
}
|
||||
public virtual string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return System.IO.Path.GetFileName (path) ?? string.Empty;
|
||||
}
|
||||
catch { return string.Empty; }
|
||||
}
|
||||
}
|
||||
public virtual string Directory
|
||||
{
|
||||
get
|
||||
{
|
||||
try { return System.IO.Path.GetDirectoryName (path) ?? string.Empty; }
|
||||
catch { return string.Empty; }
|
||||
}
|
||||
}
|
||||
public virtual string Root { get { return Directory; } }
|
||||
public virtual bool Exist
|
||||
{
|
||||
get
|
||||
{
|
||||
return File.Exists (path) || System.IO.Directory.Exists (path);
|
||||
}
|
||||
}
|
||||
public virtual string Uri
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
Uri uri;
|
||||
if (System.Uri.TryCreate (path, UriKind.Absolute, out uri))
|
||||
{
|
||||
return uri.AbsoluteUri;
|
||||
}
|
||||
else
|
||||
{
|
||||
Uri u = new Uri (System.IO.Path.GetFullPath (path));
|
||||
return u.AbsoluteUri;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
public virtual string FullPath
|
||||
{
|
||||
get
|
||||
{
|
||||
try { return System.IO.Path.GetFullPath (path); }
|
||||
catch { return path; }
|
||||
}
|
||||
}
|
||||
|
||||
// Return relative path from frontdir to this.Path; similar semantics to C++ code
|
||||
public string RelativePath (string frontdir)
|
||||
{
|
||||
if (string.IsNullOrEmpty (path) || string.IsNullOrEmpty (frontdir)) return string.Empty;
|
||||
try
|
||||
{
|
||||
string fullFile = System.IO.Path.GetFullPath (path);
|
||||
string fullDir = System.IO.Path.GetFullPath (frontdir);
|
||||
if (!fullDir.EndsWith (System.IO.Path.DirectorySeparatorChar.ToString ()))
|
||||
fullDir += System.IO.Path.DirectorySeparatorChar;
|
||||
|
||||
if (!string.Equals (System.IO.Path.GetPathRoot (fullFile), System.IO.Path.GetPathRoot (fullDir), StringComparison.OrdinalIgnoreCase))
|
||||
return string.Empty;
|
||||
|
||||
if (!fullFile.StartsWith (fullDir, StringComparison.OrdinalIgnoreCase)) return string.Empty;
|
||||
|
||||
return fullFile.Substring (fullDir.Length);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_File: _I_Entry
|
||||
{
|
||||
// last encoding used when reading
|
||||
protected Encoding lastEncoding;
|
||||
public _I_File () : base (string.Empty) { }
|
||||
public _I_File (string filepath) : base (filepath) { }
|
||||
// Read file contents; detect BOM if present by using StreamReader with detectEncodingFromByteOrderMarks = true
|
||||
public string Get ()
|
||||
{
|
||||
if (string.IsNullOrEmpty (path)) return string.Empty;
|
||||
try
|
||||
{
|
||||
using (FileStream fs = new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (StreamReader sr = new StreamReader (fs, Encoding.UTF8, true))
|
||||
{
|
||||
string text = sr.ReadToEnd ();
|
||||
lastEncoding = sr.CurrentEncoding;
|
||||
return text;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public void Set (string content)
|
||||
{
|
||||
if (string.IsNullOrEmpty (path)) return;
|
||||
try
|
||||
{
|
||||
string dir = System.IO.Path.GetDirectoryName (path);
|
||||
if (!string.IsNullOrEmpty (dir) && !System.IO.Directory.Exists (dir))
|
||||
{
|
||||
System.IO.Directory.CreateDirectory (dir);
|
||||
}
|
||||
Encoding enc = lastEncoding ?? Encoding.UTF8;
|
||||
using (FileStream fs = new FileStream (path, FileMode.Create, FileAccess.Write, FileShare.Read))
|
||||
using (StreamWriter sw = new StreamWriter (fs, enc))
|
||||
{
|
||||
sw.Write (content ?? string.Empty);
|
||||
sw.Flush ();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore write errors
|
||||
}
|
||||
}
|
||||
public string Content
|
||||
{
|
||||
get { return Get (); }
|
||||
set { Set (value); }
|
||||
}
|
||||
public override bool Exist
|
||||
{
|
||||
get { return File.Exists (path); }
|
||||
}
|
||||
public string FilePath
|
||||
{
|
||||
get { return this.Path; }
|
||||
set { this.Path = value; }
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Directory: _I_Entry
|
||||
{
|
||||
public _I_Directory () : base (string.Empty) { }
|
||||
public _I_Directory (string dirpath) : base (dirpath) { }
|
||||
public _I_Directory (_I_Entry file) : base (file != null ? file.Directory : string.Empty) { }
|
||||
|
||||
public string DirectoryPath
|
||||
{
|
||||
get { return this.Path; }
|
||||
set { this.Path = value; }
|
||||
}
|
||||
public string DirPath { get { return DirectoryPath; } set { DirectoryPath = value; } }
|
||||
public override bool Exist { get { return System.IO.Directory.Exists (path); } }
|
||||
public string EnumFilesToJson (string filter, bool withpath, bool sort, bool includesub)
|
||||
{
|
||||
_I_Path p = new _I_Path ();
|
||||
string [] arr = p.EnumFiles (DirPath, filter, withpath, sort, includesub);
|
||||
return Utilities.StringArrayToJson (arr);
|
||||
}
|
||||
public string EnumDirsToJson (bool withpath, bool sort, bool includesub)
|
||||
{
|
||||
_I_Path p = new _I_Path ();
|
||||
string [] arr = p.EnumDirs (DirPath, withpath, sort, includesub);
|
||||
return Utilities.StringArrayToJson (arr);
|
||||
}
|
||||
public string EnumSubDirsToJson (bool withpath)
|
||||
{
|
||||
_I_Path p = new _I_Path ();
|
||||
string [] arr = p.EnumSubDirs (DirPath, withpath);
|
||||
return Utilities.StringArrayToJson (arr);
|
||||
}
|
||||
public string [] EnumFiles (string filter, bool withpath, bool sort, bool includesub)
|
||||
{
|
||||
_I_Path p = new _I_Path ();
|
||||
return p.EnumFiles (DirPath, filter, withpath, sort, includesub);
|
||||
}
|
||||
public string [] EnumDirs (bool withpath, bool sort, bool includesub)
|
||||
{
|
||||
_I_Path p = new _I_Path ();
|
||||
return p.EnumDirs (DirPath, withpath, sort, includesub);
|
||||
}
|
||||
public string [] EnumSubDirs (bool withpath)
|
||||
{
|
||||
_I_Path p = new _I_Path ();
|
||||
return p.EnumSubDirs (DirPath, withpath);
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Explorer
|
||||
{
|
||||
[DllImport ("user32.dll")]
|
||||
private static extern IntPtr GetForegroundWindow ();
|
||||
class WindowWrapper: IWin32Window
|
||||
{
|
||||
private IntPtr _hwnd;
|
||||
public WindowWrapper (IntPtr handle) { _hwnd = handle; }
|
||||
public IntPtr Handle { get { return _hwnd; } }
|
||||
}
|
||||
private static IWin32Window GetActiveWindowOwner ()
|
||||
{
|
||||
IntPtr hWnd = GetForegroundWindow ();
|
||||
return hWnd != IntPtr.Zero ? new WindowWrapper (hWnd) : null;
|
||||
}
|
||||
private static void CallJS (object jsFunc, params object [] args)
|
||||
{
|
||||
if (jsFunc == null) return;
|
||||
try
|
||||
{
|
||||
object [] realArgs = new object [args.Length + 1];
|
||||
realArgs [0] = jsFunc; // thisArg
|
||||
Array.Copy (args, 0, realArgs, 1, args.Length);
|
||||
jsFunc.GetType ().InvokeMember (
|
||||
"call",
|
||||
System.Reflection.BindingFlags.InvokeMethod,
|
||||
null,
|
||||
jsFunc,
|
||||
realArgs
|
||||
);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
public void File (string filter, string initDir, object jsCallback)
|
||||
{
|
||||
IWin32Window owner = GetActiveWindowOwner ();
|
||||
Thread t = new Thread (() => {
|
||||
string result = string.Empty;
|
||||
try
|
||||
{
|
||||
using (OpenFileDialog dlg = new OpenFileDialog ())
|
||||
{
|
||||
dlg.Filter = filter;
|
||||
dlg.InitialDirectory = string.IsNullOrEmpty (initDir)
|
||||
? Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments)
|
||||
: initDir;
|
||||
dlg.Multiselect = false;
|
||||
if (dlg.ShowDialog (owner) == DialogResult.OK)
|
||||
result = dlg.FileName;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
CallJS (jsCallback, result);
|
||||
});
|
||||
t.IsBackground = true;
|
||||
t.SetApartmentState (ApartmentState.STA);
|
||||
t.Start ();
|
||||
}
|
||||
public void Files (string filter, string initDir, object jsCallback)
|
||||
{
|
||||
IWin32Window owner = GetActiveWindowOwner ();
|
||||
Thread t = new Thread (() => {
|
||||
string result = "[]";
|
||||
try
|
||||
{
|
||||
using (OpenFileDialog dlg = new OpenFileDialog ())
|
||||
{
|
||||
dlg.Filter = filter;
|
||||
dlg.InitialDirectory = string.IsNullOrEmpty (initDir)
|
||||
? Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments)
|
||||
: initDir;
|
||||
dlg.Multiselect = true;
|
||||
if (dlg.ShowDialog (owner) == DialogResult.OK)
|
||||
result = Newtonsoft.Json.JsonConvert.SerializeObject (dlg.FileNames);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
CallJS (jsCallback, result);
|
||||
});
|
||||
t.IsBackground = true;
|
||||
t.SetApartmentState (ApartmentState.STA);
|
||||
t.Start ();
|
||||
}
|
||||
public void Dir (string initDir, object jsCallback)
|
||||
{
|
||||
IWin32Window owner = GetActiveWindowOwner ();
|
||||
Thread t = new Thread (() => {
|
||||
string result = string.Empty;
|
||||
try
|
||||
{
|
||||
using (FolderBrowserDialog dlg = new FolderBrowserDialog ())
|
||||
{
|
||||
dlg.SelectedPath = string.IsNullOrEmpty (initDir)
|
||||
? Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments)
|
||||
: initDir;
|
||||
if (dlg.ShowDialog (owner) == DialogResult.OK)
|
||||
result = dlg.SelectedPath;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
CallJS (jsCallback, result);
|
||||
});
|
||||
t.IsBackground = true;
|
||||
t.SetApartmentState (ApartmentState.STA);
|
||||
t.Start ();
|
||||
}
|
||||
public void Dirs (string initDir, object jsCallback)
|
||||
{
|
||||
IWin32Window owner = GetActiveWindowOwner ();
|
||||
Thread t = new Thread (() => {
|
||||
string result = "[]";
|
||||
try
|
||||
{
|
||||
using (var dlg = new OpenFileDialog ())
|
||||
{
|
||||
// trick: 多选文件夹
|
||||
dlg.ValidateNames = false;
|
||||
dlg.CheckFileExists = false;
|
||||
dlg.CheckPathExists = true;
|
||||
dlg.FileName = "SelectFolder";
|
||||
dlg.InitialDirectory = string.IsNullOrEmpty (initDir)
|
||||
? Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments)
|
||||
: initDir;
|
||||
dlg.Multiselect = true;
|
||||
if (dlg.ShowDialog (owner) == DialogResult.OK)
|
||||
{
|
||||
var dirs = dlg.FileNames.Select (f => Path.GetDirectoryName (f)).Distinct ().ToArray ();
|
||||
result = Newtonsoft.Json.JsonConvert.SerializeObject (dirs);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
CallJS (jsCallback, result);
|
||||
});
|
||||
t.IsBackground = true;
|
||||
t.SetApartmentState (ApartmentState.STA);
|
||||
t.Start ();
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Folder
|
||||
{
|
||||
[DllImport ("shell32.dll")]
|
||||
private static extern int SHGetKnownFolderPath (
|
||||
[MarshalAs (UnmanagedType.LPStruct)] Guid rfid,
|
||||
uint dwFlags,
|
||||
IntPtr hToken,
|
||||
out IntPtr ppszPath);
|
||||
private static string KF (Guid g)
|
||||
{
|
||||
IntPtr p;
|
||||
SHGetKnownFolderPath (g, 0, IntPtr.Zero, out p);
|
||||
string s = Marshal.PtrToStringUni (p);
|
||||
Marshal.FreeCoTaskMem (p);
|
||||
return s;
|
||||
}
|
||||
private static readonly Guid FOLDERID_Downloads = new Guid ("374DE290-123F-4565-9164-39C4925E467B");
|
||||
private static readonly Guid FOLDERID_SavedPictures = new Guid ("3B193882-D3AD-4EAB-965A-69829D1FB59F");
|
||||
private static readonly Guid FOLDERID_SavedGames = new Guid ("4C5C32FF-BB9D-43B0-BF90-45A0FEEB6D0E");
|
||||
private static readonly Guid FOLDERID_Links = new Guid ("BFB9D5E0-C6A9-404C-B2B2-AE6DB6AF4968");
|
||||
private static readonly Guid FOLDERID_Contacts = new Guid ("56784854-C6CB-462B-8169-88E350ACB882");
|
||||
private static readonly Guid FOLDERID_Searches = new Guid ("7D1D3A04-DEBB-4115-95CF-2F29DA2920DA");
|
||||
public string ProgramFiles => Environment.GetFolderPath (Environment.SpecialFolder.ProgramFiles);
|
||||
public string ProgramFilesX86 => Environment.GetFolderPath (Environment.SpecialFolder.ProgramFilesX86);
|
||||
public string Windows => Environment.GetFolderPath (Environment.SpecialFolder.Windows);
|
||||
public string System32 => Environment.SystemDirectory;
|
||||
public string UserProfile => Environment.GetFolderPath (Environment.SpecialFolder.UserProfile);
|
||||
public string Desktop => Environment.GetFolderPath (Environment.SpecialFolder.Desktop);
|
||||
public string Documents => Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments);
|
||||
public string Pictures => Environment.GetFolderPath (Environment.SpecialFolder.MyPictures);
|
||||
public string Music => Environment.GetFolderPath (Environment.SpecialFolder.MyMusic);
|
||||
public string Videos => Environment.GetFolderPath (Environment.SpecialFolder.MyVideos);
|
||||
public string AppDataRoaming => Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
|
||||
public string AppDataLocal => Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData);
|
||||
public string AppDataLocalLow => Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData) + "\\Low";
|
||||
public string Temp => System.IO.Path.GetTempPath ();
|
||||
public string PublicDesktop => Environment.GetFolderPath (Environment.SpecialFolder.CommonDesktopDirectory);
|
||||
public string PublicDocuments => Environment.GetFolderPath (Environment.SpecialFolder.CommonDocuments);
|
||||
public string PublicPictures => Environment.GetFolderPath (Environment.SpecialFolder.CommonPictures);
|
||||
public string PublicMusic => Environment.GetFolderPath (Environment.SpecialFolder.CommonMusic);
|
||||
public string PublicVideos => Environment.GetFolderPath (Environment.SpecialFolder.CommonVideos);
|
||||
public string Downloads => KF (FOLDERID_Downloads);
|
||||
public string SavedPictures => KF (FOLDERID_SavedPictures);
|
||||
public string SavedGames => KF (FOLDERID_SavedGames);
|
||||
public string Links => KF (FOLDERID_Links);
|
||||
public string Contacts => KF (FOLDERID_Contacts);
|
||||
public string Searches => KF (FOLDERID_Searches);
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Storage
|
||||
{
|
||||
[DllImport ("user32.dll")]
|
||||
private static extern IntPtr GetForegroundWindow ();
|
||||
class WindowWrapper: IWin32Window
|
||||
{
|
||||
private IntPtr _hwnd;
|
||||
public WindowWrapper (IntPtr handle) { _hwnd = handle; }
|
||||
public IntPtr Handle { get { return _hwnd; } }
|
||||
}
|
||||
private static IWin32Window GetActiveWindowOwner ()
|
||||
{
|
||||
IntPtr hWnd = GetForegroundWindow ();
|
||||
return hWnd != IntPtr.Zero ? new WindowWrapper (hWnd) : null;
|
||||
}
|
||||
private static void CallJS (object jsFunc, params object [] args)
|
||||
{
|
||||
if (jsFunc == null) return;
|
||||
try
|
||||
{
|
||||
// 这里固定第一个参数为 thisArg(比如 1)
|
||||
object [] realArgs = new object [args.Length + 1];
|
||||
realArgs [0] = jsFunc; // thisArg
|
||||
Array.Copy (args, 0, realArgs, 1, args.Length);
|
||||
|
||||
jsFunc.GetType ().InvokeMember (
|
||||
"call",
|
||||
BindingFlags.InvokeMethod,
|
||||
null,
|
||||
jsFunc,
|
||||
realArgs
|
||||
);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore errors in callback invocation
|
||||
}
|
||||
}
|
||||
protected _I_Path path = new _I_Path ();
|
||||
public _I_Path Path { get { return path; } }
|
||||
public _I_File GetFile (string path) { return new _I_File (path); }
|
||||
public _I_Directory GetDirectory (string path) { return new _I_Directory (path); }
|
||||
public _I_Directory GetDir (string path) { return GetDirectory (path); }
|
||||
public _I_Explorer Explorer => new _I_Explorer ();
|
||||
public void Save (string filter, string initDir, string defaultName, object jsCallback)
|
||||
{
|
||||
IWin32Window owner = GetActiveWindowOwner ();
|
||||
Thread t = new Thread (() => {
|
||||
string result = string.Empty;
|
||||
try
|
||||
{
|
||||
using (SaveFileDialog dlg = new SaveFileDialog ())
|
||||
{
|
||||
dlg.Filter = filter;
|
||||
dlg.InitialDirectory = string.IsNullOrEmpty (initDir)
|
||||
? Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments)
|
||||
: initDir;
|
||||
if (!string.IsNullOrEmpty (defaultName))
|
||||
dlg.FileName = defaultName;
|
||||
dlg.OverwritePrompt = true;
|
||||
dlg.AddExtension = true;
|
||||
if (dlg.ShowDialog (owner) == DialogResult.OK)
|
||||
result = dlg.FileName;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
CallJS (jsCallback, result);
|
||||
});
|
||||
t.IsBackground = true;
|
||||
t.SetApartmentState (ApartmentState.STA);
|
||||
t.Start ();
|
||||
}
|
||||
public _I_Folder Folders => new _I_Folder ();
|
||||
}
|
||||
// Small shell helpers that P/Invoke for folder retrieval using CSIDL or Known Folder GUIDs
|
||||
internal static class ShellHelpers
|
||||
{
|
||||
[System.Runtime.InteropServices.DllImport ("shell32.dll")]
|
||||
private static extern int SHGetFolderPathW (IntPtr hwndOwner, int nFolder, IntPtr hToken, uint dwFlags, [System.Runtime.InteropServices.MarshalAs (System.Runtime.InteropServices.UnmanagedType.LPWStr)] StringBuilder pszPath);
|
||||
public static string GetFolderPath (int csidl)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder (260);
|
||||
int hr = SHGetFolderPathW (IntPtr.Zero, csidl, IntPtr.Zero, 0, sb);
|
||||
if (hr == 0) return sb.ToString ();
|
||||
return string.Empty;
|
||||
}
|
||||
[System.Runtime.InteropServices.DllImport ("shell32.dll")]
|
||||
private static extern int SHGetKnownFolderPath ([System.Runtime.InteropServices.MarshalAs (System.Runtime.InteropServices.UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr ppszPath);
|
||||
[System.Runtime.InteropServices.DllImport ("ole32.dll")]
|
||||
private static extern void CoTaskMemFree (IntPtr pv);
|
||||
public static string GetKnownFolderPath (Guid guid)
|
||||
{
|
||||
IntPtr pathPtr;
|
||||
int hr = SHGetKnownFolderPath (guid, 0, IntPtr.Zero, out pathPtr);
|
||||
if (hr != 0 || pathPtr == IntPtr.Zero) return string.Empty;
|
||||
try
|
||||
{
|
||||
string path = Marshal.PtrToStringUni (pathPtr);
|
||||
return path ?? string.Empty;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (pathPtr != IntPtr.Zero) CoTaskMemFree (pathPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
115
DataUtils/String.cs
Normal file
115
DataUtils/String.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_String
|
||||
{
|
||||
// Nested normalization helper
|
||||
[ComVisible (true)]
|
||||
public class _I_NString
|
||||
{
|
||||
// Normalize strings: Trim, apply Unicode normalization form KD, and to-lower invariant.
|
||||
private static string Normalize (string s)
|
||||
{
|
||||
if (s == null) return string.Empty;
|
||||
s = s.Trim ();
|
||||
return s.ToLowerInvariant ();
|
||||
}
|
||||
// Compare normalized equality
|
||||
public bool NEquals (string l, string r)
|
||||
{
|
||||
return string.Equals (Normalize (l), Normalize (r), StringComparison.Ordinal);
|
||||
}
|
||||
// Is normalized empty
|
||||
public bool Empty (string l)
|
||||
{
|
||||
string n = Normalize (l);
|
||||
return string.IsNullOrEmpty (n);
|
||||
}
|
||||
// Compare normalized strings with ordinal comparison (returns -1/0/1)
|
||||
public int Compare (string l, string r)
|
||||
{
|
||||
string nl = Normalize (l);
|
||||
string nr = Normalize (r);
|
||||
return string.CompareOrdinal (nl, nr);
|
||||
}
|
||||
// Get length of normalized string (in characters)
|
||||
public int Length (string l)
|
||||
{
|
||||
string nl = Normalize (l);
|
||||
return nl.Length;
|
||||
}
|
||||
}
|
||||
private _I_NString nstr = new _I_NString ();
|
||||
public _I_NString NString { get { return nstr; } }
|
||||
public string Trim (string src)
|
||||
{
|
||||
if (src == null) return string.Empty;
|
||||
return src.Trim ();
|
||||
}
|
||||
public string ToLower (string src)
|
||||
{
|
||||
if (src == null) return null;
|
||||
return src.ToLower (CultureInfo.InvariantCulture);
|
||||
}
|
||||
public string ToUpper (string src)
|
||||
{
|
||||
if (src == null) return null;
|
||||
return src.ToUpper (CultureInfo.InvariantCulture);
|
||||
}
|
||||
public string Format (string fmt, params object [] args)
|
||||
{
|
||||
return Utilities.FormatString (fmt, args);
|
||||
}
|
||||
// FormatInnerHTML: escape format string to inner xml, and escape each argument to inner xml wrapped in <span>...</span>
|
||||
public string FormatInnerHTML (string fmt, params object [] args)
|
||||
{
|
||||
if (fmt == null) fmt = string.Empty;
|
||||
string escapedFormat = Utilities.EscapeToInnerXml (fmt);
|
||||
if (args == null || args.Length == 0) return escapedFormat;
|
||||
|
||||
object [] newArgs = new object [args.Length];
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
string argText = args [i] != null ? args [i].ToString () : string.Empty;
|
||||
string esc = Utilities.EscapeToInnerXml (argText);
|
||||
newArgs [i] = string.Format ("<span>{0}</span>", esc);
|
||||
}
|
||||
try
|
||||
{
|
||||
// We used an escaped format string, but its indices are the same.
|
||||
return string.Format (CultureInfo.InvariantCulture, escapedFormat, newArgs);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// fallback: simple concatenation
|
||||
StringBuilder sb = new StringBuilder ();
|
||||
sb.Append (escapedFormat);
|
||||
sb.Append (" ");
|
||||
for (int i = 0; i < newArgs.Length; i++)
|
||||
{
|
||||
if (i > 0) sb.Append (", ");
|
||||
sb.Append (newArgs [i]);
|
||||
}
|
||||
return sb.ToString ();
|
||||
}
|
||||
}
|
||||
public string StringArrayToJson (string [] strs)
|
||||
{
|
||||
return Utilities.StringArrayToJson (strs);
|
||||
}
|
||||
public static string FormatDateTime (string fmt, string jsDate)
|
||||
{
|
||||
DateTime dt = Convert.ToDateTime (jsDate);
|
||||
return string.Format (fmt, dt);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
274
DataUtils/SysInit.cs
Normal file
274
DataUtils/SysInit.cs
Normal file
@@ -0,0 +1,274 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
public static class VisualElementsStore
|
||||
{
|
||||
// Publicly accessible instances for internal use
|
||||
public static readonly VisualElementManifest Vemanifest;
|
||||
public static readonly FileResXmlDoc ScaleResources;
|
||||
|
||||
static VisualElementsStore ()
|
||||
{
|
||||
try
|
||||
{
|
||||
string programRoot = GetProgramRootDirectory ();
|
||||
|
||||
// manifest path: VisualElementsManifest.xml in program root
|
||||
string manifestPath = Path.Combine (programRoot, "VisualElementsManifest.xml");
|
||||
|
||||
// scale xml candidate: VisualElements\scale.xml
|
||||
string scaleCandidate = Path.Combine (programRoot, "VisualElements", "scale.xml");
|
||||
|
||||
// If scale.xml exists use it, otherwise fall back to VisualElementsManifest.xml
|
||||
string scalePath = File.Exists (scaleCandidate) ? scaleCandidate : manifestPath;
|
||||
|
||||
// Initialize (constructors will attempt to load)
|
||||
Vemanifest = new VisualElementManifest ();
|
||||
if (File.Exists (manifestPath))
|
||||
{
|
||||
// Use Create to ensure we reflect true load status
|
||||
Vemanifest.Create (manifestPath);
|
||||
}
|
||||
|
||||
FileResXmlDoc tmp = null;
|
||||
if (File.Exists (scalePath))
|
||||
{
|
||||
tmp = new FileResXmlDoc (scalePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if both missing, try manifest as last resort (ResXmlDoc handles manifest-style layout)
|
||||
if (File.Exists (manifestPath))
|
||||
tmp = new FileResXmlDoc (manifestPath);
|
||||
}
|
||||
ScaleResources = tmp;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// swallow exceptions; leave fields null if initialization fails
|
||||
Vemanifest = new VisualElementManifest ();
|
||||
ScaleResources = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetProgramRootDirectory ()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Prefer the directory of the executing assembly
|
||||
string codeBase = Assembly.GetExecutingAssembly ().Location;
|
||||
if (!string.IsNullOrEmpty (codeBase))
|
||||
{
|
||||
string dir = Path.GetDirectoryName (codeBase);
|
||||
if (!string.IsNullOrEmpty (dir)) return dir;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
return AppDomain.CurrentDomain.BaseDirectory ?? Environment.CurrentDirectory;
|
||||
}
|
||||
catch { }
|
||||
|
||||
return Environment.CurrentDirectory;
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_VisualElement
|
||||
{
|
||||
private string _appid;
|
||||
|
||||
public _I_VisualElement ()
|
||||
{
|
||||
_appid = "App";
|
||||
}
|
||||
|
||||
public _I_VisualElement (string appid)
|
||||
{
|
||||
_appid = string.IsNullOrEmpty (appid) ? "App" : appid;
|
||||
}
|
||||
|
||||
public string Id
|
||||
{
|
||||
get { return _appid; }
|
||||
set { _appid = string.IsNullOrEmpty (value) ? "App" : value; }
|
||||
}
|
||||
|
||||
public string DisplayName
|
||||
{
|
||||
get { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.DisplayName (_appid) : string.Empty; }
|
||||
}
|
||||
|
||||
public string Logo
|
||||
{
|
||||
get { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.Logo (_appid) : string.Empty; }
|
||||
}
|
||||
|
||||
public string SmallLogo
|
||||
{
|
||||
get { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.SmallLogo (_appid) : string.Empty; }
|
||||
}
|
||||
|
||||
public string ForegroundText
|
||||
{
|
||||
get
|
||||
{
|
||||
if (VisualElementsStore.Vemanifest == null) return "dark";
|
||||
var t = VisualElementsStore.Vemanifest.ForegroundText (_appid);
|
||||
return t == ManifestTextColor.Light ? "light" : "dark";
|
||||
}
|
||||
}
|
||||
|
||||
public string Lnk32x32Logo
|
||||
{
|
||||
get { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.Lnk32x32Logo (_appid) : string.Empty; }
|
||||
}
|
||||
|
||||
public string ItemDisplayLogo
|
||||
{
|
||||
get { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.ItemDisplayLogo (_appid) : string.Empty; }
|
||||
}
|
||||
|
||||
public bool ShowNameOnTile
|
||||
{
|
||||
get { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.ShowNameOnTile (_appid) : false; }
|
||||
}
|
||||
|
||||
public string BackgroundColor
|
||||
{
|
||||
get { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.BackgroundColor (_appid) : string.Empty; }
|
||||
}
|
||||
|
||||
public string SplashScreenImage
|
||||
{
|
||||
get { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.SplashScreenImage (_appid) : string.Empty; }
|
||||
}
|
||||
|
||||
public string SplashScreenBackgroundColor
|
||||
{
|
||||
get { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.SplashScreenBackgroundColor (_appid) : string.Empty; }
|
||||
}
|
||||
|
||||
public string SplashScreenBackgroundColorDarkMode
|
||||
{
|
||||
get { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.SplashScreenBackgroundColorDarkMode (_appid) : string.Empty; }
|
||||
}
|
||||
|
||||
// Indexer for script-friendly access: v["displayname"]
|
||||
public object this [string propertyName]
|
||||
{
|
||||
get { return Get (propertyName); }
|
||||
}
|
||||
|
||||
// Generic getter by property name (case-insensitive)
|
||||
public object Get (string propertyName)
|
||||
{
|
||||
if (string.IsNullOrEmpty (propertyName)) return string.Empty;
|
||||
string key = propertyName.Trim ().ToLowerInvariant ();
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case "displayname": return DisplayName;
|
||||
case "logo": return Logo;
|
||||
case "smalllogo": return SmallLogo;
|
||||
case "foregroundtext": return ForegroundText;
|
||||
case "lnk32x32logo": return Lnk32x32Logo;
|
||||
case "itemdisplaylogo": return ItemDisplayLogo;
|
||||
case "shownameontile": return ShowNameOnTile;
|
||||
case "backgroundcolor": return BackgroundColor;
|
||||
case "splashscreenimage": return SplashScreenImage;
|
||||
case "splashscreenbackgroundcolor": return SplashScreenBackgroundColor;
|
||||
case "splashscreenbackgroundcolordarkmode": return SplashScreenBackgroundColorDarkMode;
|
||||
default: return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_VisualElements
|
||||
{
|
||||
public string [] GetIds ()
|
||||
{
|
||||
try
|
||||
{
|
||||
var list = VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.AppIds () : new System.Collections.Generic.List<string> () { "App" };
|
||||
return list.ToArray ();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new string [] { "App" };
|
||||
}
|
||||
}
|
||||
|
||||
public string GetIdsToJson ()
|
||||
{
|
||||
var ids = GetIds ();
|
||||
// Use Utilities.StringArrayToJson (which uses Newtonsoft.Json if available)
|
||||
try
|
||||
{
|
||||
return Utilities.StringArrayToJson (ids);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// fallback
|
||||
return Newtonsoft.Json.JsonConvert.SerializeObject (ids);
|
||||
}
|
||||
}
|
||||
|
||||
public _I_VisualElement Get (string id)
|
||||
{
|
||||
return new _I_VisualElement (id);
|
||||
}
|
||||
|
||||
public _I_VisualElement this [string id]
|
||||
{
|
||||
get { return Get (id); }
|
||||
}
|
||||
|
||||
// Attribute-style methods
|
||||
public string DisplayName (string appid) { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.DisplayName (string.IsNullOrEmpty (appid) ? "App" : appid) : string.Empty; }
|
||||
public string Logo (string appid) { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.Logo (string.IsNullOrEmpty (appid) ? "App" : appid) : string.Empty; }
|
||||
public string SmallLogo (string appid) { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.SmallLogo (string.IsNullOrEmpty (appid) ? "App" : appid) : string.Empty; }
|
||||
public string ForegroundText (string appid)
|
||||
{
|
||||
if (VisualElementsStore.Vemanifest == null) return "dark";
|
||||
var t = VisualElementsStore.Vemanifest.ForegroundText (string.IsNullOrEmpty (appid) ? "App" : appid);
|
||||
return t == ManifestTextColor.Light ? "light" : "dark";
|
||||
}
|
||||
public string Lnk32x32Logo (string appid) { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.Lnk32x32Logo (string.IsNullOrEmpty (appid) ? "App" : appid) : string.Empty; }
|
||||
public string ItemDisplayLogo (string appid) { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.ItemDisplayLogo (string.IsNullOrEmpty (appid) ? "App" : appid) : string.Empty; }
|
||||
public bool ShowNameOnTile (string appid) { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.ShowNameOnTile (string.IsNullOrEmpty (appid) ? "App" : appid) : false; }
|
||||
public string BackgroundColor (string appid) { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.BackgroundColor (string.IsNullOrEmpty (appid) ? "App" : appid) : string.Empty; }
|
||||
public string SplashScreenImage (string appid) { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.SplashScreenImage (string.IsNullOrEmpty (appid) ? "App" : appid) : string.Empty; }
|
||||
public string SplashScreenBackgroundColor (string appid) { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.SplashScreenBackgroundColor (string.IsNullOrEmpty (appid) ? "App" : appid) : string.Empty; }
|
||||
public string SplashScreenBackgroundColorDarkMode (string appid) { return VisualElementsStore.Vemanifest != null ? VisualElementsStore.Vemanifest.SplashScreenBackgroundColorDarkMode (string.IsNullOrEmpty (appid) ? "App" : appid) : string.Empty; }
|
||||
|
||||
// Generic getter by attribute name
|
||||
public object GetValue (string appid, string attributeName)
|
||||
{
|
||||
if (string.IsNullOrEmpty (attributeName)) return string.Empty;
|
||||
string key = attributeName.Trim ().ToLowerInvariant ();
|
||||
switch (key)
|
||||
{
|
||||
case "displayname": return DisplayName (appid);
|
||||
case "logo": return Logo (appid);
|
||||
case "smalllogo": return SmallLogo (appid);
|
||||
case "foregroundtext": return ForegroundText (appid);
|
||||
case "lnk32x32logo": return Lnk32x32Logo (appid);
|
||||
case "itemdisplaylogo": return ItemDisplayLogo (appid);
|
||||
case "shownameontile": return ShowNameOnTile (appid);
|
||||
case "backgroundcolor": return BackgroundColor (appid);
|
||||
case "splashscreenimage": return SplashScreenImage (appid);
|
||||
case "splashscreenbackgroundcolor": return SplashScreenBackgroundColor (appid);
|
||||
case "splashscreenbackgroundcolordarkmode": return SplashScreenBackgroundColorDarkMode (appid);
|
||||
default: return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
DataUtils/Taskbar.cs
Normal file
116
DataUtils/Taskbar.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
public enum TBPFLAG
|
||||
{
|
||||
TBPF_NOPROGRESS = 0x0,
|
||||
TBPF_INDETERMINATE = 0x1,
|
||||
TBPF_NORMAL = 0x2,
|
||||
TBPF_ERROR = 0x4,
|
||||
TBPF_PAUSED = 0x8
|
||||
}
|
||||
[ComImport]
|
||||
[Guid ("EA1AFB91-9E28-4B86-90E9-9E9F8A5EEA84")]
|
||||
[InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface ITaskbarList3
|
||||
{
|
||||
void HrInit ();
|
||||
void AddTab (IntPtr hwnd);
|
||||
void DeleteTab (IntPtr hwnd);
|
||||
void ActivateTab (IntPtr hwnd);
|
||||
void SetActiveAlt (IntPtr hwnd);
|
||||
void MarkFullscreenWindow (IntPtr hwnd, [MarshalAs (UnmanagedType.Bool)] bool fFullscreen);
|
||||
void SetProgressValue (IntPtr hwnd, ulong ullCompleted, ulong ullTotal);
|
||||
void SetProgressState (IntPtr hwnd, TBPFLAG tbpFlags);
|
||||
void RegisterTab (IntPtr hwndTab, IntPtr hwndMDI);
|
||||
void UnregisterTab (IntPtr hwndTab);
|
||||
void SetTabOrder (IntPtr hwndTab, IntPtr hwndInsertBefore);
|
||||
void SetTabActive (IntPtr hwndTab, IntPtr hwndMDI, uint dwReserved);
|
||||
void ThumbBarAddButtons (IntPtr hwnd, uint cButtons, IntPtr pButtons);
|
||||
void ThumbBarUpdateButtons (IntPtr hwnd, uint cButtons, IntPtr pButtons);
|
||||
void ThumbBarSetImageList (IntPtr hwnd, IntPtr himl);
|
||||
void SetOverlayIcon (IntPtr hwnd, IntPtr hIcon, string pszDescription);
|
||||
void SetThumbnailTooltip (IntPtr hwnd, string pszTip);
|
||||
void SetThumbnailClip (IntPtr hwnd, ref RECT prcClip);
|
||||
}
|
||||
[ComImport]
|
||||
[Guid ("56FDF344-FD6D-11d0-958A-006097C9A090")]
|
||||
public class TaskbarList { }
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
public struct RECT
|
||||
{
|
||||
public int left;
|
||||
public int top;
|
||||
public int right;
|
||||
public int bottom;
|
||||
}
|
||||
public sealed class TaskbarProgress: IDisposable
|
||||
{
|
||||
private readonly IntPtr _hwnd;
|
||||
private ITaskbarList3 _taskbar3;
|
||||
public TaskbarProgress (IntPtr hwnd)
|
||||
{
|
||||
_hwnd = hwnd;
|
||||
object obj = new TaskbarList ();
|
||||
ITaskbarList baseTaskbar = (ITaskbarList)obj;
|
||||
baseTaskbar.HrInit ();
|
||||
_taskbar3 = obj as ITaskbarList3;
|
||||
}
|
||||
public bool IsSupported
|
||||
{
|
||||
get { return _taskbar3 != null; }
|
||||
}
|
||||
public void SetState (TBPFLAG state)
|
||||
{
|
||||
if (_taskbar3 != null)
|
||||
_taskbar3.SetProgressState (_hwnd, state);
|
||||
}
|
||||
public void SetValue (ulong completed, ulong total)
|
||||
{
|
||||
if (_taskbar3 != null)
|
||||
_taskbar3.SetProgressValue (_hwnd, completed, total);
|
||||
}
|
||||
public void Clear ()
|
||||
{
|
||||
if (_taskbar3 != null)
|
||||
_taskbar3.SetProgressState (_hwnd, TBPFLAG.TBPF_NOPROGRESS);
|
||||
}
|
||||
public void Dispose ()
|
||||
{
|
||||
if (_taskbar3 != null)
|
||||
{
|
||||
Marshal.ReleaseComObject (_taskbar3);
|
||||
_taskbar3 = null;
|
||||
}
|
||||
}
|
||||
~TaskbarProgress () { Dispose (); }
|
||||
public ITaskbarList3 Instance => _taskbar3;
|
||||
}
|
||||
[ComImport]
|
||||
[Guid ("56FDF342-FD6D-11d0-958A-006097C9A090")]
|
||||
[InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface ITaskbarList
|
||||
{
|
||||
void HrInit ();
|
||||
void AddTab (IntPtr hwnd);
|
||||
void DeleteTab (IntPtr hwnd);
|
||||
void ActivateTab (IntPtr hwnd);
|
||||
void SetActiveAlt (IntPtr hwnd);
|
||||
}
|
||||
public interface ITaskbarProgress
|
||||
{
|
||||
double ProgressValue { set; }
|
||||
TBPFLAG ProgressStatus { set; }
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Taskbar
|
||||
{
|
||||
private ITaskbarProgress taskbar = null;
|
||||
public double Progress { set { if (taskbar == null) return; taskbar.ProgressValue = value; } }
|
||||
public int Status { set { if (taskbar == null) return; taskbar.ProgressStatus = (TBPFLAG)value; } }
|
||||
public _I_Taskbar (ITaskbarProgress tp) { taskbar = tp; }
|
||||
}
|
||||
}
|
||||
362
DataUtils/Theme.cs
Normal file
362
DataUtils/Theme.cs
Normal file
@@ -0,0 +1,362 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
public enum HighContrastTheme
|
||||
{
|
||||
None,
|
||||
Black,
|
||||
White,
|
||||
Other
|
||||
}
|
||||
|
||||
public static class UITheme
|
||||
{
|
||||
// --- P/Invoke & constants ---
|
||||
private const int SPI_GETHIGHCONTRAST = 0x0042;
|
||||
private const uint HCF_HIGHCONTRASTON = 0x00000001;
|
||||
|
||||
private const int COLOR_WINDOW = 5;
|
||||
private const int COLOR_WINDOWTEXT = 8;
|
||||
|
||||
private const int LOGPIXELSX = 88; // GetDeviceCaps index for DPI X
|
||||
// private const int HORZRES = 8; // not used now
|
||||
|
||||
private const int SM_CXSCREEN = 0;
|
||||
private const int SM_CYSCREEN = 1;
|
||||
|
||||
[StructLayout (LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
private struct HIGHCONTRAST
|
||||
{
|
||||
public int cbSize;
|
||||
public uint dwFlags;
|
||||
public IntPtr lpszDefaultScheme;
|
||||
}
|
||||
|
||||
[DllImport ("user32.dll", SetLastError = true)]
|
||||
private static extern bool SystemParametersInfo (int uiAction, int uiParam, ref HIGHCONTRAST pvParam, int fWinIni);
|
||||
|
||||
[DllImport ("user32.dll")]
|
||||
private static extern int GetSysColor (int nIndex);
|
||||
|
||||
[DllImport ("user32.dll")]
|
||||
private static extern int GetSystemMetrics (int nIndex);
|
||||
|
||||
[DllImport ("user32.dll")]
|
||||
private static extern IntPtr GetDC (IntPtr hWnd);
|
||||
|
||||
[DllImport ("user32.dll")]
|
||||
private static extern int ReleaseDC (IntPtr hWnd, IntPtr hDC);
|
||||
|
||||
[DllImport ("gdi32.dll")]
|
||||
private static extern int GetDeviceCaps (IntPtr hdc, int nIndex);
|
||||
|
||||
// DwmGetColorizationColor
|
||||
[DllImport ("dwmapi.dll", EntryPoint = "DwmGetColorizationColor", SetLastError = false)]
|
||||
private static extern int DwmGetColorizationColor (out uint pcrColorization, out bool pfOpaqueBlend);
|
||||
|
||||
// --- Methods ---
|
||||
|
||||
public static bool IsHighContrastEnabled ()
|
||||
{
|
||||
try
|
||||
{
|
||||
HIGHCONTRAST hc = new HIGHCONTRAST ();
|
||||
hc.cbSize = Marshal.SizeOf (typeof (HIGHCONTRAST));
|
||||
if (SystemParametersInfo (SPI_GETHIGHCONTRAST, hc.cbSize, ref hc, 0))
|
||||
{
|
||||
return (hc.dwFlags & HCF_HIGHCONTRASTON) != 0;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore errors
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static bool IsHighContrast => IsHighContrastEnabled ();
|
||||
public static HighContrastTheme GetHighContrastTheme ()
|
||||
{
|
||||
try
|
||||
{
|
||||
HIGHCONTRAST hc = new HIGHCONTRAST ();
|
||||
hc.cbSize = Marshal.SizeOf (typeof (HIGHCONTRAST));
|
||||
if (!SystemParametersInfo (SPI_GETHIGHCONTRAST, hc.cbSize, ref hc, 0))
|
||||
return HighContrastTheme.None;
|
||||
|
||||
if ((hc.dwFlags & HCF_HIGHCONTRASTON) == 0)
|
||||
return HighContrastTheme.None;
|
||||
|
||||
int bgColorRef = GetSysColor (COLOR_WINDOW);
|
||||
int textColorRef = GetSysColor (COLOR_WINDOWTEXT);
|
||||
|
||||
int bgR = (bgColorRef & 0x0000FF);
|
||||
int bgG = (bgColorRef & 0x00FF00) >> 8;
|
||||
int bgB = (bgColorRef & 0xFF0000) >> 16;
|
||||
|
||||
int txtR = (textColorRef & 0x0000FF);
|
||||
int txtG = (textColorRef & 0x00FF00) >> 8;
|
||||
int txtB = (textColorRef & 0xFF0000) >> 16;
|
||||
|
||||
int brightnessBg = (bgR + bgG + bgB) / 3;
|
||||
int brightnessText = (txtR + txtG + txtB) / 3;
|
||||
|
||||
if (brightnessBg < brightnessText) return HighContrastTheme.Black;
|
||||
else if (brightnessBg > brightnessText) return HighContrastTheme.White;
|
||||
else return HighContrastTheme.Other;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return HighContrastTheme.None;
|
||||
}
|
||||
}
|
||||
public static HighContrastTheme HighContrast => GetHighContrastTheme ();
|
||||
// Returns DPI as percent (100 = normal 96 DPI)
|
||||
public static int GetDPI ()
|
||||
{
|
||||
IntPtr hdc = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
hdc = GetDC (IntPtr.Zero);
|
||||
if (hdc == IntPtr.Zero) return 0;
|
||||
int dpiX = GetDeviceCaps (hdc, LOGPIXELSX);
|
||||
if (dpiX <= 0) return 0;
|
||||
// convert to percentage of 96 DPI baseline
|
||||
int percent = (int)Math.Round ((dpiX / 96.0) * 100.0);
|
||||
return percent;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (hdc != IntPtr.Zero) ReleaseDC (IntPtr.Zero, hdc);
|
||||
}
|
||||
}
|
||||
public static int DPI => GetDPI ();
|
||||
public static double DPIDouble => GetDPI () * 0.01;
|
||||
public static int GetScreenWidth ()
|
||||
{
|
||||
try { return GetSystemMetrics (SM_CXSCREEN); }
|
||||
catch { return 0; }
|
||||
}
|
||||
public static int ScreenWidth => GetScreenWidth ();
|
||||
public static int GetScreenHeight ()
|
||||
{
|
||||
try { return GetSystemMetrics (SM_CYSCREEN); }
|
||||
catch { return 0; }
|
||||
}
|
||||
public static int ScreenHeight => GetScreenHeight ();
|
||||
public static Color GetDwmThemeColor ()
|
||||
{
|
||||
try
|
||||
{
|
||||
uint color;
|
||||
bool opaque;
|
||||
int hr = DwmGetColorizationColor (out color, out opaque);
|
||||
if (hr == 0) // S_OK
|
||||
{
|
||||
byte r = (byte)((color & 0x00FF0000) >> 16);
|
||||
byte g = (byte)((color & 0x0000FF00) >> 8);
|
||||
byte b = (byte)(color & 0x000000FF);
|
||||
return Color.FromArgb (r, g, b);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
// fallback default (matches original C++ fallback)
|
||||
return Color.FromArgb (0, 120, 215);
|
||||
}
|
||||
public static Color ThemeColor => GetDwmThemeColor ();
|
||||
public static string ColorToHtml (Color color)
|
||||
{
|
||||
// Return #RRGGBB
|
||||
return string.Format ("#{0:X2}{1:X2}{2:X2}", color.R, color.G, color.B);
|
||||
}
|
||||
|
||||
public static Color StringToColor (string colorStr)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace (colorStr)) return Color.Transparent;
|
||||
string s = colorStr.Trim ();
|
||||
|
||||
// Hex: #RGB, #RRGGBB, #AARRGGBB
|
||||
if (s.StartsWith ("#"))
|
||||
{
|
||||
string hex = s.Substring (1);
|
||||
// Expand short forms (#RGB or #RGBA)
|
||||
if (hex.Length == 3 || hex.Length == 4)
|
||||
{
|
||||
string expanded = "";
|
||||
for (int i = 0; i < hex.Length; i++)
|
||||
{
|
||||
expanded += hex [i].ToString () + hex [i].ToString ();
|
||||
}
|
||||
hex = expanded;
|
||||
}
|
||||
|
||||
uint argb;
|
||||
try
|
||||
{
|
||||
argb = Convert.ToUInt32 (hex, 16);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Color.Transparent;
|
||||
}
|
||||
|
||||
if (hex.Length == 6)
|
||||
{
|
||||
int r = (int)((argb >> 16) & 0xFF);
|
||||
int g = (int)((argb >> 8) & 0xFF);
|
||||
int b = (int)(argb & 0xFF);
|
||||
return Color.FromArgb (r, g, b);
|
||||
}
|
||||
else if (hex.Length == 8)
|
||||
{
|
||||
int a = (int)((argb >> 24) & 0xFF);
|
||||
int r = (int)((argb >> 16) & 0xFF);
|
||||
int g = (int)((argb >> 8) & 0xFF);
|
||||
int b = (int)(argb & 0xFF);
|
||||
return Color.FromArgb (a, r, g, b);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Color.Transparent;
|
||||
}
|
||||
}
|
||||
|
||||
// rgb()/rgba() functional notation
|
||||
// Accept forms like: rgb(255,0,0) or rgba(255,0,0,0.5) or rgb(100%,0%,0%)
|
||||
var m = Regex.Match (s, @"^(rgba?)\s*\(\s*([^\)]+)\s*\)$", RegexOptions.IgnoreCase);
|
||||
if (m.Success)
|
||||
{
|
||||
string func = m.Groups [1].Value.ToLowerInvariant ();
|
||||
string inside = m.Groups [2].Value;
|
||||
string [] parts = inside.Split (new char [] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length >= 3)
|
||||
{
|
||||
try
|
||||
{
|
||||
Func<string, int> comp = (string v) => {
|
||||
v = v.Trim ();
|
||||
if (v.EndsWith ("%"))
|
||||
{
|
||||
// percentage
|
||||
string num = v.TrimEnd ('%');
|
||||
float p;
|
||||
if (float.TryParse (num, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out p))
|
||||
{
|
||||
return (int)Math.Round (Math.Max (0, Math.Min (100, p)) * 255.0 / 100.0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int iv;
|
||||
if (int.TryParse (v, out iv))
|
||||
{
|
||||
return Math.Max (0, Math.Min (255, iv));
|
||||
}
|
||||
// fallback parse float
|
||||
float fv;
|
||||
if (float.TryParse (v, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out fv))
|
||||
{
|
||||
return Math.Max (0, Math.Min (255, (int)Math.Round (fv)));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int r = comp (parts [0]);
|
||||
int g = comp (parts [1]);
|
||||
int b = comp (parts [2]);
|
||||
int a = 255;
|
||||
if (func == "rgba" && parts.Length >= 4)
|
||||
{
|
||||
string av = parts [3].Trim ();
|
||||
if (av.EndsWith ("%"))
|
||||
{
|
||||
string num = av.TrimEnd ('%');
|
||||
float p;
|
||||
if (float.TryParse (num, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out p))
|
||||
{
|
||||
a = (int)Math.Round (Math.Max (0, Math.Min (100, p)) * 255.0 / 100.0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// alpha may be 0..1 or 0..255
|
||||
float af;
|
||||
if (float.TryParse (av, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out af))
|
||||
{
|
||||
if (af <= 1.0f) a = (int)Math.Round (Math.Max (0.0f, Math.Min (1.0f, af)) * 255.0f);
|
||||
else a = (int)Math.Round (Math.Max (0.0f, Math.Min (255.0f, af)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return Color.FromArgb (a, r, g, b);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Color.Transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Named color
|
||||
try
|
||||
{
|
||||
Color byName = Color.FromName (s);
|
||||
if (byName.IsKnownColor || byName.IsNamedColor)
|
||||
{
|
||||
return byName;
|
||||
}
|
||||
}
|
||||
catch { /* ignore */ }
|
||||
|
||||
// fallback: try parse as known color again (case-insensitive)
|
||||
try
|
||||
{
|
||||
Color named = Color.FromName (s);
|
||||
if (named.IsKnownColor || named.IsNamedColor) return named;
|
||||
}
|
||||
catch { }
|
||||
|
||||
return Color.Transparent;
|
||||
}
|
||||
|
||||
public static bool IsAppInDarkMode ()
|
||||
{
|
||||
try
|
||||
{
|
||||
// HKCU\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize\AppsUseLightTheme
|
||||
object val = Registry.GetValue (
|
||||
@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize",
|
||||
"AppsUseLightTheme",
|
||||
null);
|
||||
|
||||
if (val == null) return false; // default to light? original returned false
|
||||
int intVal;
|
||||
if (val is int) intVal = (int)val;
|
||||
else
|
||||
{
|
||||
if (!int.TryParse (val.ToString (), out intVal)) return false;
|
||||
}
|
||||
// 0 => dark, 1 => light
|
||||
return intVal == 0;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public static bool AppDarkMode => IsAppInDarkMode ();
|
||||
}
|
||||
}
|
||||
619
DataUtils/Utils.cs
Normal file
619
DataUtils/Utils.cs
Normal file
@@ -0,0 +1,619 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
public static class Utilities
|
||||
{
|
||||
// Format string with args (compatible with your C++ FormatString wrapper)
|
||||
public static string FormatString (string fmt, params object [] args)
|
||||
{
|
||||
if (fmt == null) return string.Empty;
|
||||
if (args == null || args.Length == 0) return fmt;
|
||||
try
|
||||
{
|
||||
return string.Format (System.Globalization.CultureInfo.InvariantCulture, fmt, args);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// On format error, fallback to simple concat
|
||||
try
|
||||
{
|
||||
StringBuilder sb = new StringBuilder ();
|
||||
sb.Append (fmt);
|
||||
sb.Append (" : ");
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
if (i > 0) sb.Append (", ");
|
||||
sb.Append (args [i] != null ? args [i].ToString () : "null");
|
||||
}
|
||||
return sb.ToString ();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return fmt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Escape string to be used as InnerXml content (returns XML-escaped content)
|
||||
public static string EscapeToInnerXml (string str)
|
||||
{
|
||||
if (str == null) return string.Empty;
|
||||
var doc = new XmlDocument ();
|
||||
// create a root element and use InnerText to perform escaping
|
||||
var root = doc.CreateElement ("body");
|
||||
root.InnerText = str;
|
||||
return root.InnerXml;
|
||||
}
|
||||
|
||||
// Returns the current process full path (exe)
|
||||
public static string GetCurrentProgramPath ()
|
||||
{
|
||||
try
|
||||
{
|
||||
return System.Diagnostics.Process.GetCurrentProcess ().MainModule.FileName;
|
||||
}
|
||||
catch
|
||||
{
|
||||
try
|
||||
{
|
||||
return System.Reflection.Assembly.GetEntryAssembly ().Location;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return AppDomain.CurrentDomain.BaseDirectory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// JSON array builder using Newtonsoft.Json
|
||||
public static string StringArrayToJson (string [] values)
|
||||
{
|
||||
if (values == null) return "[]";
|
||||
try
|
||||
{
|
||||
return JsonConvert.SerializeObject (values);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Fallback to manual builder
|
||||
StringBuilder sb = new StringBuilder ();
|
||||
sb.Append ('[');
|
||||
for (int i = 0; i < values.Length; i++)
|
||||
{
|
||||
if (i > 0) sb.Append (',');
|
||||
sb.Append ('"');
|
||||
sb.Append (JsonEscape (values [i] ?? string.Empty));
|
||||
sb.Append ('"');
|
||||
}
|
||||
sb.Append (']');
|
||||
return sb.ToString ();
|
||||
}
|
||||
}
|
||||
|
||||
public static string StringListToJson (System.Collections.Generic.List<string> list)
|
||||
{
|
||||
if (list == null) return "[]";
|
||||
return StringArrayToJson (list.ToArray ());
|
||||
}
|
||||
|
||||
// Minimal JSON string escaper (fallback)
|
||||
private static string JsonEscape (string s)
|
||||
{
|
||||
if (string.IsNullOrEmpty (s)) return s ?? string.Empty;
|
||||
StringBuilder sb = new StringBuilder (s.Length + 8);
|
||||
foreach (char c in s)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '"': sb.Append ("\\\""); break;
|
||||
case '\\': sb.Append ("\\\\"); break;
|
||||
case '\b': sb.Append ("\\b"); break;
|
||||
case '\f': sb.Append ("\\f"); break;
|
||||
case '\n': sb.Append ("\\n"); break;
|
||||
case '\r': sb.Append ("\\r"); break;
|
||||
case '\t': sb.Append ("\\t"); break;
|
||||
default:
|
||||
if (c < 32 || c == '\u2028' || c == '\u2029')
|
||||
{
|
||||
sb.AppendFormat ("\\u{0:X4}", (int)c);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append (c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sb.ToString ();
|
||||
}
|
||||
|
||||
// Helper: combine multiple filters split by ';' or '\' (legacy)
|
||||
public static string [] SplitFilters (string filter)
|
||||
{
|
||||
if (string.IsNullOrEmpty (filter)) return new string [] { "*" };
|
||||
// Accept ';' or '\' or '|' as separators (common)
|
||||
string [] parts = filter.Split (new char [] { ';', '\\', '|' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
for (int i = 0; i < parts.Length; i++)
|
||||
{
|
||||
parts [i] = parts [i].Trim ();
|
||||
if (parts [i].Length == 0) parts [i] = "*";
|
||||
}
|
||||
if (parts.Length == 0) return new string [] { "*" };
|
||||
return parts;
|
||||
}
|
||||
|
||||
// Normalize full path for comparisons
|
||||
public static string NormalizeFullPath (string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty (path)) return string.Empty;
|
||||
try
|
||||
{
|
||||
return Path.GetFullPath (path).TrimEnd (Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return path.Trim ();
|
||||
}
|
||||
}
|
||||
// 忽略大小写和首尾空的比较
|
||||
public static bool NEquals (this string left, string right)
|
||||
{
|
||||
return (left ?? "")?.Trim ()?.ToLower ()?.Equals ((right ?? "")?.Trim ()?.ToLower ()) ?? false;
|
||||
}
|
||||
public static int NCompareTo (this string l, string r)
|
||||
{
|
||||
return (l ?? "")?.Trim ()?.ToLower ().CompareTo ((r ?? "")?.Trim ()?.ToLower ()) ?? 0;
|
||||
}
|
||||
public static bool NEmpty (this string l)
|
||||
{
|
||||
return (l ?? "")?.NEquals ("") ?? true;
|
||||
}
|
||||
public static int NLength (this string l)
|
||||
{
|
||||
return (l ?? "")?.Length ?? 0;
|
||||
}
|
||||
public static bool NNoEmpty (this string l) => !((l ?? "")?.NEmpty () ?? true);
|
||||
public static string NNormalize (this string l) => (l ?? "")?.Trim ()?.ToLower () ?? "";
|
||||
public interface IJsonBuild
|
||||
{
|
||||
object BuildJSON ();
|
||||
}
|
||||
}
|
||||
public static class JsUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// 调用 JS 函数。第一个参数作为 this,其余作为 JS 函数参数。
|
||||
/// </summary>
|
||||
/// <param name="callback">JS 函数对象</param>
|
||||
/// <param name="args">JS 函数参数,可选</param>
|
||||
/// <returns>JS 函数返回值</returns>
|
||||
public static void Call (object jsFunc, params object [] args)
|
||||
{
|
||||
if (jsFunc == null) return;
|
||||
object [] invokeArgs = new object [(args?.Length ?? 0) + 1];
|
||||
invokeArgs [0] = jsFunc; // this
|
||||
if (args != null)
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
invokeArgs [i + 1] = args [i];
|
||||
jsFunc.GetType ().InvokeMember (
|
||||
"call",
|
||||
BindingFlags.InvokeMethod,
|
||||
null,
|
||||
jsFunc,
|
||||
invokeArgs);
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[InterfaceType (ComInterfaceType.InterfaceIsDual)]
|
||||
public interface _I_IAsyncAction
|
||||
{
|
||||
_I_IAsyncAction Then (object resolve, object reject = null, object progress = null);
|
||||
void Done (object resolve, object reject = null);
|
||||
void Catch (object reject);
|
||||
bool IsCompleted { get; }
|
||||
bool IsCancelled { get; }
|
||||
bool IsError { get; }
|
||||
void Cancel ();
|
||||
void ReportProgress (object progress);
|
||||
object Error { get; }
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Task: _I_IAsyncAction
|
||||
{
|
||||
private object _result;
|
||||
private Exception _error;
|
||||
private bool _completed;
|
||||
private bool _cancelled;
|
||||
private List<object> _resolveCallbacks = new List<object> ();
|
||||
private List<object> _rejectCallbacks = new List<object> ();
|
||||
private List<object> _progressCallbacks = new List<object> ();
|
||||
private CancellationTokenSource _cts = new CancellationTokenSource ();
|
||||
public _I_Task (Func<object> func)
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem (_ => {
|
||||
try
|
||||
{
|
||||
if (_cts.Token.IsCancellationRequested)
|
||||
{
|
||||
_cancelled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_result = func ();
|
||||
_completed = true;
|
||||
|
||||
foreach (var cb in _resolveCallbacks)
|
||||
JsUtils.Call (cb, _result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_error = ex;
|
||||
foreach (var cb in _rejectCallbacks)
|
||||
JsUtils.Call (cb, ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
public _I_IAsyncAction Then (object resolve, object reject = null, object progress = null)
|
||||
{
|
||||
if (resolve != null) _resolveCallbacks.Add (resolve);
|
||||
if (reject != null) _rejectCallbacks.Add (reject);
|
||||
if (progress != null) _progressCallbacks.Add (progress);
|
||||
return this;
|
||||
}
|
||||
public void Done (object resolve, object reject = null)
|
||||
{
|
||||
if (resolve != null) _resolveCallbacks.Add (resolve);
|
||||
if (reject != null) _rejectCallbacks.Add (reject);
|
||||
}
|
||||
|
||||
public void Catch (object reject)
|
||||
{
|
||||
if (reject != null) _rejectCallbacks.Add (reject);
|
||||
}
|
||||
|
||||
public bool IsCompleted => _completed;
|
||||
public bool IsCancelled => _cancelled;
|
||||
public bool IsError => _error != null;
|
||||
|
||||
public object Error => _error;
|
||||
|
||||
public void Cancel ()
|
||||
{
|
||||
_cts.Cancel ();
|
||||
_cancelled = true;
|
||||
}
|
||||
|
||||
public void ReportProgress (object progress)
|
||||
{
|
||||
foreach (var cb in _progressCallbacks)
|
||||
JsUtils.Call (cb, progress);
|
||||
}
|
||||
|
||||
public object Result => _result;
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Thread: _I_IAsyncAction
|
||||
{
|
||||
private Thread _thread;
|
||||
private bool _completed;
|
||||
private bool _cancelled;
|
||||
private Exception _error;
|
||||
private List<object> _resolveCallbacks = new List<object> ();
|
||||
private List<object> _rejectCallbacks = new List<object> ();
|
||||
private List<object> _progressCallbacks = new List<object> ();
|
||||
private CancellationTokenSource _cts = new CancellationTokenSource ();
|
||||
|
||||
public _I_Thread (Action action)
|
||||
{
|
||||
_thread = new Thread (() => {
|
||||
try
|
||||
{
|
||||
if (_cts.Token.IsCancellationRequested)
|
||||
{
|
||||
_cancelled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
action ();
|
||||
_completed = true;
|
||||
|
||||
foreach (var cb in _resolveCallbacks)
|
||||
JsUtils.Call (cb);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_error = ex;
|
||||
foreach (var cb in _rejectCallbacks)
|
||||
JsUtils.Call (cb, ex);
|
||||
}
|
||||
});
|
||||
_thread.IsBackground = true;
|
||||
_thread.Start ();
|
||||
}
|
||||
|
||||
public _I_IAsyncAction Then (object resolve, object reject = null, object progress = null)
|
||||
{
|
||||
if (resolve != null) _resolveCallbacks.Add (resolve);
|
||||
if (reject != null) _rejectCallbacks.Add (reject);
|
||||
if (progress != null) _progressCallbacks.Add (progress);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Done (object resolve, object reject = null)
|
||||
{
|
||||
if (resolve != null) _resolveCallbacks.Add (resolve);
|
||||
if (reject != null) _rejectCallbacks.Add (reject);
|
||||
}
|
||||
|
||||
public void Catch (object reject)
|
||||
{
|
||||
if (reject != null) _rejectCallbacks.Add (reject);
|
||||
}
|
||||
|
||||
public bool IsCompleted => _completed;
|
||||
public bool IsCancelled => _cancelled;
|
||||
public bool IsError => _error != null;
|
||||
public object Error => _error;
|
||||
|
||||
public void Cancel ()
|
||||
{
|
||||
_cts.Cancel ();
|
||||
_cancelled = true;
|
||||
}
|
||||
|
||||
public void ReportProgress (object progress)
|
||||
{
|
||||
foreach (var cb in _progressCallbacks)
|
||||
JsUtils.Call (cb, progress);
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Exception: Exception, IDisposable
|
||||
{
|
||||
private Exception bex = null;
|
||||
public _I_Exception (Exception ex) { bex = ex; }
|
||||
public _I_Exception (string message) { bex = new Exception (message); }
|
||||
public _I_Exception (string msg, Exception innerEx) { bex = new Exception (msg, innerEx); }
|
||||
public override IDictionary Data => bex.Data;
|
||||
public override Exception GetBaseException () => bex.GetBaseException ();
|
||||
public override void GetObjectData (SerializationInfo info, StreamingContext context) => bex.GetObjectData (info, context);
|
||||
public override string HelpLink
|
||||
{
|
||||
get { return bex.HelpLink; }
|
||||
set { bex.HelpLink = value; }
|
||||
}
|
||||
public override string Message => bex.Message;
|
||||
public override string Source
|
||||
{
|
||||
get { return bex.Source; }
|
||||
set { bex.Source = value; }
|
||||
}
|
||||
public override string StackTrace => bex.StackTrace;
|
||||
public override string ToString () => bex.ToString ();
|
||||
public override int GetHashCode () => bex.GetHashCode ();
|
||||
public override bool Equals (object obj) => bex.Equals (obj);
|
||||
public void Dispose () { bex = null; }
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_KeyValuePair: IDisposable
|
||||
{
|
||||
object key = null;
|
||||
object value = null;
|
||||
public _I_KeyValuePair (object k, object v)
|
||||
{
|
||||
key = k;
|
||||
value = v;
|
||||
}
|
||||
public object Key { get { return key; } set { key = value; } }
|
||||
public object Value { get { return value; } set { this.value = value; } }
|
||||
public void Dispose ()
|
||||
{
|
||||
key = null;
|
||||
value = null;
|
||||
}
|
||||
~_I_KeyValuePair ()
|
||||
{
|
||||
key = null;
|
||||
value = null;
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_WwwFormUrlDecoder
|
||||
{
|
||||
private readonly Dictionary<string, string> _params = new Dictionary<string, string> ();
|
||||
public _I_WwwFormUrlDecoder (string query)
|
||||
{
|
||||
if (string.IsNullOrEmpty (query)) return;
|
||||
if (query.StartsWith ("?")) query = query.Substring (1);
|
||||
foreach (var pair in query.Split ('&'))
|
||||
{
|
||||
var kv = pair.Split ('=');
|
||||
if (kv.Length == 2)
|
||||
_params [Uri.UnescapeDataString (kv [0])] = Uri.UnescapeDataString (kv [1]);
|
||||
}
|
||||
}
|
||||
public string GetFirstValueByName (string name)
|
||||
{
|
||||
string value = null;
|
||||
return _params.TryGetValue (name, out value) ? value : null;
|
||||
}
|
||||
public int Size => _params.Count;
|
||||
public _I_KeyValuePair GetAt (uint index)
|
||||
{
|
||||
var pair = _params.ElementAt ((int)index);
|
||||
return new _I_KeyValuePair (pair.Key, pair.Value);
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Uri: Uri
|
||||
{
|
||||
public _I_Uri (string uri): base (uri) { }
|
||||
public _I_Uri (string baseUri, string relativeUri) : base (new Uri (baseUri), relativeUri) { }
|
||||
public string AbsoluteCanonicalUri => this.GetLeftPart (UriPartial.Authority) + this.PathAndQuery + this.Fragment;
|
||||
public string DisplayIri => Uri.UnescapeDataString (this.OriginalString);
|
||||
public string DisplayUri => Uri.UnescapeDataString (this.OriginalString);
|
||||
public string Domain => ExtractDomain (this.Host);
|
||||
public string Extension => System.IO.Path.GetExtension (this.AbsolutePath)?.TrimStart ('.') ?? "";
|
||||
public string Password => ExtractPassword (this.UserInfo);
|
||||
public string Path => this.AbsolutePath;
|
||||
public object QueryParsed => new _I_WwwFormUrlDecoder (this.Query);
|
||||
public string RawUri => this.OriginalString;
|
||||
public string SchemeName => this.Scheme;
|
||||
public bool Suspicious => !Uri.IsWellFormedUriString (this.OriginalString, UriKind.Absolute);
|
||||
public string UserName => ExtractUserName (this.UserInfo);
|
||||
public _I_Uri CombineUri (string relativeUri)
|
||||
{
|
||||
return new _I_Uri (this.AbsoluteUri, relativeUri);
|
||||
}
|
||||
public static string EscapeComponent (string component)
|
||||
{
|
||||
return Uri.EscapeDataString (component);
|
||||
}
|
||||
public static string UnescapeComponent (string component)
|
||||
{
|
||||
return Uri.UnescapeDataString (component);
|
||||
}
|
||||
private static string ExtractDomain (string host)
|
||||
{
|
||||
var parts = host.Split ('.');
|
||||
if (parts.Length >= 2)
|
||||
return string.Join (".", parts.Skip (1));
|
||||
return host;
|
||||
}
|
||||
private static string ExtractUserName (string userInfo)
|
||||
{
|
||||
if (string.IsNullOrEmpty (userInfo)) return "";
|
||||
var parts = userInfo.Split (':');
|
||||
return parts [0];
|
||||
}
|
||||
private static string ExtractPassword (string userInfo)
|
||||
{
|
||||
if (string.IsNullOrEmpty (userInfo)) return "";
|
||||
var parts = userInfo.Split (':');
|
||||
return parts.Length > 1 ? parts [1] : "";
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Utilities
|
||||
{
|
||||
public _I_Uri CreateUri (string uri) => new _I_Uri (uri);
|
||||
public _I_Uri CreateUri2 (string baseUri, string relaUri) => new _I_Uri (baseUri, relaUri);
|
||||
public _I_Exception CreateException (string message) => new _I_Exception (message);
|
||||
public _I_Exception CreateException2 (string message, _I_Exception innerEx) => new _I_Exception (message, innerEx);
|
||||
public _I_Calendar CreateCalendar () => new _I_Calendar ();
|
||||
public _I_Calendar CreateCalendar2 (object list) => new _I_Calendar (list);
|
||||
public _I_Calendar CreateCalendar3 (object list, string arg1, string arg2) => new _I_Calendar (list, arg1, arg2);
|
||||
public _I_Calendar CreateCalendar4 (object list, string arg1, string arg2, string arg3) => new _I_Calendar (list, arg1, arg2, arg3);
|
||||
public _I_DateTimeFormatter CreateDateTimeFormatterFromTemplate (string formatTemplate)
|
||||
{
|
||||
return new _I_DateTimeFormatter (formatTemplate);
|
||||
}
|
||||
public _I_DateTimeFormatter CreateDateTimeFormatterFromTemplateAndLanguages (string formatTemplate, object languagesArray)
|
||||
{
|
||||
List<string> languages = JsArrayToStringList (languagesArray);
|
||||
return new _I_DateTimeFormatter (formatTemplate, languages);
|
||||
}
|
||||
public _I_DateTimeFormatter CreateDateTimeFormatterFromTemplateFull (string formatTemplate, object languagesArray,
|
||||
string geographicRegion, string calendar, string clock)
|
||||
{
|
||||
List<string> languages = JsArrayToStringList (languagesArray);
|
||||
return new _I_DateTimeFormatter (formatTemplate, languages, geographicRegion, calendar, clock);
|
||||
}
|
||||
public _I_DateTimeFormatter CreateDateTimeFormatterFromDateEnums (int year, int month, int day, int dayOfWeek)
|
||||
{
|
||||
return new _I_DateTimeFormatter (
|
||||
(YearFormat)year,
|
||||
(MonthFormat)month,
|
||||
(DayFormat)day,
|
||||
(DayOfWeekFormat)dayOfWeek
|
||||
);
|
||||
}
|
||||
public _I_DateTimeFormatter CreateDateTimeFormatterFromTimeEnums (int hour, int minute, int second)
|
||||
{
|
||||
return new _I_DateTimeFormatter (
|
||||
(HourFormat)hour,
|
||||
(MinuteFormat)minute,
|
||||
(SecondFormat)second
|
||||
);
|
||||
}
|
||||
public _I_DateTimeFormatter CreateDateTimeFormatterFromDateTimeEnums (int year, int month, int day, int dayOfWeek,
|
||||
int hour, int minute, int second, object languagesArray)
|
||||
{
|
||||
List<string> languages = JsArrayToStringList (languagesArray);
|
||||
return new _I_DateTimeFormatter (
|
||||
(YearFormat)year,
|
||||
(MonthFormat)month,
|
||||
(DayFormat)day,
|
||||
(DayOfWeekFormat)dayOfWeek,
|
||||
(HourFormat)hour,
|
||||
(MinuteFormat)minute,
|
||||
(SecondFormat)second,
|
||||
languages
|
||||
);
|
||||
}
|
||||
public _I_DateTimeFormatter CreateDateTimeFormatterFromDateTimeEnumsFull (int year, int month, int day, int dayOfWeek,
|
||||
int hour, int minute, int second, object languagesArray,
|
||||
string geographicRegion, string calendar, string clock)
|
||||
{
|
||||
List<string> languages = JsArrayToStringList (languagesArray);
|
||||
return new _I_DateTimeFormatter (
|
||||
(YearFormat)year,
|
||||
(MonthFormat)month,
|
||||
(DayFormat)day,
|
||||
(DayOfWeekFormat)dayOfWeek,
|
||||
(HourFormat)hour,
|
||||
(MinuteFormat)minute,
|
||||
(SecondFormat)second,
|
||||
languages,
|
||||
geographicRegion,
|
||||
calendar,
|
||||
clock
|
||||
);
|
||||
}
|
||||
private List<string> JsArrayToStringList (object jsArray)
|
||||
{
|
||||
var result = new List<string> ();
|
||||
if (jsArray == null) return result;
|
||||
|
||||
Type type = jsArray.GetType ();
|
||||
try
|
||||
{
|
||||
int length = (int)type.InvokeMember ("length", BindingFlags.GetProperty, null, jsArray, null);
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
object value = type.InvokeMember (i.ToString (), BindingFlags.GetProperty, null, jsArray, null);
|
||||
if (value != null)
|
||||
result.Add (value.ToString ());
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 如果无法获取 length,则假设是单个字符串
|
||||
string single = jsArray.ToString ();
|
||||
if (!string.IsNullOrEmpty (single))
|
||||
result.Add (single);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
379
DataUtils/Version.cs
Normal file
379
DataUtils/Version.cs
Normal file
@@ -0,0 +1,379 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace DataUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Compact version type that encodes 4 x 16-bit parts into a 64-bit value:
|
||||
/// bits 48..63 = major, 32..47 = minor, 16..31 = build, 0..15 = revision.
|
||||
/// </summary>
|
||||
[ComVisible (true)]
|
||||
public class Version: IComparable<Version>, IEquatable<Version>, Utilities.IJsonBuild
|
||||
{
|
||||
// Backing fields
|
||||
private ushort major;
|
||||
private ushort minor;
|
||||
private ushort build;
|
||||
private ushort revision;
|
||||
public ushort Major
|
||||
{
|
||||
get { return major; }
|
||||
set { major = value; }
|
||||
}
|
||||
public ushort Minor
|
||||
{
|
||||
get { return minor; }
|
||||
set { minor = value; }
|
||||
}
|
||||
public ushort Build
|
||||
{
|
||||
get { return build; }
|
||||
set { build = value; }
|
||||
}
|
||||
public ushort Revision
|
||||
{
|
||||
get { return revision; }
|
||||
set { revision = value; }
|
||||
}
|
||||
public Version ()
|
||||
{
|
||||
major = minor = build = revision = 0;
|
||||
}
|
||||
public Version (ushort major, ushort minor, ushort build, ushort revision)
|
||||
{
|
||||
this.major = major;
|
||||
this.minor = minor;
|
||||
this.build = build;
|
||||
this.revision = revision;
|
||||
}
|
||||
public Version (ushort major, ushort minor, ushort build) : this (major, minor, build, 0) { }
|
||||
public Version (ushort major, ushort minor) : this (major, minor, 0, 0) { }
|
||||
public Version (ushort major) : this (major, 0, 0, 0) { }
|
||||
public Version (ulong packed)
|
||||
{
|
||||
FromUInt64 (packed);
|
||||
}
|
||||
public Version (string versionString)
|
||||
{
|
||||
ParseInto (versionString);
|
||||
}
|
||||
public Version (Version other)
|
||||
{
|
||||
if (other == null) throw new ArgumentNullException ("other");
|
||||
major = other.major;
|
||||
minor = other.minor;
|
||||
build = other.build;
|
||||
revision = other.revision;
|
||||
}
|
||||
public ulong ToUInt64 ()
|
||||
{
|
||||
// cast to ulong before shifting
|
||||
return (((ulong)major) << 48) | (((ulong)minor) << 32) | (((ulong)build) << 16) | ((ulong)revision);
|
||||
}
|
||||
public Version FromUInt64 (ulong value)
|
||||
{
|
||||
major = (ushort)((value >> 48) & 0xFFFFUL);
|
||||
minor = (ushort)((value >> 32) & 0xFFFFUL);
|
||||
build = (ushort)((value >> 16) & 0xFFFFUL);
|
||||
revision = (ushort)(value & 0xFFFFUL);
|
||||
return this;
|
||||
}
|
||||
public ulong Data { get { return ToUInt64 (); } set { FromUInt64 (value); } }
|
||||
public override string ToString ()
|
||||
{
|
||||
// use string.Format to be compatible with older compilers
|
||||
return string.Format (CultureInfo.InvariantCulture, "{0}.{1}.{2}.{3}", major, minor, build, revision);
|
||||
}
|
||||
public string ToShortString ()
|
||||
{
|
||||
// omit trailing zeros if desired: e.g. "1.2" or "1.2.3"
|
||||
if (revision != 0)
|
||||
return ToString ();
|
||||
if (build != 0)
|
||||
return string.Format (CultureInfo.InvariantCulture, "{0}.{1}.{2}", major, minor, build);
|
||||
if (minor != 0)
|
||||
return string.Format (CultureInfo.InvariantCulture, "{0}.{1}", major, minor);
|
||||
return string.Format (CultureInfo.InvariantCulture, "{0}", major);
|
||||
}
|
||||
private void ParseInto (string s)
|
||||
{
|
||||
if (string.IsNullOrEmpty (s))
|
||||
{
|
||||
major = minor = build = revision = 0;
|
||||
return;
|
||||
}
|
||||
char [] separators = new char [] { '.', ',' };
|
||||
string [] parts = s.Split (separators, StringSplitOptions.RemoveEmptyEntries);
|
||||
ushort [] values = new ushort [4];
|
||||
for (int i = 0; i < values.Length && i < parts.Length; i++)
|
||||
{
|
||||
ushort v = 0;
|
||||
try
|
||||
{
|
||||
int parsed = int.Parse (parts [i].Trim (), NumberStyles.Integer, CultureInfo.InvariantCulture);
|
||||
if (parsed < 0) parsed = 0;
|
||||
if (parsed > 0xFFFF) parsed = 0xFFFF;
|
||||
v = (ushort)parsed;
|
||||
}
|
||||
catch
|
||||
{
|
||||
v = 0;
|
||||
}
|
||||
values [i] = v;
|
||||
}
|
||||
major = values [0];
|
||||
minor = values [1];
|
||||
build = values [2];
|
||||
revision = values [3];
|
||||
}
|
||||
public string Expression { get { return this.ToString (); } set { this.ParseInto (value); } }
|
||||
public static Version Parse (string s)
|
||||
{
|
||||
if (s == null) throw new ArgumentNullException ("s");
|
||||
return new Version (s);
|
||||
}
|
||||
public static bool TryParse (string s, out Version result)
|
||||
{
|
||||
result = null;
|
||||
if (s == null) return false;
|
||||
try
|
||||
{
|
||||
result = new Version (s);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public bool IsEmpty
|
||||
{
|
||||
get { return (major == 0 && minor == 0 && build == 0 && revision == 0); }
|
||||
}
|
||||
public bool Equals (Version other)
|
||||
{
|
||||
if (object.ReferenceEquals (other, null)) return false;
|
||||
return (this.major == other.major
|
||||
&& this.minor == other.minor
|
||||
&& this.build == other.build
|
||||
&& this.revision == other.revision);
|
||||
}
|
||||
public bool Equals (ulong ver) { return this == new Version (ver); }
|
||||
public override bool Equals (object obj)
|
||||
{
|
||||
Version v = obj as Version;
|
||||
return Equals (v);
|
||||
}
|
||||
public override int GetHashCode ()
|
||||
{
|
||||
// derive from packed ulong but return int
|
||||
ulong packed = ToUInt64 ();
|
||||
// combine high and low 32 bits for a reasonable hash
|
||||
return ((int)(packed & 0xFFFFFFFF)) ^ ((int)((packed >> 32) & 0xFFFFFFFF));
|
||||
}
|
||||
public int CompareTo (Version other)
|
||||
{
|
||||
if (object.ReferenceEquals (other, null)) return 1;
|
||||
// Compare by packed value (same semantics as C++ compare())
|
||||
ulong a = this.ToUInt64 ();
|
||||
ulong b = other.ToUInt64 ();
|
||||
if (a < b) return -1;
|
||||
if (a > b) return 1;
|
||||
return 0;
|
||||
}
|
||||
public int CompareTo (ulong another) { return this.CompareTo (new Version (another)); }
|
||||
public long Compare (Version other)
|
||||
{
|
||||
if (other == null) throw new ArgumentNullException ("other");
|
||||
// return signed difference of packed values using long
|
||||
long diff = (long)this.ToUInt64 () - (long)other.ToUInt64 ();
|
||||
return diff;
|
||||
}
|
||||
public long Compare (ulong another) { return this.Compare (new Version (another)); }
|
||||
public static bool operator == (Version a, Version b)
|
||||
{
|
||||
if (object.ReferenceEquals (a, b)) return true;
|
||||
if (object.ReferenceEquals (a, null) || object.ReferenceEquals (b, null)) return false;
|
||||
return a.Equals (b);
|
||||
}
|
||||
public static bool operator != (Version a, Version b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
public static bool operator < (Version a, Version b)
|
||||
{
|
||||
if (object.ReferenceEquals (a, null))
|
||||
return !object.ReferenceEquals (b, null); // null < non-null
|
||||
return a.CompareTo (b) < 0;
|
||||
}
|
||||
public static bool operator > (Version a, Version b)
|
||||
{
|
||||
if (object.ReferenceEquals (a, null))
|
||||
return false;
|
||||
return a.CompareTo (b) > 0;
|
||||
}
|
||||
public static bool operator <= (Version a, Version b)
|
||||
{
|
||||
if (object.ReferenceEquals (a, b)) return true;
|
||||
if (object.ReferenceEquals (a, null)) return true; // null <= anything
|
||||
return a.CompareTo (b) <= 0;
|
||||
}
|
||||
public static bool operator >= (Version a, Version b)
|
||||
{
|
||||
if (object.ReferenceEquals (a, b)) return true;
|
||||
if (object.ReferenceEquals (a, null)) return false;
|
||||
return a.CompareTo (b) >= 0;
|
||||
}
|
||||
public static explicit operator ulong (Version v)
|
||||
{
|
||||
if (v == null) return 0UL;
|
||||
return v.ToUInt64 ();
|
||||
}
|
||||
public static explicit operator Version (ulong value)
|
||||
{
|
||||
return new Version (value);
|
||||
}
|
||||
public static Version Decode (ulong packed)
|
||||
{
|
||||
return new Version (packed);
|
||||
}
|
||||
public static ulong Encode (Version v)
|
||||
{
|
||||
if (v == null) return 0UL;
|
||||
return v.ToUInt64 ();
|
||||
}
|
||||
public object BuildJSON ()
|
||||
{
|
||||
return new
|
||||
{
|
||||
major = Major,
|
||||
minor = Minor,
|
||||
build = Build,
|
||||
revision = Revision
|
||||
};
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Version
|
||||
{
|
||||
private Version inner;
|
||||
public _I_Version ()
|
||||
{
|
||||
inner = new Version ();
|
||||
}
|
||||
public _I_Version (ushort p_ma, ushort p_mi, ushort p_b, ushort p_r)
|
||||
{
|
||||
inner = new Version (p_ma, p_mi, p_b, p_r);
|
||||
}
|
||||
public _I_Version (ushort p_ma, ushort p_mi, ushort p_b) : this (p_ma, p_mi, p_b, 0) { }
|
||||
public _I_Version (ushort p_ma, ushort p_mi) : this (p_ma, p_mi, 0, 0) { }
|
||||
public _I_Version (ushort p_ma) : this (p_ma, 0, 0, 0) { }
|
||||
public ushort Major
|
||||
{
|
||||
get { return inner.Major; }
|
||||
set { inner.Major = value; }
|
||||
}
|
||||
public ushort Minor
|
||||
{
|
||||
get { return inner.Minor; }
|
||||
set { inner.Minor = value; }
|
||||
}
|
||||
public ushort Build
|
||||
{
|
||||
get { return inner.Build; }
|
||||
set { inner.Build = value; }
|
||||
}
|
||||
public ushort Revision
|
||||
{
|
||||
get { return inner.Revision; }
|
||||
set { inner.Revision = value; }
|
||||
}
|
||||
public ushort [] Data
|
||||
{
|
||||
get
|
||||
{
|
||||
return new ushort [] { inner.Major, inner.Minor, inner.Build, inner.Revision };
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
inner.Major = inner.Minor = inner.Build = inner.Revision = 0;
|
||||
return;
|
||||
}
|
||||
if (value.Length > 0) inner.Major = value [0];
|
||||
else inner.Major = 0;
|
||||
if (value.Length > 1) inner.Minor = value [1];
|
||||
else inner.Minor = 0;
|
||||
if (value.Length > 2) inner.Build = value [2];
|
||||
else inner.Build = 0;
|
||||
if (value.Length > 3) inner.Revision = value [3];
|
||||
else inner.Revision = 0;
|
||||
}
|
||||
}
|
||||
public string DataStr
|
||||
{
|
||||
get { return Stringify (); }
|
||||
set { Parse (value); }
|
||||
}
|
||||
public _I_Version Parse (string ver)
|
||||
{
|
||||
if (string.IsNullOrEmpty (ver))
|
||||
{
|
||||
inner = new Version ();
|
||||
return this;
|
||||
}
|
||||
char [] separators = new char [] { '.', ',' };
|
||||
string [] parts = ver.Split (separators, StringSplitOptions.RemoveEmptyEntries);
|
||||
ushort [] vals = new ushort [4];
|
||||
for (int i = 0; i < vals.Length && i < parts.Length; i++)
|
||||
{
|
||||
ushort v = 0;
|
||||
try
|
||||
{
|
||||
int parsed = int.Parse (parts [i].Trim (), NumberStyles.Integer, CultureInfo.InvariantCulture);
|
||||
if (parsed < 0) parsed = 0;
|
||||
if (parsed > 0xFFFF) parsed = 0xFFFF;
|
||||
v = (ushort)parsed;
|
||||
}
|
||||
catch
|
||||
{
|
||||
v = 0;
|
||||
}
|
||||
vals [i] = v;
|
||||
}
|
||||
inner.Major = vals [0];
|
||||
inner.Minor = vals [1];
|
||||
inner.Build = vals [2];
|
||||
inner.Revision = vals [3];
|
||||
return this;
|
||||
}
|
||||
public string Stringify ()
|
||||
{
|
||||
return inner.ToString ();
|
||||
}
|
||||
public override string ToString ()
|
||||
{
|
||||
return Stringify ();
|
||||
}
|
||||
public bool Valid ()
|
||||
{
|
||||
return inner.Major != 0 && inner.Minor != 0 && inner.Build != 0 && inner.Revision != 0;
|
||||
}
|
||||
public ulong ToPackedUInt64 ()
|
||||
{
|
||||
return inner.ToUInt64 ();
|
||||
}
|
||||
public void FromPackedUInt64 (ulong packed)
|
||||
{
|
||||
inner.FromUInt64 (packed);
|
||||
}
|
||||
public Version InnerVersion
|
||||
{
|
||||
get { return inner; }
|
||||
set { inner = (value != null) ? new Version (value) : new Version (); }
|
||||
}
|
||||
}
|
||||
}
|
||||
280
DataUtils/VisualElements.cs
Normal file
280
DataUtils/VisualElements.cs
Normal file
@@ -0,0 +1,280 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Xml;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
public enum ManifestTextColor
|
||||
{
|
||||
Dark = 0x000000,
|
||||
Light = 0xFFFFFF
|
||||
}
|
||||
[ComVisible (true)]
|
||||
public class VisualElementManifest: IDisposable
|
||||
{
|
||||
private XmlDocument _doc;
|
||||
private bool _available;
|
||||
|
||||
public VisualElementManifest ()
|
||||
{
|
||||
_available = false;
|
||||
}
|
||||
|
||||
public VisualElementManifest (string filename)
|
||||
{
|
||||
Create (filename);
|
||||
}
|
||||
|
||||
public VisualElementManifest (Stream stream)
|
||||
{
|
||||
Create (stream);
|
||||
}
|
||||
|
||||
public bool Create (string filename)
|
||||
{
|
||||
Destroy ();
|
||||
if (string.IsNullOrEmpty (filename) || !File.Exists (filename))
|
||||
{
|
||||
_available = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_doc = new XmlDocument ();
|
||||
// Load using UTF-8/UTF-16 auto-detection
|
||||
_doc.Load (filename);
|
||||
_available = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_available = false;
|
||||
}
|
||||
return _available;
|
||||
}
|
||||
|
||||
public bool Create (Stream stream)
|
||||
{
|
||||
Destroy ();
|
||||
if (stream == null) { _available = false; return false; }
|
||||
try
|
||||
{
|
||||
_doc = new XmlDocument ();
|
||||
_doc.Load (stream);
|
||||
_available = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_available = false;
|
||||
}
|
||||
return _available;
|
||||
}
|
||||
|
||||
public void Destroy ()
|
||||
{
|
||||
if (!_available) return;
|
||||
_doc = null;
|
||||
_available = false;
|
||||
}
|
||||
|
||||
public bool Valid { get { return _available; } }
|
||||
|
||||
// Helper: find VisualElements node for an app id (if root is <Applications> iterate <Application> children)
|
||||
private XmlNode VisualElementNode (string id)
|
||||
{
|
||||
if (!_available || _doc == null) return null;
|
||||
XmlElement root = _doc.DocumentElement;
|
||||
if (root == null) return null;
|
||||
|
||||
string rootName = root.Name;
|
||||
if (string.Equals (rootName, "Applications", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
foreach (XmlNode app in root.SelectNodes ("Application"))
|
||||
{
|
||||
var attr = app.Attributes? ["Id"];
|
||||
if (attr != null && string.Equals (attr.Value, id, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return app.SelectSingleNode ("VisualElements");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (string.Equals (rootName, "Application", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return root.SelectSingleNode ("VisualElements");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Utility to get attribute string safely
|
||||
private static string Attr (XmlNode node, string attrName)
|
||||
{
|
||||
if (node == null || node.Attributes == null) return string.Empty;
|
||||
var a = node.Attributes [attrName];
|
||||
return a != null ? a.Value : string.Empty;
|
||||
}
|
||||
|
||||
public string DisplayName (string id = "App")
|
||||
{
|
||||
var visual = VisualElementNode (id);
|
||||
return visual != null ? Attr (visual, "DisplayName") : string.Empty;
|
||||
}
|
||||
|
||||
public string Logo (string id = "App")
|
||||
{
|
||||
var visual = VisualElementNode (id);
|
||||
if (visual == null) return string.Empty;
|
||||
string logo = Attr (visual, "Logo");
|
||||
if (!string.IsNullOrEmpty (logo)) return logo;
|
||||
return Attr (visual, "Square150x150Logo") ?? string.Empty;
|
||||
}
|
||||
|
||||
public string SmallLogo (string id = "App")
|
||||
{
|
||||
var visual = VisualElementNode (id);
|
||||
if (visual == null) return string.Empty;
|
||||
string small = Attr (visual, "SmallLogo");
|
||||
if (!string.IsNullOrEmpty (small)) return small;
|
||||
return Attr (visual, "Square70x70Logo") ?? string.Empty;
|
||||
}
|
||||
|
||||
public ManifestTextColor ForegroundText (string id = "App")
|
||||
{
|
||||
var visual = VisualElementNode (id);
|
||||
if (visual == null) return ManifestTextColor.Dark;
|
||||
string fg = Attr (visual, "ForegroundText");
|
||||
return string.Equals (fg, "light", StringComparison.OrdinalIgnoreCase) ? ManifestTextColor.Light : ManifestTextColor.Dark;
|
||||
}
|
||||
|
||||
public string Lnk32x32Logo (string id = "App")
|
||||
{
|
||||
var visual = VisualElementNode (id);
|
||||
return visual != null ? Attr (visual, "Lnk32x32Logo") : string.Empty;
|
||||
}
|
||||
|
||||
public string ItemDisplayLogo (string id = "App")
|
||||
{
|
||||
var visual = VisualElementNode (id);
|
||||
if (visual == null) return string.Empty;
|
||||
string item = Attr (visual, "ItemDisplayLogo");
|
||||
if (!string.IsNullOrEmpty (item)) return item;
|
||||
item = Attr (visual, "Lnk32x32Logo");
|
||||
if (!string.IsNullOrEmpty (item)) return item;
|
||||
return Attr (visual, "Square44x44Logo") ?? string.Empty;
|
||||
}
|
||||
|
||||
public bool ShowNameOnTile (string id = "App")
|
||||
{
|
||||
var visual = VisualElementNode (id);
|
||||
if (visual == null) return false;
|
||||
string val = Attr (visual, "ShowNameOnSquare150x150Logo");
|
||||
return string.Equals (val, "on", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public string BackgroundColor (string id = "App")
|
||||
{
|
||||
var visual = VisualElementNode (id);
|
||||
return visual != null ? Attr (visual, "BackgroundColor") : string.Empty;
|
||||
}
|
||||
|
||||
public string SplashScreenImage (string id = "App")
|
||||
{
|
||||
var visual = VisualElementNode (id);
|
||||
if (visual == null) return string.Empty;
|
||||
var splash = visual.SelectSingleNode ("SplashScreen");
|
||||
return splash != null ? Attr (splash, "Image") : string.Empty;
|
||||
}
|
||||
|
||||
public string SplashScreenBackgroundColor (string id = "App")
|
||||
{
|
||||
var visual = VisualElementNode (id);
|
||||
if (visual == null) return string.Empty;
|
||||
var splash = visual.SelectSingleNode ("SplashScreen");
|
||||
string bg = splash != null ? Attr (splash, "BackgroundColor") : string.Empty;
|
||||
if (!string.IsNullOrEmpty (bg)) return bg;
|
||||
return Attr (visual, "BackgroundColor") ?? string.Empty;
|
||||
}
|
||||
|
||||
public string SplashScreenBackgroundColorDarkMode (string id = "App")
|
||||
{
|
||||
var visual = VisualElementNode (id);
|
||||
if (visual == null) return string.Empty;
|
||||
var splash = visual.SelectSingleNode ("SplashScreen");
|
||||
string bg = splash != null ? Attr (splash, "DarkModeBackgroundColor") : string.Empty;
|
||||
if (!string.IsNullOrEmpty (bg)) return bg;
|
||||
return Attr (visual, "DarkModeBackgroundColor") ?? string.Empty;
|
||||
}
|
||||
|
||||
// Check if an app id exists in document
|
||||
public bool IsAppIdExists (string id)
|
||||
{
|
||||
if (!_available || _doc == null) return false;
|
||||
XmlElement root = _doc.DocumentElement;
|
||||
if (root == null) return false;
|
||||
if (string.Equals (root.Name, "Applications", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
foreach (XmlNode app in root.SelectNodes ("Application"))
|
||||
{
|
||||
var attr = app.Attributes? ["Id"];
|
||||
if (attr != null && string.Equals (attr.Value, id, StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (string.Equals (root.Name, "Application", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var attr = root.Attributes? ["Id"];
|
||||
if (attr != null && string.Equals (attr.Value, id, StringComparison.OrdinalIgnoreCase)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get all application ids as a list
|
||||
public List<string> AppIds ()
|
||||
{
|
||||
var output = new List<string> ();
|
||||
if (!_available || _doc == null)
|
||||
{
|
||||
output.Add ("App");
|
||||
return output;
|
||||
}
|
||||
|
||||
XmlElement root = _doc.DocumentElement;
|
||||
if (root == null)
|
||||
{
|
||||
output.Add ("App");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (string.Equals (root.Name, "Applications", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
foreach (XmlNode app in root.SelectNodes ("Application"))
|
||||
{
|
||||
var attr = app.Attributes? ["Id"];
|
||||
if (attr != null && !string.IsNullOrEmpty (attr.Value))
|
||||
{
|
||||
if (!output.Contains (attr.Value)) output.Add (attr.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (string.Equals (root.Name, "Application", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var attr = root.Attributes? ["Id"];
|
||||
if (attr != null && !string.IsNullOrEmpty (attr.Value))
|
||||
{
|
||||
if (!output.Contains (attr.Value)) output.Add (attr.Value);
|
||||
}
|
||||
}
|
||||
|
||||
if (output.Count == 0) output.Add ("App");
|
||||
return output;
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
{
|
||||
Destroy ();
|
||||
}
|
||||
}
|
||||
}
|
||||
328
DataUtils/Web.cs
Normal file
328
DataUtils/Web.cs
Normal file
@@ -0,0 +1,328 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
[ComVisible (true)]
|
||||
[InterfaceType (ComInterfaceType.InterfaceIsDual)]
|
||||
public interface IHttpResponse: IDisposable
|
||||
{
|
||||
int Status { get; } // 兼容旧版,等同于 StatusCode
|
||||
int StatusCode { get; }
|
||||
string StatusText { get; } // 等同于 StatusDescription
|
||||
string StatusDescription { get; }
|
||||
string ResponseUrl { get; }
|
||||
Uri ResponseUri { get; }
|
||||
string ContentType { get; }
|
||||
long ContentLength { get; } // 注意:JS 中 Number 可表示 2^53 以内整数
|
||||
string CharacterSet { get; }
|
||||
string ContentEncoding { get; }
|
||||
DateTime LastModified { get; }
|
||||
string Method { get; } // 原始请求方法 (GET, POST...)
|
||||
Version ProtocolVersion { get; } // 如 1.1,JS 中可能转为字符串
|
||||
bool IsFromCache { get; }
|
||||
bool IsMutuallyAuthenticated { get; }
|
||||
string Text ();
|
||||
_I_Enumerable Bytes ();
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class HttpResponse: IHttpResponse, IDisposable
|
||||
{
|
||||
private readonly byte [] _data;
|
||||
private readonly Dictionary<string, string> _headersDict;
|
||||
private bool _disposed = false;
|
||||
public int Status => StatusCode;
|
||||
public int StatusCode { get; private set; }
|
||||
public string StatusText => StatusDescription;
|
||||
public string StatusDescription { get; private set; }
|
||||
public string ResponseUrl => ResponseUri?.ToString ();
|
||||
public Uri ResponseUri { get; private set; }
|
||||
public string ContentType { get; private set; }
|
||||
public long ContentLength { get; private set; }
|
||||
public string CharacterSet { get; private set; }
|
||||
public string ContentEncoding { get; private set; }
|
||||
public DateTime LastModified { get; private set; }
|
||||
public string Method { get; private set; }
|
||||
public Version ProtocolVersion { get; private set; }
|
||||
public bool IsFromCache { get; private set; }
|
||||
public bool IsMutuallyAuthenticated { get; private set; }
|
||||
public HttpResponse (HttpWebResponse response)
|
||||
{
|
||||
if (response == null) throw new ArgumentNullException (nameof (response));
|
||||
using (var stream = response.GetResponseStream ())
|
||||
using (var ms = new MemoryStream ())
|
||||
{
|
||||
stream.CopyTo (ms);
|
||||
_data = ms.ToArray ();
|
||||
}
|
||||
StatusCode = (int)response.StatusCode;
|
||||
StatusDescription = response.StatusDescription;
|
||||
ResponseUri = response.ResponseUri;
|
||||
Method = response.Method;
|
||||
ProtocolVersion = new Version ((ushort)response.ProtocolVersion.Major, (ushort)response.ProtocolVersion.Minor, (ushort)response.ProtocolVersion.Build, (ushort)response.ProtocolVersion.Revision);
|
||||
IsFromCache = response.IsFromCache;
|
||||
IsMutuallyAuthenticated = response.IsMutuallyAuthenticated;
|
||||
ContentType = response.ContentType ?? "";
|
||||
ContentLength = response.ContentLength;
|
||||
CharacterSet = response.CharacterSet ?? "";
|
||||
ContentEncoding = response.ContentEncoding ?? "";
|
||||
LastModified = response.LastModified;
|
||||
_headersDict = new Dictionary<string, string> (StringComparer.OrdinalIgnoreCase);
|
||||
foreach (string key in response.Headers.AllKeys)
|
||||
{
|
||||
if (!string.IsNullOrEmpty (key))
|
||||
_headersDict [key] = response.Headers [key];
|
||||
}
|
||||
}
|
||||
public HttpResponse (int statusCode, string statusDescription, string responseUrl, byte [] data, Dictionary<string, string> headers)
|
||||
{
|
||||
StatusCode = statusCode;
|
||||
StatusDescription = statusDescription ?? "";
|
||||
ResponseUri = string.IsNullOrEmpty (responseUrl) ? null : new Uri (responseUrl);
|
||||
_data = data ?? new byte [0];
|
||||
_headersDict = headers ?? new Dictionary<string, string> ();
|
||||
ContentType = GetHeader ("Content-Type") ?? "";
|
||||
ContentLength = _data.Length;
|
||||
CharacterSet = "";
|
||||
ContentEncoding = "";
|
||||
LastModified = DateTime.MinValue;
|
||||
Method = "";
|
||||
ProtocolVersion = new Version (0, 0);
|
||||
IsFromCache = false;
|
||||
IsMutuallyAuthenticated = false;
|
||||
}
|
||||
public string GetHeader (string sName)
|
||||
{
|
||||
if (string.IsNullOrEmpty (sName)) return null;
|
||||
try
|
||||
{
|
||||
return _headersDict [sName];
|
||||
}
|
||||
catch { return null; }
|
||||
}
|
||||
public string GetHeadersToJson ()
|
||||
{
|
||||
return JsonConvert.SerializeObject (_headersDict);
|
||||
}
|
||||
public string Text ()
|
||||
{
|
||||
string charset = CharacterSet;
|
||||
Encoding enc = Encoding.UTF8;
|
||||
if (!string.IsNullOrEmpty (charset))
|
||||
{
|
||||
try { enc = Encoding.GetEncoding (charset); }
|
||||
catch { /* 保持 UTF-8 */ }
|
||||
}
|
||||
return enc.GetString (_data);
|
||||
}
|
||||
public _I_Enumerable Bytes ()
|
||||
{
|
||||
var list = new List<object> ();
|
||||
foreach (byte b in _data)
|
||||
list.Add (b);
|
||||
return new _I_List (list);
|
||||
}
|
||||
public void Dispose ()
|
||||
{
|
||||
Dispose (true);
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
protected virtual void Dispose (bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class HttpRequest: IDisposable
|
||||
{
|
||||
private string _method;
|
||||
private string _url;
|
||||
private Dictionary<string, string> _headers = new Dictionary<string, string> ();
|
||||
public int Timeout { get; set; } = 100000; // 毫秒,默认 100 秒
|
||||
public int ReadWriteTimeout { get; set; } = 300000; // 读写超时,默认 5 分钟
|
||||
public bool AllowAutoRedirect { get; set; } = true;
|
||||
public bool AllowWriteStreamBuffering { get; set; } = true;
|
||||
public bool KeepAlive { get; set; } = true;
|
||||
public int MaximumAutomaticRedirections { get; set; } = 50;
|
||||
public string UserAgent
|
||||
{
|
||||
get { return GetHeader ("User-Agent"); }
|
||||
set { SetHeader ("User-Agent", value); }
|
||||
}
|
||||
public string Referer
|
||||
{
|
||||
get { return GetHeader ("Referer"); }
|
||||
set { SetHeader ("Referer", value); }
|
||||
}
|
||||
public string ContentType
|
||||
{
|
||||
get { return GetHeader ("Content-Type"); }
|
||||
set { SetHeader ("Content-Type", value); }
|
||||
}
|
||||
public string Accept
|
||||
{
|
||||
get { return GetHeader ("Accept"); }
|
||||
set { SetHeader ("Accept", value); }
|
||||
}
|
||||
public IWebProxy Proxy { get; set; } = null;
|
||||
public CookieContainer CookieContainer { get; set; } = null;
|
||||
private string _httpver = "1.1";
|
||||
public string ProtocolVersion
|
||||
{
|
||||
get { return _httpver; }
|
||||
set { _httpver = value; }
|
||||
}
|
||||
public System.Version ProtVer
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (_httpver)
|
||||
{
|
||||
case "1.0": return HttpVersion.Version10;
|
||||
default:
|
||||
case "1.1": return HttpVersion.Version11;
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool PreAuthenticate { get; set; } = false;
|
||||
public ICredentials Credentials { get; set; } = null;
|
||||
public bool AutomaticDecompression { get; set; } = false;
|
||||
public Action<long, long> UploadProgressCallback { get; set; } = null;
|
||||
public void Open (string sMethod, string sUrl)
|
||||
{
|
||||
_method = sMethod;
|
||||
_url = sUrl;
|
||||
}
|
||||
public void SetHeader (string sName, string sValue) => _headers [sName] = sValue;
|
||||
public string GetHeader (string sName) => _headers [sName];
|
||||
public string GetHeadersToJson () => JsonConvert.SerializeObject (_headers);
|
||||
public void RemoveHeader (string sName) => _headers.Remove (sName);
|
||||
public void ClearHeader () => _headers.Clear ();
|
||||
public IHttpResponse Send (string sBody, string encoding)
|
||||
{
|
||||
var req = (HttpWebRequest)WebRequest.Create (_url);
|
||||
req.Method = _method;
|
||||
req.Timeout = Timeout;
|
||||
req.ReadWriteTimeout = ReadWriteTimeout;
|
||||
req.AllowAutoRedirect = AllowAutoRedirect;
|
||||
req.AllowWriteStreamBuffering = AllowWriteStreamBuffering;
|
||||
req.KeepAlive = KeepAlive;
|
||||
req.MaximumAutomaticRedirections = MaximumAutomaticRedirections;
|
||||
if (Proxy != null) req.Proxy = Proxy;
|
||||
if (CookieContainer != null) req.CookieContainer = CookieContainer;
|
||||
req.ProtocolVersion = ProtVer;
|
||||
req.PreAuthenticate = PreAuthenticate;
|
||||
if (Credentials != null) req.Credentials = Credentials;
|
||||
if (AutomaticDecompression)
|
||||
req.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
|
||||
if (_headers.ContainsKey ("User-Agent"))
|
||||
req.UserAgent = _headers ["User-Agent"];
|
||||
foreach (var h in _headers)
|
||||
{
|
||||
if (string.Equals (h.Key, "User-Agent", StringComparison.OrdinalIgnoreCase))
|
||||
continue;
|
||||
if (string.Equals (h.Key, "Content-Type", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string ct = h.Value;
|
||||
if (!string.IsNullOrEmpty (sBody) && !ct.Contains ("charset"))
|
||||
{
|
||||
Encoding enc = Encoding.GetEncoding (encoding);
|
||||
ct = ct + "; charset=" + enc.WebName;
|
||||
}
|
||||
req.ContentType = ct;
|
||||
}
|
||||
else if (string.Equals (h.Key, "Accept", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
req.Accept = h.Value;
|
||||
}
|
||||
else if (string.Equals (h.Key, "Referer", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
req.Referer = h.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
req.Headers [h.Key] = h.Value;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有显式设置 Content-Type 且是 POST/PUT 且有请求体,设置默认值
|
||||
bool hasContentType = _headers.Keys.Any (k => string.Equals (k, "Content-Type", StringComparison.OrdinalIgnoreCase));
|
||||
if (!hasContentType && (string.Equals (_method, "POST", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals (_method, "PUT", StringComparison.OrdinalIgnoreCase)) &&
|
||||
!string.IsNullOrEmpty (sBody))
|
||||
{
|
||||
Encoding enc = Encoding.GetEncoding (encoding);
|
||||
req.ContentType = "application/x-www-form-urlencoded; charset=" + enc.WebName;
|
||||
}
|
||||
|
||||
// 写入请求体
|
||||
if (!string.IsNullOrEmpty (sBody))
|
||||
{
|
||||
Encoding enc = Encoding.GetEncoding (encoding);
|
||||
byte [] bytes = enc.GetBytes (sBody);
|
||||
req.ContentLength = bytes.Length;
|
||||
using (var stream = req.GetRequestStream ())
|
||||
{
|
||||
if (UploadProgressCallback != null)
|
||||
{
|
||||
int totalWritten = 0;
|
||||
int bufferSize = 8192;
|
||||
for (int offset = 0; offset < bytes.Length; offset += bufferSize)
|
||||
{
|
||||
int chunkSize = Math.Min (bufferSize, bytes.Length - offset);
|
||||
stream.Write (bytes, offset, chunkSize);
|
||||
totalWritten += chunkSize;
|
||||
UploadProgressCallback (totalWritten, bytes.Length);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.Write (bytes, 0, bytes.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
using (var res = (HttpWebResponse)req.GetResponse ())
|
||||
{
|
||||
return new HttpResponse (res);
|
||||
}
|
||||
}
|
||||
public void SendAsync (string sBody, string encoding, object pfResolve, object pfReject)
|
||||
{
|
||||
System.Threading.ThreadPool.QueueUserWorkItem (delegate
|
||||
{
|
||||
try
|
||||
{
|
||||
JsUtils.Call (pfResolve, Send (sBody, encoding));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
JsUtils.Call (pfReject, new _I_Exception (ex));
|
||||
}
|
||||
});
|
||||
}
|
||||
public void Dispose () { }
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Http
|
||||
{
|
||||
public HttpRequest CreateHttpRequest () => new HttpRequest ();
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Web
|
||||
{
|
||||
public _I_Http Http => new _I_Http ();
|
||||
}
|
||||
}
|
||||
57
DataUtils/WebBrowser.cs
Normal file
57
DataUtils/WebBrowser.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
public enum OLECMDID
|
||||
{
|
||||
OLECMDID_OPTICAL_ZOOM = 63
|
||||
}
|
||||
public enum OLECMDEXECOPT
|
||||
{
|
||||
OLECMDEXECOPT_DODEFAULT = 0,
|
||||
OLECMDEXECOPT_DONTPROMPTUSER = 2
|
||||
}
|
||||
[ComImport]
|
||||
[Guid ("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E")]
|
||||
[InterfaceType (ComInterfaceType.InterfaceIsIDispatch)]
|
||||
public interface IWebBrowser2
|
||||
{
|
||||
[DispId (0x000001F4)]
|
||||
void ExecWB (
|
||||
OLECMDID cmdID,
|
||||
OLECMDEXECOPT cmdexecopt,
|
||||
[In, Optional] object pvaIn,
|
||||
[Out, Optional] object pvaOut
|
||||
);
|
||||
}
|
||||
public static class WebBrowserHelper
|
||||
{
|
||||
static Guid CGID_MSHTML = new Guid ("DE4BA900-59CA-11CF-9592-444553540000");
|
||||
public static IWebBrowser2 GetWebBrowser2 (WebBrowser browser)
|
||||
{
|
||||
return browser.ActiveXInstance as IWebBrowser2;
|
||||
}
|
||||
}
|
||||
public interface IWebBrowserPageScale
|
||||
{
|
||||
int PageScale { get; set; }
|
||||
}
|
||||
[ComImport]
|
||||
[Guid ("B722BCCB-4E68-101B-A2BC-00AA00404770")]
|
||||
[InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
|
||||
public interface IOleCommandTarget
|
||||
{
|
||||
[PreserveSig]
|
||||
int Exec (
|
||||
ref Guid pguidCmdGroup,
|
||||
uint nCmdID,
|
||||
uint nCmdexecopt,
|
||||
ref object pvaIn,
|
||||
ref object pvaOut
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
73
DataUtils/Window.cs
Normal file
73
DataUtils/Window.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
public class _I_UI_Size
|
||||
{
|
||||
private int m_width;
|
||||
private int m_height;
|
||||
public _I_UI_Size (int w, int h)
|
||||
{
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
}
|
||||
public int Width => m_width;
|
||||
public int Height => m_height;
|
||||
public int GetWidth () => m_width;
|
||||
public int GetHeight () => m_height;
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_UI
|
||||
{
|
||||
private Form wndInst;
|
||||
public _I_UI (Form wnd)
|
||||
{
|
||||
wndInst = wnd;
|
||||
}
|
||||
public int DPIPercent => UITheme.GetDPI ();
|
||||
public double DPI => DPIPercent * 0.01;
|
||||
public _I_UI_Size WndSize => new _I_UI_Size (wndInst.Width, wndInst.Height);
|
||||
public _I_UI_Size ClientSize
|
||||
{
|
||||
get
|
||||
{
|
||||
var cs = wndInst.ClientSize;
|
||||
return new _I_UI_Size (cs.Width, cs.Height);
|
||||
}
|
||||
}
|
||||
public string ThemeColor => UITheme.ColorToHtml (UITheme.GetDwmThemeColor ());
|
||||
public bool DarkMode => UITheme.IsAppInDarkMode ();
|
||||
public string HighContrast
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (UITheme.GetHighContrastTheme ())
|
||||
{
|
||||
case HighContrastTheme.None: return "none";
|
||||
case HighContrastTheme.Black: return "black";
|
||||
case HighContrastTheme.White: return "white";
|
||||
case HighContrastTheme.Other: return "high";
|
||||
default: return "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class _I_Window
|
||||
{
|
||||
private IScriptBridge iscrp;
|
||||
public _I_Window (IScriptBridge _iscrp)
|
||||
{
|
||||
iscrp = _iscrp;
|
||||
}
|
||||
public object CallEvent (string name, params object [] args)
|
||||
{
|
||||
if (iscrp == null) return null;
|
||||
object arg0 = (args != null && args.Length > 0) ? args [0] : null;
|
||||
return iscrp.CallEvent (name, arg0);
|
||||
}
|
||||
}
|
||||
}
|
||||
4
DataUtils/packages.config
Normal file
4
DataUtils/packages.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="13.0.4" targetFramework="net40" />
|
||||
</packages>
|
||||
5
Directory.Build.props
Normal file
5
Directory.Build.props
Normal file
@@ -0,0 +1,5 @@
|
||||
<Project>
|
||||
<PropertyGroup Condition="'$(MSBuildProjectExtension)'=='.vcxproj'">
|
||||
<ForceImportAfterCppProps>$(MSBuildThisFileDirectory)ArmDesktopSdk.props</ForceImportAfterCppProps>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
Binary file not shown.
38
IEHelper/AssemblyInfo.cpp
Normal file
38
IEHelper/AssemblyInfo.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
using namespace System;
|
||||
using namespace System::Reflection;
|
||||
using namespace System::Runtime::CompilerServices;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
using namespace System::Security::Permissions;
|
||||
|
||||
//
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
//
|
||||
[assembly:AssemblyTitleAttribute(L"IEHelper")];
|
||||
[assembly:AssemblyDescriptionAttribute(L"")];
|
||||
[assembly:AssemblyConfigurationAttribute(L"")];
|
||||
[assembly:AssemblyCompanyAttribute(L"")];
|
||||
[assembly:AssemblyProductAttribute(L"IEHelper")];
|
||||
[assembly:AssemblyCopyrightAttribute(L"Copyright (c) 2026")];
|
||||
[assembly:AssemblyTrademarkAttribute(L"")];
|
||||
[assembly:AssemblyCultureAttribute(L"")];
|
||||
|
||||
//
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
// 您可以指定所有值,也可以使用“修订号”和“生成号”的默认值,
|
||||
// 方法是按如下所示使用“*”: :
|
||||
|
||||
[assembly:AssemblyVersionAttribute("1.0.*")];
|
||||
|
||||
[assembly:ComVisible(false)];
|
||||
|
||||
[assembly:CLSCompliantAttribute(true)];
|
||||
43
IEHelper/IEHelper.cpp
Normal file
43
IEHelper/IEHelper.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// ÕâÊÇÖ÷ DLL Îļþ¡£
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "IEHelper.h"
|
||||
|
||||
using namespace System::Runtime::InteropServices;
|
||||
HRESULT GetWebBrowser2Interface (System::Windows::Forms::WebBrowser ^fwb, IWebBrowser2 **output)
|
||||
{
|
||||
if (fwb == nullptr || output == nullptr) return E_INVALIDARG;
|
||||
*output = nullptr;
|
||||
Object ^activeX = fwb->ActiveXInstance;
|
||||
if (activeX == nullptr) return E_FAIL;
|
||||
IntPtr pUnk = Marshal::GetIUnknownForObject (activeX);
|
||||
if (pUnk == IntPtr::Zero) return E_FAIL;
|
||||
HRESULT hr = ((IUnknown *)pUnk.ToPointer ())->QueryInterface (IID_IWebBrowser2, (void **)output);
|
||||
Marshal::Release (pUnk);
|
||||
return hr;
|
||||
}
|
||||
int IEHelper::WebBrowserHelper::GetPageScale (IEWebView ^webui)
|
||||
{
|
||||
CComPtr <IWebBrowser2> web2;
|
||||
HRESULT hr = GetWebBrowser2Interface (webui, &web2);
|
||||
if (FAILED (hr)) return 0;
|
||||
VARIANT v;
|
||||
VariantInit (&v);
|
||||
hr = web2->ExecWB (OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DODEFAULT, nullptr, &v);
|
||||
if (FAILED (hr) || v.vt != VT_I4) return 0;
|
||||
int val = v.lVal;
|
||||
VariantClear (&v);
|
||||
return val;
|
||||
}
|
||||
void IEHelper::WebBrowserHelper::SetPageScale (IEWebView ^webui, int value)
|
||||
{
|
||||
CComPtr <IWebBrowser2> web2;
|
||||
HRESULT hr = GetWebBrowser2Interface (webui, &web2);
|
||||
if (FAILED (hr)) return;
|
||||
VARIANT v;
|
||||
VariantInit (&v);
|
||||
v.vt = VT_I4;
|
||||
v.lVal = value;
|
||||
web2->ExecWB (OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, &v, nullptr);
|
||||
}
|
||||
14
IEHelper/IEHelper.h
Normal file
14
IEHelper/IEHelper.h
Normal file
@@ -0,0 +1,14 @@
|
||||
// IEHelper.h
|
||||
|
||||
#pragma once
|
||||
|
||||
using namespace System;
|
||||
using IEWebView = System::Windows::Forms::WebBrowser;
|
||||
namespace IEHelper {
|
||||
public ref class WebBrowserHelper
|
||||
{
|
||||
public:
|
||||
static int GetPageScale (IEWebView ^webui);
|
||||
static void SetPageScale (IEWebView ^webui, int zoom);
|
||||
};
|
||||
}
|
||||
164
IEHelper/IEHelper.vcxproj
Normal file
164
IEHelper/IEHelper.vcxproj
Normal file
@@ -0,0 +1,164 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{E4CA78A9-9408-4F5F-ADD6-730FD501FF8E}</ProjectGuid>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<Keyword>ManagedCProj</Keyword>
|
||||
<RootNamespace>IEHelper</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CLRSupport>true</CLRSupport>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies />
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>
|
||||
</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies />
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>
|
||||
</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="IEHelper.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="Stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AssemblyInfo.cpp" />
|
||||
<ClCompile Include="IEHelper.cpp" />
|
||||
<ClCompile Include="Stdafx.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="app.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="app.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
52
IEHelper/IEHelper.vcxproj.filters
Normal file
52
IEHelper/IEHelper.vcxproj.filters
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="IEHelper.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Stdafx.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="IEHelper.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AssemblyInfo.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Stdafx.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="app.rc">
|
||||
<Filter>资源文件</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="app.ico">
|
||||
<Filter>资源文件</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
38
IEHelper/ReadMe.txt
Normal file
38
IEHelper/ReadMe.txt
Normal file
@@ -0,0 +1,38 @@
|
||||
========================================================================
|
||||
DYNAMIC LINK LIBRARY : IEHelper Project Overview
|
||||
========================================================================
|
||||
|
||||
AppWizard has created this IEHelper DLL for you.
|
||||
|
||||
This file contains a summary of what you will find in each of the files that
|
||||
make up your IEHelper application.
|
||||
|
||||
IEHelper.vcxproj
|
||||
This is the main project file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the version of Visual C++ that generated the file, and
|
||||
information about the platforms, configurations, and project features selected with the
|
||||
Application Wizard.
|
||||
|
||||
IEHelper.vcxproj.filters
|
||||
This is the filters file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the association between the files in your project
|
||||
and the filters. This association is used in the IDE to show grouping of files with
|
||||
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
|
||||
"Source Files" filter).
|
||||
|
||||
IEHelper.cpp
|
||||
This is the main DLL source file.
|
||||
|
||||
IEHelper.h
|
||||
This file contains a class declaration.
|
||||
|
||||
AssemblyInfo.cpp
|
||||
Contains custom attributes for modifying assembly metadata.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other notes:
|
||||
|
||||
AppWizard uses "TODO:" to indicate parts of the source code you
|
||||
should add to or customize.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
5
IEHelper/Stdafx.cpp
Normal file
5
IEHelper/Stdafx.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
// stdafx.cpp : 只包括标准包含文件的源文件
|
||||
// IEHelper.pch 将作为预编译头
|
||||
// stdafx.obj 将包含预编译类型信息
|
||||
|
||||
#include "stdafx.h"
|
||||
9
IEHelper/Stdafx.h
Normal file
9
IEHelper/Stdafx.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// stdafx.h : 标准系统包含文件的包含文件,
|
||||
// 或是经常使用但不常更改的
|
||||
// 特定于项目的包含文件
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <atlbase.h>
|
||||
#include <ExDisp.h>
|
||||
BIN
IEHelper/app.ico
Normal file
BIN
IEHelper/app.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
BIN
IEHelper/app.rc
Normal file
BIN
IEHelper/app.rc
Normal file
Binary file not shown.
3
IEHelper/resource.h
Normal file
3
IEHelper/resource.h
Normal file
@@ -0,0 +1,3 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by app.rc
|
||||
202
LICENSE
Normal file
202
LICENSE
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
19
LICENSE.CodeMirror
Normal file
19
LICENSE.CodeMirror
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (C) 2014 by Marijn Haverbeke <marijnh@gmail.com> and others
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
63
LICENSE.Newtonsoft.Json
Normal file
63
LICENSE.Newtonsoft.Json
Normal file
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" href="/Content/Site.css" />
|
||||
<title>'MIT' reference</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="main-content">
|
||||
|
||||
|
||||
|
||||
<h1>MIT License</h1>
|
||||
|
||||
<h2>SPDX identifier</h2>
|
||||
<div id="license-expression">MIT</div>
|
||||
|
||||
<h2>License text</h2>
|
||||
|
||||
<div class="optional-license-text">
|
||||
<p>MIT License</p>
|
||||
|
||||
</div>
|
||||
<div class="replaceable-license-text">
|
||||
<p>Copyright (c) <year> <copyright holders>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<p>Permission is hereby granted, free of charge, to any person obtaining a copy of <var class="replaceable-license-text"> this software and
|
||||
associated documentation files</var> (the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:</p>
|
||||
|
||||
<p>The above copyright notice and this permission notice
|
||||
<var class="optional-license-text"> (including the next paragraph)</var>
|
||||
shall be included in all copies or substantial
|
||||
portions of the Software.</p>
|
||||
|
||||
<p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
NO EVENT SHALL <var class="replaceable-license-text"> THE AUTHORS OR COPYRIGHT HOLDERS</var> BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>SPDX web page</h2>
|
||||
<ul>
|
||||
<li><a href="https://spdx.org/licenses/MIT.html">https://spdx.org/licenses/MIT.html</a></li>
|
||||
</ul>
|
||||
|
||||
<h2>Notice</h2>
|
||||
<p>This license content is provided by the <a href="https://spdx.dev/">SPDX project</a>. For more information about <b>licenses.nuget.org</b>, see <a href="https://aka.ms/licenses.nuget.org">our documentation</a>.
|
||||
|
||||
<p><i>Data pulled from <a href="https://github.com/spdx/license-list-data">spdx/license-list-data</a> on November 6, 2024.</i></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
57
LICENSE.RapidJSON
Normal file
57
LICENSE.RapidJSON
Normal file
@@ -0,0 +1,57 @@
|
||||
Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
|
||||
Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
|
||||
If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License.
|
||||
If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license.
|
||||
A copy of the MIT License is included in this file.
|
||||
|
||||
Other dependencies and licenses:
|
||||
|
||||
Open Source Software Licensed Under the BSD License:
|
||||
--------------------------------------------------------------------
|
||||
|
||||
The msinttypes r29
|
||||
Copyright (c) 2006-2013 Alexander Chemeris
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Open Source Software Licensed Under the JSON License:
|
||||
--------------------------------------------------------------------
|
||||
|
||||
json.org
|
||||
Copyright (c) 2002 JSON.org
|
||||
All Rights Reserved.
|
||||
|
||||
JSON_checker
|
||||
Copyright (c) 2002 JSON.org
|
||||
All Rights Reserved.
|
||||
|
||||
|
||||
Terms of the JSON License:
|
||||
---------------------------------------------------
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
Terms of the MIT License:
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
17
LICENSE.SharpZipLib
Normal file
17
LICENSE.SharpZipLib
Normal file
@@ -0,0 +1,17 @@
|
||||
Copyright © 2000-2018 SharpZipLib Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
13
LICENSE.WinJS
Normal file
13
LICENSE.WinJS
Normal file
@@ -0,0 +1,13 @@
|
||||
WinJS
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
7
LICENSE.markdown.js
Normal file
7
LICENSE.markdown.js
Normal file
@@ -0,0 +1,7 @@
|
||||
Released under the MIT license.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
24
LICENSE.pugixml
Normal file
24
LICENSE.pugixml
Normal file
@@ -0,0 +1,24 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2006-2025 Arseny Kapoulkine
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
108
Launch/Launch.csproj
Normal file
108
Launch/Launch.csproj
Normal file
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{F0288B24-7B84-42A5-9A92-2E16A012E4DE}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Launch</RootNamespace>
|
||||
<AssemblyName>Launch</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<None Include="app.manifest" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AppxPackage\AppxPackage.csproj">
|
||||
<Project>{bd681a4f-eb60-4bb8-90b5-65968fc7da59}</Project>
|
||||
<Name>AppxPackage</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\DataUtils\DataUtils.csproj">
|
||||
<Project>{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}</Project>
|
||||
<Name>DataUtils</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
68
Launch/Program.cs
Normal file
68
Launch/Program.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Launch
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 从 args[startIndex..] 生成安全的命令行字符串
|
||||
/// </summary>
|
||||
private static string BuildCommandLine (string [] args, int startIndex)
|
||||
{
|
||||
if (args.Length <= startIndex) return null;
|
||||
var sb = new StringBuilder ();
|
||||
for (int i = startIndex; i < args.Length; i++)
|
||||
{
|
||||
if (i > startIndex) sb.Append (' ');
|
||||
sb.Append (EscapeArgument (args [i]));
|
||||
}
|
||||
return sb.ToString ();
|
||||
}
|
||||
/// <summary>
|
||||
/// 按 Win32 命令行规则转义单个参数
|
||||
/// </summary>
|
||||
private static string EscapeArgument (string arg)
|
||||
{
|
||||
if (string.IsNullOrEmpty (arg)) return "\"\"";
|
||||
bool needQuotes = false;
|
||||
foreach (char c in arg)
|
||||
{
|
||||
if (char.IsWhiteSpace (c) || c == '"')
|
||||
{
|
||||
needQuotes = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!needQuotes) return arg;
|
||||
var sb = new StringBuilder ();
|
||||
sb.Append ('"');
|
||||
foreach (char c in arg)
|
||||
{
|
||||
if (c == '"') sb.Append ("\\\"");
|
||||
else sb.Append (c);
|
||||
}
|
||||
sb.Append ('"');
|
||||
return sb.ToString ();
|
||||
}
|
||||
/// <summary>
|
||||
/// 应用程序的主入口点。
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main (string [] args)
|
||||
{
|
||||
if (args == null || args.Length == 0)
|
||||
{
|
||||
MessageBox.Show ("Missing AppUserModelId.", "Launch Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return;
|
||||
}
|
||||
string appUserModelId = args [0];
|
||||
string argumentLine = BuildCommandLine (args, 1);
|
||||
AppxPackage.PackageManager.ActiveApp (appUserModelId, argumentLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Launch/Properties/AssemblyInfo.cs
Normal file
36
Launch/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle ("Launch")]
|
||||
[assembly: AssemblyDescription ("")]
|
||||
[assembly: AssemblyConfiguration ("")]
|
||||
[assembly: AssemblyCompany ("")]
|
||||
[assembly: AssemblyProduct ("Launch")]
|
||||
[assembly: AssemblyCopyright ("Copyright © 2026")]
|
||||
[assembly: AssemblyTrademark ("")]
|
||||
[assembly: AssemblyCulture ("")]
|
||||
|
||||
//将 ComVisible 设置为 false 将使此程序集中的类型
|
||||
//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible (false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid ("f0288b24-7b84-42a5-9a92-2e16a012e4de")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
|
||||
// 方法是按如下所示使用“*”: :
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion ("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion ("1.0.0.0")]
|
||||
71
Launch/Properties/Resources.Designer.cs
generated
Normal file
71
Launch/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,71 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本: 4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能导致不正确的行为,如果
|
||||
// 重新生成代码,则所做更改将丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Launch.Properties
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 强类型资源类,用于查找本地化字符串等。
|
||||
/// </summary>
|
||||
// 此类是由 StronglyTypedResourceBuilder
|
||||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||
// 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute ("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute ()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute ()]
|
||||
internal class Resources
|
||||
{
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute ("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources ()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute (global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((resourceMan == null))
|
||||
{
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager ("Launch.Properties.Resources", typeof (Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 覆盖当前线程的 CurrentUICulture 属性
|
||||
/// 使用此强类型的资源类的资源查找。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute (global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return resourceCulture;
|
||||
}
|
||||
set
|
||||
{
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
117
Launch/Properties/Resources.resx
Normal file
117
Launch/Properties/Resources.resx
Normal file
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
30
Launch/Properties/Settings.Designer.cs
generated
Normal file
30
Launch/Properties/Settings.Designer.cs
generated
Normal file
@@ -0,0 +1,30 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Launch.Properties
|
||||
{
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute ()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute ("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings: global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized (new Settings ())));
|
||||
|
||||
public static Settings Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Launch/Properties/Settings.settings
Normal file
7
Launch/Properties/Settings.settings
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
75
Launch/app.manifest
Normal file
75
Launch/app.manifest
Normal file
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<!-- UAC 清单选项
|
||||
如果想要更改 Windows 用户帐户控制级别,请使用
|
||||
以下节点之一替换 requestedExecutionLevel 节点。n
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
|
||||
|
||||
指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
|
||||
如果你的应用程序需要此虚拟化来实现向后兼容性,则删除此
|
||||
元素。
|
||||
-->
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的
|
||||
Windows 版本的列表。取消评论适当的元素,Windows 将
|
||||
自动选择最兼容的环境。 -->
|
||||
|
||||
<!-- Windows Vista -->
|
||||
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
|
||||
|
||||
<!-- Windows 7 -->
|
||||
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
|
||||
|
||||
<!-- Windows 8 -->
|
||||
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
|
||||
|
||||
<!-- Windows 8.1 -->
|
||||
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
|
||||
|
||||
<!-- Windows 10 -->
|
||||
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
|
||||
|
||||
</application>
|
||||
</compatibility>
|
||||
|
||||
<!-- 指示该应用程序可以感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
|
||||
自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
|
||||
选择加入。选择加入此设置的 Windows 窗体应用程序(目标设定为 .NET Framework 4.6 )还应
|
||||
在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。-->
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
|
||||
|
||||
<!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->
|
||||
<!--
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
</assembly>
|
||||
85
Manager/BridgeExt.cs
Normal file
85
Manager/BridgeExt.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using DataUtils;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class BridgeExt: Bridge._I_BridgeBase
|
||||
{
|
||||
Form currentWnd = null;
|
||||
public BridgeExt (Form wnd, IScriptBridge isc, IWebBrowserPageScale iwbps, ITaskbarProgress itp) : base (wnd, isc, iwbps, itp)
|
||||
{
|
||||
currentWnd = wnd;
|
||||
}
|
||||
private static void CallJS (object jsFunc, params object [] args)
|
||||
{
|
||||
if (jsFunc == null) return;
|
||||
try
|
||||
{
|
||||
// 这里固定第一个参数为 thisArg(比如 1)
|
||||
object [] realArgs = new object [args.Length + 1];
|
||||
realArgs [0] = jsFunc; // thisArg
|
||||
Array.Copy (args, 0, realArgs, 1, args.Length);
|
||||
|
||||
jsFunc.GetType ().InvokeMember (
|
||||
"call",
|
||||
BindingFlags.InvokeMethod,
|
||||
null,
|
||||
jsFunc,
|
||||
realArgs
|
||||
);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore errors in callback invocation
|
||||
}
|
||||
}
|
||||
public Task CreateAppShortcut (string installLocation, string appUserModelId, object successCallback, object failedCallback)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<bool> ();
|
||||
var scf = new ShortcutCreateForm ();
|
||||
scf.Owner = currentWnd;
|
||||
scf.FormClosed += (s, e) =>
|
||||
{
|
||||
bool success = scf.IsSuccess;
|
||||
tcs.TrySetResult (success);
|
||||
var data = new
|
||||
{
|
||||
succeeded = scf.IsSuccess,
|
||||
message = scf.Message
|
||||
};
|
||||
string json = JsonConvert.SerializeObject (data);
|
||||
if (currentWnd.InvokeRequired)
|
||||
{
|
||||
currentWnd.BeginInvoke (new Action (() =>
|
||||
{
|
||||
if (success)
|
||||
CallJS (successCallback, json);
|
||||
else
|
||||
CallJS (failedCallback, json);
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (success)
|
||||
CallJS (successCallback, json);
|
||||
else
|
||||
CallJS (failedCallback, json);
|
||||
}
|
||||
scf.Dispose ();
|
||||
};
|
||||
scf.Show (currentWnd);
|
||||
scf.InitCreater (installLocation, appUserModelId);
|
||||
return tcs.Task;
|
||||
}
|
||||
}
|
||||
}
|
||||
126
Manager/ImageDisplay.Designer.cs
generated
Normal file
126
Manager/ImageDisplay.Designer.cs
generated
Normal file
@@ -0,0 +1,126 @@
|
||||
namespace Manager
|
||||
{
|
||||
partial class ImageDisplay
|
||||
{
|
||||
/// <summary>
|
||||
/// 必需的设计器变量。
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有正在使用的资源。
|
||||
/// </summary>
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose ();
|
||||
}
|
||||
base.Dispose (disposing);
|
||||
}
|
||||
|
||||
#region 组件设计器生成的代码
|
||||
|
||||
/// <summary>
|
||||
/// 设计器支持所需的方法 - 不要修改
|
||||
/// 使用代码编辑器修改此方法的内容。
|
||||
/// </summary>
|
||||
private void InitializeComponent ()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ImageDisplay));
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.sizeDisplay = new System.Windows.Forms.Label();
|
||||
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.backgroundPanel = new System.Windows.Forms.Panel();
|
||||
this.foregroundPicture = new System.Windows.Forms.PictureBox();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.flowLayoutPanel1.SuspendLayout();
|
||||
this.backgroundPanel.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.foregroundPicture)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.ColumnCount = 1;
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel1.Controls.Add(this.sizeDisplay, 0, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel1, 0, 1);
|
||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.RowCount = 2;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(30, 60);
|
||||
this.tableLayoutPanel1.TabIndex = 0;
|
||||
//
|
||||
// sizeDisplay
|
||||
//
|
||||
this.sizeDisplay.AutoSize = true;
|
||||
this.sizeDisplay.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.sizeDisplay.Location = new System.Drawing.Point(3, 0);
|
||||
this.sizeDisplay.Name = "sizeDisplay";
|
||||
this.sizeDisplay.Size = new System.Drawing.Size(24, 15);
|
||||
this.sizeDisplay.TabIndex = 0;
|
||||
this.sizeDisplay.Text = "16";
|
||||
this.sizeDisplay.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
|
||||
//
|
||||
// flowLayoutPanel1
|
||||
//
|
||||
this.flowLayoutPanel1.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("flowLayoutPanel1.BackgroundImage")));
|
||||
this.flowLayoutPanel1.Controls.Add(this.backgroundPanel);
|
||||
this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 15);
|
||||
this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.flowLayoutPanel1.Name = "flowLayoutPanel1";
|
||||
this.flowLayoutPanel1.Size = new System.Drawing.Size(30, 45);
|
||||
this.flowLayoutPanel1.TabIndex = 1;
|
||||
//
|
||||
// backgroundPanel
|
||||
//
|
||||
this.backgroundPanel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.backgroundPanel.Controls.Add(this.foregroundPicture);
|
||||
this.backgroundPanel.Location = new System.Drawing.Point(0, 0);
|
||||
this.backgroundPanel.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.backgroundPanel.Name = "backgroundPanel";
|
||||
this.backgroundPanel.Size = new System.Drawing.Size(24, 24);
|
||||
this.backgroundPanel.TabIndex = 0;
|
||||
//
|
||||
// foregroundPicture
|
||||
//
|
||||
this.foregroundPicture.BackColor = System.Drawing.Color.Transparent;
|
||||
this.foregroundPicture.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
|
||||
this.foregroundPicture.Location = new System.Drawing.Point(3, 4);
|
||||
this.foregroundPicture.Name = "foregroundPicture";
|
||||
this.foregroundPicture.Size = new System.Drawing.Size(16, 16);
|
||||
this.foregroundPicture.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.foregroundPicture.TabIndex = 0;
|
||||
this.foregroundPicture.TabStop = false;
|
||||
//
|
||||
// ImageDisplay
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.tableLayoutPanel1);
|
||||
this.MinimumSize = new System.Drawing.Size(30, 0);
|
||||
this.Name = "ImageDisplay";
|
||||
this.Size = new System.Drawing.Size(30, 60);
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.PerformLayout();
|
||||
this.flowLayoutPanel1.ResumeLayout(false);
|
||||
this.backgroundPanel.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.foregroundPicture)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||
private System.Windows.Forms.Label sizeDisplay;
|
||||
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
|
||||
private System.Windows.Forms.Panel backgroundPanel;
|
||||
private System.Windows.Forms.PictureBox foregroundPicture;
|
||||
}
|
||||
}
|
||||
69
Manager/ImageDisplay.cs
Normal file
69
Manager/ImageDisplay.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
public partial class ImageDisplay: UserControl
|
||||
{
|
||||
public ImageDisplay ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
IconSize = 16;
|
||||
Ratio = (decimal)(8.0 / 7.0);
|
||||
}
|
||||
private Size iconSize = new Size (16, 16);
|
||||
private decimal ratio = (decimal)(8.0 / 7.0);
|
||||
private bool originImgSize = false;
|
||||
public void RefreshPictureDisplay ()
|
||||
{
|
||||
if (originImgSize)
|
||||
{
|
||||
var backSizeWidth = (foregroundPicture.Image?.Size.Width ?? 0) * ratio;
|
||||
var backSizeHeight = (foregroundPicture.Image?.Size.Width ?? 0) * ratio;
|
||||
foregroundPicture.Size = ForegroundImage.Size;
|
||||
backgroundPanel.Size = new Size ((int)backSizeWidth, (int)backSizeHeight);
|
||||
sizeDisplay.Text = backgroundPanel.Size.ToString ();
|
||||
}
|
||||
else
|
||||
{
|
||||
foregroundPicture.Size = new Size (
|
||||
(int)(iconSize.Width / ratio),
|
||||
(int)(iconSize.Height / ratio)
|
||||
);
|
||||
backgroundPanel.Size = iconSize;
|
||||
}
|
||||
foregroundPicture.Left = (int)((backgroundPanel.Width - foregroundPicture.Width) * 0.5);
|
||||
foregroundPicture.Top = (int)((backgroundPanel.Height - foregroundPicture.Height) * 0.5);
|
||||
this.Size = new Size (
|
||||
(int)(iconSize.Width * 1),
|
||||
(int)((iconSize.Height + sizeDisplay.Height) * 1)
|
||||
);
|
||||
}
|
||||
public decimal Ratio
|
||||
{
|
||||
get { return ratio; }
|
||||
set
|
||||
{
|
||||
ratio = value;
|
||||
RefreshPictureDisplay ();
|
||||
}
|
||||
}
|
||||
public int IconSize
|
||||
{
|
||||
get { return iconSize.Width; }
|
||||
set
|
||||
{
|
||||
sizeDisplay.Text = value.ToString ();
|
||||
iconSize = new Size (value, value);
|
||||
RefreshPictureDisplay ();
|
||||
}
|
||||
}
|
||||
public bool IsOriginPicSize
|
||||
{
|
||||
get { return originImgSize; }
|
||||
set { originImgSize = true; RefreshPictureDisplay (); }
|
||||
}
|
||||
public Color BackgroundColor { get { return backgroundPanel.BackColor; } set { backgroundPanel.BackColor = value; } }
|
||||
public Image ForegroundImage { get { return foregroundPicture.Image; } set { foregroundPicture.Image = value; } }
|
||||
}
|
||||
}
|
||||
129
Manager/ImageDisplay.resx
Normal file
129
Manager/ImageDisplay.resx
Normal file
@@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="flowLayoutPanel1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAS
|
||||
dAAAEnQB3mYfeAAAAGdJREFUWEftzrENgFAQw9C//1qscv2tQBMGsEiBkF+TLvLZnqvHLMIswizCLMIs
|
||||
wizCLMIswizCLOK/WfPIZYNZxMk2pG4mvS+YRTSzctlgFmEWYRZhFmEWYRZhFmEWYRZhFvHJrN0bfh7U
|
||||
g5LtRRcAAAAASUVORK5CYII=
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
324
Manager/ImageSetForm.Designer.cs
generated
Normal file
324
Manager/ImageSetForm.Designer.cs
generated
Normal file
@@ -0,0 +1,324 @@
|
||||
namespace Manager
|
||||
{
|
||||
partial class ImageSetForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose ();
|
||||
}
|
||||
base.Dispose (disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent ()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ImageSetForm));
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||
this.radioButton1 = new System.Windows.Forms.RadioButton();
|
||||
this.panel1 = new System.Windows.Forms.Panel();
|
||||
this.initImgsSizeList = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.radioButton2 = new System.Windows.Forms.RadioButton();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.textBox2 = new System.Windows.Forms.TextBox();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.button1 = new System.Windows.Forms.Button();
|
||||
this.pictureBox1 = new System.Windows.Forms.PictureBox();
|
||||
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.button2 = new System.Windows.Forms.Button();
|
||||
this.button3 = new System.Windows.Forms.Button();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.panel1.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
||||
this.tableLayoutPanel2.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.ColumnCount = 5;
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 109F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel1.Controls.Add(this.label1, 1, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.textBox1, 2, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.radioButton1, 1, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.panel1, 1, 3);
|
||||
this.tableLayoutPanel1.Controls.Add(this.radioButton2, 1, 4);
|
||||
this.tableLayoutPanel1.Controls.Add(this.label2, 1, 5);
|
||||
this.tableLayoutPanel1.Controls.Add(this.textBox2, 2, 5);
|
||||
this.tableLayoutPanel1.Controls.Add(this.label3, 1, 6);
|
||||
this.tableLayoutPanel1.Controls.Add(this.button1, 3, 5);
|
||||
this.tableLayoutPanel1.Controls.Add(this.pictureBox1, 1, 7);
|
||||
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 1, 9);
|
||||
this.tableLayoutPanel1.Controls.Add(this.label4, 3, 6);
|
||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
||||
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.RowCount = 11;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 32F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 60F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 36F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 10F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(454, 439);
|
||||
this.tableLayoutPanel1.TabIndex = 0;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label1.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
this.label1.Location = new System.Drawing.Point(23, 20);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(97, 32);
|
||||
this.label1.TabIndex = 0;
|
||||
this.label1.Text = "Current Size";
|
||||
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.textBox1, 2);
|
||||
this.textBox1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.textBox1.Location = new System.Drawing.Point(126, 24);
|
||||
this.textBox1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.textBox1.Name = "textBox1";
|
||||
this.textBox1.ReadOnly = true;
|
||||
this.textBox1.Size = new System.Drawing.Size(305, 27);
|
||||
this.textBox1.TabIndex = 1;
|
||||
//
|
||||
// radioButton1
|
||||
//
|
||||
this.radioButton1.AutoSize = true;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.radioButton1, 3);
|
||||
this.radioButton1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.radioButton1.Location = new System.Drawing.Point(23, 56);
|
||||
this.radioButton1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.radioButton1.Name = "radioButton1";
|
||||
this.radioButton1.Size = new System.Drawing.Size(408, 24);
|
||||
this.radioButton1.TabIndex = 2;
|
||||
this.radioButton1.TabStop = true;
|
||||
this.radioButton1.Text = "Use Default Resources";
|
||||
this.radioButton1.UseVisualStyleBackColor = true;
|
||||
this.radioButton1.CheckedChanged += new System.EventHandler(this.radioButton1_CheckedChanged);
|
||||
//
|
||||
// panel1
|
||||
//
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.panel1, 3);
|
||||
this.panel1.Controls.Add(this.initImgsSizeList);
|
||||
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.panel1.Location = new System.Drawing.Point(23, 88);
|
||||
this.panel1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.panel1.Name = "panel1";
|
||||
this.panel1.Size = new System.Drawing.Size(408, 52);
|
||||
this.panel1.TabIndex = 3;
|
||||
//
|
||||
// initImgsSizeList
|
||||
//
|
||||
this.initImgsSizeList.AutoScroll = true;
|
||||
this.initImgsSizeList.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.initImgsSizeList.Location = new System.Drawing.Point(0, 0);
|
||||
this.initImgsSizeList.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.initImgsSizeList.Name = "initImgsSizeList";
|
||||
this.initImgsSizeList.Size = new System.Drawing.Size(408, 52);
|
||||
this.initImgsSizeList.TabIndex = 0;
|
||||
//
|
||||
// radioButton2
|
||||
//
|
||||
this.radioButton2.AutoSize = true;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.radioButton2, 3);
|
||||
this.radioButton2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.radioButton2.Location = new System.Drawing.Point(23, 148);
|
||||
this.radioButton2.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.radioButton2.Name = "radioButton2";
|
||||
this.radioButton2.Size = new System.Drawing.Size(408, 24);
|
||||
this.radioButton2.TabIndex = 4;
|
||||
this.radioButton2.TabStop = true;
|
||||
this.radioButton2.Text = "Use File";
|
||||
this.radioButton2.UseVisualStyleBackColor = true;
|
||||
this.radioButton2.CheckedChanged += new System.EventHandler(this.radioButton2_CheckedChanged);
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label2.Location = new System.Drawing.Point(23, 176);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(97, 36);
|
||||
this.label2.TabIndex = 5;
|
||||
this.label2.Text = "File Path";
|
||||
this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// textBox2
|
||||
//
|
||||
this.textBox2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.textBox2.Location = new System.Drawing.Point(126, 180);
|
||||
this.textBox2.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.textBox2.Name = "textBox2";
|
||||
this.textBox2.Size = new System.Drawing.Size(196, 27);
|
||||
this.textBox2.TabIndex = 6;
|
||||
this.textBox2.TextChanged += new System.EventHandler(this.textBox2_TextChanged);
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.label3, 2);
|
||||
this.label3.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label3.Location = new System.Drawing.Point(23, 212);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(299, 20);
|
||||
this.label3.TabIndex = 7;
|
||||
this.label3.Text = "Preview";
|
||||
this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// button1
|
||||
//
|
||||
this.button1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.button1.Location = new System.Drawing.Point(325, 176);
|
||||
this.button1.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(109, 36);
|
||||
this.button1.TabIndex = 8;
|
||||
this.button1.Text = "Browse...";
|
||||
this.button1.UseVisualStyleBackColor = true;
|
||||
this.button1.Click += new System.EventHandler(this.button1_Click);
|
||||
//
|
||||
// pictureBox1
|
||||
//
|
||||
this.pictureBox1.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("pictureBox1.BackgroundImage")));
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.pictureBox1, 3);
|
||||
this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pictureBox1.Location = new System.Drawing.Point(23, 236);
|
||||
this.pictureBox1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.pictureBox1.Name = "pictureBox1";
|
||||
this.pictureBox1.Size = new System.Drawing.Size(408, 129);
|
||||
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.pictureBox1.TabIndex = 9;
|
||||
this.pictureBox1.TabStop = false;
|
||||
this.pictureBox1.LoadCompleted += new System.ComponentModel.AsyncCompletedEventHandler(this.pictureBox1_LoadCompleted);
|
||||
//
|
||||
// tableLayoutPanel2
|
||||
//
|
||||
this.tableLayoutPanel2.ColumnCount = 5;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.tableLayoutPanel2, 3);
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.tableLayoutPanel2.Controls.Add(this.button2, 1, 1);
|
||||
this.tableLayoutPanel2.Controls.Add(this.button3, 3, 1);
|
||||
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel2.Location = new System.Drawing.Point(20, 379);
|
||||
this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
|
||||
this.tableLayoutPanel2.RowCount = 3;
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 36F));
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(414, 40);
|
||||
this.tableLayoutPanel2.TabIndex = 10;
|
||||
//
|
||||
// button2
|
||||
//
|
||||
this.button2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.button2.Location = new System.Drawing.Point(84, 2);
|
||||
this.button2.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.button2.Name = "button2";
|
||||
this.button2.Size = new System.Drawing.Size(80, 36);
|
||||
this.button2.TabIndex = 0;
|
||||
this.button2.Text = "Set";
|
||||
this.button2.UseVisualStyleBackColor = true;
|
||||
this.button2.Click += new System.EventHandler(this.button2_Click);
|
||||
//
|
||||
// button3
|
||||
//
|
||||
this.button3.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.button3.Location = new System.Drawing.Point(248, 2);
|
||||
this.button3.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.button3.Name = "button3";
|
||||
this.button3.Size = new System.Drawing.Size(80, 36);
|
||||
this.button3.TabIndex = 1;
|
||||
this.button3.Text = "Cancel";
|
||||
this.button3.UseVisualStyleBackColor = true;
|
||||
this.button3.Click += new System.EventHandler(this.button3_Click);
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label4.Location = new System.Drawing.Point(328, 212);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(103, 20);
|
||||
this.label4.TabIndex = 11;
|
||||
this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// ImageSetForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.White;
|
||||
this.ClientSize = new System.Drawing.Size(454, 439);
|
||||
this.Controls.Add(this.tableLayoutPanel1);
|
||||
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.Name = "ImageSetForm";
|
||||
this.ShowIcon = false;
|
||||
this.Text = "Setting Current Image";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ImageSetForm_FormClosing);
|
||||
this.Load += new System.EventHandler(this.ImageSetForm_Load);
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.PerformLayout();
|
||||
this.panel1.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
|
||||
this.tableLayoutPanel2.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.TextBox textBox1;
|
||||
private System.Windows.Forms.RadioButton radioButton1;
|
||||
private System.Windows.Forms.Panel panel1;
|
||||
private System.Windows.Forms.FlowLayoutPanel initImgsSizeList;
|
||||
private System.Windows.Forms.RadioButton radioButton2;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.TextBox textBox2;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.Button button1;
|
||||
private System.Windows.Forms.PictureBox pictureBox1;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
|
||||
private System.Windows.Forms.Button button2;
|
||||
private System.Windows.Forms.Button button3;
|
||||
private System.Windows.Forms.Label label4;
|
||||
}
|
||||
}
|
||||
178
Manager/ImageSetForm.cs
Normal file
178
Manager/ImageSetForm.cs
Normal file
@@ -0,0 +1,178 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using Bridge;
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
public partial class ImageSetForm: Form
|
||||
{
|
||||
public ImageSetForm ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_SETIMG_TITLE");
|
||||
label1.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_SETIMG_CURRSIZE");
|
||||
radioButton1.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_SETIMG_USEDEF");
|
||||
radioButton2.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_SETIMG_USEFILE");
|
||||
label2.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_SETIMG_FILEPATH");
|
||||
button1.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_BROWSE");
|
||||
label3.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_PREVIEW");
|
||||
button2.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_SETIMG_SET");
|
||||
button3.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_CANCEL");
|
||||
}
|
||||
private Dictionary<int, Image> defimages = new Dictionary<int, Image> ();
|
||||
private void RefreshDefaultImagesSettings ()
|
||||
{
|
||||
try
|
||||
{
|
||||
initImgsSizeList.Controls.Clear ();
|
||||
foreach (var kv in defimages)
|
||||
{
|
||||
RadioButton rb = new RadioButton ();
|
||||
rb.Text = kv.Key.ToString ();
|
||||
rb.CheckedChanged += DefaultImgsRadio_CheckedChanged;
|
||||
initImgsSizeList.Controls.Add (rb);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
public Dictionary <int, Image> DefaultImages
|
||||
{
|
||||
get { return defimages; }
|
||||
set { defimages = value; RefreshDefaultImagesSettings (); }
|
||||
}
|
||||
public int CurrentSize { set { textBox1.Text = value.ToString (); } }
|
||||
private void RefreshImagesType ()
|
||||
{
|
||||
initImgsSizeList.Enabled = radioButton1.Checked;
|
||||
textBox2.Enabled = button1.Enabled = radioButton2.Checked;
|
||||
}
|
||||
private Image finalUse = null;
|
||||
private void RefreshImagesPreview ()
|
||||
{
|
||||
pictureBox1.Image = null;
|
||||
try
|
||||
{
|
||||
if (radioButton1.Checked)
|
||||
{
|
||||
foreach (RadioButton ctrl in initImgsSizeList.Controls)
|
||||
{
|
||||
if (ctrl.Checked)
|
||||
{
|
||||
int value = int.Parse (ctrl.Text);
|
||||
pictureBox1.Image = defimages [value];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
pictureBox1.Image = Image.FromFile (textBox2.Text);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { pictureBox1.Image = null; }
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
label4.Text = $"{pictureBox1.Image.Width} x {pictureBox1.Image.Height}";
|
||||
}
|
||||
catch { label4.Text = ""; }
|
||||
}
|
||||
}
|
||||
private void DefaultImgsRadio_CheckedChanged (object sender, EventArgs e)
|
||||
{
|
||||
RefreshImagesPreview ();
|
||||
}
|
||||
private void ImageSetForm_Load (object sender, EventArgs e)
|
||||
{
|
||||
RefreshImagesType ();
|
||||
//RefreshImagesPreview ();
|
||||
}
|
||||
private void textBox2_TextChanged (object sender, EventArgs e)
|
||||
{
|
||||
RefreshImagesPreview ();
|
||||
}
|
||||
private void radioButton1_CheckedChanged (object sender, EventArgs e)
|
||||
{
|
||||
RefreshImagesType ();
|
||||
RefreshImagesPreview ();
|
||||
}
|
||||
private void radioButton2_CheckedChanged (object sender, EventArgs e)
|
||||
{
|
||||
RefreshImagesType ();
|
||||
RefreshImagesPreview ();
|
||||
}
|
||||
public Image FinalImage
|
||||
{
|
||||
set
|
||||
{
|
||||
pictureBox1.Image = value;
|
||||
try
|
||||
{
|
||||
label4.Text = $"{pictureBox1.Image.Width} x {pictureBox1.Image.Height}";
|
||||
}
|
||||
catch { label4.Text = ""; }
|
||||
}
|
||||
get { return finalUse; }
|
||||
}
|
||||
private void button3_Click (object sender, EventArgs e)
|
||||
{
|
||||
this.Close ();
|
||||
}
|
||||
private void button2_Click (object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (radioButton1.Checked)
|
||||
{
|
||||
foreach (RadioButton ctrl in initImgsSizeList.Controls)
|
||||
{
|
||||
if (ctrl.Checked)
|
||||
{
|
||||
int value = int.Parse (ctrl.Text);
|
||||
finalUse = defimages [value];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
finalUse = Image.FromFile (textBox2.Text);
|
||||
}
|
||||
if (finalUse == null) throw new Exception ("Error: none valid image.");
|
||||
this.Close ();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show (ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
}
|
||||
private void ImageSetForm_FormClosing (object sender, FormClosingEventArgs e)
|
||||
{
|
||||
}
|
||||
private void pictureBox1_LoadCompleted (object sender, System.ComponentModel.AsyncCompletedEventArgs e)
|
||||
{
|
||||
label4.Text = $"{pictureBox1.Image.Width} x {pictureBox1.Image.Height}";
|
||||
}
|
||||
private void button1_Click (object sender, EventArgs e)
|
||||
{
|
||||
using (OpenFileDialog ofd = new OpenFileDialog ())
|
||||
{
|
||||
ofd.Title = "Please select the image file: ";
|
||||
ofd.Filter = "Image Files (*.png;*.bmp;*.jpg;*.jpeg)|*.png;*.bmp;*.jpg;*.jpeg";
|
||||
ofd.Multiselect = false;
|
||||
ofd.CheckFileExists = true;
|
||||
ofd.CheckPathExists = true;
|
||||
if (ofd.ShowDialog (this) == DialogResult.OK)
|
||||
{
|
||||
textBox2.Text = ofd.FileName;
|
||||
radioButton2.Checked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
129
Manager/ImageSetForm.resx
Normal file
129
Manager/ImageSetForm.resx
Normal file
@@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="pictureBox1.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAS
|
||||
dAAAEnQB3mYfeAAAAGlJREFUWEftzrENACEQA0H6r4SG6OAKAfHXwOodEOwkzqwdlTNzzCLMIswizCLM
|
||||
IswizCLMIswizCLMIjJZ6+rLhFezehO+uKNjfzCLSGb1ZYJZhFmEWYRZhFmEWYRZhFmEWYRZxJNZVRvc
|
||||
pafKc4vMkgAAAABJRU5ErkJggg==
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
89
Manager/LoadingStatusForm.Designer.cs
generated
Normal file
89
Manager/LoadingStatusForm.Designer.cs
generated
Normal file
@@ -0,0 +1,89 @@
|
||||
namespace Manager
|
||||
{
|
||||
partial class LoadingStatusForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose ();
|
||||
}
|
||||
base.Dispose (disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent ()
|
||||
{
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.ColumnCount = 3;
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel1.Controls.Add(this.label1, 1, 1);
|
||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.RowCount = 3;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(241, 123);
|
||||
this.tableLayoutPanel1.TabIndex = 0;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label1.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.label1.Location = new System.Drawing.Point(55, 48);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(131, 27);
|
||||
this.label1.TabIndex = 1;
|
||||
this.label1.Text = "Please wait...";
|
||||
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// LoadingStatusForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(120F, 120F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||
this.ClientSize = new System.Drawing.Size(241, 123);
|
||||
this.ControlBox = false;
|
||||
this.Controls.Add(this.tableLayoutPanel1);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
|
||||
this.MaximizeBox = false;
|
||||
this.Name = "LoadingStatusForm";
|
||||
this.ShowIcon = false;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "Please wait...";
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||
private System.Windows.Forms.Label label1;
|
||||
}
|
||||
}
|
||||
19
Manager/LoadingStatusForm.cs
Normal file
19
Manager/LoadingStatusForm.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Windows.Forms;
|
||||
using Bridge;
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
public partial class LoadingStatusForm: Form
|
||||
{
|
||||
public LoadingStatusForm ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
label1.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_LOADING");
|
||||
}
|
||||
public string TipText
|
||||
{
|
||||
get { return label1.Text; }
|
||||
set { label1.Text = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
120
Manager/LoadingStatusForm.resx
Normal file
120
Manager/LoadingStatusForm.resx
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
208
Manager/Manager.csproj
Normal file
208
Manager/Manager.csproj
Normal file
@@ -0,0 +1,208 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{DC074727-72E4-43C5-BAAF-E0D548104797}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Manager</RootNamespace>
|
||||
<AssemblyName>Manager</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>..\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>Project1.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.4\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.DirectoryServices" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BridgeExt.cs" />
|
||||
<Compile Include="ImageDisplay.cs">
|
||||
<SubType>UserControl</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ImageDisplay.Designer.cs">
|
||||
<DependentUpon>ImageDisplay.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ImageSetForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ImageSetForm.Designer.cs">
|
||||
<DependentUpon>ImageSetForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="LoadingStatusForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="LoadingStatusForm.Designer.cs">
|
||||
<DependentUpon>LoadingStatusForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ManagerShell.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ManagerShell.Designer.cs">
|
||||
<DependentUpon>ManagerShell.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Polyfill.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ShortcutCreateForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ShortcutCreateForm.Designer.cs">
|
||||
<DependentUpon>ShortcutCreateForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ShortcutHelper.cs" />
|
||||
<EmbeddedResource Include="ImageDisplay.resx">
|
||||
<DependentUpon>ImageDisplay.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="ImageSetForm.resx">
|
||||
<DependentUpon>ImageSetForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="LoadingStatusForm.resx">
|
||||
<DependentUpon>LoadingStatusForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="ManagerShell.resx">
|
||||
<DependentUpon>ManagerShell.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="ShortcutCreateForm.resx">
|
||||
<DependentUpon>ShortcutCreateForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<None Include="app.manifest" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AppxPackage\AppxPackage.csproj">
|
||||
<Project>{bd681a4f-eb60-4bb8-90b5-65968fc7da59}</Project>
|
||||
<Name>AppxPackage</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Bridge\Bridge.csproj">
|
||||
<Project>{3c2f5446-33f0-41d5-813a-64a94aa474af}</Project>
|
||||
<Name>Bridge</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\DataUtils\DataUtils.csproj">
|
||||
<Project>{ffd3fd52-37a8-4f43-883c-de8d996cb0e0}</Project>
|
||||
<Name>DataUtils</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\PrivateInit\PrivateInit.csproj">
|
||||
<Project>{8e708d9a-6325-4aa9-b5a5-d1b5eca8eef7}</Project>
|
||||
<Name>PrivateInit</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\WAShell\WAShell.csproj">
|
||||
<Project>{4ec16578-efbf-41e6-8d7f-976e3646dd1d}</Project>
|
||||
<Name>WAShell</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Project1.ico" />
|
||||
<None Include="Resources\32_manager.ico" />
|
||||
<None Include="Resources\IconMetro.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
54
Manager/ManagerShell.Designer.cs
generated
Normal file
54
Manager/ManagerShell.Designer.cs
generated
Normal file
@@ -0,0 +1,54 @@
|
||||
namespace Manager
|
||||
{
|
||||
partial class ManagerShell
|
||||
{
|
||||
/// <summary>
|
||||
/// 必需的设计器变量。
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有正在使用的资源。
|
||||
/// </summary>
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose ();
|
||||
}
|
||||
base.Dispose (disposing);
|
||||
}
|
||||
|
||||
#region Windows 窗体设计器生成的代码
|
||||
|
||||
/// <summary>
|
||||
/// 设计器支持所需的方法 - 不要修改
|
||||
/// 使用代码编辑器修改此方法的内容。
|
||||
/// </summary>
|
||||
private void InitializeComponent ()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ManagerShell));
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// ManagerShell
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(657, 414);
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.Location = new System.Drawing.Point(0, 0);
|
||||
this.Name = "ManagerShell";
|
||||
this.PageScale = 125;
|
||||
this.Text = "Form1";
|
||||
this.WindowIcon = ((System.Drawing.Icon)(resources.GetObject("$this.WindowIcon")));
|
||||
this.Load += new System.EventHandler(this.ManagerShell_Load);
|
||||
this.Resize += new System.EventHandler(this.ManagerShell_Resize);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
102
Manager/ManagerShell.cs
Normal file
102
Manager/ManagerShell.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
public partial class ManagerShell: WAShell.WebAppForm
|
||||
{
|
||||
public ManagerShell ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
this.PublicObjectForScripting = new BridgeExt (this, this, this, this);
|
||||
try
|
||||
{
|
||||
var relativePath = DataUtils.VisualElementsStore.Vemanifest.SplashScreenImage (Program.g_appId);
|
||||
var img = Image.FromFile (relativePath);
|
||||
SplashScreen.SplashImage = img;
|
||||
} catch (Exception e) {
|
||||
var ex = e;
|
||||
}
|
||||
try
|
||||
{
|
||||
SplashScreen.SplashBackgroundColor = DataUtils.UITheme.StringToColor (DataUtils.VisualElementsStore.Vemanifest.SplashScreenBackgroundColor (Program.g_appId));
|
||||
}
|
||||
catch { }
|
||||
InitSize ();
|
||||
Text = Bridge.ResXmlStore.StringRes.Get ("MANAGER_APPTITLE");
|
||||
this.Load += Form_Load;
|
||||
}
|
||||
private void InitSize ()
|
||||
{
|
||||
uint ww = 0, wh = 0;
|
||||
var ini = Bridge.InitFileStore.Config;
|
||||
var setsect = ini ["Settings"];
|
||||
var savepos = setsect.GetKey ("PackageManager:SavePosAndSizeBeforeCancel");
|
||||
var lastw = setsect.GetKey ("PackageManager:LastWidth");
|
||||
var lasth = setsect.GetKey ("PackageManager:LastHeight");
|
||||
var defw = setsect.GetKey ("PackageManager:DefaultWidth");
|
||||
var defh = setsect.GetKey ("PackageManager:DefaultHeight");
|
||||
var minw = setsect.GetKey ("PackageManager:MinimumWidth");
|
||||
var minh = setsect.GetKey ("PackageManager:MinimumHeight");
|
||||
var lasts = setsect.GetKey ("PackageManager:LastWndState");
|
||||
if (savepos.ReadBool ())
|
||||
{
|
||||
ww = lastw.ReadUInt (defw.ReadUInt (Properties.Resources.IDS_DEFAULTWIDTH.ParseTo <uint> ()));
|
||||
wh = lasth.ReadUInt (defh.ReadUInt (Properties.Resources.IDS_DEFAULTHEIGHT.ParseTo <uint> ()));
|
||||
}
|
||||
else
|
||||
{
|
||||
ww = defw.ReadUInt (Properties.Resources.IDS_DEFAULTWIDTH.ParseTo<uint> ());
|
||||
wh = defh.ReadUInt (Properties.Resources.IDS_DEFAULTHEIGHT.ParseTo<uint> ());
|
||||
}
|
||||
ClientSize = new Size ((int)(ww * DataUtils.UITheme.DPIDouble), (int)(wh * DataUtils.UITheme.DPIDouble));
|
||||
int hborder = Size.Width - ClientSize.Width,
|
||||
vborder = Size.Height - ClientSize.Height;
|
||||
MinimumSize = new Size (
|
||||
(int)(minw.ReadUInt (Properties.Resources.IDS_MINWIDTH.ParseTo <uint> ()) * DataUtils.UITheme.DPIDouble) + hborder,
|
||||
(int)(minh.ReadUInt (Properties.Resources.IDS_MINHEIGHT.ParseTo <uint> ()) * DataUtils.UITheme.DPIDouble) + vborder
|
||||
);
|
||||
WindowState = (FormWindowState)lasts.ReadInt ((int)FormWindowState.Normal);
|
||||
}
|
||||
private void Form_Load (object sender, EventArgs e)
|
||||
{
|
||||
var current = Process.GetCurrentProcess ();
|
||||
var processes = Process.GetProcessesByName (current.ProcessName);
|
||||
int count = processes.Length;
|
||||
int offset = 30; // 每个窗口偏移
|
||||
int x = 20 + (count - 1) * offset;
|
||||
int y = 20 + (count - 1) * offset;
|
||||
this.StartPosition = FormStartPosition.Manual;
|
||||
this.Location = new Point (x, y);
|
||||
}
|
||||
private void ManagerShell_Load (object sender, EventArgs e)
|
||||
{
|
||||
var root = Path.GetDirectoryName (DataUtils.Utilities.GetCurrentProgramPath ());
|
||||
WebUI.Navigate (Path.Combine (root, "html\\manager.html"));
|
||||
}
|
||||
private void ManagerShell_Resize (object sender, EventArgs e)
|
||||
{
|
||||
var ini = Bridge.InitFileStore.Config;
|
||||
var setsect = ini ["Settings"];
|
||||
var savepos = setsect.GetKey ("PackageManager:SavePosAndSizeBeforeCancel");
|
||||
var lastw = setsect.GetKey ("PackageManager:LastWidth");
|
||||
var lasth = setsect.GetKey ("PackageManager:LastHeight");
|
||||
var lasts = setsect.GetKey ("PackageManager:LastWndState");
|
||||
switch (WindowState)
|
||||
{
|
||||
case FormWindowState.Normal:
|
||||
case FormWindowState.Maximized:
|
||||
lasts.Write ((int)WindowState);
|
||||
break;
|
||||
}
|
||||
if (WindowState == FormWindowState.Normal && savepos.ReadBool ())
|
||||
{
|
||||
lastw.Write ((int)(ClientSize.Width / DataUtils.UITheme.DPIDouble));
|
||||
lasth.Write ((int)(ClientSize.Height / DataUtils.UITheme.DPIDouble));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9224
Manager/ManagerShell.resx
Normal file
9224
Manager/ManagerShell.resx
Normal file
File diff suppressed because it is too large
Load Diff
40
Manager/Polyfill.cs
Normal file
40
Manager/Polyfill.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
public static class Polyfill
|
||||
{
|
||||
public static T ParseTo <T> (this string src, T dflt = default (T))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace (src)) return dflt;
|
||||
try
|
||||
{
|
||||
Type targetType = typeof (T);
|
||||
Type underlying = Nullable.GetUnderlyingType (targetType);
|
||||
if (underlying != null)
|
||||
{
|
||||
object v = Convert.ChangeType (src, underlying, CultureInfo.InvariantCulture);
|
||||
return (T)v;
|
||||
}
|
||||
if (targetType.IsEnum)
|
||||
{
|
||||
object enumValue = Enum.Parse (targetType, src, true);
|
||||
return (T)enumValue;
|
||||
}
|
||||
TypeConverter converter = TypeDescriptor.GetConverter (targetType);
|
||||
if (converter != null && converter.CanConvertFrom (typeof (string)))
|
||||
{
|
||||
object v = converter.ConvertFrom (null, CultureInfo.InvariantCulture, src);
|
||||
return (T)v;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return dflt;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Manager/Program.cs
Normal file
32
Manager/Program.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Manager
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
static public readonly string g_appUserId = "WindowsModern.PracticalToolsProject!Manager";
|
||||
static public readonly string g_appId = "Manager";
|
||||
/// <summary>
|
||||
/// 应用程序的主入口点。
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main (string [] args)
|
||||
{
|
||||
Directory.SetCurrentDirectory (AppDomain.CurrentDomain.BaseDirectory);
|
||||
//System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo ("en-US");
|
||||
//System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo ("en-US");
|
||||
AppxPackage.PackageReader.AddApplicationItem ("SmallLogo");
|
||||
AppxPackage.PackageReader.AddApplicationItem ("Square30x30Logo");
|
||||
AppxPackage.PackageReader.AddApplicationItem ("Logo");
|
||||
AppxPackage.PackageReader.AddApplicationItem ("Square44x44Logo");
|
||||
DataUtils.BrowserEmulation.SetWebBrowserEmulation ();
|
||||
Application.EnableVisualStyles ();
|
||||
Application.SetCompatibleTextRenderingDefault (false);
|
||||
Application.Run (new ManagerShell ());
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Manager/Project1.ico
Normal file
BIN
Manager/Project1.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 268 KiB |
36
Manager/Properties/AssemblyInfo.cs
Normal file
36
Manager/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle ("Manager")]
|
||||
[assembly: AssemblyDescription ("")]
|
||||
[assembly: AssemblyConfiguration ("")]
|
||||
[assembly: AssemblyCompany ("")]
|
||||
[assembly: AssemblyProduct ("Manager")]
|
||||
[assembly: AssemblyCopyright ("Copyright © 2026")]
|
||||
[assembly: AssemblyTrademark ("")]
|
||||
[assembly: AssemblyCulture ("")]
|
||||
|
||||
//将 ComVisible 设置为 false 将使此程序集中的类型
|
||||
//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible (false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid ("dc074727-72e4-43c5-baaf-e0d548104797")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
|
||||
// 方法是按如下所示使用“*”: :
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion ("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion ("1.0.0.0")]
|
||||
99
Manager/Properties/Resources.Designer.cs
generated
Normal file
99
Manager/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,99 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Manager.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 一个强类型的资源类,用于查找本地化的字符串等。
|
||||
/// </summary>
|
||||
// 此类是由 StronglyTypedResourceBuilder
|
||||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存的 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Manager.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用此强类型资源类,为所有资源查找
|
||||
/// 重写当前线程的 CurrentUICulture 属性。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 600 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string IDS_DEFAULTHEIGHT {
|
||||
get {
|
||||
return ResourceManager.GetString("IDS_DEFAULTHEIGHT", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 800 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string IDS_DEFAULTWIDTH {
|
||||
get {
|
||||
return ResourceManager.GetString("IDS_DEFAULTWIDTH", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 412 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string IDS_MINHEIGHT {
|
||||
get {
|
||||
return ResourceManager.GetString("IDS_MINHEIGHT", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 504 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string IDS_MINWIDTH {
|
||||
get {
|
||||
return ResourceManager.GetString("IDS_MINWIDTH", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
136
Manager/Properties/Resources.resx
Normal file
136
Manager/Properties/Resources.resx
Normal file
@@ -0,0 +1,136 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="IDS_DEFAULTHEIGHT" xml:space="preserve">
|
||||
<value>600</value>
|
||||
<comment>默认窗口高度</comment>
|
||||
</data>
|
||||
<data name="IDS_DEFAULTWIDTH" xml:space="preserve">
|
||||
<value>800</value>
|
||||
<comment>默认窗口宽度</comment>
|
||||
</data>
|
||||
<data name="IDS_MINHEIGHT" xml:space="preserve">
|
||||
<value>412</value>
|
||||
<comment>默认最小窗口高度</comment>
|
||||
</data>
|
||||
<data name="IDS_MINWIDTH" xml:space="preserve">
|
||||
<value>504</value>
|
||||
<comment>默认最小窗口宽度</comment>
|
||||
</data>
|
||||
</root>
|
||||
30
Manager/Properties/Settings.Designer.cs
generated
Normal file
30
Manager/Properties/Settings.Designer.cs
generated
Normal file
@@ -0,0 +1,30 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Manager.Properties
|
||||
{
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute ()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute ("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings: global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized (new Settings ())));
|
||||
|
||||
public static Settings Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
Manager/Properties/Settings.settings
Normal file
7
Manager/Properties/Settings.settings
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
BIN
Manager/Resources/32_manager.ico
Normal file
BIN
Manager/Resources/32_manager.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 265 KiB |
BIN
Manager/Resources/IconMetro.ico
Normal file
BIN
Manager/Resources/IconMetro.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
663
Manager/ShortcutCreateForm.Designer.cs
generated
Normal file
663
Manager/ShortcutCreateForm.Designer.cs
generated
Normal file
@@ -0,0 +1,663 @@
|
||||
namespace Manager
|
||||
{
|
||||
partial class ShortcutCreateForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose ();
|
||||
}
|
||||
base.Dispose (disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent ()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ShortcutCreateForm));
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.iconSetGen = new System.Windows.Forms.RadioButton();
|
||||
this.iconSetFromFile = new System.Windows.Forms.RadioButton();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.iconFileInput = new System.Windows.Forms.TextBox();
|
||||
this.iconFileBrowser = new System.Windows.Forms.Button();
|
||||
this.label7 = new System.Windows.Forms.Label();
|
||||
this.customIconDisplay = new System.Windows.Forms.PictureBox();
|
||||
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.colorPickerButton = new System.Windows.Forms.Button();
|
||||
this.colorInputAndPreview = new System.Windows.Forms.TextBox();
|
||||
this.label6 = new System.Windows.Forms.Label();
|
||||
this.ratio8_7 = new System.Windows.Forms.RadioButton();
|
||||
this.ratio3_2 = new System.Windows.Forms.RadioButton();
|
||||
this.ratio1_1 = new System.Windows.Forms.RadioButton();
|
||||
this.ratioCustom = new System.Windows.Forms.RadioButton();
|
||||
this.label10 = new System.Windows.Forms.Label();
|
||||
this.tableLayoutPanel6 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.ratioCustomBack = new System.Windows.Forms.TextBox();
|
||||
this.ratioCustomFore = new System.Windows.Forms.TextBox();
|
||||
this.label11 = new System.Windows.Forms.Label();
|
||||
this.label12 = new System.Windows.Forms.Label();
|
||||
this.shortcutNameInput = new System.Windows.Forms.TextBox();
|
||||
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.label8 = new System.Windows.Forms.Label();
|
||||
this.label9 = new System.Windows.Forms.Label();
|
||||
this.imageSizeList = new System.Windows.Forms.DataGridView();
|
||||
this.Column1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.Column2 = new System.Windows.Forms.DataGridViewImageColumn();
|
||||
this.imagesPreview = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.buttonGen = new System.Windows.Forms.Button();
|
||||
this.buttonCancel = new System.Windows.Forms.Button();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.tableLayoutPanel2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.customIconDisplay)).BeginInit();
|
||||
this.tableLayoutPanel3.SuspendLayout();
|
||||
this.tableLayoutPanel6.SuspendLayout();
|
||||
this.tableLayoutPanel4.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.imageSizeList)).BeginInit();
|
||||
this.tableLayoutPanel5.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.ColumnCount = 7;
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 24F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 5F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 5F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 25F));
|
||||
this.tableLayoutPanel1.Controls.Add(this.label1, 1, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.label2, 1, 3);
|
||||
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 1, 5);
|
||||
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel3, 3, 5);
|
||||
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel4, 5, 5);
|
||||
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel5, 1, 7);
|
||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
|
||||
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.RowCount = 9;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 10F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 10F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 10F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(782, 553);
|
||||
this.tableLayoutPanel1.TabIndex = 0;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.label1, 5);
|
||||
this.label1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label1.Font = new System.Drawing.Font("Segoe UI", 19.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label1.Location = new System.Drawing.Point(27, 24);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(727, 46);
|
||||
this.label1.TabIndex = 0;
|
||||
this.label1.Text = "Create Desktop Shortcut";
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.label2, 5);
|
||||
this.label2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label2.Location = new System.Drawing.Point(27, 80);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(727, 60);
|
||||
this.label2.TabIndex = 1;
|
||||
this.label2.Text = resources.GetString("label2.Text");
|
||||
//
|
||||
// tableLayoutPanel2
|
||||
//
|
||||
this.tableLayoutPanel2.ColumnCount = 2;
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 103F));
|
||||
this.tableLayoutPanel2.Controls.Add(this.label3, 0, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.iconSetGen, 0, 2);
|
||||
this.tableLayoutPanel2.Controls.Add(this.iconSetFromFile, 0, 3);
|
||||
this.tableLayoutPanel2.Controls.Add(this.label4, 0, 5);
|
||||
this.tableLayoutPanel2.Controls.Add(this.iconFileInput, 0, 6);
|
||||
this.tableLayoutPanel2.Controls.Add(this.iconFileBrowser, 1, 7);
|
||||
this.tableLayoutPanel2.Controls.Add(this.label7, 0, 8);
|
||||
this.tableLayoutPanel2.Controls.Add(this.customIconDisplay, 0, 9);
|
||||
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel2.Location = new System.Drawing.Point(27, 153);
|
||||
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
|
||||
this.tableLayoutPanel2.RowCount = 10;
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 8F));
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 8F));
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 34F));
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 39F));
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 18F));
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 13F));
|
||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(235, 323);
|
||||
this.tableLayoutPanel2.TabIndex = 2;
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.tableLayoutPanel2.SetColumnSpan(this.label3, 2);
|
||||
this.label3.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label3.Location = new System.Drawing.Point(3, 0);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(229, 40);
|
||||
this.label3.TabIndex = 0;
|
||||
this.label3.Text = "Please select the method for setting the icon.";
|
||||
//
|
||||
// iconSetGen
|
||||
//
|
||||
this.iconSetGen.AutoSize = true;
|
||||
this.iconSetGen.Checked = true;
|
||||
this.tableLayoutPanel2.SetColumnSpan(this.iconSetGen, 2);
|
||||
this.iconSetGen.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.iconSetGen.Location = new System.Drawing.Point(3, 51);
|
||||
this.iconSetGen.Name = "iconSetGen";
|
||||
this.iconSetGen.Size = new System.Drawing.Size(229, 24);
|
||||
this.iconSetGen.TabIndex = 1;
|
||||
this.iconSetGen.TabStop = true;
|
||||
this.iconSetGen.Text = "Generate an icon";
|
||||
this.iconSetGen.UseVisualStyleBackColor = true;
|
||||
this.iconSetGen.CheckedChanged += new System.EventHandler(this.iconSetGen_CheckedChanged);
|
||||
//
|
||||
// iconSetFromFile
|
||||
//
|
||||
this.iconSetFromFile.AutoSize = true;
|
||||
this.tableLayoutPanel2.SetColumnSpan(this.iconSetFromFile, 2);
|
||||
this.iconSetFromFile.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.iconSetFromFile.Location = new System.Drawing.Point(3, 81);
|
||||
this.iconSetFromFile.Name = "iconSetFromFile";
|
||||
this.iconSetFromFile.Size = new System.Drawing.Size(229, 24);
|
||||
this.iconSetFromFile.TabIndex = 2;
|
||||
this.iconSetFromFile.Text = "Use existing icons";
|
||||
this.iconSetFromFile.UseVisualStyleBackColor = true;
|
||||
this.iconSetFromFile.CheckedChanged += new System.EventHandler(this.iconSetFromFile_CheckedChanged);
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.tableLayoutPanel2.SetColumnSpan(this.label4, 2);
|
||||
this.label4.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label4.Location = new System.Drawing.Point(3, 116);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(229, 20);
|
||||
this.label4.TabIndex = 3;
|
||||
this.label4.Text = "Custom icon file path:";
|
||||
//
|
||||
// iconFileInput
|
||||
//
|
||||
this.tableLayoutPanel2.SetColumnSpan(this.iconFileInput, 2);
|
||||
this.iconFileInput.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.iconFileInput.Location = new System.Drawing.Point(3, 139);
|
||||
this.iconFileInput.Name = "iconFileInput";
|
||||
this.iconFileInput.Size = new System.Drawing.Size(229, 27);
|
||||
this.iconFileInput.TabIndex = 4;
|
||||
this.iconFileInput.TextChanged += new System.EventHandler(this.iconFileInput_TextChanged);
|
||||
//
|
||||
// iconFileBrowser
|
||||
//
|
||||
this.iconFileBrowser.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.iconFileBrowser.Location = new System.Drawing.Point(135, 173);
|
||||
this.iconFileBrowser.Name = "iconFileBrowser";
|
||||
this.iconFileBrowser.Size = new System.Drawing.Size(97, 33);
|
||||
this.iconFileBrowser.TabIndex = 5;
|
||||
this.iconFileBrowser.Text = "Browser...";
|
||||
this.iconFileBrowser.UseVisualStyleBackColor = true;
|
||||
this.iconFileBrowser.Click += new System.EventHandler(this.iconFileBrowser_Click);
|
||||
//
|
||||
// label7
|
||||
//
|
||||
this.label7.AutoSize = true;
|
||||
this.label7.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label7.Location = new System.Drawing.Point(3, 209);
|
||||
this.label7.Name = "label7";
|
||||
this.label7.Size = new System.Drawing.Size(126, 18);
|
||||
this.label7.TabIndex = 6;
|
||||
this.label7.Text = "Preview:";
|
||||
//
|
||||
// customIconDisplay
|
||||
//
|
||||
this.customIconDisplay.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
|
||||
this.tableLayoutPanel2.SetColumnSpan(this.customIconDisplay, 2);
|
||||
this.customIconDisplay.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.customIconDisplay.Location = new System.Drawing.Point(3, 230);
|
||||
this.customIconDisplay.Name = "customIconDisplay";
|
||||
this.customIconDisplay.Size = new System.Drawing.Size(229, 90);
|
||||
this.customIconDisplay.TabIndex = 7;
|
||||
this.customIconDisplay.TabStop = false;
|
||||
//
|
||||
// tableLayoutPanel3
|
||||
//
|
||||
this.tableLayoutPanel3.ColumnCount = 2;
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 97F));
|
||||
this.tableLayoutPanel3.Controls.Add(this.label5, 0, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.colorPickerButton, 1, 1);
|
||||
this.tableLayoutPanel3.Controls.Add(this.colorInputAndPreview, 0, 1);
|
||||
this.tableLayoutPanel3.Controls.Add(this.label6, 0, 2);
|
||||
this.tableLayoutPanel3.Controls.Add(this.ratio8_7, 0, 3);
|
||||
this.tableLayoutPanel3.Controls.Add(this.ratio3_2, 0, 4);
|
||||
this.tableLayoutPanel3.Controls.Add(this.ratio1_1, 0, 5);
|
||||
this.tableLayoutPanel3.Controls.Add(this.ratioCustom, 0, 6);
|
||||
this.tableLayoutPanel3.Controls.Add(this.label10, 0, 7);
|
||||
this.tableLayoutPanel3.Controls.Add(this.tableLayoutPanel6, 0, 8);
|
||||
this.tableLayoutPanel3.Controls.Add(this.label12, 0, 9);
|
||||
this.tableLayoutPanel3.Controls.Add(this.shortcutNameInput, 0, 10);
|
||||
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(273, 153);
|
||||
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
|
||||
this.tableLayoutPanel3.RowCount = 11;
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 35F));
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 32F));
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 18F));
|
||||
this.tableLayoutPanel3.Size = new System.Drawing.Size(235, 323);
|
||||
this.tableLayoutPanel3.TabIndex = 3;
|
||||
//
|
||||
// label5
|
||||
//
|
||||
this.label5.AutoSize = true;
|
||||
this.tableLayoutPanel3.SetColumnSpan(this.label5, 2);
|
||||
this.label5.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label5.Location = new System.Drawing.Point(3, 0);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(229, 20);
|
||||
this.label5.TabIndex = 0;
|
||||
this.label5.Text = "Background Color:";
|
||||
//
|
||||
// colorPickerButton
|
||||
//
|
||||
this.colorPickerButton.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.colorPickerButton.Location = new System.Drawing.Point(141, 23);
|
||||
this.colorPickerButton.Name = "colorPickerButton";
|
||||
this.colorPickerButton.Size = new System.Drawing.Size(91, 29);
|
||||
this.colorPickerButton.TabIndex = 1;
|
||||
this.colorPickerButton.Text = "Select";
|
||||
this.colorPickerButton.UseVisualStyleBackColor = true;
|
||||
this.colorPickerButton.Click += new System.EventHandler(this.colorPickerButton_Click);
|
||||
//
|
||||
// colorInputAndPreview
|
||||
//
|
||||
this.colorInputAndPreview.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.colorInputAndPreview.Location = new System.Drawing.Point(3, 23);
|
||||
this.colorInputAndPreview.Name = "colorInputAndPreview";
|
||||
this.colorInputAndPreview.Size = new System.Drawing.Size(132, 27);
|
||||
this.colorInputAndPreview.TabIndex = 2;
|
||||
this.colorInputAndPreview.TextChanged += new System.EventHandler(this.colorInputAndPreview_TextChanged);
|
||||
//
|
||||
// label6
|
||||
//
|
||||
this.label6.AutoSize = true;
|
||||
this.tableLayoutPanel3.SetColumnSpan(this.label6, 2);
|
||||
this.label6.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label6.Location = new System.Drawing.Point(3, 55);
|
||||
this.label6.Name = "label6";
|
||||
this.label6.Size = new System.Drawing.Size(229, 40);
|
||||
this.label6.TabIndex = 3;
|
||||
this.label6.Text = "Background-to-foreground edge ratio";
|
||||
//
|
||||
// ratio8_7
|
||||
//
|
||||
this.ratio8_7.AutoSize = true;
|
||||
this.ratio8_7.Checked = true;
|
||||
this.tableLayoutPanel3.SetColumnSpan(this.ratio8_7, 2);
|
||||
this.ratio8_7.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ratio8_7.Location = new System.Drawing.Point(3, 98);
|
||||
this.ratio8_7.Name = "ratio8_7";
|
||||
this.ratio8_7.Size = new System.Drawing.Size(229, 24);
|
||||
this.ratio8_7.TabIndex = 4;
|
||||
this.ratio8_7.TabStop = true;
|
||||
this.ratio8_7.Text = "8:7";
|
||||
this.ratio8_7.UseVisualStyleBackColor = true;
|
||||
this.ratio8_7.CheckedChanged += new System.EventHandler(this.ratio8_7_CheckedChanged);
|
||||
//
|
||||
// ratio3_2
|
||||
//
|
||||
this.ratio3_2.AutoSize = true;
|
||||
this.tableLayoutPanel3.SetColumnSpan(this.ratio3_2, 2);
|
||||
this.ratio3_2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ratio3_2.Location = new System.Drawing.Point(3, 128);
|
||||
this.ratio3_2.Name = "ratio3_2";
|
||||
this.ratio3_2.Size = new System.Drawing.Size(229, 24);
|
||||
this.ratio3_2.TabIndex = 5;
|
||||
this.ratio3_2.Text = "3:2";
|
||||
this.ratio3_2.UseVisualStyleBackColor = true;
|
||||
this.ratio3_2.CheckedChanged += new System.EventHandler(this.ratio3_2_CheckedChanged);
|
||||
//
|
||||
// ratio1_1
|
||||
//
|
||||
this.ratio1_1.AutoSize = true;
|
||||
this.tableLayoutPanel3.SetColumnSpan(this.ratio1_1, 2);
|
||||
this.ratio1_1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ratio1_1.Location = new System.Drawing.Point(3, 158);
|
||||
this.ratio1_1.Name = "ratio1_1";
|
||||
this.ratio1_1.Size = new System.Drawing.Size(229, 24);
|
||||
this.ratio1_1.TabIndex = 6;
|
||||
this.ratio1_1.Text = "1:1";
|
||||
this.ratio1_1.UseVisualStyleBackColor = true;
|
||||
this.ratio1_1.CheckedChanged += new System.EventHandler(this.ratio1_1_CheckedChanged);
|
||||
//
|
||||
// ratioCustom
|
||||
//
|
||||
this.ratioCustom.AutoSize = true;
|
||||
this.tableLayoutPanel3.SetColumnSpan(this.ratioCustom, 2);
|
||||
this.ratioCustom.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ratioCustom.Location = new System.Drawing.Point(3, 188);
|
||||
this.ratioCustom.Name = "ratioCustom";
|
||||
this.ratioCustom.Size = new System.Drawing.Size(229, 24);
|
||||
this.ratioCustom.TabIndex = 7;
|
||||
this.ratioCustom.Text = "Custom";
|
||||
this.ratioCustom.UseVisualStyleBackColor = true;
|
||||
this.ratioCustom.CheckedChanged += new System.EventHandler(this.ratioCustom_CheckedChanged);
|
||||
//
|
||||
// label10
|
||||
//
|
||||
this.label10.AutoSize = true;
|
||||
this.tableLayoutPanel3.SetColumnSpan(this.label10, 2);
|
||||
this.label10.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label10.Location = new System.Drawing.Point(3, 215);
|
||||
this.label10.Name = "label10";
|
||||
this.label10.Size = new System.Drawing.Size(229, 20);
|
||||
this.label10.TabIndex = 8;
|
||||
this.label10.Text = "Custom Ratio:";
|
||||
//
|
||||
// tableLayoutPanel6
|
||||
//
|
||||
this.tableLayoutPanel6.ColumnCount = 3;
|
||||
this.tableLayoutPanel3.SetColumnSpan(this.tableLayoutPanel6, 2);
|
||||
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel6.Controls.Add(this.ratioCustomBack, 0, 0);
|
||||
this.tableLayoutPanel6.Controls.Add(this.ratioCustomFore, 2, 0);
|
||||
this.tableLayoutPanel6.Controls.Add(this.label11, 1, 0);
|
||||
this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 235);
|
||||
this.tableLayoutPanel6.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tableLayoutPanel6.Name = "tableLayoutPanel6";
|
||||
this.tableLayoutPanel6.RowCount = 1;
|
||||
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel6.Size = new System.Drawing.Size(235, 32);
|
||||
this.tableLayoutPanel6.TabIndex = 9;
|
||||
//
|
||||
// ratioCustomBack
|
||||
//
|
||||
this.ratioCustomBack.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ratioCustomBack.Location = new System.Drawing.Point(3, 3);
|
||||
this.ratioCustomBack.Name = "ratioCustomBack";
|
||||
this.ratioCustomBack.Size = new System.Drawing.Size(101, 27);
|
||||
this.ratioCustomBack.TabIndex = 0;
|
||||
this.ratioCustomBack.Text = "8";
|
||||
this.ratioCustomBack.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// ratioCustomFore
|
||||
//
|
||||
this.ratioCustomFore.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.ratioCustomFore.Location = new System.Drawing.Point(130, 3);
|
||||
this.ratioCustomFore.Name = "ratioCustomFore";
|
||||
this.ratioCustomFore.Size = new System.Drawing.Size(102, 27);
|
||||
this.ratioCustomFore.TabIndex = 1;
|
||||
this.ratioCustomFore.Text = "7";
|
||||
this.ratioCustomFore.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
//
|
||||
// label11
|
||||
//
|
||||
this.label11.AutoSize = true;
|
||||
this.label11.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label11.Location = new System.Drawing.Point(110, 0);
|
||||
this.label11.Name = "label11";
|
||||
this.label11.Size = new System.Drawing.Size(14, 32);
|
||||
this.label11.TabIndex = 2;
|
||||
this.label11.Text = ":";
|
||||
this.label11.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// label12
|
||||
//
|
||||
this.label12.AutoSize = true;
|
||||
this.tableLayoutPanel3.SetColumnSpan(this.label12, 2);
|
||||
this.label12.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label12.Location = new System.Drawing.Point(3, 267);
|
||||
this.label12.Name = "label12";
|
||||
this.label12.Size = new System.Drawing.Size(229, 20);
|
||||
this.label12.TabIndex = 10;
|
||||
this.label12.Text = "Shortcut Display Name";
|
||||
//
|
||||
// shortcutNameInput
|
||||
//
|
||||
this.tableLayoutPanel3.SetColumnSpan(this.shortcutNameInput, 2);
|
||||
this.shortcutNameInput.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.shortcutNameInput.Location = new System.Drawing.Point(3, 290);
|
||||
this.shortcutNameInput.Name = "shortcutNameInput";
|
||||
this.shortcutNameInput.Size = new System.Drawing.Size(229, 27);
|
||||
this.shortcutNameInput.TabIndex = 11;
|
||||
//
|
||||
// tableLayoutPanel4
|
||||
//
|
||||
this.tableLayoutPanel4.ColumnCount = 1;
|
||||
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel4.Controls.Add(this.label8, 0, 0);
|
||||
this.tableLayoutPanel4.Controls.Add(this.label9, 0, 2);
|
||||
this.tableLayoutPanel4.Controls.Add(this.imageSizeList, 0, 1);
|
||||
this.tableLayoutPanel4.Controls.Add(this.imagesPreview, 0, 3);
|
||||
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel4.Location = new System.Drawing.Point(519, 153);
|
||||
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
|
||||
this.tableLayoutPanel4.RowCount = 4;
|
||||
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel4.Size = new System.Drawing.Size(235, 323);
|
||||
this.tableLayoutPanel4.TabIndex = 4;
|
||||
//
|
||||
// label8
|
||||
//
|
||||
this.label8.AutoSize = true;
|
||||
this.label8.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label8.Location = new System.Drawing.Point(3, 0);
|
||||
this.label8.Name = "label8";
|
||||
this.label8.Size = new System.Drawing.Size(229, 20);
|
||||
this.label8.TabIndex = 0;
|
||||
this.label8.Text = "Image List:";
|
||||
//
|
||||
// label9
|
||||
//
|
||||
this.label9.AutoSize = true;
|
||||
this.label9.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label9.Location = new System.Drawing.Point(3, 161);
|
||||
this.label9.Name = "label9";
|
||||
this.label9.Size = new System.Drawing.Size(229, 20);
|
||||
this.label9.TabIndex = 1;
|
||||
this.label9.Text = "Preview:";
|
||||
//
|
||||
// imageSizeList
|
||||
//
|
||||
this.imageSizeList.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this.imageSizeList.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
||||
this.Column1,
|
||||
this.Column2});
|
||||
this.imageSizeList.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.imageSizeList.Location = new System.Drawing.Point(3, 23);
|
||||
this.imageSizeList.Name = "imageSizeList";
|
||||
this.imageSizeList.RowTemplate.Height = 27;
|
||||
this.imageSizeList.Size = new System.Drawing.Size(229, 135);
|
||||
this.imageSizeList.TabIndex = 2;
|
||||
this.imageSizeList.CellDoubleClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.imageSizeList_CellDoubleClick);
|
||||
//
|
||||
// Column1
|
||||
//
|
||||
this.Column1.HeaderText = "Size";
|
||||
this.Column1.Name = "Column1";
|
||||
this.Column1.Width = 50;
|
||||
//
|
||||
// Column2
|
||||
//
|
||||
this.Column2.HeaderText = "Image";
|
||||
this.Column2.Name = "Column2";
|
||||
//
|
||||
// imagesPreview
|
||||
//
|
||||
this.imagesPreview.AutoScroll = true;
|
||||
this.imagesPreview.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.imagesPreview.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
|
||||
this.imagesPreview.Location = new System.Drawing.Point(3, 184);
|
||||
this.imagesPreview.Name = "imagesPreview";
|
||||
this.imagesPreview.Size = new System.Drawing.Size(229, 136);
|
||||
this.imagesPreview.TabIndex = 3;
|
||||
//
|
||||
// tableLayoutPanel5
|
||||
//
|
||||
this.tableLayoutPanel5.ColumnCount = 5;
|
||||
this.tableLayoutPanel1.SetColumnSpan(this.tableLayoutPanel5, 5);
|
||||
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 100F));
|
||||
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 172F));
|
||||
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 100F));
|
||||
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel5.Controls.Add(this.buttonGen, 1, 1);
|
||||
this.tableLayoutPanel5.Controls.Add(this.buttonCancel, 3, 1);
|
||||
this.tableLayoutPanel5.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel5.Location = new System.Drawing.Point(24, 489);
|
||||
this.tableLayoutPanel5.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tableLayoutPanel5.Name = "tableLayoutPanel5";
|
||||
this.tableLayoutPanel5.RowCount = 3;
|
||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 32F));
|
||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel5.Size = new System.Drawing.Size(733, 40);
|
||||
this.tableLayoutPanel5.TabIndex = 5;
|
||||
//
|
||||
// buttonGen
|
||||
//
|
||||
this.buttonGen.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.buttonGen.Location = new System.Drawing.Point(180, 4);
|
||||
this.buttonGen.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.buttonGen.Name = "buttonGen";
|
||||
this.buttonGen.Size = new System.Drawing.Size(100, 32);
|
||||
this.buttonGen.TabIndex = 0;
|
||||
this.buttonGen.Text = "Generate";
|
||||
this.buttonGen.UseVisualStyleBackColor = true;
|
||||
this.buttonGen.Click += new System.EventHandler(this.buttonGen_Click);
|
||||
//
|
||||
// buttonCancel
|
||||
//
|
||||
this.buttonCancel.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.buttonCancel.Location = new System.Drawing.Point(452, 4);
|
||||
this.buttonCancel.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.buttonCancel.Name = "buttonCancel";
|
||||
this.buttonCancel.Size = new System.Drawing.Size(100, 32);
|
||||
this.buttonCancel.TabIndex = 1;
|
||||
this.buttonCancel.Text = "Cancel";
|
||||
this.buttonCancel.UseVisualStyleBackColor = true;
|
||||
this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
|
||||
//
|
||||
// ShortcutCreateForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.Color.White;
|
||||
this.ClientSize = new System.Drawing.Size(782, 553);
|
||||
this.Controls.Add(this.tableLayoutPanel1);
|
||||
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||
this.Name = "ShortcutCreateForm";
|
||||
this.ShowIcon = false;
|
||||
this.Text = "ShortcutCreateForm";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ShortcutCreateForm_FormClosing);
|
||||
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ShortcutCreateForm_FormClosed);
|
||||
this.Load += new System.EventHandler(this.ShortcutCreateForm_Load);
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.PerformLayout();
|
||||
this.tableLayoutPanel2.ResumeLayout(false);
|
||||
this.tableLayoutPanel2.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.customIconDisplay)).EndInit();
|
||||
this.tableLayoutPanel3.ResumeLayout(false);
|
||||
this.tableLayoutPanel3.PerformLayout();
|
||||
this.tableLayoutPanel6.ResumeLayout(false);
|
||||
this.tableLayoutPanel6.PerformLayout();
|
||||
this.tableLayoutPanel4.ResumeLayout(false);
|
||||
this.tableLayoutPanel4.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.imageSizeList)).EndInit();
|
||||
this.tableLayoutPanel5.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.RadioButton iconSetGen;
|
||||
private System.Windows.Forms.RadioButton iconSetFromFile;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.TextBox iconFileInput;
|
||||
private System.Windows.Forms.Button iconFileBrowser;
|
||||
private System.Windows.Forms.Label label7;
|
||||
private System.Windows.Forms.PictureBox customIconDisplay;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3;
|
||||
private System.Windows.Forms.Label label5;
|
||||
private System.Windows.Forms.Button colorPickerButton;
|
||||
private System.Windows.Forms.TextBox colorInputAndPreview;
|
||||
private System.Windows.Forms.Label label6;
|
||||
private System.Windows.Forms.RadioButton ratio8_7;
|
||||
private System.Windows.Forms.RadioButton ratio3_2;
|
||||
private System.Windows.Forms.RadioButton ratio1_1;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
|
||||
private System.Windows.Forms.Label label8;
|
||||
private System.Windows.Forms.Label label9;
|
||||
private System.Windows.Forms.RadioButton ratioCustom;
|
||||
private System.Windows.Forms.Label label10;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6;
|
||||
private System.Windows.Forms.TextBox ratioCustomBack;
|
||||
private System.Windows.Forms.TextBox ratioCustomFore;
|
||||
private System.Windows.Forms.Label label11;
|
||||
private System.Windows.Forms.DataGridView imageSizeList;
|
||||
private System.Windows.Forms.DataGridViewTextBoxColumn Column1;
|
||||
private System.Windows.Forms.DataGridViewImageColumn Column2;
|
||||
private System.Windows.Forms.FlowLayoutPanel imagesPreview;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel5;
|
||||
private System.Windows.Forms.Button buttonGen;
|
||||
private System.Windows.Forms.Button buttonCancel;
|
||||
private System.Windows.Forms.Label label12;
|
||||
private System.Windows.Forms.TextBox shortcutNameInput;
|
||||
}
|
||||
}
|
||||
571
Manager/ShortcutCreateForm.cs
Normal file
571
Manager/ShortcutCreateForm.cs
Normal file
@@ -0,0 +1,571 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Bridge;
|
||||
namespace Manager
|
||||
{
|
||||
public partial class ShortcutCreateForm: Form
|
||||
{
|
||||
public ShortcutCreateForm ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_TITLE");
|
||||
label1.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_TITLE");
|
||||
label2.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_DESC");
|
||||
label3.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_ICONTYPE");
|
||||
iconSetGen.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_ICONTYPE_GEN");
|
||||
iconSetFromFile.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_ICONTYPE_SEL");
|
||||
label4.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_ICONTYPE_SEL_ICONPATH");
|
||||
iconFileBrowser.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_BROWSE");
|
||||
label7.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_PREVIEW");
|
||||
label5.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_BACKGROUNDCOLOR");
|
||||
colorPickerButton.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_SELECT");
|
||||
label6.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_RATIO");
|
||||
ratioCustom.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_RATIO_CUSTOM");
|
||||
label10.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_RATIO_CUSTOMRATIO");
|
||||
label12.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_DISPLAYNAME");
|
||||
label8.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_IMAGELIST");
|
||||
label9.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_PREVIEW");
|
||||
buttonGen.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_GENERATE");
|
||||
buttonCancel.Text = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_CANCEL");
|
||||
Column1.HeaderText = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_SIZE");
|
||||
Column2.HeaderText = ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_IMAGE");
|
||||
_imageItems.ListChanged += ImageItems_ListChanged;
|
||||
RefreshCustomRatioStatus ();
|
||||
RefreshIconSourceMode ();
|
||||
}
|
||||
private void ImageItems_ListChanged (object sender, ListChangedEventArgs e) { RefreshImagePreview (); }
|
||||
void RefreshImagePreview ()
|
||||
{
|
||||
imagesPreview.SuspendLayout ();
|
||||
imagesPreview.Controls.Clear ();
|
||||
foreach (var item in _imageItems.OrderBy (i => i.Size))
|
||||
{
|
||||
var display = new ImageDisplay
|
||||
{
|
||||
IconSize = item.Size,
|
||||
ForegroundImage = item.Image,
|
||||
BackgroundColor = GetCurrentBackgroundColor (),
|
||||
Ratio = GetCurrentRatio ()
|
||||
};
|
||||
imagesPreview.Controls.Add (display);
|
||||
}
|
||||
imagesPreview.ResumeLayout ();
|
||||
}
|
||||
void UpdateRatio (decimal ratio)
|
||||
{
|
||||
foreach (ImageDisplay d in imagesPreview.Controls) d.Ratio = ratio;
|
||||
}
|
||||
void UpdateBackgroundColor (Color color)
|
||||
{
|
||||
foreach (ImageDisplay d in imagesPreview.Controls) d.BackgroundColor = color;
|
||||
}
|
||||
public Color GetCurrentBackgroundColor () => DataUtils.UITheme.StringToColor (colorInputAndPreview.Text);
|
||||
public decimal GetCurrentRatio ()
|
||||
{
|
||||
if (ratio8_7.Checked) return (decimal)(8m / 7m);
|
||||
if (ratio3_2.Checked) return 1.5m;
|
||||
if (ratio1_1.Checked) return 1m;
|
||||
try
|
||||
{
|
||||
if (ratioCustom.Checked)
|
||||
{
|
||||
decimal l = 0m, r = 0m;
|
||||
decimal.TryParse (ratioCustomBack.Text, out l);
|
||||
decimal.TryParse (ratioCustomFore.Text, out r);
|
||||
return l / r;
|
||||
}
|
||||
} catch { }
|
||||
return 0m;
|
||||
}
|
||||
class ImageItem
|
||||
{
|
||||
public int Size { get; set; }
|
||||
public Image Image { get; set; }
|
||||
}
|
||||
private BindingList<ImageItem> _imageItems = new BindingList<ImageItem>();
|
||||
Dictionary<int, string> ExtractBest (Dictionary<AppxPackage.PriResourceKey, string> source, int baseSize)
|
||||
{
|
||||
if (source == null || source.Count == 0) return null;
|
||||
var result = new Dictionary<int, string> ();
|
||||
foreach (var kv in source)
|
||||
{
|
||||
if (kv.Key.IsTargetSize &&
|
||||
kv.Key.Contrast == AppxPackage.PriResourceKey.PriContrast.None)
|
||||
{
|
||||
result [kv.Key.Value] = kv.Value;
|
||||
}
|
||||
}
|
||||
if (result.Count > 0) return result;
|
||||
foreach (var kv in source)
|
||||
{
|
||||
if (kv.Key.IsTargetSize)
|
||||
{
|
||||
result [kv.Key.Value] = kv.Value;
|
||||
}
|
||||
}
|
||||
if (result.Count > 0) return result;
|
||||
foreach (var kv in source)
|
||||
{
|
||||
if (kv.Key.IsScale &&
|
||||
kv.Key.Contrast == AppxPackage.PriResourceKey.PriContrast.None)
|
||||
{
|
||||
int size = (int)(kv.Key.Value * 0.01 * baseSize);
|
||||
result [size] = kv.Value;
|
||||
}
|
||||
}
|
||||
if (result.Count > 0)
|
||||
return result;
|
||||
foreach (var kv in source)
|
||||
{
|
||||
if (kv.Key.IsScale)
|
||||
{
|
||||
int size = (int)(kv.Key.Value * 0.01 * baseSize);
|
||||
result [size] = kv.Value;
|
||||
}
|
||||
}
|
||||
return result.Count > 0 ? result : null;
|
||||
}
|
||||
void InitImageList (Dictionary<int, Image> images)
|
||||
{
|
||||
_imageItems = new BindingList<ImageItem> (
|
||||
images.Select (kv => new ImageItem
|
||||
{
|
||||
Size = kv.Key,
|
||||
Image = kv.Value
|
||||
}).ToList ()
|
||||
);
|
||||
imageSizeList.AutoGenerateColumns = false;
|
||||
Column1.DataPropertyName = nameof (ImageItem.Size);
|
||||
Column2.DataPropertyName = nameof (ImageItem.Image);
|
||||
imageSizeList.DataSource = _imageItems;
|
||||
|
||||
}
|
||||
private string installLocation = "";
|
||||
private string genAppUserId = "";
|
||||
private Dictionary<int, Image> _initList = new Dictionary<int, Image> ();
|
||||
private void InitInfos ()
|
||||
{
|
||||
try
|
||||
{
|
||||
_initList?.Clear ();
|
||||
_initList = null;
|
||||
using (var m = new AppxPackage.ManifestReader (Path.Combine (installLocation, "AppxManifest.xml")))
|
||||
{
|
||||
m.EnablePri = false;
|
||||
m.UsePri = true;
|
||||
AppxPackage.MRApplication app = null;
|
||||
string logo_30 = "",
|
||||
smallLogo = "",
|
||||
logo = "",
|
||||
logo_44 = "";
|
||||
foreach (var i in m.Applications)
|
||||
{
|
||||
if (i.UserModelID?.Trim ()?.ToLowerInvariant () == genAppUserId?.Trim ()?.ToLowerInvariant ())
|
||||
{
|
||||
app = i;
|
||||
logo_44 = app ["Square44x44Logo"];
|
||||
logo_30 = app ["Square30x30Logo"];
|
||||
logo = app ["Logo"];
|
||||
smallLogo = app ["SmallLogo"];
|
||||
break;
|
||||
}
|
||||
}
|
||||
m.EnablePri = true;
|
||||
foreach (var i in m.Applications)
|
||||
{
|
||||
if (i.UserModelID?.Trim ()?.ToLowerInvariant () == genAppUserId?.Trim ()?.ToLowerInvariant ())
|
||||
{
|
||||
app = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.Invoke ((Action)(() =>
|
||||
{
|
||||
colorInputAndPreview.Text = app ["BackgroundColor"];
|
||||
shortcutNameInput.Text = app ["DisplayName"];
|
||||
if (string.IsNullOrWhiteSpace (shortcutNameInput.Text))
|
||||
shortcutNameInput.Text = app ["SmallLogo"];
|
||||
}));
|
||||
Dictionary<AppxPackage.PriResourceKey, string> logo_30list = m.PriFile.ResourceAllValues (logo_30),
|
||||
logo_smalllist = m.PriFile.ResourceAllValues (smallLogo),
|
||||
logo_list = m.PriFile.ResourceAllValues (logo),
|
||||
logo_44list = m.PriFile.ResourceAllValues (logo_44);
|
||||
Dictionary<int, string> filteredlist = null;
|
||||
filteredlist =
|
||||
ExtractBest (logo_44list, 44)
|
||||
?? ExtractBest (logo_30list, 30)
|
||||
?? ExtractBest (logo_smalllist, 30)
|
||||
?? ExtractBest (logo_list, 150);
|
||||
Dictionary<int, Image> imageList = new Dictionary<int, Image> ();
|
||||
foreach (var kv in filteredlist)
|
||||
{
|
||||
try
|
||||
{
|
||||
var imgPath = Path.Combine (installLocation, kv.Value);
|
||||
var img = Image.FromFile (imgPath);
|
||||
if (img == null) continue;
|
||||
imageList [kv.Key] = img;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
_initList = imageList;
|
||||
this.Invoke ((Action)(() =>
|
||||
{
|
||||
InitImageList (imageList);
|
||||
RefreshImagePreview ();
|
||||
RefreshCustomRatioStatus ();
|
||||
RefreshIconSourceMode ();
|
||||
}));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.Invoke ((Action)(() => _imageItems.Clear ()));
|
||||
}
|
||||
}
|
||||
private void InitAsync ()
|
||||
{
|
||||
var loading = new LoadingStatusForm ();
|
||||
{
|
||||
loading.Show (this);
|
||||
loading.Refresh ();
|
||||
this.Invoke ((Action)(() => { Enabled = false; }));
|
||||
|
||||
Task.Factory.StartNew (() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
InitInfos ();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Invoke ((Action)(() =>
|
||||
{
|
||||
MessageBox.Show ($"Initialization failed: {ex.Message}");
|
||||
}));
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Invoke ((Action)(() =>
|
||||
{
|
||||
loading.Close ();
|
||||
Enabled = true;
|
||||
}));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
public string InstallLocation
|
||||
{
|
||||
get { return installLocation; }
|
||||
set { installLocation = value; InitAsync (); }
|
||||
}
|
||||
public string AppUserModelID
|
||||
{
|
||||
get { return genAppUserId; }
|
||||
set { genAppUserId = value; InitAsync (); }
|
||||
}
|
||||
public void InitCreater (string inslocation, string appUserId)
|
||||
{
|
||||
installLocation = inslocation;
|
||||
genAppUserId = appUserId;
|
||||
InitAsync ();
|
||||
}
|
||||
private void ShortcutCreateForm_Load (object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
private void ratio8_7_CheckedChanged (object sender, EventArgs e) { RefreshCustomRatioStatus (); }
|
||||
private void ratio3_2_CheckedChanged (object sender, EventArgs e) { RefreshCustomRatioStatus (); }
|
||||
private void ratio1_1_CheckedChanged (object sender, EventArgs e) { RefreshCustomRatioStatus (); }
|
||||
private void ratioCustom_CheckedChanged (object sender, EventArgs e) { RefreshCustomRatioStatus (); }
|
||||
private void RefreshCustomRatioStatus ()
|
||||
{
|
||||
ratioCustomBack.Enabled = ratioCustomFore.Enabled = ratioCustom.Checked;
|
||||
UpdateRatio (GetCurrentRatio ());
|
||||
}
|
||||
private void iconSetGen_CheckedChanged (object sender, EventArgs e) { RefreshIconSourceMode (); }
|
||||
private void iconSetFromFile_CheckedChanged (object sender, EventArgs e) { RefreshIconSourceMode (); }
|
||||
private void RefreshIconSourceMode ()
|
||||
{
|
||||
iconFileInput.Enabled = iconFileBrowser.Enabled = iconSetFromFile.Checked;
|
||||
colorInputAndPreview.Enabled = colorPickerButton.Enabled =
|
||||
ratio8_7.Enabled = ratio3_2.Enabled = ratio1_1.Enabled =
|
||||
ratioCustom.Enabled = ratioCustomBack.Enabled = ratioCustomFore.Enabled =
|
||||
iconSetGen.Checked;
|
||||
if (iconSetGen.Checked)
|
||||
{
|
||||
RefreshCustomRatioStatus ();
|
||||
}
|
||||
if (iconSetFromFile.Checked)
|
||||
{
|
||||
try
|
||||
{
|
||||
customIconDisplay.Image = new Icon (iconFileInput.Text)?.ToBitmap ();
|
||||
}
|
||||
catch
|
||||
{
|
||||
customIconDisplay.Image = null;
|
||||
}
|
||||
}
|
||||
else customIconDisplay.Image = null;
|
||||
}
|
||||
private void colorInputAndPreview_TextChanged (object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Color nowColor = DataUtils.UITheme.StringToColor (colorInputAndPreview.Text);
|
||||
double luminance = nowColor.R * 0.299 + nowColor.G * 0.587 + nowColor.B * 0.114;
|
||||
Color foreground = luminance < 128 ? Color.White : Color.Black;
|
||||
colorInputAndPreview.BackColor = nowColor;
|
||||
colorInputAndPreview.ForeColor = foreground;
|
||||
UpdateBackgroundColor (nowColor);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
private Bitmap GenerateIconBitmap (int size, Image foreground, Color background, decimal ratio)
|
||||
{
|
||||
var bmp = new Bitmap (size, size);
|
||||
using (var g = Graphics.FromImage (bmp))
|
||||
{
|
||||
g.Clear (background);
|
||||
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
|
||||
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
|
||||
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
|
||||
float foreSize = (float)(size / ratio);
|
||||
float x = (size - foreSize) / 2f;
|
||||
float y = (size - foreSize) / 2f;
|
||||
var destRect = new RectangleF (x, y, foreSize, foreSize);
|
||||
g.DrawImage (foreground, destRect);
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
Dictionary<int, Image> GenerateAllIconImages ()
|
||||
{
|
||||
var result = new Dictionary<int, Image> ();
|
||||
Color bg = GetCurrentBackgroundColor ();
|
||||
decimal ratio = GetCurrentRatio ();
|
||||
foreach (var item in _imageItems)
|
||||
{
|
||||
var bmp = GenerateIconBitmap (item.Size, item.Image, bg, ratio);
|
||||
result [item.Size] = bmp;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static void SaveAsIcon (Dictionary<int, Image> images, string filePath)
|
||||
{
|
||||
using (var fs = new FileStream (filePath, FileMode.Create))
|
||||
using (var bw = new BinaryWriter (fs))
|
||||
{
|
||||
bw.Write ((short)0); // reserved
|
||||
bw.Write ((short)1); // type = icon
|
||||
bw.Write ((short)images.Count);
|
||||
int offset = 6 + (16 * images.Count);
|
||||
var imageData = new List<byte []> ();
|
||||
foreach (var kv in images.OrderBy (i => i.Key))
|
||||
{
|
||||
using (var ms = new MemoryStream ())
|
||||
{
|
||||
kv.Value.Save (ms, System.Drawing.Imaging.ImageFormat.Png);
|
||||
byte [] data = ms.ToArray ();
|
||||
imageData.Add (data);
|
||||
bw.Write ((byte)(kv.Key >= 256 ? 0 : kv.Key)); // width
|
||||
bw.Write ((byte)(kv.Key >= 256 ? 0 : kv.Key)); // height
|
||||
bw.Write ((byte)0); // color count
|
||||
bw.Write ((byte)0); // reserved
|
||||
bw.Write ((short)1); // planes
|
||||
bw.Write ((short)32); // bit count
|
||||
bw.Write (data.Length);
|
||||
bw.Write (offset);
|
||||
offset += data.Length;
|
||||
}
|
||||
}
|
||||
foreach (var data in imageData) bw.Write (data);
|
||||
}
|
||||
}
|
||||
private void iconFileInput_TextChanged (object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
customIconDisplay.Image = new Icon (iconFileInput.Text)?.ToBitmap ();
|
||||
}
|
||||
catch
|
||||
{
|
||||
customIconDisplay.Image = null;
|
||||
}
|
||||
}
|
||||
private void imageSizeList_CellDoubleClick (object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
if (e.RowIndex < 0) return;
|
||||
if (imageSizeList.Columns [e.ColumnIndex] != Column2) return;
|
||||
var item = _imageItems [e.RowIndex];
|
||||
var isf = new ImageSetForm ();
|
||||
isf.CurrentSize = item.Size;
|
||||
isf.DefaultImages = _initList;
|
||||
isf.FinalImage = item.Image;
|
||||
isf.ShowDialog (this);
|
||||
var newimg = isf.FinalImage;
|
||||
if (newimg != null)
|
||||
{
|
||||
item.Image = newimg;
|
||||
RefreshImagePreview ();
|
||||
}
|
||||
}
|
||||
public bool IsSuccess { get; private set; } = false;
|
||||
public string Message { get; private set; } = "";
|
||||
private void buttonCancel_Click (object sender, EventArgs e)
|
||||
{
|
||||
IsSuccess = false;
|
||||
Message = "User canceled.";
|
||||
this.Close ();
|
||||
}
|
||||
private void ShortcutCreateForm_FormClosed (object sender, FormClosedEventArgs e)
|
||||
{
|
||||
_imageItems?.Clear ();
|
||||
_imageItems = null;
|
||||
_initList?.Clear ();
|
||||
_initList = null;
|
||||
}
|
||||
public static bool IsValidFileName (string fileName, bool requireExtension = true)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace (fileName)) return false;
|
||||
if (fileName.IndexOfAny (Path.GetInvalidFileNameChars ()) >= 0) return false;
|
||||
if (fileName.EndsWith (" ") || fileName.EndsWith (".")) return false;
|
||||
if (requireExtension)
|
||||
{
|
||||
if (!Path.HasExtension (fileName)) return false;
|
||||
string ext = Path.GetExtension (fileName);
|
||||
if (string.IsNullOrWhiteSpace (ext) || ext == ".") return false;
|
||||
}
|
||||
string nameWithoutExtension = Path.GetFileNameWithoutExtension (fileName);
|
||||
string [] reservedNames =
|
||||
{
|
||||
"CON", "PRN", "AUX", "NUL",
|
||||
"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
|
||||
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"
|
||||
};
|
||||
if (reservedNames.Contains (nameWithoutExtension.ToUpper ())) return false;
|
||||
if (fileName.Length > 255) return false;
|
||||
return true;
|
||||
}
|
||||
private void buttonGen_Click (object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsValidFileName (shortcutNameInput.Text, false))
|
||||
{
|
||||
MessageBox.Show (this, "Invalid shortcut name.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return;
|
||||
}
|
||||
var iconfilename = "";
|
||||
var iconfilepath = "";
|
||||
if (iconSetGen.Checked)
|
||||
{
|
||||
iconfilename = genAppUserId.Replace ('!', '-') + ".ico";
|
||||
iconfilepath = Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "icons", iconfilename);
|
||||
if (File.Exists (iconfilepath))
|
||||
{
|
||||
#region gen twice;
|
||||
var dlgres = MessageBox.Show (
|
||||
this,
|
||||
ResXmlStore.StringRes.Get ("MANAGER_APP_SHORTCUTCREATE_ASK_ICONEXISTS"),
|
||||
"Ask",
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Question
|
||||
);
|
||||
if (dlgres == DialogResult.Yes)
|
||||
{
|
||||
try
|
||||
{
|
||||
iconfilename = genAppUserId.Replace ('!', '-') + "-" + DateTime.Now.GetHashCode () + ".ico";
|
||||
iconfilepath = Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "icons", iconfilename);
|
||||
var icons = GenerateAllIconImages ();
|
||||
SaveAsIcon (icons, iconfilepath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show (this, "Cannot create icon, we will fallback. Message: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
iconfilename = genAppUserId.Replace ('!', '-') + ".ico";
|
||||
iconfilepath = Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "icons", iconfilename);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
else
|
||||
{
|
||||
var icons = GenerateAllIconImages ();
|
||||
SaveAsIcon (icons, iconfilepath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iconfilepath = iconFileInput.Text;
|
||||
}
|
||||
var shortcutname = shortcutNameInput.Text + ".lnk";
|
||||
var shortcutpath = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Desktop), shortcutname);
|
||||
ShortcutHelper.CreateShortcut (
|
||||
shortcutpath,
|
||||
Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "Launch.exe"),
|
||||
genAppUserId,
|
||||
null,
|
||||
iconfilepath,
|
||||
shortcutNameInput.Text,
|
||||
genAppUserId
|
||||
);
|
||||
IsSuccess = true;
|
||||
Message = "";
|
||||
this.Close ();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
IsSuccess = false;
|
||||
Message = ex.Message;
|
||||
this.Close ();
|
||||
}
|
||||
}
|
||||
private void ShortcutCreateForm_FormClosing (object sender, FormClosingEventArgs e)
|
||||
{
|
||||
if (!IsSuccess && string.IsNullOrWhiteSpace (Message))
|
||||
{
|
||||
IsSuccess = false;
|
||||
Message = "User canceled.";
|
||||
}
|
||||
}
|
||||
|
||||
private void colorPickerButton_Click (object sender, EventArgs e)
|
||||
{
|
||||
using (var colorpicker = new ColorDialog ())
|
||||
{
|
||||
colorpicker.Color = GetCurrentBackgroundColor ();
|
||||
var dlgres = colorpicker.ShowDialog (this);
|
||||
if (dlgres == DialogResult.OK)
|
||||
{
|
||||
colorInputAndPreview.Text = DataUtils.UITheme.ColorToHtml (colorpicker.Color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void iconFileBrowser_Click (object sender, EventArgs e)
|
||||
{
|
||||
using (OpenFileDialog dlg = new OpenFileDialog ())
|
||||
{
|
||||
dlg.Title = "Please select the icon file:";
|
||||
dlg.Filter = "Icon File (*.ico)|*.ico";
|
||||
dlg.CheckFileExists = true;
|
||||
dlg.CheckPathExists = true;
|
||||
dlg.Multiselect = false;
|
||||
dlg.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
if (dlg.ShowDialog () == DialogResult.OK)
|
||||
{
|
||||
iconFileInput.Text = dlg.FileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user