Update
@@ -44,6 +44,22 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "priformatcli", "priformatcl
|
||||
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
|
||||
{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}
|
||||
{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
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -174,6 +190,66 @@ Global
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{512BF866-1AA0-4169-A7D6-D2776B5D731E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}.Release|x86.Build.0 = Release|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Debug|x64.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|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BD681A4F-EB60-4BB8-90B5-65968FC7DA59}.Release|x64.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|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|x64.Build.0 = Release|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{FFD3FD52-37A8-4F43-883C-DE8D996CB0E0}.Release|x86.Build.0 = Release|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|x64.Build.0 = Release|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{3C2F5446-33F0-41D5-813A-64A94AA474AF}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
74
AppxPackage/AppxPackage.csproj
Normal file
@@ -0,0 +1,74 @@
|
||||
<?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="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="PkgMgrNative.cs" />
|
||||
<Compile Include="PkgReadNative.cs" />
|
||||
<Compile Include="PriFileNative.cs" />
|
||||
<Compile Include="PriReader.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</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>
|
||||
189
AppxPackage/PkgMgrNative.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
// 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;
|
||||
|
||||
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);
|
||||
|
||||
// ========== 托管辅助 ==========
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
301
AppxPackage/PkgReadNative.cs
Normal file
@@ -0,0 +1,301 @@
|
||||
// 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;
|
||||
|
||||
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
|
||||
{
|
||||
crt_free (nativePtr);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 忽略释放失败(注意可能的 CRT 不匹配风险)
|
||||
}
|
||||
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
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
77
AppxPackage/PriFileNative.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
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, ref LPCWSTRLIST hUriList);
|
||||
|
||||
[DllImport (DLL, CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void FindPriPathResource (PCSPRIFILE pFilePri, ref LPCWSTRLIST 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, ref LPCWSTRLIST 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);
|
||||
public static string PtrToString (IntPtr ptr)
|
||||
{
|
||||
if (ptr == IntPtr.Zero) return null;
|
||||
string s = Marshal.PtrToStringUni (ptr);
|
||||
Marshal.FreeHGlobal (ptr); // 如果 DLL 返回的内存要求 free
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
[StructLayout (LayoutKind.Sequential)]
|
||||
public struct LPCWSTRLIST
|
||||
{
|
||||
public uint dwLength; // DWORD
|
||||
[MarshalAs (UnmanagedType.ByValArray, SizeConst = 1)]
|
||||
public IntPtr [] aswArray; // LPCWSTR*,数组
|
||||
}
|
||||
|
||||
}
|
||||
12
AppxPackage/PriReader.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AppxPackage
|
||||
{
|
||||
class PriReader
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
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")]
|
||||
80
Bridge/Bridge.csproj
Normal file
@@ -0,0 +1,80 @@
|
||||
<?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>
|
||||
<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="..\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
@@ -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")]
|
||||
183
Bridge/SysInit.cs
Normal file
@@ -0,0 +1,183 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Win32;
|
||||
using DataUtils;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
using System.Drawing;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
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
|
||||
{
|
||||
InitConfig Create (string filepath) => new InitConfig (filepath);
|
||||
InitConfig GetConfig () => InitFileStore.Config;
|
||||
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_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 string CmdArgs
|
||||
{
|
||||
get
|
||||
{
|
||||
return JsonConvert.SerializeObject (
|
||||
Environment.GetCommandLineArgs ()
|
||||
);
|
||||
}
|
||||
}
|
||||
public _I_BridgeBase (Form wnd, IScriptBridge isc, IWebBrowserPageScale iwbps)
|
||||
{
|
||||
window = new _I_Window (isc);
|
||||
system = new _I_System (wnd);
|
||||
ieframe = new _I_IEFrame (iwbps);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
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
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="13.0.4" targetFramework="net40" />
|
||||
</packages>
|
||||
78
DataUtils/DataUtils.csproj
Normal file
@@ -0,0 +1,78 @@
|
||||
<?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>
|
||||
<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="Download.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="WebBrowser.cs" />
|
||||
<Compile Include="Window.cs" />
|
||||
</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>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
373
DataUtils/Locale.cs
Normal file
@@ -0,0 +1,373 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
[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;
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
201
DataUtils/Process.cs
Normal file
@@ -0,0 +1,201 @@
|
||||
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 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
@@ -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")]
|
||||
272
DataUtils/ResourceXml.cs
Normal file
@@ -0,0 +1,272 @@
|
||||
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 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
@@ -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 */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
519
DataUtils/Storage.cs
Normal file
@@ -0,0 +1,519 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
// 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_Storage
|
||||
{
|
||||
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); }
|
||||
}
|
||||
// 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
@@ -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
@@ -0,0 +1,274 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DataUtils
|
||||
{
|
||||
internal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
80
DataUtils/Taskbar.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
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 ITaskbarList3 _taskbar;
|
||||
private readonly IntPtr _hwnd;
|
||||
public TaskbarProgress (IntPtr hwnd)
|
||||
{
|
||||
_hwnd = hwnd;
|
||||
_taskbar = (ITaskbarList3)new TaskbarList ();
|
||||
_taskbar.HrInit ();
|
||||
}
|
||||
public void SetState (TBPFLAG state)
|
||||
{
|
||||
_taskbar.SetProgressState (_hwnd, state);
|
||||
}
|
||||
public void SetValue (ulong completed, ulong total)
|
||||
{
|
||||
_taskbar.SetProgressValue (_hwnd, completed, total);
|
||||
}
|
||||
public void Clear ()
|
||||
{
|
||||
_taskbar.SetProgressState (_hwnd, TBPFLAG.TBPF_NOPROGRESS);
|
||||
}
|
||||
public void Dispose ()
|
||||
{
|
||||
Clear ();
|
||||
Marshal.ReleaseComObject (_taskbar);
|
||||
}
|
||||
}
|
||||
}
|
||||
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 ();
|
||||
|
||||
// Named color
|
||||
try
|
||||
{
|
||||
Color byName = Color.FromName (s);
|
||||
if (byName.IsKnownColor || byName.IsNamedColor)
|
||||
{
|
||||
return byName;
|
||||
}
|
||||
}
|
||||
catch { /* ignore */ }
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 ();
|
||||
}
|
||||
}
|
||||
185
DataUtils/Utils.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
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 () ?? "";
|
||||
}
|
||||
}
|
||||
368
DataUtils/Version.cs
Normal file
@@ -0,0 +1,368 @@
|
||||
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>
|
||||
{
|
||||
// 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 void FromUInt64 (ulong value)
|
||||
{
|
||||
major = (ushort)((value >> 48) & 0xFFFFUL);
|
||||
minor = (ushort)((value >> 32) & 0xFFFFUL);
|
||||
build = (ushort)((value >> 16) & 0xFFFFUL);
|
||||
revision = (ushort)(value & 0xFFFFUL);
|
||||
}
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
[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
@@ -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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
40
DataUtils/WebBrowser.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
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,
|
||||
ref object pvaIn,
|
||||
ref object pvaOut
|
||||
);
|
||||
}
|
||||
public static class WebBrowserHelper
|
||||
{
|
||||
public static IWebBrowser2 GetWebBrowser2 (WebBrowser browser)
|
||||
{
|
||||
return browser.ActiveXInstance as IWebBrowser2;
|
||||
}
|
||||
}
|
||||
public interface IWebBrowserPageScale
|
||||
{
|
||||
int PageScale { get; set; }
|
||||
}
|
||||
}
|
||||
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
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="13.0.4" targetFramework="net40" />
|
||||
</packages>
|
||||
@@ -1,3 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
</configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/></startup></configuration>
|
||||
|
||||
236
PrivateInit/InitHelper.cs
Normal file
@@ -0,0 +1,236 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace InitFileHelper
|
||||
{
|
||||
public static class IniFile
|
||||
{
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Ansi)]
|
||||
private static extern uint GetPrivateProfileStringA (string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, uint nSize, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern uint GetPrivateProfileStringW (string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, uint nSize, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Ansi)]
|
||||
private static extern uint GetPrivateProfileSectionA (string lpAppName, byte [] lpReturnedString, uint nSize, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern uint GetPrivateProfileSectionW (string lpAppName, char [] lpReturnedString, uint nSize, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Ansi)]
|
||||
private static extern uint GetPrivateProfileSectionNamesA (byte [] lpszReturnBuffer, uint nSize, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern uint GetPrivateProfileSectionNamesW (char [] lpszReturnBuffer, uint nSize, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Ansi)]
|
||||
private static extern uint GetPrivateProfileIntA (string lpAppName, string lpKeyName, int nDefault, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern uint GetPrivateProfileIntW (string lpAppName, string lpKeyName, int nDefault, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Ansi)]
|
||||
private static extern bool WritePrivateProfileStringA (string lpAppName, string lpKeyName, string lpString, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern bool WritePrivateProfileStringW (string lpAppName, string lpKeyName, string lpString, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Ansi)]
|
||||
private static extern bool WritePrivateProfileSectionA (string lpAppName, string lpString, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern bool WritePrivateProfileSectionW (string lpAppName, string lpString, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Ansi)]
|
||||
private static extern bool GetPrivateProfileStructA (string lpAppName, string lpKeyName, IntPtr lpStruct, uint uSize, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern bool GetPrivateProfileStructW (string lpAppName, string lpKeyName, IntPtr lpStruct, uint uSize, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Ansi)]
|
||||
private static extern bool WritePrivateProfileStructA (string lpAppName, string lpKeyName, IntPtr lpStruct, uint uSize, string lpFileName);
|
||||
[DllImport ("kernel32.dll", CharSet = CharSet.Unicode)]
|
||||
private static extern bool WritePrivateProfileStructW (string lpAppName, string lpKeyName, IntPtr lpStruct, uint uSize, string lpFileName);
|
||||
|
||||
public static string GetPrivateProfileStringA (string filePath, string section, string key, string defaultValue = "")
|
||||
{
|
||||
StringBuilder buf = new StringBuilder (32768);
|
||||
GetPrivateProfileStringA (section, key, defaultValue, buf, (uint)buf.Capacity, filePath);
|
||||
return buf.ToString ();
|
||||
}
|
||||
public static string GetPrivateProfileStringW (string filePath, string section, string key, string defaultValue = "")
|
||||
{
|
||||
StringBuilder buf = new StringBuilder (32768);
|
||||
GetPrivateProfileStringW (section, key, defaultValue, buf, (uint)buf.Capacity, filePath);
|
||||
return buf.ToString ();
|
||||
}
|
||||
public static uint GetPrivateProfileIntA (string filePath, string section, string key, int defaultValue = 0)
|
||||
{
|
||||
return GetPrivateProfileIntA (section, key, defaultValue, filePath);
|
||||
}
|
||||
public static uint GetPrivateProfileIntW (string filePath, string section, string key, int defaultValue = 0)
|
||||
{
|
||||
return GetPrivateProfileIntW (section, key, defaultValue, filePath);
|
||||
}
|
||||
public static bool WritePrivateProfileString (string filePath, string section, string key, string value)
|
||||
{
|
||||
return WritePrivateProfileStringW (section, key, value, filePath);
|
||||
}
|
||||
public static int GetPrivateProfileSectionA (string filePath, string section, List<string> output)
|
||||
{
|
||||
byte [] buf = new byte [32768];
|
||||
uint len = GetPrivateProfileSectionA (section, buf, (uint)buf.Length, filePath);
|
||||
output.Clear ();
|
||||
if (len == 0) return 0;
|
||||
int i = 0;
|
||||
while (i < len)
|
||||
{
|
||||
int start = i;
|
||||
while (i < len && buf [i] != 0) i++;
|
||||
if (i > start) output.Add (Encoding.Default.GetString (buf, start, i - start));
|
||||
i++;
|
||||
}
|
||||
return output.Count;
|
||||
}
|
||||
public static int GetPrivateProfileSectionW (string filePath, string section, List<string> output)
|
||||
{
|
||||
char [] buf = new char [32768];
|
||||
uint len = GetPrivateProfileSectionW (section, buf, (uint)buf.Length, filePath);
|
||||
output.Clear ();
|
||||
if (len == 0) return 0;
|
||||
int i = 0;
|
||||
while (i < len)
|
||||
{
|
||||
int start = i;
|
||||
while (i < len && buf [i] != '\0') i++;
|
||||
if (i > start) output.Add (new string (buf, start, i - start));
|
||||
i++;
|
||||
}
|
||||
return output.Count;
|
||||
}
|
||||
public static int GetPrivateProfileSectionNamesA (string filePath, List<string> output)
|
||||
{
|
||||
byte [] buf = new byte [32768];
|
||||
uint len = GetPrivateProfileSectionNamesA (buf, (uint)buf.Length, filePath);
|
||||
output.Clear ();
|
||||
if (len == 0) return 0;
|
||||
int i = 0;
|
||||
while (i < len)
|
||||
{
|
||||
int start = i;
|
||||
while (i < len && buf [i] != 0) i++;
|
||||
if (i > start) output.Add (Encoding.Default.GetString (buf, start, i - start));
|
||||
i++;
|
||||
}
|
||||
return output.Count;
|
||||
}
|
||||
public static int GetPrivateProfileSectionNamesW (string filePath, List<string> output)
|
||||
{
|
||||
char [] buf = new char [32768];
|
||||
uint len = GetPrivateProfileSectionNamesW (buf, (uint)buf.Length, filePath);
|
||||
output.Clear ();
|
||||
if (len == 0) return 0;
|
||||
int i = 0;
|
||||
while (i < len)
|
||||
{
|
||||
int start = i;
|
||||
while (i < len && buf [i] != '\0') i++;
|
||||
if (i > start) output.Add (new string (buf, start, i - start));
|
||||
i++;
|
||||
}
|
||||
return output.Count;
|
||||
}
|
||||
public static bool WritePrivateProfileSectionA (string filePath, string section, List<string> lines)
|
||||
{
|
||||
string buf = string.Join ("\0", lines) + "\0\0";
|
||||
return WritePrivateProfileSectionA (section, buf, filePath);
|
||||
}
|
||||
public static bool WritePrivateProfileSectionW (string filePath, string section, List<string> lines)
|
||||
{
|
||||
string buf = string.Join ("\0", lines) + "\0\0";
|
||||
return WritePrivateProfileSectionW (section, buf, filePath);
|
||||
}
|
||||
public static bool GetPrivateProfileStructA (string filePath, string section, string key, IntPtr output, uint size)
|
||||
{
|
||||
return GetPrivateProfileStructA (section, key, output, size, filePath);
|
||||
}
|
||||
public static bool GetPrivateProfileStructW (string filePath, string section, string key, IntPtr output, uint size)
|
||||
{
|
||||
return GetPrivateProfileStructW (section, key, output, size, filePath);
|
||||
}
|
||||
public static bool WritePrivateProfileStructA (string filePath, string section, string key, IntPtr data, uint size)
|
||||
{
|
||||
return WritePrivateProfileStructA (section, key, data, size, filePath);
|
||||
}
|
||||
public static bool WritePrivateProfileStructW (string filePath, string section, string key, IntPtr data, uint size)
|
||||
{
|
||||
return WritePrivateProfileStructW (section, key, data, size, filePath);
|
||||
}
|
||||
public static int GetPrivateProfileKeysA (string filePath, string section, List<string> keys)
|
||||
{
|
||||
List<string> lines = new List<string> ();
|
||||
int count = GetPrivateProfileSectionA (filePath, section, lines);
|
||||
keys.Clear ();
|
||||
foreach (var line in lines)
|
||||
{
|
||||
int pos = line.IndexOf ('=');
|
||||
if (pos != -1) keys.Add (line.Substring (0, pos));
|
||||
}
|
||||
return keys.Count;
|
||||
}
|
||||
public static int GetPrivateProfileKeysW (string filePath, string section, List<string> keys)
|
||||
{
|
||||
List<string> lines = new List<string> ();
|
||||
int count = GetPrivateProfileSectionW (filePath, section, lines);
|
||||
keys.Clear ();
|
||||
foreach (var line in lines)
|
||||
{
|
||||
int pos = line.IndexOf ('=');
|
||||
if (pos != -1) keys.Add (line.Substring (0, pos));
|
||||
}
|
||||
return keys.Count;
|
||||
}
|
||||
public static bool DeletePrivateProfileKeyA (string filePath, string section, string key)
|
||||
{
|
||||
return WritePrivateProfileStringA (section, key, null, filePath);
|
||||
}
|
||||
public static bool DeletePrivateProfileKeyW (string filePath, string section, string key)
|
||||
{
|
||||
return WritePrivateProfileStringW (section, key, null, filePath);
|
||||
}
|
||||
public static bool DeletePrivateProfileSectionA (string filePath, string section)
|
||||
{
|
||||
return WritePrivateProfileStringA (section, null, null, filePath);
|
||||
}
|
||||
public static bool DeletePrivateProfileSectionW (string filePath, string section)
|
||||
{
|
||||
return WritePrivateProfileStringW (section, null, null, filePath);
|
||||
}
|
||||
}
|
||||
[ComVisible (true)]
|
||||
public static class BoolHelper
|
||||
{
|
||||
public static readonly string [] trueValue =
|
||||
{
|
||||
"true", "zhen", "yes", "真", "1"
|
||||
};
|
||||
public static readonly string [] falseValue =
|
||||
{
|
||||
"false", "jia", "no", "假", "0"
|
||||
};
|
||||
public static bool ConvertToBool (string str)
|
||||
{
|
||||
if (str == null) throw new ArgumentNullException (nameof (str));
|
||||
str = str.Trim ().ToLowerInvariant ();
|
||||
if (trueValue.Any (s => s.ToLowerInvariant () == str)) return true;
|
||||
if (falseValue.Any (s => s.ToLowerInvariant () == str)) return false;
|
||||
throw new FormatException ($"Cannot convert '{str}' to bool.");
|
||||
}
|
||||
public static bool TryParseBool (string str, out bool result)
|
||||
{
|
||||
result = false;
|
||||
if (str == null) return false;
|
||||
str = str.Trim ().ToLowerInvariant ();
|
||||
if (trueValue.Any (s => s.ToLowerInvariant () == str))
|
||||
{
|
||||
result = true;
|
||||
return true;
|
||||
}
|
||||
if (falseValue.Any (s => s.ToLowerInvariant () == str))
|
||||
{
|
||||
result = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
55
PrivateInit/PrivateInit.csproj
Normal file
@@ -0,0 +1,55 @@
|
||||
<?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>{8E708D9A-6325-4AA9-B5A5-D1B5ECA8EEF7}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>PrivateInit</RootNamespace>
|
||||
<AssemblyName>PrivateInit</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</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>
|
||||
<RegisterForComInterop>false</RegisterForComInterop>
|
||||
</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.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="InitHelper.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Win32.cs" />
|
||||
</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
PrivateInit/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle ("初始化配置文件读取")]
|
||||
[assembly: AssemblyDescription ("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany ("Windows Modern")]
|
||||
[assembly: AssemblyProduct ("Windows 现代风格实用工具")]
|
||||
[assembly: AssemblyCopyright ("Copyright © 2026 Windows Modern。版权所有。")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//将 ComVisible 设置为 false 将使此程序集中的类型
|
||||
//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible (true)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("8e708d9a-6325-4aa9-b5a5-d1b5eca8eef7")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
|
||||
// 方法是按如下所示使用“*”: :
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
198
PrivateInit/Win32.cs
Normal file
@@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using InitFileHelper;
|
||||
|
||||
namespace Win32
|
||||
{
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class RefString
|
||||
{
|
||||
public string Value { get; set; }
|
||||
public RefString (string value) { Value = value; }
|
||||
public RefString (ref string value) { Value = value; }
|
||||
public static RefString operator + (RefString a, RefString b)
|
||||
{
|
||||
if (ReferenceEquals (a, null)) return b;
|
||||
if (ReferenceEquals (b, null)) return a;
|
||||
return new RefString (a.Value + b.Value);
|
||||
}
|
||||
|
||||
public static RefString operator + (RefString a, string b)
|
||||
{
|
||||
if (ReferenceEquals (a, null)) return new RefString (b);
|
||||
return new RefString (a.Value + b);
|
||||
}
|
||||
public static RefString operator + (string a, RefString b)
|
||||
{
|
||||
if (ReferenceEquals (b, null)) return new RefString (a);
|
||||
return new RefString (a + b.Value);
|
||||
}
|
||||
public static implicit operator RefString (string v) => new RefString (v);
|
||||
public static implicit operator string (RefString r) => r?.Value;
|
||||
public static bool operator == (RefString a, RefString b)
|
||||
{
|
||||
if (ReferenceEquals (a, b)) return true;
|
||||
if (ReferenceEquals (a, null) || ReferenceEquals (b, null)) return false;
|
||||
return a.Value == b.Value;
|
||||
}
|
||||
public static bool operator != (RefString a, RefString b) => !(a == b);
|
||||
|
||||
public static bool operator == (RefString a, string b)
|
||||
{
|
||||
if (ReferenceEquals (a, null)) return b == null;
|
||||
return a.Value == b;
|
||||
}
|
||||
|
||||
public static bool operator != (RefString a, string b) => !(a == b);
|
||||
public override bool Equals (object obj)
|
||||
{
|
||||
if (obj is RefString) return this == (RefString)obj;
|
||||
if (obj is string) return this == (string)obj;
|
||||
return false;
|
||||
}
|
||||
public override int GetHashCode () => Value?.GetHashCode () ?? 0;
|
||||
public override string ToString () => Value;
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class InitKey
|
||||
{
|
||||
private RefString filepath = "";
|
||||
private RefString section = "";
|
||||
private RefString key = "";
|
||||
public string FilePath => filepath.Value;
|
||||
public string Section => section.Value;
|
||||
public string Key { get { return key; } set { key.Value = value; } }
|
||||
public InitKey (RefString _fp, RefString _sect, RefString _key)
|
||||
{
|
||||
filepath = _fp;
|
||||
section = _sect;
|
||||
key = _key;
|
||||
}
|
||||
public string ReadString (string dflt = "") { return IniFile.GetPrivateProfileStringW (filepath, section, key, dflt); }
|
||||
private T ReadTo<T> (T dflt, Func<string, T> convTo)
|
||||
{
|
||||
string str = ReadString (dflt?.ToString () ?? "");
|
||||
try { return convTo (str); }
|
||||
catch { return dflt; }
|
||||
}
|
||||
public short ReadShort (short dflt = 0) { return ReadTo (dflt, Convert.ToInt16); }
|
||||
public ushort ReadUShort (ushort dflt = 0) { return ReadTo (dflt, Convert.ToUInt16); }
|
||||
public int ReadInt (int dflt = 0) { return ReadTo (dflt, Convert.ToInt32); }
|
||||
public uint ReadUInt (uint dflt = 0) { return ReadTo (dflt, Convert.ToUInt32); }
|
||||
public long ReadLong (long dflt = 0) { return ReadTo (dflt, Convert.ToInt64); }
|
||||
public ulong ReadULong (ulong dflt = 0) { return ReadTo (dflt, Convert.ToUInt64); }
|
||||
public Int16 ReadInt16 (Int16 dflt = 0) { return ReadTo (dflt, Convert.ToInt16); }
|
||||
public UInt16 ReadUInt16 (UInt16 dflt = 0) { return ReadTo (dflt, Convert.ToUInt16); }
|
||||
public Int32 ReadInt32 (Int32 dflt = 0) { return ReadTo (dflt, Convert.ToInt32); }
|
||||
public UInt32 ReadUInt32 (UInt32 dflt = 0) { return ReadTo (dflt, Convert.ToUInt32); }
|
||||
public Int64 ReadInt64 (Int64 dflt = 0) { return ReadTo (dflt, Convert.ToInt64); }
|
||||
public UInt64 ReadUInt64 (UInt64 dflt = 0) { return ReadTo (dflt, Convert.ToUInt64); }
|
||||
public bool ReadBool (bool dflt = false) { return ReadTo (dflt, BoolHelper.ConvertToBool); }
|
||||
public float ReadFloat (float dflt = 0) { return ReadTo (dflt, Convert.ToSingle); }
|
||||
public double ReadDouble (double dflt = 0) { return ReadTo (dflt, Convert.ToDouble); }
|
||||
public decimal ReadDecimal (decimal dflt = 0) { return ReadTo (dflt, Convert.ToDecimal); }
|
||||
public sbyte ReadInt8 (sbyte dflt = 0) { return ReadTo (dflt, Convert.ToSByte); }
|
||||
public byte ReadUInt8 (byte dflt = 0) { return ReadTo (dflt, Convert.ToByte); }
|
||||
public byte ReadByte (byte dflt = 0) { return ReadTo (dflt, Convert.ToByte); }
|
||||
public sbyte ReadSByte (sbyte dflt = 0) { return ReadTo (dflt, Convert.ToSByte); }
|
||||
public DateTime ReadDateTime (DateTime dflt = default (DateTime)) { return ReadTo (dflt, Convert.ToDateTime); }
|
||||
public object Get (object dflt) { return ReadString (dflt?.ToString () ?? ""); }
|
||||
public object Get () { return ReadString (); }
|
||||
public bool WriteString (string value) { return IniFile.WritePrivateProfileString (filepath, section, key, value); }
|
||||
public bool Write (string value) { return WriteString (value); }
|
||||
private bool WriteTo <T> (T value) { return WriteString (value?.ToString ()); }
|
||||
public bool Write (byte value) { return WriteTo (value); }
|
||||
public bool Write (sbyte value) { return WriteTo (value); }
|
||||
public bool Write (short value) { return WriteTo (value); }
|
||||
public bool Write (ushort value) { return WriteTo (value); }
|
||||
public bool Write (int value) { return WriteTo (value); }
|
||||
public bool Write (uint value) { return WriteTo (value); }
|
||||
public bool Write (long value) { return WriteTo (value); }
|
||||
public bool Write (ulong value) { return WriteTo (value); }
|
||||
public bool Write (bool value) { return WriteTo (value); }
|
||||
public bool Write (float value) { return WriteTo (value); }
|
||||
public bool Write (double value) { return WriteTo (value); }
|
||||
public bool Write (decimal value) { return WriteTo (value); }
|
||||
public bool Write (DateTime value) { return WriteTo (value); }
|
||||
public bool Set (object value) { return Write (value?.ToString ()); }
|
||||
public object Value { get { return Get (); } set { Set (value); } }
|
||||
public bool KeyExists
|
||||
{
|
||||
get
|
||||
{
|
||||
string val = IniFile.GetPrivateProfileStringW (filepath, section, key, null);
|
||||
return val != null;
|
||||
}
|
||||
}
|
||||
public bool ValueExists
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!KeyExists) return false;
|
||||
string val = IniFile.GetPrivateProfileStringW (filepath, section, key, "");
|
||||
return !string.IsNullOrEmpty (val);
|
||||
}
|
||||
}
|
||||
public bool DeleteKey () => IniFile.WritePrivateProfileString (filepath, section, key, null);
|
||||
public bool Clear () => DeleteKey ();
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class InitSection
|
||||
{
|
||||
private RefString filepath = "";
|
||||
private RefString section = "";
|
||||
public string FilePath => filepath.Value;
|
||||
public string Section { get { return section; } set { section.Value = value; } }
|
||||
public InitSection (RefString _fp, RefString _sect)
|
||||
{
|
||||
filepath = _fp;
|
||||
section = _sect;
|
||||
}
|
||||
public InitKey GetKey (string key) => new InitKey (filepath, section, key);
|
||||
public object Get (string key, object dflt = null) => GetKey (key).Get (dflt);
|
||||
public object Get (string key) => GetKey (key).Get ();
|
||||
public bool Set (string key, object value) => GetKey (key).Set (value);
|
||||
public object this [string key]
|
||||
{
|
||||
get { return Get (key); }
|
||||
set { Set (key, value); }
|
||||
}
|
||||
public string [] GetAllKeys ()
|
||||
{
|
||||
var keys = new System.Collections.Generic.List<string> ();
|
||||
IniFile.GetPrivateProfileKeysW (filepath, section, keys);
|
||||
return keys.ToArray ();
|
||||
}
|
||||
public InitKey [] Keys
|
||||
{
|
||||
get { return GetAllKeys ().Select (k => new InitKey (filepath, section, k)).ToArray (); }
|
||||
}
|
||||
public bool DeleteSection () => IniFile.WritePrivateProfileString (filepath, section, null, null);
|
||||
public bool Clear () => DeleteSection ();
|
||||
}
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public class InitConfig
|
||||
{
|
||||
private RefString filepath = "";
|
||||
public string FilePath { get { return filepath.Value; } set { filepath.Value = value; } }
|
||||
public InitConfig (string _fp = "") { FilePath = _fp; }
|
||||
public InitSection GetSection (string section) => new InitSection (filepath, section);
|
||||
public InitKey GetKey (string section, string key) => new InitKey (filepath, section, key);
|
||||
public object Get (string section, string key, object dflt) => GetKey (section, key).Get (dflt);
|
||||
public object Get (string section, string key) => GetKey (section, key).Get ();
|
||||
public bool Set (string section, string key, object value) => GetKey (section, key).Set (value);
|
||||
public object this [string key] => GetSection (key);
|
||||
public string [] GetAllSections ()
|
||||
{
|
||||
var sections = new System.Collections.Generic.List<string> ();
|
||||
IniFile.GetPrivateProfileSectionNamesW (filepath, sections);
|
||||
return sections.ToArray ();
|
||||
}
|
||||
public InitSection [] Sections => GetAllSections ().Select (s => new InitSection (filepath, s)).ToArray ();
|
||||
}
|
||||
}
|
||||
@@ -5,12 +5,12 @@ using System.Runtime.InteropServices;
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle ("Update")]
|
||||
[assembly: AssemblyTitle ("更新")]
|
||||
[assembly: AssemblyDescription ("")]
|
||||
[assembly: AssemblyConfiguration ("")]
|
||||
[assembly: AssemblyCompany ("")]
|
||||
[assembly: AssemblyProduct ("Update")]
|
||||
[assembly: AssemblyCopyright ("Copyright © 2026")]
|
||||
[assembly: AssemblyCompany ("Windows Modern")]
|
||||
[assembly: AssemblyProduct ("Windows 现代风格实用工具")]
|
||||
[assembly: AssemblyCopyright ("Copyright © 2026 Windows Modern。版权所有。")]
|
||||
[assembly: AssemblyTrademark ("")]
|
||||
[assembly: AssemblyCulture ("")]
|
||||
|
||||
|
||||
@@ -73,6 +73,12 @@
|
||||
<ItemGroup>
|
||||
<Content Include="Project1.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\settings\settings.vcxproj">
|
||||
<Project>{ad25497f-a15f-4dff-ac7a-b8abf5f411d6}</Project>
|
||||
<Name>settings</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.
|
||||
|
||||
36
WAShell/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("WAShell")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("WAShell")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2026")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
//将 ComVisible 设置为 false 将使此程序集中的类型
|
||||
//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible (true)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("4ec16578-efbf-41e6-8d7f-976e3646dd1d")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
|
||||
// 方法是按如下所示使用“*”: :
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
83
WAShell/SplashForm.Designer.cs
generated
Normal file
@@ -0,0 +1,83 @@
|
||||
namespace WAShell
|
||||
{
|
||||
partial class SplashForm
|
||||
{
|
||||
/// <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.components = new System.ComponentModel.Container();
|
||||
this.picbox = new System.Windows.Forms.PictureBox();
|
||||
this.timer = new System.Windows.Forms.Timer(this.components);
|
||||
((System.ComponentModel.ISupportInitialize)(this.picbox)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// picbox
|
||||
//
|
||||
this.picbox.Anchor = System.Windows.Forms.AnchorStyles.None;
|
||||
this.picbox.BackColor = System.Drawing.Color.Transparent;
|
||||
this.picbox.Location = new System.Drawing.Point(6, 47);
|
||||
this.picbox.Name = "picbox";
|
||||
this.picbox.Size = new System.Drawing.Size(620, 300);
|
||||
this.picbox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.picbox.TabIndex = 0;
|
||||
this.picbox.TabStop = false;
|
||||
//
|
||||
// timer
|
||||
//
|
||||
this.timer.Tick += new System.EventHandler(this.timer_Tick);
|
||||
//
|
||||
// SplashForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.BackColor = System.Drawing.SystemColors.Window;
|
||||
this.ClientSize = new System.Drawing.Size(632, 425);
|
||||
this.Controls.Add(this.picbox);
|
||||
this.DoubleBuffered = true;
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "SplashForm";
|
||||
this.ShowIcon = false;
|
||||
this.ShowInTaskbar = false;
|
||||
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Splash Screen";
|
||||
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.SplashForm_FormClosed);
|
||||
this.Load += new System.EventHandler(this.SplashForm_Load);
|
||||
this.Shown += new System.EventHandler(this.SplashForm_Shown);
|
||||
this.Resize += new System.EventHandler(this.SplashForm_Resize);
|
||||
((System.ComponentModel.ISupportInitialize)(this.picbox)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.PictureBox picbox;
|
||||
private System.Windows.Forms.Timer timer;
|
||||
}
|
||||
}
|
||||
229
WAShell/SplashForm.cs
Normal file
@@ -0,0 +1,229 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using DataUtils;
|
||||
namespace WAShell
|
||||
{
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public partial class SplashForm: Form
|
||||
{
|
||||
public enum FadeType
|
||||
{
|
||||
Gradually,
|
||||
Immediately
|
||||
};
|
||||
private Image splashImage = null;
|
||||
private Color background = Color.Transparent;
|
||||
private FadeType fadeMode = FadeType.Gradually;
|
||||
double opastep = 0.05;
|
||||
private Control _host = null;
|
||||
public Control Host
|
||||
{
|
||||
get { return _host; }
|
||||
set
|
||||
{
|
||||
if (ReferenceEquals (_host, value)) return;
|
||||
DetachHostEvents (_host);
|
||||
_host = value;
|
||||
AttachHostEvents (_host);
|
||||
if (this.Visible)
|
||||
{
|
||||
ResizeSplashScreen ();
|
||||
}
|
||||
}
|
||||
}
|
||||
private void AttachHostEvents (Control host)
|
||||
{
|
||||
if (host == null) return;
|
||||
host.Resize += Host_Changed;
|
||||
host.LocationChanged += Host_Changed;
|
||||
}
|
||||
private void DetachHostEvents (Control host)
|
||||
{
|
||||
if (host == null) return;
|
||||
|
||||
host.Resize -= Host_Changed;
|
||||
host.LocationChanged -= Host_Changed;
|
||||
}
|
||||
private void Host_Changed (object sender, EventArgs e)
|
||||
{
|
||||
if (!this.IsHandleCreated) return;
|
||||
ResizeSplashScreen ();
|
||||
}
|
||||
public SplashForm ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
Init ();
|
||||
}
|
||||
private void Init ()
|
||||
{
|
||||
this.AllowTransparency = true;
|
||||
picbox.Size = new Size (
|
||||
(int)(620 * UITheme.DPIDouble),
|
||||
(int)(300 * UITheme.DPIDouble)
|
||||
);
|
||||
try { picbox.Image = splashImage; } catch (Exception) { }
|
||||
try { this.BackColor = background; } catch (Exception) { }
|
||||
}
|
||||
public Image SplashImage
|
||||
{
|
||||
get { return splashImage; }
|
||||
set
|
||||
{
|
||||
splashImage = value;
|
||||
if (picbox != null && picbox.IsHandleCreated)
|
||||
{
|
||||
splashImage = picbox.Image;
|
||||
}
|
||||
}
|
||||
}
|
||||
public Color SplashBackgroundColor
|
||||
{
|
||||
get { try { return background = this.BackColor; } catch (Exception) { return background; } }
|
||||
set
|
||||
{
|
||||
background = value;
|
||||
try { this.BackColor = background; }
|
||||
catch (Exception) { background = this.BackColor; }
|
||||
}
|
||||
}
|
||||
private void SplashForm_Load (object sender, EventArgs e)
|
||||
{
|
||||
ResizeSplashScreen ();
|
||||
}
|
||||
private void ResizeSplashScreen ()
|
||||
{
|
||||
Control owner = this.Owner;
|
||||
if (owner == null) owner = this.Parent;
|
||||
if (owner == null) return;
|
||||
owner.Update ();
|
||||
var pt = owner.PointToScreen (owner.ClientRectangle.Location);
|
||||
Location = pt;
|
||||
Size = owner.ClientSize;
|
||||
ResizeSplashImage ();
|
||||
}
|
||||
private void ResizeSplashImage ()
|
||||
{
|
||||
if (picbox != null && picbox.IsHandleCreated)
|
||||
{
|
||||
var sz = this.ClientSize;
|
||||
picbox.Location = new Point (
|
||||
(int)((sz.Width - picbox.Width) * 0.5),
|
||||
(int)((sz.Height - picbox.Height) * 0.5)
|
||||
);
|
||||
}
|
||||
}
|
||||
private void SplashForm_Resize (object sender, EventArgs e)
|
||||
{
|
||||
ResizeSplashImage ();
|
||||
}
|
||||
private bool fadeAwayArmed = false; // 用于 FadeAway 的“第一次 / 第二次”
|
||||
private bool fading = false; // 防止重复启动 Timer
|
||||
protected virtual void OnFormFade ()
|
||||
{
|
||||
switch (fadeMode)
|
||||
{
|
||||
case FadeType.Gradually:
|
||||
if (this.Opacity > 0)
|
||||
{
|
||||
this.Opacity -= opastep;
|
||||
if (this.Opacity < 0) this.Opacity = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
timer.Stop ();
|
||||
this.Visible = false;
|
||||
fading = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case FadeType.Immediately:
|
||||
if (fadeAwayArmed)
|
||||
{
|
||||
this.Opacity = 0;
|
||||
timer.Stop ();
|
||||
this.Visible = false;
|
||||
fading = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fadeAwayArmed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
private void timer_Tick (object sender, EventArgs e)
|
||||
{
|
||||
OnFormFade ();
|
||||
}
|
||||
public void OwnerWnd_Resize (object sender, EventArgs e)
|
||||
{
|
||||
if (this != null && this.IsHandleCreated && this.picbox != null && this.picbox.IsHandleCreated)
|
||||
{
|
||||
ResizeSplashScreen ();
|
||||
}
|
||||
}
|
||||
// 渐变消失
|
||||
public void FadeOut ()
|
||||
{
|
||||
if (fading) return;
|
||||
fadeMode = FadeType.Gradually;
|
||||
fadeAwayArmed = false;
|
||||
fading = true;
|
||||
this.Opacity = Math.Min (this.Opacity, 1.0);
|
||||
timer.Interval = 15;
|
||||
timer.Start ();
|
||||
}
|
||||
// 立即消失
|
||||
public void FadeAway ()
|
||||
{
|
||||
if (fading) return;
|
||||
fadeMode = FadeType.Immediately;
|
||||
fadeAwayArmed = false;
|
||||
fading = true;
|
||||
timer.Interval = 15;
|
||||
timer.Start ();
|
||||
}
|
||||
public void ResetSplash ()
|
||||
{
|
||||
this.Opacity = 1.0;
|
||||
this.Visible = false;
|
||||
this.Enabled = true;
|
||||
fadeMode = FadeType.Gradually;
|
||||
fadeAwayArmed = false;
|
||||
fading = false;
|
||||
if (timer != null) timer.Stop ();
|
||||
if (picbox != null)
|
||||
{
|
||||
picbox.Image = splashImage;
|
||||
picbox.BackColor = background;
|
||||
}
|
||||
ResizeSplashScreen ();
|
||||
}
|
||||
private void SplashForm_FormClosed (object sender, FormClosedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
DetachHostEvents (_host);
|
||||
_host = null;
|
||||
base.OnFormClosed (e);
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
private void SplashForm_Shown (object sender, EventArgs e)
|
||||
{
|
||||
base.OnShown (e);
|
||||
this.Opacity = 1.0;
|
||||
this.Visible = true;
|
||||
this.Enabled = true;
|
||||
ResizeSplashScreen ();
|
||||
}
|
||||
}
|
||||
}
|
||||
123
WAShell/SplashForm.resx
Normal file
@@ -0,0 +1,123 @@
|
||||
<?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>
|
||||
<metadata name="timer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
||||
92
WAShell/WAShell.csproj
Normal file
@@ -0,0 +1,92 @@
|
||||
<?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>{4EC16578-EFBF-41E6-8D7F-976E3646DD1D}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>WAShell</RootNamespace>
|
||||
<AssemblyName>WAShell</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>2</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>
|
||||
<ItemGroup>
|
||||
<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="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SplashForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="SplashForm.Designer.cs">
|
||||
<DependentUpon>SplashForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="WebAppForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="WebAppForm.Designer.cs">
|
||||
<DependentUpon>WebAppForm.cs</DependentUpon>
|
||||
</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>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="SplashForm.resx">
|
||||
<DependentUpon>SplashForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="WebAppForm.resx">
|
||||
<DependentUpon>WebAppForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
</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>
|
||||
60
WAShell/WebAppForm.Designer.cs
generated
Normal file
@@ -0,0 +1,60 @@
|
||||
namespace WAShell
|
||||
{
|
||||
partial class WebAppForm
|
||||
{
|
||||
/// <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.webui = new System.Windows.Forms.WebBrowser();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// webui
|
||||
//
|
||||
this.webui.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.webui.Location = new System.Drawing.Point(0, 0);
|
||||
this.webui.MinimumSize = new System.Drawing.Size(20, 20);
|
||||
this.webui.Name = "webui";
|
||||
this.webui.Size = new System.Drawing.Size(661, 416);
|
||||
this.webui.TabIndex = 0;
|
||||
//
|
||||
// WebAppForm
|
||||
//
|
||||
this.AllowDrop = true;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(661, 416);
|
||||
this.Controls.Add(this.webui);
|
||||
this.Name = "WebAppForm";
|
||||
this.Text = "Main Web App Form";
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.WebBrowser webui;
|
||||
}
|
||||
}
|
||||
67
WAShell/WebAppForm.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using DataUtils;
|
||||
namespace WAShell
|
||||
{
|
||||
[ComVisible (true)]
|
||||
[ClassInterface (ClassInterfaceType.AutoDual)]
|
||||
public partial class WebAppForm: Form, IScriptBridge, IWebBrowserPageScale
|
||||
{
|
||||
SplashForm splash;
|
||||
ITaskbarList3 taskbar = null;
|
||||
public WebAppForm ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
}
|
||||
public int PageScale
|
||||
{
|
||||
get
|
||||
{
|
||||
var web2 = WebBrowserHelper.GetWebBrowser2 (webui);
|
||||
if (web2 == null) return 0;
|
||||
object inArg = null;
|
||||
object outArg = null;
|
||||
try
|
||||
{
|
||||
web2.ExecWB (
|
||||
OLECMDID.OLECMDID_OPTICAL_ZOOM,
|
||||
OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT,
|
||||
ref inArg,
|
||||
ref outArg
|
||||
);
|
||||
if (outArg is int) return (int)outArg;
|
||||
}
|
||||
catch { }
|
||||
return 0;
|
||||
}
|
||||
set
|
||||
{
|
||||
var web2 = WebBrowserHelper.GetWebBrowser2 (webui);
|
||||
if (web2 == null) return;
|
||||
object inArg = value;
|
||||
object outArg = null;
|
||||
try
|
||||
{
|
||||
web2.ExecWB (
|
||||
OLECMDID.OLECMDID_OPTICAL_ZOOM,
|
||||
OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER,
|
||||
ref inArg,
|
||||
ref outArg
|
||||
);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
public object CallEvent (string funcName, object e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
120
WAShell/WebAppForm.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>
|
||||
@@ -56,11 +56,11 @@ System::Drawing::Color GetDwmThemeColor ()
|
||||
}
|
||||
else return System::Drawing::Color::FromArgb (0, 120, 215); // 如果获取失败,返回默认颜色
|
||||
}
|
||||
String ^ColorToHtml (System::Drawing::Color color)
|
||||
System::String ^ColorToHtml (System::Drawing::Color color)
|
||||
{
|
||||
return String::Format ("#{0:X2}{1:X2}{2:X2}", color.R, color.G, color.B);
|
||||
return System::String::Format ("#{0:X2}{1:X2}{2:X2}", color.R, color.G, color.B);
|
||||
}
|
||||
System::Drawing::Color StringToColor (String ^colorStr)
|
||||
System::Drawing::Color StringToColor (System::String ^colorStr)
|
||||
{
|
||||
using Color = System::Drawing::Color;
|
||||
using Regex = System::Text::RegularExpressions::Regex;
|
||||
@@ -68,7 +68,7 @@ System::Drawing::Color StringToColor (String ^colorStr)
|
||||
{
|
||||
return (value < min) ? min : (value > max) ? max : value;
|
||||
};
|
||||
String ^normalized = colorStr->Trim ()->ToLower ();
|
||||
System::String ^normalized = colorStr->Trim ()->ToLower ();
|
||||
if (normalized == "transparent") return Color::Transparent;
|
||||
if (Color::FromName (normalized).IsKnownColor)
|
||||
{
|
||||
@@ -76,17 +76,17 @@ System::Drawing::Color StringToColor (String ^colorStr)
|
||||
}
|
||||
if (normalized->StartsWith ("#"))
|
||||
{
|
||||
String^ hex = normalized->Substring (1);
|
||||
System::String^ hex = normalized->Substring (1);
|
||||
if (hex->Length == 3 || hex->Length == 4)
|
||||
{
|
||||
hex = String::Concat (
|
||||
hex = System::String::Concat (
|
||||
hex [0].ToString () + hex [0],
|
||||
hex [1].ToString () + hex [1],
|
||||
hex [2].ToString () + hex [2],
|
||||
(hex->Length == 4) ? (hex [3].ToString () + hex [3]) : ""
|
||||
);
|
||||
}
|
||||
uint32_t argb = Convert::ToUInt32 (hex, 16);
|
||||
uint32_t argb = System::Convert::ToUInt32 (hex, 16);
|
||||
switch (hex->Length)
|
||||
{
|
||||
case 6: return Color::FromArgb (
|
||||
@@ -101,19 +101,19 @@ System::Drawing::Color StringToColor (String ^colorStr)
|
||||
(argb >> 8) & 0xFF,
|
||||
argb & 0xFF
|
||||
);
|
||||
default: throw gcnew ArgumentException ("Invalid hex color format");
|
||||
default: throw gcnew System::ArgumentException ("Invalid hex color format");
|
||||
}
|
||||
}
|
||||
System::Text::RegularExpressions::Match ^match = Regex::Match (normalized,
|
||||
"^(rgba?)\\s*\\(\\s*(\\d+%?)\\s*,\\s*(\\d+%?)\\s*,\\s*(\\d+%?)\\s*,?\\s*([\\d.]+%?)?\\s*\\)$");
|
||||
if (match->Success)
|
||||
{
|
||||
auto GetComponent = [&] (String^ val) -> int
|
||||
auto GetComponent = [&] (System::String^ val) -> int
|
||||
{
|
||||
if (val->EndsWith ("%"))
|
||||
{
|
||||
float percent = float::Parse (val->TrimEnd ('%')) / 100.0f;
|
||||
return Clamp ((int)Math::Round (percent * 255), 0, 255);
|
||||
return Clamp ((int)System::Math::Round (percent * 255), 0, 255);
|
||||
}
|
||||
return Clamp (int::Parse (val), 0, 255);
|
||||
};
|
||||
@@ -122,16 +122,16 @@ System::Drawing::Color StringToColor (String ^colorStr)
|
||||
int b = GetComponent (match->Groups [4]->Value);
|
||||
if (match->Groups [1]->Value == "rgba")
|
||||
{
|
||||
String^ alphaVal = match->Groups [5]->Value;
|
||||
System::String^ alphaVal = match->Groups [5]->Value;
|
||||
int a = 255;
|
||||
if (alphaVal->EndsWith ("%"))
|
||||
{
|
||||
float percent = float::Parse (alphaVal->TrimEnd ('%')) / 100.0f;
|
||||
a = Clamp ((int)Math::Round (percent * 255), 0, 255);
|
||||
a = Clamp ((int)System::Math::Round (percent * 255), 0, 255);
|
||||
}
|
||||
else if (!String::IsNullOrEmpty (alphaVal))
|
||||
else if (!System::String::IsNullOrEmpty (alphaVal))
|
||||
{
|
||||
a = Clamp ((int)Math::Round (float::Parse (alphaVal) * 255), 0, 255);
|
||||
a = Clamp ((int)System::Math::Round (float::Parse (alphaVal) * 255), 0, 255);
|
||||
}
|
||||
return Color::FromArgb (a, r, g, b);
|
||||
}
|
||||
|
||||
@@ -683,7 +683,7 @@
|
||||
<SCDesk>0</SCDesk>
|
||||
<SCQLaunch>0</SCQLaunch>
|
||||
<SCStartPinOption>0</SCStartPinOption>
|
||||
<SCCust>1</SCCust>
|
||||
<SCCust>0</SCCust>
|
||||
<CustSCPath>%StartProgramsFolderCommon%\\%AppShortcutFolderName%</CustSCPath>
|
||||
<SCDesc>Update</SCDesc>
|
||||
<SCComment/>
|
||||
@@ -1099,6 +1099,79 @@
|
||||
<CRC>0</CRC>
|
||||
<StoreOnly>0</StoreOnly>
|
||||
</FileData>
|
||||
<FileData>
|
||||
<FldRef>0</FldRef>
|
||||
<FullName>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release\Update.exe</FullName>
|
||||
<FileName>Update.exe</FileName>
|
||||
<Source>E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstallerReset\Release</Source>
|
||||
<Ext>exe</Ext>
|
||||
<RTSource>档案</RTSource>
|
||||
<Desc/>
|
||||
<Recurse>1</Recurse>
|
||||
<MatchMode>0</MatchMode>
|
||||
<Dest>%AppFolder%</Dest>
|
||||
<Overwrite>1</Overwrite>
|
||||
<Backup>0</Backup>
|
||||
<Protect>0</Protect>
|
||||
<InstallOrder>1000</InstallOrder>
|
||||
<SCStartRoot>0</SCStartRoot>
|
||||
<SCStartProgs>0</SCStartProgs>
|
||||
<SCAppFld>1</SCAppFld>
|
||||
<SCStartup>0</SCStartup>
|
||||
<SCDesk>0</SCDesk>
|
||||
<SCQLaunch>0</SCQLaunch>
|
||||
<SCStartPinOption>0</SCStartPinOption>
|
||||
<SCCust>0</SCCust>
|
||||
<CustSCPath/>
|
||||
<SCDesc>Update</SCDesc>
|
||||
<SCComment/>
|
||||
<SCArgs/>
|
||||
<SCWork/>
|
||||
<UseExtIco>0</UseExtIco>
|
||||
<IcoFN/>
|
||||
<IcoIdx>0</IcoIdx>
|
||||
<IcoShowMd>0</IcoShowMd>
|
||||
<IcoHK>0</IcoHK>
|
||||
<RegTTF>0</RegTTF>
|
||||
<TTFName/>
|
||||
<RegOCX>0</RegOCX>
|
||||
<RegTLB>0</RegTLB>
|
||||
<SupInUse>0</SupInUse>
|
||||
<Compress>1</Compress>
|
||||
<UseOrigAttr>1</UseOrigAttr>
|
||||
<Attr>0</Attr>
|
||||
<NoCRC>0</NoCRC>
|
||||
<NoRemove>0</NoRemove>
|
||||
<Shared>0</Shared>
|
||||
<OSCond>
|
||||
<OS>32768</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
<OS>65535</OS>
|
||||
</OSCond>
|
||||
<RTCond/>
|
||||
<BuildConfigs>
|
||||
<Cfg>All</Cfg>
|
||||
</BuildConfigs>
|
||||
<Package>None</Package>
|
||||
<Packages/>
|
||||
<Notes/>
|
||||
<CompSize>0</CompSize>
|
||||
<CRC>0</CRC>
|
||||
<StoreOnly>0</StoreOnly>
|
||||
</FileData>
|
||||
</ArchiveFiles>
|
||||
<ExternalFiles/>
|
||||
<BeforeInstallingScreens>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#using "./PriFileFormat.dll"
|
||||
// #using "./PriFileFormat.dll"
|
||||
using namespace PriFileFormat;
|
||||
#include <comip.h>
|
||||
#include <atlbase.h>
|
||||
|
||||
@@ -186,6 +186,11 @@
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="priformatcli.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PriFileFormat\PriFile.csproj">
|
||||
<Project>{ef4012d4-ef08-499c-b803-177739350b2d}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<VisualElements DisplayName="Update" BackgroundColor="#F1F7C0" ShowNameOnSquare150x150Logo="on" ForegroundText="light" Square150x150Logo="Update.Assets\150x150Logo.png" Square70x70Logo="Update.Assets\70x70Logo.png" />
|
||||
</Application>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" GeneratedByTileIconifier="true">
|
||||
<VisualElements ShowNameOnSquare150x150Logo="on" Square150x150Logo="VisualElements\MediumIconUpdate.png" Square70x70Logo="VisualElements\SmallIconUpdate.png" ForegroundText="light" BackgroundColor="#ffc107" TileIconifierColorSelection="Custom" TileIconifierCreatedWithUpgrade="false" />
|
||||
</Application>
|
||||
BIN
shared/VisualElements/MediumIconUpdate.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
9
shared/VisualElements/MediumIconUpdate_Metadata.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<ShortcutItemImage xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<OriginalBytes>iVBORw0KGgoAAAANSUhEUgAAANIAAADSCAYAAAA/mZ5CAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAuISURBVHhe7d0L0KxzHcBxMSnFcUlmonKpyBlHJNTEoSldDaaaKZcZpSmOYdyKGoNjNFFEOCdJRUlyGdQoSiEjJcalznRDYqKGcolE49L3v89v37Pn3cu7u8+zu8+zz/cz85vdff7//+/5v2d/v2O9Z/fZlSRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkiRJkpR5/vnn57/wwgsrx0NJg0pNRCyjkZLFxMtiSKo2inkT4jwK/Jo4NBKzmqjVYo6vE9OkaqF430CcH8XcdHEMF6pHE7VKDbV+LJHKjYJ9IwX7vax22zF2dkwtRJ9NNIO5n+dmk1gulUsU9EVZuc7ppFiWy6BN1Ip1p6T1kUqaLIpxAXFJ1GffWHNUpBhKagJiqCZqRY4lxNaRVhovanArCvCyrByHw/qDIt1AWFdIE7Ui39eIN8cppNGi5rah4H6QlV9+5FoUqfvC/MKbqIm8zxFncXerOJ1ULApsW+LKrOSKRd5Pxml6Yt7ImqgV53iWWEq8KU4t5UMxvZW4KmpsZDjHfnHKjhgfSxO14nz/I9L/Qy2IbUiDoXjeTvw0amosON++cfoVcHzsTdSKcz9DnEFsEVuSeqNYFhI/jxoaO869T2ylgccTbaJW7OO/xOlpT7E9qR21kt6fNnEU6kfTflLBEqVoolbs6SniNGLzxh+cNBvFcWHUy0Sxj0OIO+JhKbG/J4lTic3ij09ajsKY/R65cbqV8+8Y+9iY+HYcLy32+ASR3imxaeMPUGqiPs7LymQ8KMLbiQO4+6LYwgyOv474bjazvNjj48TJxOtj61KjgL8RNTIynOO3xIHcXSVO2xXzNiW6viG2RB5jn1/k1jfHKkNBnJ3VRrHIu4w4mLurxqn6xrrNiX7fIDsx7PERbk7iduPYuuqMQlialUZ+5PoDcSixWqQfGjm2IC6N1KXFHv9FfIHYMLauuqIITo+6GArr/0wcwd3VI2VhyLslcXl2pvJijw8T6fNQr42tq44oglOzkugfa+4mPkPMizQjwzm2Jgp7Q+2osMeHiBOIV8fWVTc8+V+KeuiJefdy81li7Vg6Npz7LcRI3mBbJPb4D+J4YoPYuuqEJ/7EqIU2jN1PHM3ddWP6xLCP7YmRv+E2L/b4IDfpmhKviq2rLnjST8jKIMPjB4hjiPViSmmwp7cRP4mtltn1sWXVCU984715FOk5ROn/NmWrO7DPn6U9lw37ujG2qbrhyX8FcRN1UKl/eGTPOxHXZSU8eezl5tia6ooiuIH4N3E+Uan3mrHfdxC/iHqeCM5/S2xHdUYhzPzNzv30a90LiUp9Xoetv4s935j9FOPDOX8dW1DdUQxtL5E49ghxLrFlTKsE9vseIr1UHTnO88s4rdS5kZoYS++G/jJRqctcsd/3EzfHj1E4ct8Qp5IyFMWc/9POnP8QXyG2i2WVwH53Zfu3Zj9FMdKfV6SXlkuFETUyJ+Y+TZxJVOoyV+x3d+K2+DGGRo6RfiOHKozi6LuRmliTrht3FlG1l3wfJO6MH2MgrLs60kjtKJCBG6kV69PnnbaJdJXAnj9M9H1RFub+KJZKneVtpKaKNtRHiN9nP0FnjP8wpkvdFdVITRVtqL2IP2U/wXIcuzymSL0V3UhNFW2ofYi7Y/+XxmFpbqNqpKaKNtTHiTPZ9855I1Jq2o26kZqq0lDsM10z/cfZrvMhz2mRVtNuXI3UVNaGYl/bEV/PdplPWX9GjdC4G6mpLMXGPtKHBr+V7SofG6jGJtVITZMqPs67I1HI5ZRtIE28kZrGVYycY2fOdUHjpDnZQJpRlkZqGlVxkjN9Zun7jZPkZAOpTdkaqamoYiVP+oxSIVdztYHUVVkbqWnY4mXdB4hCrt5qA2lOZW+kplTMxJyf2GVO+negQq7Wms7JjQ2kuVEslWikhL2mi9m/L7behrHtY2ouNpAGVqVGStjvubH1Nozl+jIzG0hDq2Ajdf2oN2ND/T+RDaTcpqmRGE5Xjk3X4D6ueb/T49ZgzK+5VH7T1EjSxNhIUgFsJKkA09RIjKVr76UviH5pHJLGY8oa6ZKYk75J79NE7i+MlvqSCrNRoRWR9htbb8PYRTGtgcfpy5OPJtaIKdJopMKMuquEtN/YehvGGv9Fmo3j6UsBjuXumjFVKtY0NRLDF2ezOouG8t+NVLxpaiTGVnhp14qx9KXOlfpmQlXIlDVS20s7jj1K7BlTpNGYskaa/cuG64gNYlganSlrpJn/InF/CTerxJA0WtPUSAxfzPhz3H4qDknjMU2NxFj63tud4qE0PlPWSL6TQZMxTY2UB3m3JtLF888gbiCeINJbjX5DXEqkr/zcny2sGkuk5SiOWjcS+dKXjf0q0s+JucuII4h1IkVPLFkcdzXNKIhaNhJ5FhKXRdqBsfY+bro2CWMrM+erxKNxSNOMJ7p2jUSOEyJdbuRaEmlncHhNjjcuxMKtjVQHqTDTE14Vab+x9aGw/rRI1ctjzLuHuJm4k3gqjnfEePqH4HUj/wbEldmIjVQbPNG1aSTWfjPSrIDj9xEXEPvxsNEQszG2GbGI6PjlzRy/lphP3BiHGnhsI9UBT3QtGol13ZroiJjSF+bPI9JnnJ6JFDM4tizuzuCYjVQHPNFT30is2S2Wz+DYXcTGMWVgrH03cW+k64o5NlId8ETXoZFmv9x6KIZyIdVG5Lopy9oZ4zZSHfBEF/KNDePCfgdqJOYfGUtbFfZt4+TfO3J2ZCPVBE90P7/FKo1BGonpqzD/7mxlhsdHxXBu5Dos0nbFHBupDniu98ie8moYpJGYu3ssa+Bx+jaLl8dwLuQ5MdL2xDwbqQ54rtfiyb4re9rLj70O0kjnxLIGHp8SQ7mQ5zuRck7MtZHqgif7nfG8lx577auRmJd+Tf1wLGvg8bYxPBTWr0aa67Ns/WGNjVQnPOfp275L/xu8tMfYck9M3Xl2xNBQWJ9+Q3cMcRRxOHEwsT/xCWJfYm8ivQH2Q8TuxK7Eewk/H1VHPPGpOG6jcEqJvfX90k6aOAr2QOLOqN/SsJFUSRTuQcTvoo4nzkZSpVHAhxAd37A5TjaSpgKFfBjxx6jrsbORNFUo6PS1KWP/9ycbSVOJwj6SuCfqfOT6baQ0b4jYLZYPhfWvnJUvxZYxLM2Ngvkc8deo95FJxRmn7Cmm94WcjxMLY+nQyHFKpGzg8bUxJA2G4kkfers/aqlw5C60kcj3F2JBLMuFPH+LtA083j+GpOFQRMcSD0RNFYachTUSuW4hXhNLciHPnpG2gccPcbNWDEv5UEyLKaq/N6qrAOQqpJHIczU3q8f0XMi1IXF7ljnD46UxLBWHwjqeSH9L50KOohqpkO9MIs8aaU+RtoHH6SPoG8UUqXgUWWqof2YlN7hUtJGqp5jeE7kWxfShkCJ9BOWKLNsKPhZTpNGKhno0Cq9vRTZSSC89+7r8cCvW7cG6FV7OJRw7N6ZI40PhpYZ6POpwTswdupFY23a5rITj6YpCB8fSnpi3gOj48XyO38GNL+k0ORRhaqgns5LsjjlDNRLrHiTmc7frN58z/gBxBZHetbELsRdxKHEycQ2xwgcFWzF2FbFenF6aLIoxNVTXSwQzNnAjseZpbnaIoXSO47KRYpDvnEgtlQvFmRqq09VMh2mktrf+pGNEx5d6/WJ9+i2kX9ui8qNYU0M9m5XuUI3U9Tdo5FqfWEoM9Gt55j9FpJd7Q1+pVZoIijY1VNJ3IzH38HjYE1NXZ+4BKXda1w3jqYHOIraIpVI1Uc9rxt2eKPaXxN2BkP/FxNqzg3zzuF05pkmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSJEmSNForrfR/3s15gMpdcisAAAAASUVORK5CYII=</OriginalBytes>
|
||||
<OriginalPath>C:\Program Files (x86)\Desktop App Installer\Update.Assets\150x150Logo.scale-140.png</OriginalPath>
|
||||
<Height>100</Height>
|
||||
<Width>100</Width>
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
</ShortcutItemImage>
|
||||
BIN
shared/VisualElements/SmallIconUpdate.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
9
shared/VisualElements/SmallIconUpdate_Metadata.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<ShortcutItemImage xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<OriginalBytes>iVBORw0KGgoAAAANSUhEUgAAAGIAAABiCAYAAACrpQYOAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAaaSURBVHhe7ZxbqBVlFMcNrZDKQgkUKkiLQKIXIY0eurxIFPYQJ0oSVOiYmt2sJC3yQR8KwgjMougKFSVYUBFdOA9ShHhJOWQXs9Qio6KS7pdz+q3Z/z2cac+ePbP3zOTMXj/4MzPft761Zq11PHOcmb3HOY7jOI7jOI7jOI7jOI7jOI7jOI7jpGNkZOQcNIQu15DTDRRwEVqjw0yMjo5OZ+0HbAPYfxldoGknDdRtkKIdapQwKOISTaUC+9PRNi2PwPij6FyZOnFQoOXosGr2XwZklgh2U/HxbmNJPMz/g+5n9wwtcwyKcgv6vlGmRBKbgY8paEi2HcH2MLqX3aly0Z9QhNvRkUZZUhPbDPxMQm/KJhOsO4TuRqfKXX9Awneh31SHbog0A18T0Wua6xp8HECr0RS5rickeA/6S3n3StAMthPwuaUxlA/4249WsXtKcOJ1gqQGgixzhGLNR5t1mDv43ofuQJOURj0gt1yaQWG+ZrOW7WS2C9l+EUwUBP4/RrehE5RK9SGvrptBIb5D69BpchfC2GJ0UKaFgP+9yP7Cm6iw1YacsjbjR5K/D50pF23B5nr0ldYVAv6H0Qp2j1PY6kISHZtBsr+gB9DZWpYa1ixB9iusMPC/By1nd4LCVhMSiG0Gyf2BHkIzZdo1+FiKvpHrQsD/LnQDu8cobPXg5MNmkIzxMDpP07mBT7t98q1CFQL+d6AV6CyFrRbkMMDJv8F2loYKgzg3oTS3U7oC31coVDUhgWdRaXdFiWV//fyg+uUC/i6V++pCEluVzBZ0iYYLh1j2/4Os97tawMccuaw2JPKecgrg+B10taYLh1h2A/Jnhc8E63K/pv1vkEzsgxzYzpxdaE+SaaEQZxX6VbE7gm01L8ztIKGdyi0W5j9jsxaV8uyAeHaH+PcgeBuYnybz+kBSe5RfIth9iUp7dkCcNehPhR/LyTKpFyT7oRJMBfb27MB+aifLRaEQx27h/63wx2q4fpDkJ0oyE6yzZwd3slvKTyixNhDLfkXa3V97zGrb9egJ9DraiZq3VlI9Zz+q4OTtGtA1rP8UrWT3RLnMFfwOou0WqxOcx3NotpZWC078gPLoCfx8hHK7VY3LLA14CV2kpdWEBHK9dY2/nm5Vsy5LAzajuVpabUikkDuk+N2NlrE7XqESwS5LA15FV2ppPSChwm7EGfi3i2jbNwYxydKAt9hU70KcBpL7qZFmsRDnfYUMsTFNJ4LdVjRfy+oJCXZ1n6cbFDJEw23h3LahRTKvNySaeDshTxQyhKGLkySz/oBGNP/XWjgK6cShGpWCQobwQ2B3XEu5u3vUoxqVgkKG0AR7X8pUn3eWukU1KgWFDLEmaMouzM2X2PrrzfAmqkMpKGTI2EYYHNtj2+ma7i8aJSgHhQxpNoLtEVTt95N6xQpRFgoZYo1Adm9qhob6F9WoFBQyhAZsRPV507sXVKNSUMjM0Kzz0a1oAZqNSnk6WCqqUSkoZCown0XB7SPBsbfpbY5N7BuKzK3UbnVopFUOCtkRFTkV2K7TsgCON6D9OqwOyqcUFDIRzF5sWDegqPbJ003sNp9Xb0KRT7FyvNHWsn1cx96IJBSyLRTwSZlaMQ+ieZpqgbnr0G6ZG2EDGfdGJKGQsTC9sGEVsF3DiVBw+4z3C1oTUslGcNK7dP6Fo5AtcA72zQWfmw3bYQ2nAvv1gfMxMFbJRqzW+ReOQrbAOSySiZH6USjrHtSaCFVtxEw0rBwKRSFbIP4rMul4HWmC6VONFa1UshGGNYPzT/UAvxcULgKxZzCV6ancWPs44bOaL5k1IYnUb1R0g8I4aaFmhTRE7p2sULtcGyK3TrdQw1waIncRGLbf68H/mhPU8WGRrnOBPfs3a7iekGRPDZGbCAxbI2KhoPZi2fEyTQRza0KANUXD9YZEF5Nv5oZoeQSGYxtBjKdlkgrsgz/B2b6tof6BpBeQe+qGaFkEhuMasVbTqeA8HtM6a8Q1Gu4/LHlq0LEhMo/AcLt/EY+gxDc6mJ+G6dhfSTdqqr+hEFdRj7YNkVkEhiONwEf43U/s2zeZLUORhnA8h2m7KIcPjdgf0rTThKLMQy2f39Z0BIbDRrDGbm3bY9G4O6r2FdemvRoKYewZuXPioECXofBLeTUcgeGgEdgt01AAx/ZtM/tsLgH71zeoJU4nKOiF6HkdRmB8DlqqwwgUeTxzc5E9u7ZPsTZlH1q8VmaO4ziO4ziO4ziO4ziO4ziO4ziO49SEceP+Bdbzgt+r46efAAAAAElFTkSuQmCC</OriginalBytes>
|
||||
<OriginalPath>C:\Program Files (x86)\Desktop App Installer\Update.Assets\70x70Logo.scale-140.png</OriginalPath>
|
||||
<Height>50</Height>
|
||||
<Width>50</Width>
|
||||
<X>0</X>
|
||||
<Y>0</Y>
|
||||
</ShortcutItemImage>
|
||||