├── Miner-WPF
├── 设置.png
├── Ulord.ico
├── Ulord.png
├── UlordRig.exe
├── App.config
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── packages.config
├── Miner-WPF.csproj.user
├── Models
│ ├── AppInfo.cs
│ ├── Enums.cs
│ ├── ViewModels
│ │ ├── MainWindowViewModel.cs
│ │ ├── BindableBase.cs
│ │ └── ConfigWindowViewModel.cs
│ ├── Result.cs
│ ├── Converters
│ │ ├── PerfomanceLabelContentConverter.cs
│ │ ├── IsAutomaticEnabledConverter.cs
│ │ ├── IsParamInputEnabledConverter.cs
│ │ └── MiningButtonContentConverter.cs
│ ├── ConstantParameters.cs
│ └── Config.cs
├── Controls
│ ├── WPFNotifyIcon.cs
│ ├── NotifyWindow.xaml.cs
│ ├── ResourceDictionary.xaml
│ ├── NotifyWindow.xaml
│ ├── NoticeTextBox.xaml.cs
│ ├── WPFNotifyIcon.Designer.cs
│ ├── NoticeTextBox.xaml
│ └── WPFNotifyIcon.resx
├── App.xaml
├── Program.cs
├── MainWindow.xaml
├── App.xaml.cs
├── Commons
│ ├── FileHelper.cs
│ ├── Win32Native.cs
│ └── Configuration.cs
├── Miner-WPF.csproj
├── WindowConfig.xaml.cs
├── MainWindow.xaml.cs
└── WindowConfig.xaml
├── .vs
└── Miner
│ └── v15
│ └── .suo
├── Common
├── packages.config
├── Properties
│ └── AssemblyInfo.cs
├── Connection.cs
├── Common.csproj
├── ProcessControl.cs
└── FileOperation.cs
├── Test
├── packages.config
├── App.config
├── Properties
│ └── AssemblyInfo.cs
├── Config.cs
├── Test.csproj
└── Program.cs
├── packages
├── Newtonsoft.Json.11.0.2
│ ├── Newtonsoft.Json.11.0.2.nupkg
│ ├── lib
│ │ └── net45
│ │ │ └── Newtonsoft.Json.dll
│ └── LICENSE.md
└── Microsoft.Expression.Drawing.3.0.0
│ ├── Microsoft.Expression.Drawing.3.0.0.nupkg
│ └── lib
│ └── net45
│ └── Microsoft.Expression.Drawing.dll
├── Contract
├── IPerformance.cs
├── IMiner.cs
├── Properties
│ └── AssemblyInfo.cs
└── Contract.csproj
├── .gitignore
├── README.md
├── Ulord
├── Performance.cs
├── Properties
│ └── AssemblyInfo.cs
├── Miner.cs
└── Ulord.csproj
└── Miner.sln
/Miner-WPF/设置.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UlordChain/UlordMiner-Desktop/HEAD/Miner-WPF/设置.png
--------------------------------------------------------------------------------
/.vs/Miner/v15/.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UlordChain/UlordMiner-Desktop/HEAD/.vs/Miner/v15/.suo
--------------------------------------------------------------------------------
/Miner-WPF/Ulord.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UlordChain/UlordMiner-Desktop/HEAD/Miner-WPF/Ulord.ico
--------------------------------------------------------------------------------
/Miner-WPF/Ulord.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UlordChain/UlordMiner-Desktop/HEAD/Miner-WPF/Ulord.png
--------------------------------------------------------------------------------
/Miner-WPF/UlordRig.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UlordChain/UlordMiner-Desktop/HEAD/Miner-WPF/UlordRig.exe
--------------------------------------------------------------------------------
/Common/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Test/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.11.0.2/Newtonsoft.Json.11.0.2.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UlordChain/UlordMiner-Desktop/HEAD/packages/Newtonsoft.Json.11.0.2/Newtonsoft.Json.11.0.2.nupkg
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.11.0.2/lib/net45/Newtonsoft.Json.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UlordChain/UlordMiner-Desktop/HEAD/packages/Newtonsoft.Json.11.0.2/lib/net45/Newtonsoft.Json.dll
--------------------------------------------------------------------------------
/Test/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Miner-WPF/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/packages/Microsoft.Expression.Drawing.3.0.0/Microsoft.Expression.Drawing.3.0.0.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UlordChain/UlordMiner-Desktop/HEAD/packages/Microsoft.Expression.Drawing.3.0.0/Microsoft.Expression.Drawing.3.0.0.nupkg
--------------------------------------------------------------------------------
/packages/Microsoft.Expression.Drawing.3.0.0/lib/net45/Microsoft.Expression.Drawing.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UlordChain/UlordMiner-Desktop/HEAD/packages/Microsoft.Expression.Drawing.3.0.0/lib/net45/Microsoft.Expression.Drawing.dll
--------------------------------------------------------------------------------
/Miner-WPF/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Miner-WPF/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Miner-WPF/Miner-WPF.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ProjectFiles
5 |
6 |
--------------------------------------------------------------------------------
/Miner-WPF/Models/AppInfo.cs:
--------------------------------------------------------------------------------
1 | namespace Miner_WPF.Models
2 | {
3 | public class AppInfo
4 | {
5 | public string Version { set; get; }
6 | public string Address { set; get; }
7 | public string MD5 { set; get; }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Miner-WPF/Models/Enums.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Miner_WPF.Models
8 | {
9 | public enum TailDirection
10 | {
11 | Left,
12 | Right,
13 | Both,
14 | None
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Miner-WPF/Models/ViewModels/MainWindowViewModel.cs:
--------------------------------------------------------------------------------
1 | namespace Miner_WPF.Models.ViewModels
2 | {
3 | public class MainWindowViewModel : BindableBase
4 | {
5 | private double computeAbility;
6 |
7 | public double ComputeAbility { get => computeAbility; set => SetProperty(ref computeAbility, value); }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Contract/IPerformance.cs:
--------------------------------------------------------------------------------
1 | namespace Contract
2 | {
3 | public interface IPerformance
4 | {
5 | int Sum { get; }
6 | int Accept { get; }
7 | double Hashrate { get; }
8 | double Difficulty { get; }
9 | void SetPerformance(int sum, int accept, double hashrate, double difficulty);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/Miner-WPF/Models/Result.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Miner_WPF.Models
8 | {
9 | internal class Result
10 | {
11 | public double Hashrate { set; get; }
12 | public int Accept { set; get; }
13 | public int Total { set; get; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Miner-WPF/Controls/WPFNotifyIcon.cs:
--------------------------------------------------------------------------------
1 | using System.Windows.Forms;
2 |
3 | namespace Miner_WPF.Controls
4 | {
5 | public partial class WPFNotifyIcon : Control
6 | {
7 | public WPFNotifyIcon()
8 | {
9 | InitializeComponent();
10 | }
11 |
12 | protected override void OnPaint(PaintEventArgs pe)
13 | {
14 | base.OnPaint(pe);
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。
3 | ################################################################################
4 |
5 | /Common/bin
6 | /Common/obj
7 | /Contract/obj
8 | /Contract/bin
9 | /Installer/Debug
10 | /Installer/Release
11 | /Miner-UWP
12 | /Miner-WPF/bin
13 | /Miner-WPF/obj
14 | /Ulord/obj
15 | /Ulord/bin
16 | /Test/obj
17 | /Test/bin
18 | /.vs
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UlordMiner-Desktop
2 |
3 | Ulord miner desktop application
4 |
5 | ## Requirements
6 |
7 | - Microsoft Visual Studio 2017 or higher
8 | - .Net Framework 4.6
9 | - [Microsoft Visual Studio 2017 Installer Projects](https://marketplace.visualstudio.com/items?itemName=VisualStudioProductTeam.MicrosoftVisualStudio2017InstallerProjects) (If you need to generate an installer)
10 |
11 | ## Usage
12 |
13 | - Reference: [Ulord miner help](https://testnet-pool.ulord.one/)
--------------------------------------------------------------------------------
/Contract/IMiner.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Net;
4 |
5 | namespace Contract
6 | {
7 | public interface IMiner
8 | {
9 | bool Run(string file, string arg, DataReceivedEventHandler outputHandler = default(DataReceivedEventHandler), DataReceivedEventHandler errorHandler = default(DataReceivedEventHandler));
10 | bool Alive(string file, string arg);
11 | bool Terminate(string file);
12 | IPerformance GetPerformance(string file, string arg, IPEndPoint endPoint, string request, Func parseResult, Action setPerformance, out bool alive);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Miner-WPF/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Miner-WPF/Models/Converters/PerfomanceLabelContentConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 |
5 | namespace Miner_WPF.Models.Converters
6 | {
7 | [ValueConversion(typeof(double), typeof(object))]
8 | class PerfomanceLabelContentConverter : IValueConverter
9 | {
10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
11 | {
12 | return Binary.GetBinaryString((double)value,1);
13 | }
14 |
15 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
16 | {
17 | throw new NotImplementedException();
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Miner-WPF/Models/Converters/IsAutomaticEnabledConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 |
5 | namespace Miner_WPF.Models.Converters
6 | {
7 | [ValueConversion(typeof(bool), typeof(bool?))]
8 | public class IsAutomaticEnabledConverter : IMultiValueConverter
9 | {
10 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
11 | {
12 | bool isAlive = (bool)values[0];
13 | bool automatic = (bool)values[1];
14 | return !isAlive || automatic;
15 | }
16 |
17 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
18 | {
19 | throw new NotImplementedException();
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Miner-WPF/Models/Converters/IsParamInputEnabledConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 |
5 | namespace Miner_WPF.Models.Converters
6 | {
7 | [ValueConversion(typeof(bool), typeof(bool?))]
8 | public class IsParamInputEnabledConverter : IMultiValueConverter
9 | {
10 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
11 | {
12 | bool isAlive = (bool)values[0];
13 | bool automatic = (bool)values[1];
14 | return !isAlive && !automatic;
15 | }
16 |
17 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
18 | {
19 | throw new NotImplementedException();
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Miner-WPF/Models/Converters/MiningButtonContentConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 |
5 | namespace Miner_WPF.Models.Converters
6 | {
7 | [ValueConversion(typeof(bool), typeof(object))]
8 | class MiningButtonContentConverter : IValueConverter
9 | {
10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
11 | {
12 | if ((bool)value)
13 | {
14 | return "结束挖矿";
15 | }
16 | else
17 | {
18 | return "开始挖矿";
19 | }
20 | }
21 |
22 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
23 | {
24 | throw new NotImplementedException();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Miner-WPF/Models/ViewModels/BindableBase.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Runtime.CompilerServices;
4 |
5 | namespace Miner_WPF.Models.ViewModels
6 | {
7 | public class BindableBase : INotifyPropertyChanged
8 | {
9 | public event PropertyChangedEventHandler PropertyChanged;
10 |
11 | protected void SetProperty(ref T prop, T value, [CallerMemberName] string callerName = "")
12 | {
13 | if (!EqualityComparer.Default.Equals(prop, value))
14 | {
15 | prop = value;
16 | OnPropertyChanged(callerName);
17 | }
18 | }
19 |
20 | protected virtual void OnPropertyChanged(string propertyName)
21 | {
22 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Ulord/Performance.cs:
--------------------------------------------------------------------------------
1 | using Contract;
2 |
3 | namespace Ulord
4 | {
5 | public class Performance : IPerformance
6 | {
7 | private int sum;
8 | private int accept;
9 | private double hashrate;
10 | private double difficulty;
11 |
12 | public int Sum { get => sum; internal set => sum = value; }
13 |
14 | public int Accept { get => accept; internal set => accept = value; }
15 |
16 | public double Hashrate { get => hashrate; internal set => hashrate = value; }
17 |
18 | public double Difficulty { get => difficulty; internal set => difficulty = value; }
19 |
20 | public void SetPerformance(int sum, int accept, double hashrate, double difficulty)
21 | {
22 | Sum = sum;
23 | Accept = accept;
24 | Hashrate = hashrate;
25 | Difficulty = difficulty;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Miner-WPF/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 |
4 | namespace Miner_WPF
5 | {
6 | class Program
7 | {
8 | ///
9 | /// Application Entry Point.
10 | ///
11 | [System.STAThreadAttribute()]
12 | //[System.Diagnostics.DebuggerNonUserCodeAttribute()]
13 | [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
14 | public static void Main()
15 | {
16 | // Only one instance
17 | bool createNew;
18 | Mutex mutex = new Mutex(true, "UlordMiner", out createNew);
19 | if (!createNew)
20 | {
21 | Commons.Configuration.ShowErrMessage("已经有一个客户端在您的计算机上运行!");
22 | Environment.Exit(0);
23 | return;
24 | }
25 | Miner_WPF.App app = new Miner_WPF.App();
26 | app.InitializeComponent();
27 | app.Run();
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Miner-WPF/Models/ViewModels/ConfigWindowViewModel.cs:
--------------------------------------------------------------------------------
1 | using Contract;
2 |
3 | namespace Miner_WPF.Models.ViewModels
4 | {
5 | public class ConfigWindowViewModel : BindableBase
6 | {
7 | private bool isAlive;
8 | private double computeAbility;
9 | private double accept;
10 | private double reject;
11 | public Config Config { set; get; }
12 | public bool IsAlive { get => isAlive; set => SetProperty(ref isAlive, value); }
13 | public double ComputeAbility { get => computeAbility; set => SetProperty(ref computeAbility, value); }
14 | public double Accept { get => accept; set => SetProperty(ref accept, value); }
15 | public double Reject { get => reject; set => SetProperty(ref reject, value); }
16 | public void SetPerformance(IPerformance perfmon)
17 | {
18 | ComputeAbility = perfmon.Hashrate;
19 | Accept = perfmon.Accept;
20 | Reject = perfmon.Sum - perfmon.Accept;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Common/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("Common")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Common")]
13 | [assembly: AssemblyCopyright("Copyright © 2018")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("084b4296-6da9-435a-b3f1-403268095a05")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
33 | //通过使用 "*",如下所示:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Test/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("Test")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Test")]
13 | [assembly: AssemblyCopyright("Copyright © 2018")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("034cd5af-f956-4fe4-b79f-ef907a653e89")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
33 | // 方法是按如下所示使用“*”: :
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Ulord/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("Ulord")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Ulord")]
13 | [assembly: AssemblyCopyright("Copyright © 2018")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("f82039b3-5473-4536-8834-7ba7ac66f103")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
33 | //通过使用 "*",如下所示:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Miner-WPF/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Miner_WPF.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.3.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Contract/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("Contract")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Contract")]
13 | [assembly: AssemblyCopyright("Copyright © 2018")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("ab1f9fef-bce7-446e-9039-eb215501c773")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
33 | //通过使用 "*",如下所示:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/Test/Config.cs:
--------------------------------------------------------------------------------
1 | using Contract;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Test
9 | {
10 | public class Config
11 | {
12 | private string url;
13 | private string user;
14 | private string id;
15 | private string pass;
16 | private int thread;
17 | private int cpuUsage;
18 | private bool automatic;
19 |
20 | public string Url { get => url; set => url = value; }
21 | public string User { get => user; set => user = value; }
22 | public string Id { get => id; set => id = value; }
23 | public string Pass { get => pass; set => pass = value; }
24 | public int Thread { get => thread; set => thread = value; }
25 | public int CpuUsage { get => cpuUsage; set => cpuUsage = value; }
26 | public bool Automatic { get => automatic; set => automatic = value; }
27 | }
28 | internal class Result
29 | {
30 | public double Hashrate { set; get; }
31 | public int Accept { set; get; }
32 | public int Total { set; get; }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/packages/Newtonsoft.Json.11.0.2/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2007 James Newton-King
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/Miner-WPF/Controls/NotifyWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using System.Windows;
4 | using System.Windows.Media.Animation;
5 |
6 | namespace Miner_WPF.Controls
7 | {
8 | ///
9 | /// NotifyWindow.xaml 的交互逻辑
10 | ///
11 | public partial class NotifyWindow : Window
12 | {
13 | public NotifyWindow()
14 | {
15 | InitializeComponent();
16 | this.Left = SystemParameters.WorkArea.Width - this.Width - 5;
17 | this.Top = SystemParameters.WorkArea.Height - this.Height - 5;
18 | this.Loaded += (s, e) =>
19 | {
20 | Storyboard storyboard = (Storyboard)this.Resources["load"];
21 | storyboard.Begin();
22 | };
23 | }
24 | public void StartTask(Action task)
25 | {
26 | Task.Factory.StartNew(() =>
27 | {
28 | task.Invoke();
29 | this.Dispatcher.Invoke(() => this.Visibility = Visibility.Collapsed);
30 | });
31 | }
32 | public void SetMessage(string message)
33 | {
34 | text_Msg.Dispatcher.Invoke(() => text_Msg.Text = message);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Miner-WPF/Models/ConstantParameters.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Miner_WPF.Models
4 | {
5 | public class Binary
6 | {
7 | public const int K = 1024;
8 | public const int M = 1024 * 1024;
9 | public const int G = 1024 * 1024 * 1024;
10 | public const long T = 1099511627776L;
11 | public const long P = 1125899906842624L;
12 | public static string GetBinaryString(double value, int digits = 1)
13 | {
14 |
15 | if (value >= P)
16 | {
17 | return $"{Math.Round(value / P, digits)}P";
18 | }
19 | else if (value >= T)
20 | {
21 | return $"{Math.Round(value / T, digits)}T";
22 | }
23 | else if (value >= G)
24 | {
25 | return $"{Math.Round(value / G, digits)}G";
26 | }
27 | else if (value >= M)
28 | {
29 | return $"{Math.Round(value / M, digits)}M";
30 | }
31 | else if (value >= K)
32 | {
33 | return $"{Math.Round(value / K, digits)}K";
34 | }
35 | else
36 | {
37 | return Math.Round(value, digits).ToString();
38 | }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Miner-WPF/Models/Config.cs:
--------------------------------------------------------------------------------
1 | using Miner_WPF.Models.ViewModels;
2 |
3 | namespace Miner_WPF.Models
4 | {
5 | public class Config : BindableBase
6 | {
7 | private string url;
8 | private string user;
9 | private string id;
10 | private string pass;
11 | private int thread;
12 | private int cpuUsage;
13 | private bool automatic;
14 |
15 | public string Url { get => url; set => SetProperty(ref url, value); }
16 | public string User { get => user; set => SetProperty(ref user, value); }
17 | public string Id { get => id; set => SetProperty(ref id, value); }
18 | public string Pass { get => pass; set => SetProperty(ref pass, value); }
19 | public int Thread { get => thread; set => SetProperty(ref thread, value); }
20 | public int CpuUsage { get => cpuUsage; set => SetProperty(ref cpuUsage, value); }
21 | public bool Automatic { get => automatic; set => SetProperty(ref automatic, value); }
22 |
23 | public void SetConfig(Config config)
24 | {
25 | this.Url = config.Url;
26 | this.User = config.User;
27 | this.Id = config.Id;
28 | this.Pass = config.Pass;
29 | this.Automatic = config.Automatic;
30 | this.CpuUsage = config.CpuUsage;
31 | this.Thread = config.Thread;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Common/Connection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net;
3 | using System.Net.Sockets;
4 | using System.Text;
5 |
6 | namespace Common
7 | {
8 | public class Connection
9 | {
10 | private const int TIMEOUT = 5 * 1000;
11 | private IPEndPoint endPoint;
12 | public Connection(IPEndPoint endPoint)
13 | {
14 | this.endPoint = endPoint;
15 | }
16 | #region Received
17 | public T Received(string request, long size, Func parseResult, Action action = null)
18 | {
19 | string str = string.Empty;
20 | byte[] bys = new byte[size];
21 | try
22 | {
23 | using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) { SendTimeout = TIMEOUT, ReceiveTimeout = TIMEOUT })
24 | {
25 | socket.Connect(endPoint);
26 | socket.Receive(bys);
27 | }
28 |
29 | str = Encoding.UTF8.GetString(bys).Trim('\0');
30 | return parseResult(str);
31 | }
32 | catch (Exception ex)
33 | {
34 | action?.Invoke(ex);
35 | return default(T);
36 | }
37 | }
38 | public T Received(string request, Func parseResult, Action action = null)
39 | {
40 | return Received(request, 4096, parseResult, action);
41 | }
42 | #endregion
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Miner-WPF/Controls/ResourceDictionary.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Miner-WPF/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Ulord/Miner.cs:
--------------------------------------------------------------------------------
1 | using Common;
2 | using Contract;
3 | using System;
4 | using System.ComponentModel.Composition;
5 | using System.Diagnostics;
6 | using System.Net;
7 |
8 | namespace Ulord
9 | {
10 | [Export(typeof(IMiner))]
11 | public class Miner : IMiner
12 | {
13 | private ProcessControl processControl;
14 | private Connection connection;
15 | public Miner()
16 | {
17 | processControl = new ProcessControl();
18 | }
19 | public bool Alive(string file, string arg)
20 | {
21 | return processControl.Alive;
22 | }
23 | public bool Terminate(string file)
24 | {
25 | return processControl.TerminateProcess(file);
26 | }
27 |
28 | public IPerformance GetPerformance(string file, string arg, IPEndPoint endPoint, string request, Func parseResult, Action setPerformance, out bool alive)
29 | {
30 | IPerformance performance = new Performance();
31 | if (alive = Alive(file, arg))
32 | {
33 | if (connection == null)
34 | {
35 | connection = new Connection(endPoint);
36 | }
37 | T result = connection.Received(request, parseResult);
38 | if (result != null)
39 | {
40 | setPerformance(performance, result);
41 | }
42 | }
43 | return performance;
44 | }
45 |
46 | public bool Run(string file, string arg, DataReceivedEventHandler outputHandler = default(DataReceivedEventHandler), DataReceivedEventHandler errorHandler = default(DataReceivedEventHandler))
47 | {
48 | return processControl.CreateProcess(file, arg, outputHandler, errorHandler);
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Miner-WPF/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using Contract;
2 | using Miner_WPF.Commons;
3 | using Miner_WPF.Controls;
4 | using System;
5 | using System.ComponentModel.Composition;
6 | using System.ComponentModel.Composition.Hosting;
7 | using System.IO;
8 | using System.Windows;
9 |
10 | namespace Miner_WPF
11 | {
12 | ///
13 | /// App.xaml 的交互逻辑
14 | ///
15 | public partial class App : Application
16 | {
17 | [Import]
18 | public IMiner Miner { set; get; }
19 | protected override void OnStartup(StartupEventArgs e)
20 | {
21 | NotifyWindow notifyWindow = new NotifyWindow();
22 | notifyWindow.StartTask(() =>
23 | {
24 | try
25 | {
26 | notifyWindow.SetMessage("正在加载程序组件...");
27 | DirectoryCatalog directoryCatalog = new DirectoryCatalog(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins"));
28 | CompositionContainer compositionContainer = new CompositionContainer(directoryCatalog);
29 | compositionContainer.ComposeParts(this);
30 | Configuration.Init(Miner, notifyWindow.SetMessage);
31 | }
32 | catch (FileLoadException ex)
33 | {
34 | Configuration.DebugExceptionHandle(ex);
35 | Configuration.ShowErrMessage("校验文件完整性失败,程序即将退出!");
36 | Environment.Exit(0);
37 | }
38 | catch (Exception ex)
39 | {
40 | Configuration.DebugExceptionHandle(ex);
41 | Configuration.ShowErrMessage("加载组件失败,程序即将退出!");
42 | Environment.Exit(0);
43 | }
44 | });
45 | notifyWindow.ShowDialog();
46 | base.OnStartup(e);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Miner-WPF/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // 有关程序集的一般信息由以下
8 | // 控制。更改这些特性值可修改
9 | // 与程序集关联的信息。
10 | [assembly: AssemblyTitle("Ulord挖矿客户端")]
11 | [assembly: AssemblyDescription("Ulord CPU 挖矿客户端")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("Ulord Foundation Ltd.")]
14 | [assembly: AssemblyProduct("Ulord挖矿客户端")]
15 | [assembly: AssemblyCopyright("© Ulord Foundation Ltd. All rights reserved.")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // 将 ComVisible 设置为 false 会使此程序集中的类型
20 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
21 | //请将此类型的 ComVisible 特性设置为 true。
22 | [assembly: ComVisible(false)]
23 |
24 | //若要开始生成可本地化的应用程序,请设置
25 | //.csproj 文件中的 CultureYouAreCodingWith
26 | //例如,如果您在源文件中使用的是美国英语,
27 | //使用的是美国英语,请将 设置为 en-US。 然后取消
28 | //对以下 NeutralResourceLanguage 特性的注释。 更新
29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置
36 | //(未在页面中找到资源时使用,
37 | //或应用程序资源字典中找到时使用)
38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
39 | //(未在页面中找到资源时使用,
40 | //、应用程序或任何主题专用资源字典中找到时使用)
41 | )]
42 |
43 |
44 | // 程序集的版本信息由下列四个值组成:
45 | //
46 | // 主版本
47 | // 次版本
48 | // 生成号
49 | // 修订号
50 | //
51 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
52 | // 方法是按如下所示使用“*”: :
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.3")]
55 | [assembly: AssemblyFileVersion("1.0.3")]
56 | [assembly: NeutralResourcesLanguage("zh-CN")]
57 |
58 |
--------------------------------------------------------------------------------
/Miner-WPF/Controls/NotifyWindow.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
15 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Contract/Contract.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}
8 | Library
9 | Properties
10 | Contract
11 | Contract
12 | v4.6
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Miner-WPF/Controls/NoticeTextBox.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using System.Windows.Media;
4 |
5 | namespace Miner_WPF.Controls
6 | {
7 | ///
8 | /// NoticeTextBox.xaml 的交互逻辑
9 | ///
10 | public partial class NoticeTextBox : UserControl
11 | {
12 | public string Text
13 | {
14 | get { return (string)GetValue(TextProperty); }
15 | set { SetValue(TextProperty, value); }
16 | }
17 | public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(NoticeTextBox), new PropertyMetadata(default(string)));
18 |
19 | public Brush TBorderBrush
20 | {
21 | get { return (Brush)GetValue(TBorderBrushProperty); }
22 | set { SetValue(TBorderBrushProperty, value); }
23 | }
24 | public static readonly DependencyProperty TBorderBrushProperty = DependencyProperty.Register("TBorderBrush", typeof(Brush), typeof(NoticeTextBox), new PropertyMetadata(Brushes.Black));
25 |
26 | public string BText
27 | {
28 | get { return (string)GetValue(BTextProperty); }
29 | set { SetValue(BTextProperty, value); }
30 | }
31 | public static readonly DependencyProperty BTextProperty = DependencyProperty.Register("BText", typeof(string), typeof(NoticeTextBox), new PropertyMetadata(default(string)));
32 |
33 | public string UText
34 | {
35 | get { return (string)GetValue(UTextProperty); }
36 | set { SetValue(UTextProperty, value); }
37 | }
38 | public static readonly DependencyProperty UTextProperty = DependencyProperty.Register("UText", typeof(string), typeof(NoticeTextBox), new PropertyMetadata(default(string)));
39 | public Visibility UVisibility
40 | {
41 | get { return (Visibility)GetValue(UVisibilityProperty); }
42 | set { SetValue(UVisibilityProperty, value); }
43 | }
44 | public static readonly DependencyProperty UVisibilityProperty = DependencyProperty.Register("UVisibility", typeof(Visibility), typeof(NoticeTextBox), new PropertyMetadata(default(Visibility)));
45 | public NoticeTextBox()
46 | {
47 | InitializeComponent();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Common/Common.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {084B4296-6DA9-435A-B3F1-403268095A05}
8 | Library
9 | Properties
10 | Common
11 | Common
12 | v4.6
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 | ..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/Miner-WPF/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Miner_WPF.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// 一个强类型的资源类,用于查找本地化的字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// 返回此类使用的缓存的 ResourceManager 实例。
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Miner_WPF.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// 使用此强类型资源类,为所有资源查找
51 | /// 重写当前线程的 CurrentUICulture 属性。
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。
65 | ///
66 | internal static System.Drawing.Icon Ulord {
67 | get {
68 | object obj = ResourceManager.GetObject("Ulord", resourceCulture);
69 | return ((System.Drawing.Icon)(obj));
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Common/ProcessControl.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.IO;
3 | using System.Linq;
4 |
5 | namespace Common
6 | {
7 | public class ProcessControl
8 | {
9 | private bool alive;
10 | public bool Alive => alive;
11 | #region Create process
12 | public bool CreateProcess(string file, string command, DataReceivedEventHandler outputHandler = default(DataReceivedEventHandler), DataReceivedEventHandler errorHandler = default(DataReceivedEventHandler))
13 | {
14 | if (TerminateProcess(file))
15 | {
16 | try
17 | {
18 | ProcessStartInfo processStartInfo = new ProcessStartInfo(file, command);
19 | processStartInfo.CreateNoWindow = true;
20 | processStartInfo.UseShellExecute = false;
21 | processStartInfo.RedirectStandardOutput = true;
22 | processStartInfo.RedirectStandardError = true;
23 |
24 | Process process = Process.Start(processStartInfo);
25 | process.OutputDataReceived += outputHandler;
26 | process.ErrorDataReceived += errorHandler;
27 | process.Exited += (s, e) => alive = false;
28 | process.EnableRaisingEvents = true;
29 | process.BeginOutputReadLine();
30 | process.BeginErrorReadLine();
31 | alive = true;
32 | return true;
33 | }
34 | catch
35 | {
36 | alive = false;
37 | return false;
38 | }
39 | }
40 | else
41 | {
42 | return false;
43 | }
44 | }
45 | #endregion
46 | #region Terminate process
47 | public bool TerminateProcess(string file)
48 | {
49 | bool isSuccess = true;
50 | foreach (Process item in GetProcesses(file))
51 | {
52 | try
53 | {
54 | item.Kill();
55 | }
56 | catch
57 | {
58 | if (ExistProcess(item.Id))
59 | {
60 | isSuccess = false;
61 | }
62 | }
63 | }
64 | return isSuccess;
65 | }
66 | private bool ExistProcess(int processId)
67 | {
68 | try
69 | {
70 | return Process.GetProcessById(processId) != null;
71 | }
72 | catch
73 | {
74 | return false;
75 | }
76 | }
77 | private Process[] GetProcesses(string file)
78 | {
79 | try
80 | {
81 | return Process.GetProcessesByName(Path.GetFileNameWithoutExtension(file)).Where(p => p.MainModule.FileName == file).ToArray();
82 | }
83 | catch
84 | {
85 | return new Process[0];
86 | }
87 | }
88 | #endregion
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Ulord/Ulord.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {F82039B3-5473-4536-8834-7BA7AC66F103}
8 | Library
9 | Properties
10 | Ulord
11 | Ulord
12 | v4.6
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | {084b4296-6da9-435a-b3f1-403268095a05}
51 | Common
52 | False
53 |
54 |
55 | {ab1f9fef-bce7-446e-9039-eb215501c773}
56 | Contract
57 | False
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | xcopy "$(TargetPath)" "$(SolutionDir)Miner-WPF\bin\Debug\plugins\" /Y
67 | xcopy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)Miner-WPF\bin\Debug\plugins\" /Y
68 | xcopy "$(TargetPath)" "$(SolutionDir)Test\bin\Debug\plugins\" /Y
69 | xcopy "$(TargetDir)$(TargetName).pdb" "$(SolutionDir)Test\bin\Debug\plugins\" /Y
70 |
71 |
--------------------------------------------------------------------------------
/Test/Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}
8 | Exe
9 | Test
10 | Test
11 | v4.6
12 | 512
13 | true
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | false
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 | ..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | {084b4296-6da9-435a-b3f1-403268095a05}
61 | Common
62 |
63 |
64 | {ab1f9fef-bce7-446e-9039-eb215501c773}
65 | Contract
66 |
67 |
68 |
69 |
70 | echo f |xcopy "$(SolutionDir)Miner-WPF\UMiner.exe" "$(TargetDir)UMiner.exe" /Y
71 |
72 |
--------------------------------------------------------------------------------
/Common/FileOperation.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.IO;
4 | using System.IO.IsolatedStorage;
5 |
6 | namespace Common
7 | {
8 | public class FileOperation
9 | {
10 | public static void SolatedStorageWrite(string file, T t)
11 | {
12 | SolatedStorageWrite(file, JsonConvert.SerializeObject(t));
13 | }
14 | public static void SolatedStorageWrite(string file, string text)
15 | {
16 | using (IsolatedStorageFile isolatedStrorageFile = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly, null, null))
17 | {
18 | if (!isolatedStrorageFile.FileExists(file))
19 | {
20 | string dir = Path.GetDirectoryName(file);
21 | if (!string.IsNullOrEmpty(dir) && !isolatedStrorageFile.DirectoryExists(dir))
22 | {
23 | isolatedStrorageFile.CreateDirectory(dir);
24 | }
25 | }
26 | using (IsolatedStorageFileStream isolatedStorageFileStream = new IsolatedStorageFileStream(file, FileMode.Create, isolatedStrorageFile))
27 | {
28 | using (StreamWriter streamWriter = new StreamWriter(isolatedStorageFileStream))
29 | {
30 | streamWriter.Write(text);
31 | }
32 | }
33 | }
34 | }
35 | public static T SolatedStorageRead(string file)
36 | {
37 | return JsonConvert.DeserializeObject(SolatedStorageRead(file) ?? string.Empty);
38 | }
39 | public static string SolatedStorageRead(string file)
40 | {
41 | using (IsolatedStorageFile isolatedStrorageFile = IsolatedStorageFile.GetStore(IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly, null, null))
42 | {
43 | if (!isolatedStrorageFile.FileExists(file))
44 | {
45 | return default(string);
46 | }
47 | using (IsolatedStorageFileStream isolatedStorageFileStream = new IsolatedStorageFileStream(file, FileMode.Open, isolatedStrorageFile))
48 | {
49 | using (StreamReader streamReader = new StreamReader(isolatedStorageFileStream))
50 | {
51 | return streamReader.ReadToEnd();
52 | }
53 | }
54 | }
55 | }
56 | public static void LocalWrite(string file, T t)
57 | {
58 | if (string.IsNullOrEmpty(Path.GetPathRoot(file)))
59 | {
60 | file = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file);
61 | }
62 | string dir = Path.GetDirectoryName(file);
63 | if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
64 | {
65 | Directory.CreateDirectory(dir);
66 | }
67 | File.WriteAllText(file, JsonConvert.SerializeObject(t));
68 | }
69 | public static T LocalRead(string file)
70 | {
71 | if (string.IsNullOrEmpty(Path.GetPathRoot(file)))
72 | {
73 | file = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file);
74 | }
75 | if (File.Exists(file))
76 | {
77 | string json = File.ReadAllText(file);
78 | if (!string.IsNullOrEmpty(json))
79 | {
80 | return JsonConvert.DeserializeObject(json);
81 | }
82 | }
83 | return default(T);
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/Miner-WPF/Controls/WPFNotifyIcon.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Miner_WPF.Controls
2 | {
3 | partial class WPFNotifyIcon
4 | {
5 | ///
6 | /// 必需的设计器变量。
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// 清理所有正在使用的资源。
12 | ///
13 | /// 如果应释放托管资源,为 true;否则为 false。
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region 组件设计器生成的代码
24 |
25 | ///
26 | /// 设计器支持所需的方法 - 不要修改
27 | /// 使用代码编辑器修改此方法的内容。
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.components = new System.ComponentModel.Container();
32 | this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
33 | this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
34 | this.打开ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
35 | this.开机启动ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
36 | this.关于我们ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
37 | this.退出ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
38 | this.contextMenuStrip.SuspendLayout();
39 | this.SuspendLayout();
40 | //
41 | // notifyIcon
42 | //
43 | this.notifyIcon.ContextMenuStrip = this.contextMenuStrip;
44 | this.notifyIcon.Text = "notifyIcon";
45 | this.notifyIcon.Visible = true;
46 | //
47 | // contextMenuStrip
48 | //
49 | this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
50 | this.打开ToolStripMenuItem,
51 | this.开机启动ToolStripMenuItem,
52 | this.关于我们ToolStripMenuItem,
53 | this.退出ToolStripMenuItem});
54 | this.contextMenuStrip.Name = "contextMenuStrip1";
55 | this.contextMenuStrip.Size = new System.Drawing.Size(125, 92);
56 | //
57 | // 打开ToolStripMenuItem
58 | //
59 | this.打开ToolStripMenuItem.Name = "打开ToolStripMenuItem";
60 | this.打开ToolStripMenuItem.Size = new System.Drawing.Size(124, 22);
61 | this.打开ToolStripMenuItem.Text = "打开";
62 | //
63 | // 开机启动ToolStripMenuItem
64 | //
65 | this.开机启动ToolStripMenuItem.Checked = true;
66 | this.开机启动ToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
67 | this.开机启动ToolStripMenuItem.Name = "开机启动ToolStripMenuItem";
68 | this.开机启动ToolStripMenuItem.Size = new System.Drawing.Size(124, 22);
69 | this.开机启动ToolStripMenuItem.Text = "开机启动";
70 | //
71 | // 关于我们ToolStripMenuItem
72 | //
73 | this.关于我们ToolStripMenuItem.Name = "关于我们ToolStripMenuItem";
74 | this.关于我们ToolStripMenuItem.Size = new System.Drawing.Size(124, 22);
75 | this.关于我们ToolStripMenuItem.Text = "关于我们";
76 | //
77 | // 退出ToolStripMenuItem
78 | //
79 | this.退出ToolStripMenuItem.Name = "退出ToolStripMenuItem";
80 | this.退出ToolStripMenuItem.Size = new System.Drawing.Size(124, 22);
81 | this.退出ToolStripMenuItem.Text = "退出";
82 | this.contextMenuStrip.ResumeLayout(false);
83 | this.ResumeLayout(false);
84 |
85 | }
86 |
87 | #endregion
88 |
89 | public System.Windows.Forms.NotifyIcon notifyIcon;
90 | public System.Windows.Forms.ContextMenuStrip contextMenuStrip;
91 | public System.Windows.Forms.ToolStripMenuItem 打开ToolStripMenuItem;
92 | public System.Windows.Forms.ToolStripMenuItem 开机启动ToolStripMenuItem;
93 | public System.Windows.Forms.ToolStripMenuItem 关于我们ToolStripMenuItem;
94 | public System.Windows.Forms.ToolStripMenuItem 退出ToolStripMenuItem;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/Miner-WPF/Commons/FileHelper.cs:
--------------------------------------------------------------------------------
1 | using Miner_WPF.Models;
2 | using Newtonsoft.Json;
3 | using System;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Net;
7 | using System.Text;
8 |
9 | namespace Miner_WPF.Commons
10 | {
11 | public class FileHelper
12 | {
13 | public static void SaveString(string file, string text)
14 | {
15 | File.WriteAllBytes(file, Encoding.UTF8.GetBytes(text));
16 | }
17 | public static string LoadString(string file)
18 | {
19 | return Encoding.UTF8.GetString(File.ReadAllBytes(file));
20 | }
21 | public static AppInfo GetAppInfo(string url)
22 | {
23 | using (WebClient webClient = new WebClient() { Proxy = null, Encoding = Encoding.UTF8 })
24 | {
25 | string json = webClient.DownloadString(url);
26 | return JsonConvert.DeserializeObject(json);
27 | }
28 | }
29 | public static void DownloadFile(string url, string path, Action action = default(Action))
30 | {
31 | // Test address
32 | // url = "https://download.microsoft.com/download/6/7/4/674A281B-84BF-4B49-848C-14873B22F977/SQLManagementStudio_x64_ENU.exe";
33 | using (WebResponse response = WebRequest.Create(url).GetResponse())
34 | {
35 | long totalBytes = response.ContentLength;
36 | long receivedBytes = 0;
37 | int bufferSize = 1024 * 16;
38 | int chunkCount = 2;
39 | long chunkBytes = (int)Math.Ceiling(totalBytes * 1.0 / chunkCount);
40 | long lastChunkBytes = totalBytes - chunkBytes * (chunkCount - 1);
41 | Tuple[] chunkInfos = new Tuple[chunkCount];
42 | for (int i = 0; i < chunkCount; i++)
43 | {
44 | if (i < chunkCount - 1)
45 | {
46 | chunkInfos[i] = new Tuple(chunkBytes * i, chunkBytes);
47 | }
48 | else
49 | {
50 | chunkInfos[i] = new Tuple(chunkBytes * i, lastChunkBytes);
51 | }
52 | }
53 | chunkInfos.AsParallel().ForAll(p =>
54 | {
55 | DownloadFile(url, path, p.Item1, p.Item2, bufferSize, totalBytes, ref receivedBytes, action);
56 | });
57 | }
58 | }
59 | private static void DownloadFile(string url, string path, long offset, long count, int bufferSize, long totalBytes, ref long receivedBytes, Action action = default(Action))
60 | {
61 | HttpWebRequest httpWebRequest = WebRequest.Create(url) as HttpWebRequest;
62 | httpWebRequest.AddRange(offset, offset + count - 1);
63 | using (WebResponse response = httpWebRequest.GetResponse())
64 | {
65 | byte[] bytes = new byte[bufferSize];
66 | int length = 0;
67 | using (Stream stream = response.GetResponseStream())
68 | {
69 | using (FileStream writer = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite, bufferSize, true))
70 | {
71 | while ((length = stream.Read(bytes, 0, bytes.Length)) > 0)
72 | {
73 | writer.Seek(offset, SeekOrigin.Begin);
74 | writer.Write(bytes, 0, length);
75 | offset += length;
76 | receivedBytes += length;
77 | action?.Invoke($"更新进度: {(receivedBytes * 1.0 / totalBytes):P}");
78 | }
79 | }
80 | }
81 | }
82 | httpWebRequest.Abort();
83 | }
84 | public static string ComputeFileMD5(string path)
85 | {
86 | using (FileStream reader = new FileStream(path, FileMode.Open, FileAccess.Read))
87 | {
88 | System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
89 | byte[] bys = md5.ComputeHash(reader);
90 | StringBuilder sb = new StringBuilder();
91 | foreach (byte item in bys)
92 | {
93 | sb.Append(item.ToString("X2"));
94 | }
95 | return sb.ToString();
96 | }
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/Miner-WPF/Controls/NoticeTextBox.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
74 |
75 |
76 |
77 |
78 |
79 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/Miner-WPF/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\Ulord.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
123 |
124 |
--------------------------------------------------------------------------------
/Miner-WPF/Controls/WPFNotifyIcon.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 55
122 |
123 |
124 | 128, 17
125 |
126 |
127 | False
128 |
129 |
--------------------------------------------------------------------------------
/Miner-WPF/Commons/Win32Native.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System;
3 | using System.Reflection;
4 | using System.Runtime.InteropServices;
5 |
6 | namespace Miner_WPF.Commons
7 | {
8 | internal delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
9 |
10 | internal class NativeMethods
11 | {
12 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
13 | public static extern IntPtr SetWindowsHookEx(HookType hookType, HookProc callback, IntPtr hMod, uint dwThreadId);
14 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
15 | public static extern bool UnhookWindowsHookEx(IntPtr hhk);
16 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
17 | public static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
18 | }
19 |
20 | internal enum HookType
21 | {
22 | WH_KEYBOARD = 2,
23 | WH_MOUSE = 7,
24 | WH_KEYBOARD_LL = 13,
25 | WH_MOUSE_LL = 14
26 | }
27 |
28 | internal enum MouseMessage
29 | {
30 | WM_MOUSEMOVE = 0x0200,
31 | WM_LBUTTONDOWN = 0x0201,
32 | WM_LBUTTONUP = 0x0202,
33 | WM_LBUTTONDBLCLK = 0x0203,
34 | WM_RBUTTONDOWN = 0x0204,
35 | WM_RBUTTONUP = 0x0205,
36 | WM_RBUTTONDBLCLK = 0x0206,
37 | WM_MBUTTONDOWN = 0x0207,
38 | WM_MBUTTONUP = 0x0208,
39 | WM_MBUTTONDBLCLK = 0x0209,
40 |
41 | WM_MOUSEWHEEL = 0x020A,
42 | WM_MOUSEHWHEEL = 0x020E,
43 |
44 | WM_NCMOUSEMOVE = 0x00A0,
45 | WM_NCLBUTTONDOWN = 0x00A1,
46 | WM_NCLBUTTONUP = 0x00A2,
47 | WM_NCLBUTTONDBLCLK = 0x00A3,
48 | WM_NCRBUTTONDOWN = 0x00A4,
49 | WM_NCRBUTTONUP = 0x00A5,
50 | WM_NCRBUTTONDBLCLK = 0x00A6,
51 | WM_NCMBUTTONDOWN = 0x00A7,
52 | WM_NCMBUTTONUP = 0x00A8,
53 | WM_NCMBUTTONDBLCLK = 0x00A9
54 | }
55 |
56 | public class Win32Native
57 | {
58 | [DllImport("User32.dll")]
59 | private static extern bool GetLastInputInfo(ref LASTINPUTINFO Dummy);
60 | [DllImport("User32.dll")]
61 | private static extern bool GetCursorPos(out POINT pt);
62 | [DllImport("User32.dll", SetLastError = true)]
63 | public static extern bool BringWindowToTop(IntPtr hWnd);
64 | internal struct LASTINPUTINFO
65 | {
66 | public uint cbSize;
67 | public uint dwTime;
68 | }
69 | internal struct POINT
70 | {
71 | public int X;
72 | public int Y;
73 | public POINT(int x, int y)
74 | {
75 | this.X = x;
76 | this.Y = y;
77 | }
78 | }
79 | public static uint GetIdleTime()
80 | {
81 | LASTINPUTINFO LastUserAction = new LASTINPUTINFO();
82 | LastUserAction.cbSize = (uint)Marshal.SizeOf(LastUserAction);
83 | GetLastInputInfo(ref LastUserAction);
84 | uint idleTime = (uint)Environment.TickCount - LastUserAction.dwTime;
85 | return idleTime;
86 | }
87 | public static Tuple GetCursorPos()
88 | {
89 | POINT point;
90 | GetCursorPos(out point);
91 | return new Tuple(point.X, point.Y);
92 | }
93 | private static event EventHandler MouseEventHandler;
94 |
95 | private static IntPtr hGlobalLLMouseHook = IntPtr.Zero;
96 | private static HookProc globalLLMouseHookCallback = null;
97 |
98 | public static bool SetGlobalLLMouseHook(EventHandler handler)
99 | {
100 | MouseEventHandler += handler;
101 | // Create an instance of HookProc.
102 | globalLLMouseHookCallback = new HookProc(LowLevelMouseProc);
103 |
104 | hGlobalLLMouseHook = NativeMethods.SetWindowsHookEx(
105 | HookType.WH_MOUSE_LL, // Must be LL for the global hook
106 | globalLLMouseHookCallback,
107 | // Get the handle of the current module
108 | Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),
109 | // The hook procedure is associated with all existing threads running
110 | // in the same desktop as the calling thread.
111 | 0);
112 | return hGlobalLLMouseHook != IntPtr.Zero;
113 | }
114 |
115 | public static bool RemoveGlobalLLMouseHook()
116 | {
117 | if (hGlobalLLMouseHook != IntPtr.Zero)
118 | {
119 | if (!NativeMethods.UnhookWindowsHookEx(hGlobalLLMouseHook))
120 | return false;
121 | hGlobalLLMouseHook = IntPtr.Zero;
122 | }
123 | return true;
124 | }
125 |
126 | private static int LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam)
127 | {
128 | if (nCode >= 0)
129 | {
130 | MouseMessage wmMouse = (MouseMessage)wParam;
131 | if (wmMouse == MouseMessage.WM_LBUTTONDOWN || wmMouse == MouseMessage.WM_RBUTTONDOWN)
132 | {
133 | MouseEventHandler?.Invoke(default(object), default(EventArgs));
134 | }
135 | }
136 | return NativeMethods.CallNextHookEx(hGlobalLLMouseHook, nCode, wParam, lParam);
137 | }
138 |
139 | public static void SetRegistryKey(string registryKeyPath, params RegistryKeyValue[] registryKeyValues)
140 | {
141 | using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(registryKeyPath, true))
142 | {
143 | foreach (RegistryKeyValue item in registryKeyValues)
144 | {
145 | registryKey.SetValue(item.Key, item.Value, item.RegistryValueKind);
146 | }
147 | }
148 | }
149 | public static void DeleteRegistryKey(string registryKeyPath, params string[] keys)
150 | {
151 | using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(registryKeyPath, true))
152 | {
153 | foreach (string key in keys)
154 | {
155 | registryKey.DeleteValue(key);
156 | }
157 | }
158 | }
159 | public static object GetRegistryValue(string registryKeyPath, string key)
160 | {
161 | using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(registryKeyPath))
162 | {
163 | return registryKey.GetValue(key);
164 | }
165 | }
166 | }
167 | public class RegistryKeyValue
168 | {
169 | public RegistryKeyValue(string key, object value, RegistryValueKind registryValueKind)
170 | {
171 | Key = key;
172 | Value = value;
173 | RegistryValueKind = registryValueKind;
174 | }
175 | public RegistryKeyValue(string key, object value) : this(key, value, RegistryValueKind.Unknown)
176 | {
177 | }
178 | public string Key { set; get; }
179 | public object Value { set; get; }
180 | public RegistryValueKind RegistryValueKind { set; get; }
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/Miner-WPF/Miner-WPF.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}
8 | WinExe
9 | Miner_WPF
10 | UlordMiner
11 | v4.6
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 | true
16 |
17 |
18 | AnyCPU
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 | false
27 |
28 |
29 | AnyCPU
30 | pdbonly
31 | true
32 | bin\Debug\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 | Ulord.ico
39 |
40 |
41 | Miner_WPF.Program
42 |
43 |
44 |
45 | ..\packages\Microsoft.Expression.Drawing.3.0.0\lib\net45\Microsoft.Expression.Drawing.dll
46 | True
47 |
48 |
49 | ..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | 4.0
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | MSBuild:Compile
76 | Designer
77 |
78 |
79 |
80 |
81 |
82 | NoticeTextBox.xaml
83 |
84 |
85 | NotifyWindow.xaml
86 |
87 |
88 | Component
89 |
90 |
91 | WPFNotifyIcon.cs
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | True
107 | True
108 | Resources.resx
109 |
110 |
111 | WindowConfig.xaml
112 |
113 |
114 | Designer
115 | MSBuild:Compile
116 |
117 |
118 | Designer
119 | MSBuild:Compile
120 |
121 |
122 | Designer
123 | MSBuild:Compile
124 |
125 |
126 | MSBuild:Compile
127 | Designer
128 |
129 |
130 | App.xaml
131 | Code
132 |
133 |
134 | MainWindow.xaml
135 | Code
136 |
137 |
138 | Designer
139 | MSBuild:Compile
140 |
141 |
142 |
143 |
144 | Code
145 |
146 |
147 | True
148 | Settings.settings
149 | True
150 |
151 |
152 | WPFNotifyIcon.cs
153 |
154 |
155 | ResXFileCodeGenerator
156 | Resources.Designer.cs
157 |
158 |
159 |
160 | SettingsSingleFileGenerator
161 | Settings.Designer.cs
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 | {084b4296-6da9-435a-b3f1-403268095a05}
174 | Common
175 |
176 |
177 | {ab1f9fef-bce7-446e-9039-eb215501c773}
178 | Contract
179 |
180 |
181 |
182 |
183 | Always
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 | echo f |xcopy "$(ProjectDir)Ulord.ico" "$(TargetDir)Ulord.ico" /Y
196 |
197 |
--------------------------------------------------------------------------------
/Test/Program.cs:
--------------------------------------------------------------------------------
1 | using Common;
2 | using Contract;
3 | using Newtonsoft.Json;
4 | using System;
5 | using System.ComponentModel.Composition;
6 | using System.ComponentModel.Composition.Hosting;
7 | using System.Diagnostics;
8 | using System.IO;
9 | using System.Net;
10 | using System.Runtime.InteropServices;
11 | using System.Threading;
12 |
13 | namespace Test
14 | {
15 | class Program
16 | {
17 | public delegate bool HandlerRoutine(int ctrlType);
18 | [DllImport("kernel32.dll")]
19 | private static extern bool SetConsoleCtrlHandler(HandlerRoutine handlerRoutine, bool Add);
20 |
21 | [Import]
22 | public IMiner Miner { set; get; }
23 | static void Main(string[] args)
24 | {
25 | Program program = new Program();
26 | program.Inject();
27 | program.Test();
28 | }
29 |
30 | public void Inject()
31 | {
32 | Console.WriteLine("Load component...");
33 | Console.ReadLine();
34 | DirectoryCatalog directoryCatalog = new DirectoryCatalog(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins"));
35 | CompositionContainer compositionContainer = new CompositionContainer(directoryCatalog);
36 | try
37 | {
38 | compositionContainer.ComposeParts(this);
39 | }
40 | catch (ChangeRejectedException ex)
41 | {
42 | Console.WriteLine($"Exception: {ex.Message}");
43 | }
44 | Console.WriteLine("Load component successed!");
45 | Console.ReadLine();
46 | }
47 |
48 | private void Test()
49 | {
50 | #region Initialize
51 | Console.WriteLine("Init component...");
52 | Console.ReadLine();
53 | string configFile = "config.json";
54 | string request = "Results";
55 | string file = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UlordRig.exe");
56 | Func format = c => $"-o \"stratum+tcp://{c.Url}\" -u \"{(string.IsNullOrEmpty(c.Id) ? c.User : $"{c.User}.{c.Id}")}\" -p \"{c.Pass}\" -t {c.Thread} --max-cpu-usage {c.CpuUsage}"/*+" -q"*/;
57 | #region Load config
58 | Console.WriteLine("Load last config...");
59 | Console.ReadLine();
60 | Config config = new Config();
61 | Config lastConfig = LoadConfig(configFile);
62 | if (lastConfig != null)
63 | {
64 | config.Url = lastConfig.Url;
65 | config.Pass = lastConfig.Pass;
66 | config.User = lastConfig.User;
67 | config.Id = lastConfig.Id;
68 | config.Thread = lastConfig.Thread;
69 | config.CpuUsage = lastConfig.CpuUsage;
70 | config.Automatic = lastConfig.Automatic;
71 | Console.WriteLine($"Last config: {lastConfig.Url}");
72 | }
73 | else
74 | {
75 | config.Url = "u2pool.org:7100";
76 | config.Pass = "x";
77 | config.User = "UQhw1PcMUg1TrodymTWWihed7ZonBdkgi6";
78 | config.Id = "test";
79 | config.Thread = 2;
80 | config.CpuUsage = 50;
81 | config.Automatic = false;
82 | }
83 | Console.WriteLine("Load last config successed!");
84 | Console.ReadLine();
85 | #endregion
86 | #region Performance
87 | Func fr = s =>
88 | {
89 | s = s.Substring(s.IndexOf('H')).Replace("/ ", ":").Replace(" ", "").Replace("Hashrate", "{\"Hashrate\"").Replace("accept", ",\"Accept\"").Replace("total", ",\"Total\"") + "}";
90 | return JsonConvert.DeserializeObject(s);
91 | };
92 | Action rp = (p, r) => p.SetPerformance(r.Total, r.Accept, r.Hashrate, 0);
93 | #endregion
94 | DataReceivedEventHandler dataReceivedEventHandler = (s, e) => Debug.WriteLine(e.Data);
95 | Console.WriteLine("Init component successed!");
96 | Console.ReadLine();
97 | #endregion
98 |
99 | #region Function test
100 | Console.WriteLine("Start mining...");
101 | Console.ReadLine();
102 | bool isRun = Miner.Run(file, format(config), dataReceivedEventHandler, dataReceivedEventHandler);
103 | bool exit = false;
104 | HandlerRoutine handlerRoutine = (i) =>
105 | {
106 | switch ((dwCtrlType)i)
107 | {
108 | case dwCtrlType.CTRL_C_EVENT:
109 | Console.WriteLine("Terminate mining...");
110 | isRun = !Miner.Terminate(file);
111 | Console.WriteLine($"Terminate mining {(!isRun ? "successed" : "Failed")}!");
112 |
113 | Console.WriteLine("Get mining status...");
114 | isRun = Miner.Alive(file, format(config));
115 | Console.WriteLine($"Mining status: {(isRun ? "Runing" : "Stopped")}");
116 |
117 | Console.WriteLine("Save config...");
118 | SaveConfig(configFile, config);
119 | Console.WriteLine("Save config successed!");
120 | exit = true;
121 | return true;
122 | case dwCtrlType.CTRL_BREAK_EVENT:
123 | case dwCtrlType.CTRL_CLOSE_EVENT:
124 | case dwCtrlType.CTRL_LOGOFF_EVENT:
125 | case dwCtrlType.CTRL_SHUTDOWN_EVENT:
126 | default:
127 | return false;
128 | }
129 | };
130 | Console.WriteLine($"Start mining {(isRun ? "successed" : "Failed")}!");
131 | bool setSuccess = SetConsoleCtrlHandler(handlerRoutine, true);
132 | Console.WriteLine($"Inject Crtl+C event handler {(setSuccess ? "successed" : "failed")}");
133 | Console.ReadLine();
134 |
135 | Console.WriteLine("Get perfmon...");
136 | Console.ReadLine();
137 | while (true)
138 | {
139 | if (exit)
140 | {
141 | break;
142 | }
143 | IPerformance perfmon = Miner.GetPerformance(file, format(config), new IPEndPoint(IPAddress.Loopback, 8087), request, fr, rp, out isRun);
144 | Console.WriteLine($"Performance: {JsonConvert.SerializeObject(perfmon)}");
145 | Thread.Sleep(1000);
146 | }
147 | #endregion
148 |
149 | Console.ReadLine();
150 | }
151 | static void SaveConfig(string file, Config config, StorgaeType strorageType = StorgaeType.SolatedStorage)
152 | {
153 | if (strorageType == StorgaeType.LocalStorage)
154 | {
155 | FileOperation.LocalWrite(file, config);
156 | }
157 | else
158 | {
159 | string isolatedFile = $"Configuration/Mining/{file}";
160 | FileOperation.SolatedStorageWrite(isolatedFile, config);
161 | }
162 | }
163 | static Config LoadConfig(string file, StorgaeType strorageType = StorgaeType.SolatedStorage)
164 | {
165 | if (strorageType == StorgaeType.LocalStorage)
166 | {
167 | return FileOperation.LocalRead(file);
168 | }
169 | else
170 | {
171 | string isolatedFile = $"Configuration/Mining/{file}";
172 | return FileOperation.SolatedStorageRead(isolatedFile);
173 | }
174 | }
175 | }
176 | enum StorgaeType
177 | {
178 | LocalStorage,
179 | SolatedStorage
180 | }
181 | enum dwCtrlType
182 | {
183 | CTRL_C_EVENT = 0,
184 | //A CTRL+C signal was received, either from keyboard input or from a signal generated by the GenerateConsoleCtrlEvent function.
185 | CTRL_BREAK_EVENT = 1,
186 | //A CTRL+BREAK signal was received, either from keyboard input or from a signal generated by GenerateConsoleCtrlEvent.
187 | CTRL_CLOSE_EVENT = 2,
188 | //A signal that the system sends to all processes attached to a console when the user closes the console (either by clicking Close on the console window's window menu, or by clicking the End Task button command from Task Manager).
189 | CTRL_LOGOFF_EVENT = 5,
190 | //A signal that the system sends to all console processes when a user is logging off. This signal does not indicate which user is logging off, so no assumptions can be made.
191 | CTRL_SHUTDOWN_EVENT = 6
192 | //A signal that the system sends when the system is shutting down. Interactive applications are not present by the time the system sends this signal, therefore it can be received only be services in this situation. Services also have their own notification mechanism for shutdown events. For more information, see Handler.
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/Miner.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26730.16
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Contract", "Contract\Contract.csproj", "{AB1F9FEF-BCE7-446E-9039-EB215501C773}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ulord", "Ulord\Ulord.csproj", "{F82039B3-5473-4536-8834-7BA7AC66F103}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csproj", "{084B4296-6DA9-435A-B3F1-403268095A05}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{034CD5AF-F956-4FE4-B79F-EF907A653E89}"
13 | ProjectSection(ProjectDependencies) = postProject
14 | {F82039B3-5473-4536-8834-7BA7AC66F103} = {F82039B3-5473-4536-8834-7BA7AC66F103}
15 | EndProjectSection
16 | EndProject
17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Miner-WPF", "Miner-WPF\Miner-WPF.csproj", "{83A50874-901B-4B77-B6B0-60AEEEA4CD08}"
18 | ProjectSection(ProjectDependencies) = postProject
19 | {F82039B3-5473-4536-8834-7BA7AC66F103} = {F82039B3-5473-4536-8834-7BA7AC66F103}
20 | EndProjectSection
21 | EndProject
22 | Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "Installer", "Installer\Installer.vdproj", "{36CF04D3-B58D-4FAC-BEEE-818FBF0EC555}"
23 | EndProject
24 | Global
25 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
26 | Debug|Any CPU = Debug|Any CPU
27 | Debug|ARM = Debug|ARM
28 | Debug|x64 = Debug|x64
29 | Debug|x86 = Debug|x86
30 | Release|Any CPU = Release|Any CPU
31 | Release|ARM = Release|ARM
32 | Release|x64 = Release|x64
33 | Release|x86 = Release|x86
34 | EndGlobalSection
35 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
36 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Debug|ARM.ActiveCfg = Debug|Any CPU
39 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Debug|ARM.Build.0 = Debug|Any CPU
40 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Debug|x64.ActiveCfg = Debug|Any CPU
41 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Debug|x64.Build.0 = Debug|Any CPU
42 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Debug|x86.ActiveCfg = Debug|Any CPU
43 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Debug|x86.Build.0 = Debug|Any CPU
44 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Release|ARM.ActiveCfg = Release|Any CPU
47 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Release|ARM.Build.0 = Release|Any CPU
48 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Release|x64.ActiveCfg = Release|Any CPU
49 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Release|x64.Build.0 = Release|Any CPU
50 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Release|x86.ActiveCfg = Release|Any CPU
51 | {AB1F9FEF-BCE7-446E-9039-EB215501C773}.Release|x86.Build.0 = Release|Any CPU
52 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Debug|Any CPU.Build.0 = Debug|Any CPU
54 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Debug|ARM.ActiveCfg = Debug|Any CPU
55 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Debug|ARM.Build.0 = Debug|Any CPU
56 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Debug|x64.ActiveCfg = Debug|Any CPU
57 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Debug|x64.Build.0 = Debug|Any CPU
58 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Debug|x86.ActiveCfg = Debug|Any CPU
59 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Debug|x86.Build.0 = Debug|Any CPU
60 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Release|Any CPU.ActiveCfg = Release|Any CPU
61 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Release|Any CPU.Build.0 = Release|Any CPU
62 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Release|ARM.ActiveCfg = Release|Any CPU
63 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Release|ARM.Build.0 = Release|Any CPU
64 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Release|x64.ActiveCfg = Release|Any CPU
65 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Release|x64.Build.0 = Release|Any CPU
66 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Release|x86.ActiveCfg = Release|Any CPU
67 | {F82039B3-5473-4536-8834-7BA7AC66F103}.Release|x86.Build.0 = Release|Any CPU
68 | {084B4296-6DA9-435A-B3F1-403268095A05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
69 | {084B4296-6DA9-435A-B3F1-403268095A05}.Debug|Any CPU.Build.0 = Debug|Any CPU
70 | {084B4296-6DA9-435A-B3F1-403268095A05}.Debug|ARM.ActiveCfg = Debug|Any CPU
71 | {084B4296-6DA9-435A-B3F1-403268095A05}.Debug|ARM.Build.0 = Debug|Any CPU
72 | {084B4296-6DA9-435A-B3F1-403268095A05}.Debug|x64.ActiveCfg = Debug|Any CPU
73 | {084B4296-6DA9-435A-B3F1-403268095A05}.Debug|x64.Build.0 = Debug|Any CPU
74 | {084B4296-6DA9-435A-B3F1-403268095A05}.Debug|x86.ActiveCfg = Debug|Any CPU
75 | {084B4296-6DA9-435A-B3F1-403268095A05}.Debug|x86.Build.0 = Debug|Any CPU
76 | {084B4296-6DA9-435A-B3F1-403268095A05}.Release|Any CPU.ActiveCfg = Release|Any CPU
77 | {084B4296-6DA9-435A-B3F1-403268095A05}.Release|Any CPU.Build.0 = Release|Any CPU
78 | {084B4296-6DA9-435A-B3F1-403268095A05}.Release|ARM.ActiveCfg = Release|Any CPU
79 | {084B4296-6DA9-435A-B3F1-403268095A05}.Release|ARM.Build.0 = Release|Any CPU
80 | {084B4296-6DA9-435A-B3F1-403268095A05}.Release|x64.ActiveCfg = Release|Any CPU
81 | {084B4296-6DA9-435A-B3F1-403268095A05}.Release|x64.Build.0 = Release|Any CPU
82 | {084B4296-6DA9-435A-B3F1-403268095A05}.Release|x86.ActiveCfg = Release|Any CPU
83 | {084B4296-6DA9-435A-B3F1-403268095A05}.Release|x86.Build.0 = Release|Any CPU
84 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
85 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Debug|Any CPU.Build.0 = Debug|Any CPU
86 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Debug|ARM.ActiveCfg = Debug|Any CPU
87 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Debug|ARM.Build.0 = Debug|Any CPU
88 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Debug|x64.ActiveCfg = Debug|Any CPU
89 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Debug|x64.Build.0 = Debug|Any CPU
90 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Debug|x86.ActiveCfg = Debug|Any CPU
91 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Debug|x86.Build.0 = Debug|Any CPU
92 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Release|Any CPU.ActiveCfg = Release|Any CPU
93 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Release|Any CPU.Build.0 = Release|Any CPU
94 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Release|ARM.ActiveCfg = Release|Any CPU
95 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Release|ARM.Build.0 = Release|Any CPU
96 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Release|x64.ActiveCfg = Release|Any CPU
97 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Release|x64.Build.0 = Release|Any CPU
98 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Release|x86.ActiveCfg = Release|Any CPU
99 | {034CD5AF-F956-4FE4-B79F-EF907A653E89}.Release|x86.Build.0 = Release|Any CPU
100 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
101 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Debug|Any CPU.Build.0 = Debug|Any CPU
102 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Debug|ARM.ActiveCfg = Debug|Any CPU
103 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Debug|ARM.Build.0 = Debug|Any CPU
104 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Debug|x64.ActiveCfg = Debug|Any CPU
105 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Debug|x64.Build.0 = Debug|Any CPU
106 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Debug|x86.ActiveCfg = Debug|Any CPU
107 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Debug|x86.Build.0 = Debug|Any CPU
108 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Release|Any CPU.ActiveCfg = Release|Any CPU
109 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Release|Any CPU.Build.0 = Release|Any CPU
110 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Release|ARM.ActiveCfg = Release|Any CPU
111 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Release|ARM.Build.0 = Release|Any CPU
112 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Release|x64.ActiveCfg = Release|Any CPU
113 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Release|x64.Build.0 = Release|Any CPU
114 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Release|x86.ActiveCfg = Release|Any CPU
115 | {83A50874-901B-4B77-B6B0-60AEEEA4CD08}.Release|x86.Build.0 = Release|Any CPU
116 | {36CF04D3-B58D-4FAC-BEEE-818FBF0EC555}.Debug|Any CPU.ActiveCfg = Debug
117 | {36CF04D3-B58D-4FAC-BEEE-818FBF0EC555}.Debug|ARM.ActiveCfg = Debug
118 | {36CF04D3-B58D-4FAC-BEEE-818FBF0EC555}.Debug|x64.ActiveCfg = Debug
119 | {36CF04D3-B58D-4FAC-BEEE-818FBF0EC555}.Debug|x86.ActiveCfg = Debug
120 | {36CF04D3-B58D-4FAC-BEEE-818FBF0EC555}.Release|Any CPU.ActiveCfg = Release
121 | {36CF04D3-B58D-4FAC-BEEE-818FBF0EC555}.Release|ARM.ActiveCfg = Release
122 | {36CF04D3-B58D-4FAC-BEEE-818FBF0EC555}.Release|x64.ActiveCfg = Release
123 | {36CF04D3-B58D-4FAC-BEEE-818FBF0EC555}.Release|x86.ActiveCfg = Release
124 | EndGlobalSection
125 | GlobalSection(SolutionProperties) = preSolution
126 | HideSolutionNode = FALSE
127 | EndGlobalSection
128 | GlobalSection(ExtensibilityGlobals) = postSolution
129 | SolutionGuid = {C1B6441F-AD71-4BB4-AF80-9962528896E3}
130 | EndGlobalSection
131 | EndGlobal
132 |
--------------------------------------------------------------------------------
/Miner-WPF/Commons/Configuration.cs:
--------------------------------------------------------------------------------
1 | using Common;
2 | using Contract;
3 | using Miner_WPF.Models;
4 | using Newtonsoft.Json;
5 | using System;
6 | using System.Diagnostics;
7 | using System.IO;
8 | using System.Net;
9 | using System.Text.RegularExpressions;
10 | using System.Windows;
11 |
12 | namespace Miner_WPF.Commons
13 | {
14 | public class Configuration
15 | {
16 | private static object asyncConfigRoot = new object();
17 | private static object asyncCounterRoot = new object();
18 | private static readonly string CONFIGPATH = "config.json";
19 | private static PerformanceCounter performanceCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
20 |
21 | private static string file;
22 | private static IMiner miner;
23 | private static Config config;
24 | private static string request;
25 | private static IPEndPoint endPoint;
26 | private static Func format;
27 |
28 | private static Func parseResult;
29 | private static Action setPerformance;
30 |
31 | private static EventHandler exitHandler;
32 | private static DataReceivedEventHandler errorHandler;
33 | private static DataReceivedEventHandler outputHandler;
34 |
35 | private static string validateCode;
36 |
37 | internal static void Init(IMiner minerd, Action action = null)
38 | {
39 | file = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UlordRig.exe");
40 | string md5File = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.bin");
41 | string fileMD5 = default(string);
42 | try
43 | {
44 | action?.Invoke("正在获取最新挖矿软件信息...");
45 | AppInfo appInfo = FileHelper.GetAppInfo("http://backup.u1pool.com/api/rig_stats");
46 | appInfo.Version = Regex.Match(appInfo.Version, "\\d[\\d\\.]+")?.Value;
47 | if (!File.Exists(file) || FileVersionInfo.GetVersionInfo(file).ProductVersion != appInfo.Version || FileHelper.ComputeFileMD5(file) != appInfo.MD5.ToUpper())
48 | {
49 | action?.Invoke("正在更新挖矿软件...");
50 | FileHelper.DownloadFile(appInfo.Address, file, action);
51 | }
52 | action?.Invoke("正在校验挖矿软件...");
53 | validateCode = appInfo.MD5.ToUpper();
54 | fileMD5 = FileHelper.ComputeFileMD5(file);
55 | }
56 | catch
57 | {
58 | validateCode = FileHelper.LoadString(md5File);
59 | fileMD5 = FileHelper.ComputeFileMD5(file);
60 | }
61 | if (fileMD5 != validateCode)
62 | {
63 | throw new FileLoadException();
64 | }
65 | try
66 | {
67 | FileHelper.SaveString(md5File, validateCode);
68 | }
69 | catch
70 | {
71 | }
72 |
73 | miner = minerd;
74 | Load();
75 | request = "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"getMinerParam\"}";
76 | endPoint = new IPEndPoint(IPAddress.Loopback, 8087);
77 | format = c => $"-o \"stratum+tcp://{c.Url}\" -u \"{(string.IsNullOrEmpty(c.Id) ? c.User : $"{c.User}.{c.Id}")}\" -p \"{c.Pass}\" -t {c.Thread}";
78 |
79 | parseResult = s =>
80 | {
81 | s = s.Substring(s.IndexOf('H')).Replace("/ ", ":").Replace(" ", "").Replace("Hashrate", "{\"Hashrate\"").Replace("accept", ",\"Accept\"").Replace("total", ",\"Total\"") + "}";
82 | return JsonConvert.DeserializeObject(s);
83 | };
84 | setPerformance = (p, r) => p.SetPerformance(r.Total, r.Accept, r.Hashrate, 0);
85 |
86 | outputHandler += (s, e) => DebugMessageHandle(e.Data);
87 | errorHandler += (s, e) => DebugMessageHandle(e.Data);
88 | exitHandler += (s, e) => DebugMessageHandle($"Exited with {(s as Process).ExitCode}");
89 | }
90 | #region Load & Save
91 | public static void Load()
92 | {
93 | config = new Config();
94 | try
95 | {
96 | Config lastConfig = FileOperation.SolatedStorageRead(CONFIGPATH);
97 | if (lastConfig != null)
98 | {
99 | lock (asyncConfigRoot)
100 | {
101 | config.SetConfig(lastConfig);
102 | }
103 | }
104 | }
105 | catch (Exception ex)
106 | {
107 | DebugExceptionHandle(ex);
108 | }
109 | }
110 | public static void Save()
111 | {
112 | try
113 | {
114 | lock (asyncConfigRoot)
115 | {
116 | FileOperation.SolatedStorageWrite(CONFIGPATH, config);
117 | }
118 | }
119 | catch (Exception ex)
120 | {
121 | DebugExceptionHandle(ex);
122 | }
123 | }
124 | #endregion
125 | #region Notify information
126 | public static void ShowErrMessage(string message)
127 | {
128 | MessageBox.Show(message, "系统消息", MessageBoxButton.OK, MessageBoxImage.Error);
129 | }
130 | public static void DebugExceptionHandle(Exception ex)
131 | {
132 | DebugMessageHandle($"Exception: {ex}");
133 | }
134 | public static void DebugMessageHandle(string message)
135 | {
136 | Debug.WriteLine($"{DateTime.Now}: {message}");
137 | }
138 | #endregion
139 | #region Get perfmon & IsRun & Run & Terminate
140 | public static IPerformance GetPerfmon(out bool isRun)
141 | {
142 | return miner.GetPerformance(file, format(config), endPoint, request, parseResult, setPerformance, out isRun);
143 | }
144 | public static bool IsRun()
145 | {
146 | return miner.Alive(file, format(config));
147 | }
148 | public static bool TryRun(Config newConfig)
149 | {
150 | try
151 | {
152 | if (FileHelper.ComputeFileMD5(file) != validateCode)
153 | {
154 | throw new FileLoadException();
155 | }
156 | }
157 | catch
158 | {
159 | TryTerminate();
160 | return false;
161 | }
162 | if (miner.Run(file, format(newConfig), outputHandler, errorHandler))
163 | {
164 | lock (asyncConfigRoot)
165 | {
166 | config.SetConfig(newConfig);
167 | }
168 | return true;
169 | }
170 | return false;
171 | }
172 | public static bool TryTerminate()
173 | {
174 | if (miner.Terminate(file))
175 | {
176 | return true;
177 | }
178 | return false;
179 | }
180 | #endregion
181 | #region Boot start
182 | public static bool IsBootStart()
183 | {
184 | return Process.GetCurrentProcess().MainModule.FileName.Equals(Win32Native.GetRegistryValue(@"Software\Microsoft\Windows\CurrentVersion\Run", "UlordMiner"));
185 | }
186 | public static bool BootStart(bool power, Action action = null)
187 | {
188 | try
189 | {
190 | if (power)
191 | {
192 | Win32Native.SetRegistryKey(@"Software\Microsoft\Windows\CurrentVersion\Run", new RegistryKeyValue("UlordMiner", Process.GetCurrentProcess().MainModule.FileName));
193 | }
194 | else
195 | {
196 | Win32Native.DeleteRegistryKey(@"Software\Microsoft\Windows\CurrentVersion\Run", "UlordMiner");
197 | }
198 | return true;
199 | }
200 | catch
201 | {
202 | action?.Invoke(power);
203 | return false;
204 | }
205 | }
206 | #endregion
207 | #region Automatic & Idle & CPU usage
208 | public static void SetAutomatic(bool automatic)
209 | {
210 | lock (asyncConfigRoot)
211 | {
212 | config.Automatic = automatic;
213 | }
214 | }
215 | public static bool GetAutomatic()
216 | {
217 | lock (asyncConfigRoot)
218 | {
219 | return config.Automatic;
220 | }
221 | }
222 | public static bool IsIdle()
223 | {
224 | return Win32Native.GetIdleTime() >= 2 * 60 * 1000;
225 | }
226 | public static Config GetConfig()
227 | {
228 | return config;
229 | }
230 | public static float GetCPUUsage(Action action = null)
231 | {
232 | try
233 | {
234 | lock (asyncCounterRoot)
235 | {
236 | return performanceCounter.NextValue();
237 | }
238 | }
239 | catch (Exception ex)
240 | {
241 | action?.Invoke(ex);
242 | return default(float);
243 | }
244 | }
245 | #endregion
246 | }
247 | }
248 |
--------------------------------------------------------------------------------
/Miner-WPF/WindowConfig.xaml.cs:
--------------------------------------------------------------------------------
1 | using Contract;
2 | using Miner_WPF.Commons;
3 | using Miner_WPF.Models;
4 | using Miner_WPF.Models.ViewModels;
5 | using System;
6 | using System.Diagnostics;
7 | using System.Globalization;
8 | using System.Text.RegularExpressions;
9 | using System.Windows;
10 | using System.Windows.Data;
11 | using System.Windows.Documents;
12 |
13 | namespace Miner_WPF
14 | {
15 | ///
16 | /// WindowConfig.xaml 的交互逻辑
17 | ///
18 | public partial class WindowConfig : Window
19 | {
20 | private readonly int MinThreadCount = (int)Math.Ceiling(Environment.ProcessorCount / 2.0);
21 | private ConfigWindowViewModel model;
22 | public WindowConfig()
23 | {
24 | InitializeComponent();
25 | #region Binding events
26 | // Load
27 | this.Loaded += (s, e) =>
28 | {
29 | int maximum = Environment.ProcessorCount;
30 | for (int i = 1; i <= maximum; i++)
31 | {
32 | comboBox_Thread.Items.Add(i);
33 | }
34 | Config config = Configuration.GetConfig();
35 | config.Thread = config.Thread <= 0 ? MinThreadCount : config.Thread > maximum ? maximum : config.Thread;
36 | model = new ConfigWindowViewModel() { Config = config, IsAlive = false };
37 | this.DataContext = model;
38 | };
39 | // Drag
40 | this.MouseLeftButtonDown += (s, e) => { try { this.DragMove(); } catch { } };
41 | // Close
42 | btn_Close.MouseDown += (s, e) => this.Close();
43 | // Closing
44 | this.Closing += (s, e) => { this.Hide(); e.Cancel = true; };
45 | // State changed
46 | this.StateChanged += (s, e) =>
47 | {
48 | switch (this.WindowState)
49 | {
50 | case WindowState.Minimized:
51 | this.WindowState = WindowState.Normal;
52 | this.Hide();
53 | break;
54 | case WindowState.Maximized:
55 | this.WindowState = WindowState.Normal;
56 | this.Show();
57 | break;
58 | default:
59 | break;
60 | }
61 | };
62 | // View incoming
63 | btn_Incoming.Click += (s, e) =>
64 | {
65 | string urlFormate = "http://{0}/miners/{1}";
66 | string url = "www.u1pool.com";
67 | if (!string.IsNullOrEmpty(model.Config.Url))
68 | {
69 | string address = model.Config.Url.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries)[0];
70 | if (address != "u1pool.com")
71 | {
72 | url = address;
73 | }
74 | }
75 | Process.Start(string.Format(urlFormate, url, model.Config.User));
76 | };
77 | // Mining
78 | btn_Mining.Click += Btn_Mining_Click;
79 | // Help
80 | btn_Help.MouseDown += (s, e) =>
81 | {
82 | view_help.ScrollToTop();
83 | grid_help.Visibility = Visibility.Visible;
84 | };
85 | btn_return.MouseDown += (s, e) => grid_help.Visibility = Visibility.Hidden;
86 | #endregion
87 | }
88 | #region Set perfomance & Start mining, stop mining
89 | public void SetPerformance(bool isRun, IPerformance perfmon)
90 | {
91 | if (model != null)
92 | {
93 | model.IsAlive = isRun;
94 | model.SetPerformance(perfmon);
95 | }
96 | }
97 | public void StartMining()
98 | {
99 | if (model != null)
100 | {
101 | if (!TryFormatConfig())
102 | {
103 | return;
104 | }
105 | else
106 | {
107 | if (Configuration.TryRun(model.Config))
108 | {
109 | model.IsAlive = true;
110 | Configuration.Save();
111 | }
112 | else
113 | {
114 | return;
115 | }
116 | }
117 | }
118 | }
119 | #endregion
120 | #region Start mining & Stop mining
121 | private void Btn_Mining_Click(object sender, RoutedEventArgs e)
122 | {
123 | if ("开始挖矿".Equals(btn_Mining.Content))
124 | {
125 | if (TryFormatConfig())
126 | {
127 | if (Configuration.TryRun(model.Config))
128 | {
129 | model.IsAlive = true;
130 | Configuration.Save();
131 | }
132 | else
133 | {
134 | Configuration.ShowErrMessage("启动挖矿程序失败!");
135 | }
136 | }
137 | }
138 | else
139 | {
140 | if (Configuration.TryTerminate())
141 | {
142 | model.IsAlive = false;
143 | model.Config.Automatic = false;
144 | Configuration.SetAutomatic(false);
145 | }
146 | else
147 | {
148 | Configuration.ShowErrMessage("结束挖矿程序失败!");
149 | }
150 | }
151 | }
152 | #endregion
153 | #region Format input
154 | private bool TryFormatConfig(Action action = null)
155 | {
156 | if (string.IsNullOrEmpty(model.Config.Url))
157 | {
158 | action?.Invoke("请输入地址!");
159 | }
160 | else if (string.IsNullOrEmpty(model.Config.User) || !Regex.IsMatch(model.Config.User, "^[uU][a-zA-Z0-9]{33}$"))
161 | {
162 | action?.Invoke(@"账户只能为以u\U开头的34个字母和数字字符组合!");
163 | }
164 | else if (!string.IsNullOrEmpty(model.Config.Id) && !Regex.IsMatch(model.Config.Id, "^[a-zA-Z0-9]{0,20}$"))
165 | {
166 | action?.Invoke("编号只能为不超过20位字符的数字和字母!");
167 | }
168 | else if (model.Config.Thread < 0)
169 | {
170 | action?.Invoke("线程数输入错误!");
171 | }
172 | else
173 | {
174 | model.Config.Url = model.Config.Url.Trim();
175 | model.Config.User = model.Config.User.Trim();
176 | return true;
177 | }
178 | return false;
179 | }
180 | #endregion
181 | #region Automatic
182 | private void CheckBox_Checked(object sender, RoutedEventArgs e)
183 | {
184 | if (!TryFormatConfig())
185 | {
186 | check_Automatic.IsChecked = false;
187 | }
188 | else
189 | {
190 | Configuration.SetAutomatic(true);
191 | }
192 | }
193 | private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
194 | {
195 | Configuration.TryTerminate();
196 | Configuration.SetAutomatic(false);
197 | }
198 | #endregion
199 |
200 | private void Hyperlink_Click(object sender, RoutedEventArgs e)
201 | {
202 | Process.Start((sender as Hyperlink).NavigateUri.AbsoluteUri);
203 | }
204 | }
205 | #region Paramter value binding and converter
206 | public enum ValidateTypes
207 | {
208 | Url,
209 | User,
210 | Id
211 | }
212 | public class ValidateBinding : Binding
213 | {
214 | public ValidateBinding() : this(ValidateTypes.Url)
215 | {
216 | }
217 | public ValidateBinding(ValidateTypes validateTypes) : base("Text")
218 | {
219 | RelativeSource = RelativeSource.Self;
220 | Converter = new ValidateConverter(validateTypes);
221 | }
222 | }
223 | [ValueConversion(typeof(string), typeof(bool))]
224 | public class ValidateConverter : IValueConverter
225 | {
226 | private ValidateTypes validateType;
227 | public ValidateConverter(ValidateTypes validateType)
228 | {
229 | this.validateType = validateType;
230 | }
231 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
232 | {
233 | bool validate;
234 | string text = (string)value;
235 | switch (validateType)
236 | {
237 | case ValidateTypes.Url:
238 | validate = string.IsNullOrEmpty(text);
239 | break;
240 | case ValidateTypes.User:
241 | validate = string.IsNullOrEmpty(text) || !Regex.IsMatch(text, "^[uU][a-zA-Z0-9]{33}$");
242 | break;
243 | case ValidateTypes.Id:
244 | validate = !string.IsNullOrEmpty(text) && !Regex.IsMatch(text, "^[a-zA-Z0-9]{0,20}$");
245 | break;
246 | default:
247 | validate = false;
248 | break;
249 | }
250 | return validate;
251 | }
252 |
253 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
254 | {
255 | throw new NotImplementedException();
256 | }
257 | }
258 | #endregion
259 | }
260 |
--------------------------------------------------------------------------------
/Miner-WPF/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using Contract;
2 | using Miner_WPF.Commons;
3 | using Miner_WPF.Controls;
4 | using Miner_WPF.Models.ViewModels;
5 | using System;
6 | using System.Diagnostics;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 | using System.Windows;
10 | using System.Windows.Input;
11 | using System.Windows.Interop;
12 | using System.Windows.Media;
13 |
14 | namespace Miner_WPF
15 | {
16 | ///
17 | /// MainWindow.xaml 的交互逻辑
18 | ///
19 | public partial class MainWindow : Window
20 | {
21 |
22 | private bool isHidden = false;
23 |
24 | private WPFNotifyIcon notifyIcon = new WPFNotifyIcon();
25 | private WindowConfig windowConfig = new WindowConfig() { Left = 0, Top = 0 };
26 | private bool follow = true;
27 | private MainWindowViewModel model;
28 | public MainWindow()
29 | {
30 | InitializeComponent();
31 | #region Binding events
32 | int automaticTimeout = 30 * 1000;
33 | int performanceTimeout = 1000;
34 | SolidColorBrush normBrush = (SolidColorBrush)FindResource("NormBrush");
35 | SolidColorBrush warnBrush = (SolidColorBrush)FindResource("WarnBrush");
36 | SolidColorBrush dangerBrush = (SolidColorBrush)FindResource("DangerBrush");
37 | // Load
38 | this.Loaded += (s, e) =>
39 | {
40 | model = new MainWindowViewModel();
41 | this.DataContext = model;
42 | Win32Native.SetGlobalLLMouseHook(Mouse_Down);
43 | windowConfig.LocationChanged += WindowConfig_LocationChanged;
44 | windowConfig.Show();
45 | };
46 | // Close
47 | this.Closed += (s, e) =>
48 | {
49 | Win32Native.RemoveGlobalLLMouseHook();
50 | Configuration.TryTerminate();
51 | notifyIcon.Dispose();
52 | Environment.Exit(0);
53 | };
54 | // Drag
55 | this.MouseLeftButtonDown += (s, e) =>
56 | {
57 | try
58 | {
59 | this.DragMove();
60 | }
61 | catch
62 | {
63 | }
64 | };
65 | // Show config window
66 | this.MouseRightButtonDown += WindowConfig_Show;
67 | this.MouseDoubleClick += WindowConfig_Show;
68 | // State changed
69 | this.StateChanged += (s, e) =>
70 | {
71 | switch (this.WindowState)
72 | {
73 | case WindowState.Normal:
74 | InitializeLocation();
75 | break;
76 | case WindowState.Minimized:
77 | case WindowState.Maximized:
78 | this.WindowState = WindowState.Normal;
79 | break;
80 | default:
81 | break;
82 | }
83 | };
84 | // Hidden window
85 | rec.MouseEnter += MainWindow_OnMouseEnter;
86 | rec.MouseLeave += MainWidow_OnMouseLeave;
87 | this.LocationChanged += MainWindow_LocationChanged;
88 | #endregion
89 | #region Performance
90 | Task.Factory.StartNew(() =>
91 | {
92 | while (true)
93 | {
94 | try
95 | {
96 | bool isRun;
97 | IPerformance perfmon = Configuration.GetPerfmon(out isRun);
98 | model.ComputeAbility = perfmon.Hashrate;
99 | windowConfig.SetPerformance(isRun, perfmon);
100 | this.Dispatcher.Invoke(() =>
101 | {
102 | if (isRun)
103 | {
104 | panel_Run.Visibility = Visibility.Visible;
105 | panel_Stop.Visibility = Visibility.Collapsed;
106 | }
107 | else
108 | {
109 | panel_Run.Visibility = Visibility.Collapsed;
110 | panel_Stop.Visibility = Visibility.Visible;
111 | }
112 | });
113 | }
114 | catch
115 | {
116 | }
117 | Thread.Sleep(performanceTimeout);
118 | }
119 | });
120 | #endregion
121 | #region CPU usage
122 | Task.Factory.StartNew(() =>
123 | {
124 | while (true)
125 | {
126 | try
127 | {
128 | float usage = Configuration.GetCPUUsage();
129 | double angle = usage * 3.6;
130 | SolidColorBrush solidColorBrush = usage >= 90 ? dangerBrush : usage >= 50 ? warnBrush : normBrush;
131 | this.Dispatcher.Invoke(() =>
132 | {
133 | arc.EndAngle = angle;
134 | arc.Fill = solidColorBrush;
135 | });
136 | }
137 | catch
138 | {
139 | }
140 | Thread.Sleep(performanceTimeout);
141 | }
142 | });
143 | #endregion
144 | #region Automatic mining
145 | Task.Factory.StartNew(() =>
146 | {
147 | while (true)
148 | {
149 | try
150 | {
151 | if (Configuration.GetAutomatic())
152 | {
153 | if (!Configuration.IsRun())
154 | {
155 | if (Configuration.IsIdle())
156 | {
157 | windowConfig.StartMining();
158 | }
159 | }
160 | }
161 | }
162 | catch
163 | {
164 | }
165 | Thread.Sleep(automaticTimeout);
166 | }
167 | });
168 | #endregion
169 | InitializeNotifyIcon();
170 | InitializeLocation();
171 | }
172 | #region Hidden window
173 | private void InitializeLocation()
174 | {
175 | this.Top = SystemParameters.WorkArea.Height - this.Height;
176 | this.Left = SystemParameters.WorkArea.Width - this.Width;
177 | }
178 | private void MainWindow_OnMouseEnter(object sender, MouseEventArgs e)
179 | {
180 | if (isHidden)
181 | {
182 | Task.Factory.StartNew(() =>
183 | {
184 | this.Dispatcher.Invoke(() =>
185 | {
186 | if (this.Top < 0)
187 | {
188 | while (++this.Top < 0)
189 | {
190 | }
191 | isHidden = false;
192 | }
193 | if (this.Left < 0)
194 | {
195 | while (++this.Left < 0)
196 | {
197 | }
198 | isHidden = false;
199 | }
200 | if (this.Left > SystemParameters.WorkArea.Width - this.Width)
201 | {
202 | while (--this.Left > SystemParameters.WorkArea.Width - this.Width)
203 | {
204 | }
205 | isHidden = false;
206 | }
207 | });
208 | });
209 | }
210 | }
211 |
212 | private void MainWidow_OnMouseLeave(object sender, MouseEventArgs e)
213 | {
214 | if (!isHidden)
215 | {
216 | // Distance from the form to the boundary
217 | int windowDirection = 0;
218 | // Width or height displayed after the form is hidden
219 | int showWidthOrHeight = 10;
220 | if (this.Top <= 0)
221 | {
222 | Task.Factory.StartNew(() =>
223 | {
224 | this.Dispatcher.Invoke(() =>
225 | {
226 | if (windowConfig.Visibility == Visibility.Visible)
227 | {
228 | this.Top = 0;
229 | }
230 | else
231 | {
232 | while (this.Top >= -this.Height + showWidthOrHeight)
233 | {
234 | --this.Top;
235 | }
236 | isHidden = true;
237 | }
238 | });
239 | });
240 | }
241 | else if (this.Left <= windowDirection)
242 | {
243 | Task.Factory.StartNew(() =>
244 | {
245 | this.Dispatcher.Invoke(() =>
246 | {
247 | if (windowConfig.Visibility == Visibility.Visible)
248 | {
249 | this.Left = 0;
250 | }
251 | else
252 | {
253 | while (this.Left >= -this.Width + showWidthOrHeight)
254 | {
255 | --this.Left;
256 | }
257 | isHidden = true;
258 | }
259 | });
260 | });
261 | }
262 | else if (this.Left >= SystemParameters.WorkArea.Width - this.Width - windowDirection)
263 | {
264 | Task.Factory.StartNew(() =>
265 | {
266 | this.Dispatcher.Invoke(() =>
267 | {
268 | if (windowConfig.Visibility == Visibility.Visible)
269 | {
270 | this.Left = SystemParameters.WorkArea.Width - this.Width;
271 | }
272 | else
273 | {
274 | while (this.Left <= SystemParameters.WorkArea.Width - showWidthOrHeight)
275 | {
276 | ++this.Left;
277 | }
278 | isHidden = true;
279 | }
280 | });
281 | });
282 | }
283 | }
284 | }
285 | private bool PointInWindow(Window window, Tuple tuple)
286 | {
287 | if (window.Left <= tuple.Item1 && tuple.Item1 <= window.Left + window.Width && window.Top <= tuple.Item2 && tuple.Item2 <= window.Top + window.Height)
288 | {
289 | return true;
290 | }
291 | return false;
292 | }
293 | #endregion
294 | #region WindowConfig
295 | private void Mouse_Down(object sender, EventArgs e)
296 | {
297 | if (windowConfig != null && windowConfig.IsVisible)
298 | {
299 | if (!this.IsMouseOver && !windowConfig.IsMouseOver)
300 | {
301 | windowConfig.Hide();
302 | }
303 | }
304 | }
305 | private void WindowConfig_Show(object sender, MouseButtonEventArgs e)
306 | {
307 | if (windowConfig.Visibility != Visibility.Visible)
308 | {
309 | follow = true;
310 | bool change = false;
311 | if (this.Top < 0)
312 | {
313 | this.Top = 0;
314 | change = true;
315 | }
316 | if (this.Left < 0)
317 | {
318 | this.Left = 0;
319 | change = true;
320 | }
321 | if (this.Left > SystemParameters.WorkArea.Width - this.Width)
322 | {
323 | this.Left = SystemParameters.WorkArea.Width - this.Width;
324 | change = true;
325 | }
326 | if (!change)
327 | {
328 | MainWindow_LocationChanged(default(object), default(EventArgs));
329 | }
330 | windowConfig.grid_help.Visibility = Visibility.Hidden;
331 | windowConfig.Show();
332 | }
333 | }
334 | private void WindowConfig_LocationChanged(object sender, EventArgs e)
335 | {
336 | bool bl = this.Left <= windowConfig.Left && windowConfig.Left <= this.Left + this.Width || windowConfig.Left <= this.Left && this.Left <= windowConfig.Left + windowConfig.Width;
337 | bool bt = this.Top <= windowConfig.Top && windowConfig.Top <= this.Top + this.Height || windowConfig.Top < this.Top && this.Top <= windowConfig.Top + windowConfig.Height;
338 | follow = bl && bt;
339 | }
340 | private void MainWindow_LocationChanged(object sender, EventArgs e)
341 | {
342 | // windows center point
343 | double centerML = this.Left + this.Width * 0.5;
344 | double centerMT = this.Top + this.Height * 0.5;
345 | double centerCL = windowConfig.Left + windowConfig.Width * 0.5;
346 | double centerCT = windowConfig.Top + windowConfig.Height * 0.5;
347 | // config window follow location
348 | double l = this.Left + 0.5 * this.Width - windowConfig.Width;
349 | double t = this.Top + 0.5 * this.Height - windowConfig.Height;
350 | double r = this.Left + 0.5 * this.Width;
351 | double b = this.Top + 0.5 * this.Height;
352 | // config window location range
353 | double minl = 0;
354 | double mint = 0;
355 | double maxl = SystemParameters.WorkArea.Width - windowConfig.Width;
356 | double maxt = SystemParameters.WorkArea.Height - windowConfig.Height;
357 | // config window really location
358 | double cl;
359 | double ct;
360 | if (!follow)
361 | {
362 | WindowConfig_LocationChanged(default(object), default(EventArgs));
363 | }
364 | if (follow)
365 | {
366 | // calculate config window location
367 | if (centerML > centerCL)
368 | {
369 | // Left, Top
370 | if (centerMT > centerCT)
371 | {
372 | cl = l;
373 | ct = t;
374 | }
375 | // Left, Bottom
376 | else
377 | {
378 | cl = l;
379 | ct = b;
380 | }
381 | }
382 | else
383 | {
384 | // Right, Top
385 | if (centerMT > centerCT)
386 | {
387 | cl = r;
388 | ct = t;
389 | }
390 | // Right, Bottom
391 | else
392 | {
393 | cl = r;
394 | ct = b;
395 | }
396 | }
397 | // limit config window location
398 | if (cl < minl)
399 | {
400 | cl = r;
401 | }
402 | if (cl > maxl)
403 | {
404 | cl = l;
405 | }
406 | if (ct < mint)
407 | {
408 | ct = b;
409 | }
410 | if (ct > maxt)
411 | {
412 | ct = t;
413 | }
414 | windowConfig.Left = cl;
415 | windowConfig.Top = ct;
416 | }
417 | // limit main window top
418 | if (this.Top > SystemParameters.WorkArea.Height - this.Height)
419 | {
420 | this.Top = SystemParameters.WorkArea.Height - this.Height;
421 | }
422 | }
423 | #endregion
424 | #region Notify icon
425 | private void InitializeNotifyIcon()
426 | {
427 | notifyIcon.notifyIcon.Icon = Properties.Resources.Ulord;
428 | notifyIcon.notifyIcon.Text = "挖矿程序运行中...";
429 | notifyIcon.打开ToolStripMenuItem.Click += (s, e) =>
430 | {
431 | this.WindowState = WindowState.Normal;
432 | Win32Native.BringWindowToTop(new WindowInteropHelper(this).Handle);
433 | WindowConfig_Show(default(object), default(MouseButtonEventArgs));
434 | };
435 | notifyIcon.开机启动ToolStripMenuItem.Click += (s, e) => Configuration.BootStart(!notifyIcon.开机启动ToolStripMenuItem.Checked, f => Configuration.ShowErrMessage($"{(f ? "设置" : "禁止")}程序开机启动失败,需要管理员权限!"));
436 | notifyIcon.关于我们ToolStripMenuItem.Click += (s, e) => Process.Start("https://ulord.one/");
437 | notifyIcon.退出ToolStripMenuItem.Click += (s, e) => this.Close();
438 | notifyIcon.notifyIcon.MouseDoubleClick += (o, e) => notifyIcon.打开ToolStripMenuItem.PerformClick();
439 | notifyIcon.contextMenuStrip.Opening += (s, e) => notifyIcon.开机启动ToolStripMenuItem.Checked = Configuration.IsBootStart();
440 | notifyIcon.notifyIcon.Visible = true;
441 | }
442 | #endregion
443 | }
444 | }
445 |
--------------------------------------------------------------------------------
/Miner-WPF/WindowConfig.xaml:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
24 |
25 |
29 |
30 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
92 |
124 |
125 |
134 |
167 |
168 |
200 |
201 |
231 |
232 |
240 |
241 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
357 |
358 |
368 |
369 |
370 |
371 |
375 |
376 |
386 |
387 |
388 |
389 |
393 |
394 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 | 5
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
478 |
479 |
484 |
485 |
490 |
491 |
496 |
497 |
498 |
499 |
504 |
505 |
506 |
507 |
508 |
509 |
510 | Ulord Foundation Ltd.
511 |
512 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
--------------------------------------------------------------------------------