├── .gitignore
├── LICENSE
├── README.md
├── SalamanderWnmp.VC.db
├── SalamanderWnmp.sln
├── SalamanderWnmp.v12.suo
├── SalamanderWnmp
├── App.xaml
├── App.xaml.cs
├── AttachProperty
│ └── ControlAttachProperty.cs
├── Common.cs
├── Configuration
│ ├── Ini.cs
│ ├── Option.cs
│ └── PHPConfigurationManager.cs
├── Constants.cs
├── Converter
│ ├── LanToBoolConverter .cs
│ ├── ProcessColorConverter.cs
│ └── ProcessTextConverter.cs
├── CustomHighlighting.xshd
├── EditorClass
│ ├── BraceFoldingStrategy.cs
│ └── MyCompletionData.cs
├── Icons
│ └── logo.ico
├── Images
│ ├── Editor
│ │ ├── Copy.png
│ │ ├── Cut.png
│ │ ├── Delete.png
│ │ ├── Open.png
│ │ ├── Paste.png
│ │ ├── Redo.png
│ │ ├── Run.png
│ │ ├── Save.png
│ │ ├── Undo.png
│ │ ├── WordWrap.png
│ │ ├── font_add.png
│ │ └── font_minus.png
│ ├── Menu
│ │ ├── Redis.png
│ │ ├── about.png
│ │ ├── author.png
│ │ ├── code.png
│ │ ├── dir.png
│ │ ├── hosts.png
│ │ ├── http.png
│ │ ├── js.png
│ │ ├── scan.png
│ │ ├── settings.png
│ │ └── skin.png
│ ├── author.jpg
│ ├── code.png
│ ├── dir.png
│ ├── erha.png
│ ├── exit.png
│ ├── http.png
│ ├── menu.png
│ ├── minimize.png
│ ├── mysql.png
│ ├── nginx.png
│ ├── php.png
│ ├── redis.png
│ └── skin.png
├── Programs
│ ├── BaseProgram.cs
│ ├── Mysql.cs
│ ├── Nginx.cs
│ ├── PHP.cs
│ └── Redis.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ ├── Settings.settings
│ └── app.manifest
├── ReadMe.text
├── Resources
│ ├── iconfont.ttf
│ ├── logo.ico
│ └── logo.png
├── SalamanderWnmp.csproj
├── Tool
│ ├── CodeHelper.cs
│ ├── DispatcherHelper.cs
│ ├── EnvironmentAutoConfig.cs
│ ├── HttpHelper.cs
│ ├── IEProxySetting.cs
│ ├── Log.cs
│ ├── PortScanHelper.cs
│ ├── ProxyHelper.cs
│ ├── RedisHelper.cs
│ └── ViewHelper.cs
├── UI
│ ├── AboutWin.xaml
│ ├── AboutWin.xaml.cs
│ ├── AddRedisConnWin.xaml
│ ├── AddRedisConnWin.xaml.cs
│ ├── AuthorWin.xaml
│ ├── AuthorWin.xaml.cs
│ ├── ChangeThemeColorWin.xaml
│ ├── ChangeThemeColorWin.xaml.cs
│ ├── CodePanelWin.xaml
│ ├── CodePanelWin.xaml.cs
│ ├── HttpRequesterWin.xaml
│ ├── HttpRequesterWin.xaml.cs
│ ├── LoadingWin.xaml
│ ├── LoadingWin.xaml.cs
│ ├── MainWin.xaml
│ ├── MainWin.xaml.cs
│ ├── PortScanWin.xaml
│ ├── PortScanWin.xaml.cs
│ ├── QuestionsWin.xaml
│ ├── QuestionsWin.xaml.cs
│ ├── RedisWin.xaml
│ ├── RedisWin.xaml.cs
│ ├── SettingWin.xaml
│ └── SettingWin.xaml.cs
├── UserClass
│ ├── ImageMenu.cs
│ ├── NotificationAreaIcon.cs
│ └── SalamanderListBox.cs
├── UserComponent
│ ├── ColorPicker.xaml
│ ├── ColorPicker.xaml.cs
│ ├── Loading.xaml
│ ├── Loading.xaml.cs
│ ├── NumericControl.xaml
│ └── NumericControl.xaml.cs
├── XAML
│ ├── Colors.xaml
│ ├── ComboBox.xaml
│ ├── FIcon.xaml
│ ├── Loading.xaml
│ ├── RadioButton.xaml
│ ├── ScrollViewer.xaml
│ ├── TabControl.xaml
│ ├── TextBox.xaml
│ └── ToggleButton.xaml
├── app.config
├── logo.ico
└── packages.config
├── WnmpUI
├── BaseWindows.cs
├── Properties
│ └── AssemblyInfo.cs
└── WnmpUI.csproj
└── support_img
├── alipay.jpg
└── wxpay.jpg
/.gitignore:
--------------------------------------------------------------------------------
1 | bin/
2 | obj/
3 | x64/
4 | *.suo
5 | Debug/
6 | Release/
7 | *.mdb
8 | *.ldb
9 | /.vs
10 | /packages
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 meng hang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WNMP Based On WPF(WPF制作的wnmp环境)
2 |
3 | [](https://travis-ci.org/slimphp/Slim)
4 | [](https://coveralls.io/r/slimphp/Slim)
5 | [](https://packagist.org/packages/slim/slim)
6 |
7 | ## Download(集成包下载)
8 | * [下载地址(Nginx)](http://file.51lucy.com/SalamanderWnmp.7z)
9 | * [下载地址(OpenResty)](http://file.51lucy.com/SalamanderWnmp-OpenResty.7z)
10 |
11 | ## Main Window(主界面)
12 |
13 |
14 |
15 | ## Usage(使用)
16 | 1. 下载集成包后,运行`SalamanderWnmp.exe`(首次运行会自动配置)
17 | 2. 开启nginx和php,然后在浏览器中输入http://localhost/ 即可看到`Hello Salamander!`字样,说明配置成功。(使用数据库功能,则打开mysql)
18 |
19 |
20 | ## Notice(注意)
21 | * php 版本为**7.3.21** 64位版本,需要MSVC15 (Visual C++ 2017)运行库支持,[下载](https://aka.ms/vs/16/release/vc_redist.x64.exe)
22 | * MySQL的默认账户为root,密码为空
23 |
24 |
25 | ## Other Functions(其他功能)
26 | #### Regulaer Settings(常规设置)
27 |
28 |
29 |
30 | #### Theme Color Panel(调色面板)
31 |
32 |
33 |
34 | #### Coding Panel(编程面板)
35 |
36 |
37 | #### Questions Panel(常见问题面板)
38 |
39 |
40 |
41 | ## Switch PHP Version(切换PHP版本)
42 | 1. 从php官网下载某个版本的PHP,放入你的wnmp目录中(这里假设下载了PHP5.6,可以命名为php5.6)
43 | 2. 修改php.ini(这个文件可以从php.ini-development或php.ini-production重命名过来)中extension_dir选项,改为wnmp中php5.6的ext目录的绝对路径(举例:D:/SalamanderWnmp/php5.6/ext),另外顺便把一些扩展也加载进来(去掉前面分号即可)
44 | ```
45 | extension=php_bz2.dll
46 | extension=php_curl.dll
47 | extension=php_fileinfo.dll
48 | extension=php_ftp.dll
49 | extension=php_gd2.dll
50 | extension=php_gettext.dll
51 | ```
52 | 3. wnmp软件修改php目录配置
53 |
54 |
55 |
56 | 4. 重启PHP
57 |
58 |
59 | ## Third Party Libraries(第三方库)
60 | * [AvalonEdit](https://github.com/icsharpcode/AvalonEdit)
61 | * [StackExchange.Redis](https://github.com/StackExchange/StackExchange.Redis)
62 |
63 |
64 |
65 | ## Contact Me(联系我)
66 | * [Blog](http://blog.51lucy.com/)
67 | * [segmentfault](https://segmentfault.com/u/salamander)
68 |
69 | ## Sponsor(赞助)
70 | #### 支付宝
71 |
72 |
73 | #### 微信支付
74 |
75 |
76 |
--------------------------------------------------------------------------------
/SalamanderWnmp.VC.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp.VC.db
--------------------------------------------------------------------------------
/SalamanderWnmp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.23107.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SalamanderWnmp", "SalamanderWnmp\SalamanderWnmp.csproj", "{7EA83075-7BCE-4E41-85CD-DD6CBFC2A7B7}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WnmpUI", "WnmpUI\WnmpUI.csproj", "{A3A1695D-1595-4E59-AE47-C4C8C02DB6A3}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|x64 = Debug|x64
14 | Debug|x86 = Debug|x86
15 | Release|Any CPU = Release|Any CPU
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {7EA83075-7BCE-4E41-85CD-DD6CBFC2A7B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {7EA83075-7BCE-4E41-85CD-DD6CBFC2A7B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {7EA83075-7BCE-4E41-85CD-DD6CBFC2A7B7}.Debug|x64.ActiveCfg = Debug|Any CPU
23 | {7EA83075-7BCE-4E41-85CD-DD6CBFC2A7B7}.Debug|x64.Build.0 = Debug|Any CPU
24 | {7EA83075-7BCE-4E41-85CD-DD6CBFC2A7B7}.Debug|x64.Deploy.0 = Debug|Any CPU
25 | {7EA83075-7BCE-4E41-85CD-DD6CBFC2A7B7}.Debug|x86.ActiveCfg = Debug|x86
26 | {7EA83075-7BCE-4E41-85CD-DD6CBFC2A7B7}.Debug|x86.Build.0 = Debug|x86
27 | {7EA83075-7BCE-4E41-85CD-DD6CBFC2A7B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
28 | {7EA83075-7BCE-4E41-85CD-DD6CBFC2A7B7}.Release|Any CPU.Build.0 = Release|Any CPU
29 | {7EA83075-7BCE-4E41-85CD-DD6CBFC2A7B7}.Release|x64.ActiveCfg = Release|Any CPU
30 | {7EA83075-7BCE-4E41-85CD-DD6CBFC2A7B7}.Release|x64.Build.0 = Release|Any CPU
31 | {7EA83075-7BCE-4E41-85CD-DD6CBFC2A7B7}.Release|x86.ActiveCfg = Release|x86
32 | {7EA83075-7BCE-4E41-85CD-DD6CBFC2A7B7}.Release|x86.Build.0 = Release|x86
33 | {A3A1695D-1595-4E59-AE47-C4C8C02DB6A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
34 | {A3A1695D-1595-4E59-AE47-C4C8C02DB6A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
35 | {A3A1695D-1595-4E59-AE47-C4C8C02DB6A3}.Debug|x64.ActiveCfg = Debug|Any CPU
36 | {A3A1695D-1595-4E59-AE47-C4C8C02DB6A3}.Debug|x64.Build.0 = Debug|Any CPU
37 | {A3A1695D-1595-4E59-AE47-C4C8C02DB6A3}.Debug|x86.ActiveCfg = Debug|Any CPU
38 | {A3A1695D-1595-4E59-AE47-C4C8C02DB6A3}.Debug|x86.Build.0 = Debug|Any CPU
39 | {A3A1695D-1595-4E59-AE47-C4C8C02DB6A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
40 | {A3A1695D-1595-4E59-AE47-C4C8C02DB6A3}.Release|Any CPU.Build.0 = Release|Any CPU
41 | {A3A1695D-1595-4E59-AE47-C4C8C02DB6A3}.Release|x64.ActiveCfg = Release|Any CPU
42 | {A3A1695D-1595-4E59-AE47-C4C8C02DB6A3}.Release|x64.Build.0 = Release|Any CPU
43 | {A3A1695D-1595-4E59-AE47-C4C8C02DB6A3}.Release|x86.ActiveCfg = Release|Any CPU
44 | {A3A1695D-1595-4E59-AE47-C4C8C02DB6A3}.Release|x86.Build.0 = Release|Any CPU
45 | EndGlobalSection
46 | GlobalSection(SolutionProperties) = preSolution
47 | HideSolutionNode = FALSE
48 | EndGlobalSection
49 | EndGlobal
50 |
--------------------------------------------------------------------------------
/SalamanderWnmp.v12.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp.v12.suo
--------------------------------------------------------------------------------
/SalamanderWnmp/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.Properties;
2 | using SalamanderWnmp.Tool;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Configuration;
6 | using System.Data;
7 | using System.Diagnostics;
8 | using System.Linq;
9 | using System.Reflection;
10 | using System.Runtime.InteropServices;
11 | using System.Threading;
12 | using System.Windows;
13 |
14 | namespace SalamanderWnmp
15 | {
16 | ///
17 | /// App.xaml 的交互逻辑
18 | ///
19 | public partial class SalamanderApp : Application
20 | {
21 |
22 | public SalamanderApp()
23 | {
24 | Process process = GetRuningInstance();
25 | if (process != null)
26 | {
27 | Settings s = new Settings();
28 | ShowWindowAsync((IntPtr)s.hMainWnd, SW_SHOWNORMAL);
29 | Environment.Exit(0);
30 | }
31 | DispatcherHelper.Initialize();
32 | }
33 |
34 | protected override void OnExit(ExitEventArgs e)
35 | {
36 | Settings s = new Settings();
37 | s.Reset();
38 | Common.PHP.StopWatchPHPFCGINum();
39 | base.OnExit(e);
40 | }
41 |
42 | // API 常數定義
43 | private const int SW_HIDE = 0;
44 | private const int SW_SHOWNORMAL = 1;
45 | private const int SW_MAXIMIZE = 3;
46 | private const int SW_SHOWNOACTIVATE = 4;
47 | private const int SW_SHOW = 5;
48 | private const int SW_RESTORE = 9;
49 |
50 |
51 | private static void HandleRunningInstance(Process instance)
52 | {
53 | ShowWindowAsync(instance.MainWindowHandle, SW_SHOWNORMAL);// 显示
54 | SetForegroundWindow(instance.MainWindowHandle);// 当到最前端
55 | }
56 |
57 |
58 | ///
59 | /// 获取已经运行的进程实例
60 | ///
61 | ///
62 | private static Process GetRuningInstance()
63 | {
64 | Process currentProcess = Process.GetCurrentProcess();
65 | Process[] Processes = Process.GetProcessesByName(currentProcess.ProcessName);
66 | foreach (Process process in Processes)
67 | {
68 | if (process.Id != currentProcess.Id)
69 | {
70 | if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == currentProcess.MainModule.FileName)
71 | {
72 | return process;
73 | }
74 | }
75 | }
76 | return null;
77 | }
78 |
79 | ///
80 | /// 该函数设置由不同线程产生的窗口的显示状态
81 | ///
82 | /// 窗口句柄
83 | /// 指定窗口如何显示。查看允许值列表,请查阅ShowWlndow函数的说明部分
84 | /// 如果函数原来可见,返回值为非零;如果函数原来被隐藏,返回值为零
85 | [DllImport("User32.dll")]
86 | private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
87 |
88 |
89 |
90 | ///
91 | /// 该函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。
92 | /// 系统给创建前台窗口的线程分配的权限稍高于其他线程。
93 | ///
94 | /// 将被激活并被调入前台的窗口句柄
95 | /// 如果窗口设入了前台,返回值为非零;如果窗口未被设入前台,返回值为零
96 | [DllImport("User32.dll")]
97 | private static extern bool SetForegroundWindow(IntPtr hWnd);
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/SalamanderWnmp/AttachProperty/ControlAttachProperty.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows;
6 |
7 | namespace SalamanderWnmp.AttachProperty
8 | {
9 | class ControlAttachProperty
10 | {
11 | #region FIconProperty 字体图标
12 | ///
13 | /// 字体图标
14 | ///
15 | public static readonly DependencyProperty FIconProperty = DependencyProperty.RegisterAttached(
16 | "FIcon", typeof(string), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(""));
17 |
18 | public static string GetFIcon(DependencyObject d)
19 | {
20 | return (string)d.GetValue(FIconProperty);
21 | }
22 |
23 | public static void SetFIcon(DependencyObject obj, string value)
24 | {
25 | obj.SetValue(FIconProperty, value);
26 | }
27 | #endregion
28 |
29 | #region FIconSizeProperty 字体图标大小
30 | ///
31 | /// 字体图标
32 | ///
33 | public static readonly DependencyProperty FIconSizeProperty = DependencyProperty.RegisterAttached(
34 | "FIconSize", typeof(double), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(12D));
35 |
36 | public static double GetFIconSize(DependencyObject d)
37 | {
38 | return (double)d.GetValue(FIconSizeProperty);
39 | }
40 |
41 | public static void SetFIconSize(DependencyObject obj, double value)
42 | {
43 | obj.SetValue(FIconSizeProperty, value);
44 | }
45 | #endregion
46 |
47 | #region FIconMarginProperty 字体图标边距
48 | ///
49 | /// 字体图标
50 | ///
51 | public static readonly DependencyProperty FIconMarginProperty = DependencyProperty.RegisterAttached(
52 | "FIconMargin", typeof(Thickness), typeof(ControlAttachProperty), new FrameworkPropertyMetadata(null));
53 |
54 | public static Thickness GetFIconMargin(DependencyObject d)
55 | {
56 | return (Thickness)d.GetValue(FIconMarginProperty);
57 | }
58 |
59 | public static void SetFIconMargin(DependencyObject obj, Thickness value)
60 | {
61 | obj.SetValue(FIconMarginProperty, value);
62 | }
63 | #endregion
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Common.cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.Configuration;
2 | using SalamanderWnmp.Programs;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using static SalamanderWnmp.Tool.RedisHelper;
8 |
9 | namespace SalamanderWnmp
10 | {
11 | class Common
12 | {
13 | ///
14 | /// 不能实例化Common类
15 | ///
16 | private Common()
17 | {
18 |
19 | }
20 |
21 | private static Ini settings = null;
22 |
23 | ///
24 | /// 应用程序配置(单例模式)
25 | ///
26 | public static Ini Settings {
27 | get
28 | {
29 | if(settings == null)
30 | {
31 | settings = new Ini();
32 | }
33 | return settings;
34 | }
35 | }
36 |
37 | ///
38 | /// 改变全局设置量
39 | ///
40 | ///
41 | public static void ChangeSettings(Ini settingsNew)
42 | {
43 | if(settingsNew != null)
44 | {
45 | settings = settingsNew;
46 | }
47 | }
48 |
49 |
50 | // 应用启动目录
51 | public static readonly String APP_STARTUP_PATH = AppDomain.CurrentDomain.BaseDirectory;
52 |
53 |
54 | // Redis连接配置列表
55 | public static Dictionary ConnConfigList = null;
56 |
57 |
58 |
59 | public static readonly MysqlProgram Mysql = new MysqlProgram();
60 | public static readonly BaseProgram Nginx = new NginxProgram();
61 | public static readonly PHPProgram PHP = new PHPProgram();
62 | public static readonly RedisProgram Redis = new RedisProgram();
63 |
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Configuration/Option.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.IO;
4 | using System.Windows;
5 |
6 | namespace SalamanderWnmp.Configuration
7 | {
8 | public interface IOption
9 | {
10 | void ReadIniValue(string IniFileStr);
11 | void Convert();
12 | void PrintIniOption(StreamWriter sw);
13 | }
14 |
15 | public class Option : IOption
16 | {
17 | public string Name { get; set; }
18 | public string Description { get; set; }
19 | public string iniValue { get; set; }
20 | public T Value { get; set; }
21 |
22 | public void ReadIniValue(string IniFileStr)
23 | {
24 | string key = Name + "=";
25 | using (var sr = new StringReader(IniFileStr)) {
26 | string line;
27 | while ((line = sr.ReadLine()) != null) {
28 | if (line.StartsWith(key)) {
29 | iniValue = line.Remove(0, key.Length);
30 | return;
31 | }
32 | }
33 | }
34 | iniValue = "";
35 | }
36 |
37 | public void PrintIniOption(StreamWriter sw)
38 | {
39 | sw.WriteLine("; " + Description);
40 | sw.WriteLine(Name + "=" + Value.ToString());
41 | }
42 |
43 | public void Convert()
44 | {
45 | if (iniValue == "")
46 | return;
47 | var converter = TypeDescriptor.GetConverter(typeof(T));
48 | if (converter != null) {
49 | try {
50 | Value = (T)converter.ConvertFromString(iniValue);
51 | } catch (Exception ex) {
52 | // Could be made a bit more elegant but considering its a rare user-caused exception....
53 | var message = String.Format("{0}={1}\n{2}\n\nThe Default Value '{3}' will be used instead.",
54 | Name, iniValue, ex.Message, Value.ToString());
55 | MessageBox.Show(message, "ERROR", MessageBoxButton.OK, MessageBoxImage.Error);
56 | }
57 | }
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Configuration/PHPConfigurationManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Text.RegularExpressions;
5 | using System.Windows;
6 |
7 | namespace SalamanderWnmp.Configuration
8 | {
9 | ///
10 | /// 不考虑zend扩展
11 | ///
12 | class PHPConfigurationManager
13 | {
14 | [Flags]
15 | public enum PHPExtensionFlag
16 | {
17 | Disabled = 1,
18 | Enabled = 2,
19 | ZendExt = 3,
20 | }
21 | public bool[] UserPHPExtentionValues;
22 | public string[] phpExtNames;
23 | public PHPExtensionFlag[] flags;
24 | // 集合对象
25 | private List extesions = new List();
26 |
27 | private string ExtensionPath;
28 | private string IniFilePath;
29 | private string TmpIniFile;
30 |
31 | private void LoadPHPIni()
32 | {
33 | TmpIniFile = File.ReadAllText(IniFilePath);
34 | }
35 |
36 | ///
37 | /// 获取ext目录下所有扩展
38 | ///
39 | /// php目录名
40 | public void LoadPHPExtensions(string phpDirName)
41 | {
42 |
43 | ExtensionPath = Constants.APP_STARTUP_PATH + String.Format("{0}/ext/", phpDirName);
44 | IniFilePath = Constants.APP_STARTUP_PATH + String.Format("{0}/php.ini", phpDirName);
45 | if (!Directory.Exists(ExtensionPath))
46 | {
47 | MessageBox.Show("php 扩展目录未找到");
48 | return;
49 | }
50 | phpExtNames = Directory.GetFiles(ExtensionPath, "*.dll");
51 | flags = new PHPExtensionFlag[phpExtNames.Length];
52 | UserPHPExtentionValues = new bool[phpExtNames.Length];
53 |
54 | for (var i = 0; i < phpExtNames.Length; i++) {
55 | string name = phpExtNames[i].Remove(0, ExtensionPath.Length);
56 | phpExtNames[i] = name;
57 | extesions.Add(new ExtesionHelper() { ExtName = name });
58 | }
59 |
60 | LoadPHPIni();
61 | ParsePHPIni();
62 | }
63 |
64 | public void ParsePHPIni()
65 | {
66 | using (var sr = new StringReader(TmpIniFile)) {
67 | string str;
68 | while ((str = sr.ReadLine()) != null) {
69 | for (var i = 0; i < phpExtNames.Length; i++) {
70 | if (str.StartsWith(";extension=" + phpExtNames[i])) {
71 | flags[i] = PHPExtensionFlag.Disabled;
72 | extesions[i].IsLoad = false;
73 | break;
74 | }
75 | if (str.StartsWith("extension=" + phpExtNames[i])) {
76 | flags[i] = PHPExtensionFlag.Enabled;
77 | extesions[i].IsLoad = true;
78 | break;
79 | }
80 | if (str.StartsWith(";zend_extension=" + phpExtNames[i])) {
81 | flags[i] = PHPExtensionFlag.Disabled | PHPExtensionFlag.ZendExt;
82 | break;
83 | }
84 | if (str.StartsWith("zend_extension=" + phpExtNames[i])) {
85 | flags[i] = PHPExtensionFlag.Enabled | PHPExtensionFlag.ZendExt;
86 | break;
87 | }
88 | }
89 | }
90 | }
91 | }
92 |
93 | public void SavePHPIniOptions()
94 | {
95 | for (var i = 0; i < extesions.Count; i++) {
96 | if(extesions[i].IsLoad)
97 | {
98 | TmpIniFile = Regex.Replace(TmpIniFile, "[;]+extension=" + phpExtNames[i], "extension=" + phpExtNames[i]);
99 | }
100 | else
101 | {
102 | // 已经注释了
103 | if (Regex.IsMatch(TmpIniFile, "[ ]*[;]+[ ]*extension=" + phpExtNames[i]))
104 | continue;
105 | else
106 | {
107 | TmpIniFile = Regex.Replace(TmpIniFile, "[ ]*extension=" + phpExtNames[i], ";extension=" + phpExtNames[i]);
108 | }
109 | }
110 | }
111 |
112 | File.WriteAllText(IniFilePath, TmpIniFile);
113 |
114 | }
115 |
116 | ///
117 | /// 扩展状态对象集合
118 | ///
119 | ///
120 | public List GetExtensions()
121 | {
122 | return this.extesions;
123 | }
124 |
125 | public class ExtesionHelper
126 | {
127 | ///
128 | /// 扩展名
129 | ///
130 | public string ExtName { get; set; }
131 |
132 | ///
133 | /// 是否加载
134 | ///
135 | public bool IsLoad { get; set; }
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Constants.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 |
4 | namespace SalamanderWnmp
5 | {
6 | class Constants
7 | {
8 | public static readonly Version CPVER = new Version("1.0.0");
9 | public static readonly Version APPVER = new Version("1.0.0");
10 | // 应用启动目录
11 | public static readonly String APP_STARTUP_PATH = AppDomain.CurrentDomain.BaseDirectory;
12 |
13 | public static readonly String HOSTS_DIR = "C:\\Windows\\System32\\drivers\\etc";
14 |
15 | public static readonly string AUTHOR = "salamander";
16 |
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Converter/LanToBoolConverter .cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.UI;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Globalization;
5 | using System.Windows.Data;
6 |
7 | namespace SalamanderWnmp.Converter
8 | {
9 | class LanToBoolConverter : IValueConverter
10 | {
11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
12 | {
13 | Tool.CodeHelper.ProgramLan lan = (Tool.CodeHelper.ProgramLan)value;
14 | return lan == (Tool.CodeHelper.ProgramLan)int.Parse(parameter.ToString());
15 | }
16 |
17 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
18 | {
19 | bool isChecked = (bool)value;
20 | if (!isChecked)
21 | {
22 | return null;
23 | }
24 | return (Tool.CodeHelper.ProgramLan)int.Parse(parameter.ToString());
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Converter/ProcessColorConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Windows.Data;
7 | using System.Windows.Media;
8 |
9 | namespace SalamanderWnmp.Converter
10 | {
11 | class ProcessColorConverter : IValueConverter
12 | {
13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
14 | {
15 | bool isRunning = (bool)value;
16 | if(isRunning)
17 | {
18 | return new SolidColorBrush(Colors.Green);
19 | }
20 | else
21 | {
22 | return new SolidColorBrush(Colors.Red);
23 | }
24 | }
25 |
26 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
27 | {
28 | throw new NotImplementedException();
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Converter/ProcessTextConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Windows.Data;
7 |
8 | namespace SalamanderWnmp.Converter
9 | {
10 | class ProcessTextConverter : IValueConverter
11 | {
12 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
13 | {
14 | bool isRunning = (bool)value;
15 | if(isRunning)
16 | {
17 | return "\u221A";
18 | }
19 | else
20 | {
21 | return "X";
22 | }
23 | }
24 |
25 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
26 | {
27 | throw new NotImplementedException();
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/SalamanderWnmp/CustomHighlighting.xshd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | "
13 | "
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | if
22 | else
23 |
24 |
25 |
26 |
27 | AvalonEdit
28 |
29 |
30 |
31 |
32 | \b0[xX][0-9a-fA-F]+ # hex number
33 | | \b
34 | ( \d+(\.[0-9]+)? #number with optional floating point
35 | | \.[0-9]+ #or just starting with floating point
36 | )
37 | ([eE][+-]?[0-9]+)? # optional exponent
38 |
39 |
40 |
--------------------------------------------------------------------------------
/SalamanderWnmp/EditorClass/BraceFoldingStrategy.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using ICSharpCode.AvalonEdit.Document;
4 | using ICSharpCode.AvalonEdit.Folding;
5 | #if NREFACTORY
6 | using ICSharpCode.NRefactory.Editor;
7 | #endif
8 |
9 | namespace SalamanderWnmp.EditorClass
10 | {
11 | ///
12 | /// Allows producing foldings from a document based on braces.
13 | ///
14 | public class BraceFoldingStrategy
15 | {
16 | ///
17 | /// Gets/Sets the opening brace. The default value is '{'.
18 | ///
19 | public char OpeningBrace { get; set; }
20 |
21 | ///
22 | /// Gets/Sets the closing brace. The default value is '}'.
23 | ///
24 | public char ClosingBrace { get; set; }
25 |
26 | ///
27 | /// Creates a new BraceFoldingStrategy.
28 | ///
29 | public BraceFoldingStrategy()
30 | {
31 | this.OpeningBrace = '{';
32 | this.ClosingBrace = '}';
33 | }
34 |
35 | public void UpdateFoldings(FoldingManager manager, TextDocument document)
36 | {
37 | int firstErrorOffset;
38 | IEnumerable newFoldings = CreateNewFoldings(document, out firstErrorOffset);
39 | manager.UpdateFoldings(newFoldings, firstErrorOffset);
40 | }
41 |
42 | ///
43 | /// Create s for the specified document.
44 | ///
45 | public IEnumerable CreateNewFoldings(TextDocument document, out int firstErrorOffset)
46 | {
47 | firstErrorOffset = -1;
48 | return CreateNewFoldings(document);
49 | }
50 |
51 | ///
52 | /// Create s for the specified document.
53 | ///
54 | public IEnumerable CreateNewFoldings(ITextSource document)
55 | {
56 | List newFoldings = new List();
57 |
58 | Stack startOffsets = new Stack();
59 | int lastNewLineOffset = 0;
60 | char openingBrace = this.OpeningBrace;
61 | char closingBrace = this.ClosingBrace;
62 | for (int i = 0; i < document.TextLength; i++) {
63 | char c = document.GetCharAt(i);
64 | if (c == openingBrace) {
65 | startOffsets.Push(i);
66 | } else if (c == closingBrace && startOffsets.Count > 0) {
67 | int startOffset = startOffsets.Pop();
68 | // don't fold if opening and closing brace are on the same line
69 | if (startOffset < lastNewLineOffset) {
70 | newFoldings.Add(new NewFolding(startOffset, i + 1));
71 | }
72 | } else if (c == '\n' || c == '\r') {
73 | lastNewLineOffset = i + 1;
74 | }
75 | }
76 | newFoldings.Sort((a,b) => a.StartOffset.CompareTo(b.StartOffset));
77 | return newFoldings;
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/SalamanderWnmp/EditorClass/MyCompletionData.cs:
--------------------------------------------------------------------------------
1 |
2 | using System;
3 | using ICSharpCode.AvalonEdit.CodeCompletion;
4 | using ICSharpCode.AvalonEdit.Document;
5 | using ICSharpCode.AvalonEdit.Editing;
6 | #if NREFACTORY
7 | using ICSharpCode.NRefactory.Editor;
8 | #endif
9 |
10 | namespace SalamanderWnmp.EditorClass
11 | {
12 | ///
13 | /// Implements AvalonEdit ICompletionData interface to provide the entries in the completion drop down.
14 | ///
15 | public class MyCompletionData : ICompletionData
16 | {
17 | public MyCompletionData(string text)
18 | {
19 | this.Text = text;
20 | }
21 |
22 | public System.Windows.Media.ImageSource Image {
23 | get { return null; }
24 | }
25 |
26 | public string Text { get; private set; }
27 |
28 | // Use this property if you want to show a fancy UIElement in the drop down list.
29 | public object Content {
30 | get { return this.Text; }
31 | }
32 |
33 | public object Description {
34 | get { return "Description for " + this.Text; }
35 | }
36 |
37 | public double Priority { get { return 0; } }
38 |
39 | public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs)
40 | {
41 | textArea.Document.Replace(completionSegment, this.Text);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Icons/logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Icons/logo.ico
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Editor/Copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Editor/Copy.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Editor/Cut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Editor/Cut.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Editor/Delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Editor/Delete.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Editor/Open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Editor/Open.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Editor/Paste.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Editor/Paste.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Editor/Redo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Editor/Redo.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Editor/Run.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Editor/Run.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Editor/Save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Editor/Save.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Editor/Undo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Editor/Undo.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Editor/WordWrap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Editor/WordWrap.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Editor/font_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Editor/font_add.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Editor/font_minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Editor/font_minus.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Menu/Redis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Menu/Redis.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Menu/about.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Menu/about.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Menu/author.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Menu/author.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Menu/code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Menu/code.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Menu/dir.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Menu/dir.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Menu/hosts.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Menu/hosts.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Menu/http.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Menu/http.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Menu/js.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Menu/js.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Menu/scan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Menu/scan.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Menu/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Menu/settings.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/Menu/skin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/Menu/skin.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/author.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/author.jpg
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/code.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/dir.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/dir.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/erha.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/erha.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/exit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/exit.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/http.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/http.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/menu.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/minimize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/minimize.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/mysql.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/mysql.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/nginx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/nginx.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/php.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/php.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/redis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/redis.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Images/skin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Images/skin.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Programs/BaseProgram.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.ComponentModel;
4 | using SalamanderWnmp.Tool;
5 |
6 | namespace SalamanderWnmp.Programs
7 | {
8 | public abstract class BaseProgram: INotifyPropertyChanged
9 | {
10 | ///
11 | /// exe 执行文件位置
12 | ///
13 | public string exeFile { get; set; }
14 |
15 | ///
16 | /// 进程名称
17 | ///
18 | public string procName { get; set; }
19 |
20 | ///
21 | /// 进程别名,用来在日志窗口显示
22 | ///
23 | public string programName { get; set; }
24 |
25 | ///
26 | /// 进程工作目录(Nginx需要这个参数)
27 | ///
28 | public string workingDir { get; set; }
29 |
30 | ///
31 | /// 进程日志前缀
32 | ///
33 | public Log.LogSection progLogSection { get; set; }
34 |
35 | ///
36 | /// 进程开启的参数
37 | ///
38 | public string startArgs { get; set; }
39 |
40 | ///
41 | /// 关闭进程参数
42 | ///
43 | public string stopArgs { get; set; }
44 |
45 | ///
46 | ///
47 | ///
48 | public bool killStop { get; set; }
49 |
50 | ///
51 | /// 进程配置目录
52 | ///
53 | public string confDir { get; set; }
54 |
55 | ///
56 | /// 进程日志目录
57 | ///
58 | public string logDir { get; set; }
59 |
60 |
61 | ///
62 | /// 进程异常退出的记录信息
63 | ///
64 | protected string errOutput = "";
65 |
66 |
67 |
68 | public Process ps = new Process();
69 |
70 | public event PropertyChangedEventHandler PropertyChanged;
71 | // 是否在运行
72 | private bool running = false;
73 |
74 | public bool Running
75 | {
76 | get
77 | {
78 | return this.running;
79 | }
80 | set
81 | {
82 | this.running = value;
83 | if(PropertyChanged != null)
84 | {
85 | PropertyChanged(this, new PropertyChangedEventArgs("Running"));
86 | }
87 | }
88 | }
89 |
90 |
91 | ///
92 | /// 设置状态
93 | ///
94 | public void SetStatus()
95 | {
96 | if (IsRunning())
97 | {
98 | this.Running = true;
99 | }
100 | else
101 | {
102 | this.Running = false;
103 | }
104 | }
105 |
106 | ///
107 | /// 启动进程
108 | ///
109 | ///
110 | ///
111 | ///
112 | public void StartProcess(string exe, string args, EventHandler exitedHandler = null)
113 | {
114 | ps = new Process();
115 | ps.StartInfo.FileName = exe;
116 | ps.StartInfo.Arguments = args;
117 | ps.StartInfo.UseShellExecute = false;
118 | ps.StartInfo.RedirectStandardOutput = true;
119 | ps.StartInfo.RedirectStandardError = true;
120 | ps.StartInfo.WorkingDirectory = workingDir;
121 | ps.StartInfo.CreateNoWindow = true;
122 | ps.Start();
123 | // ErrorDataReceived event signals each time the process writes a line
124 | // to the redirected StandardError stream
125 | ps.ErrorDataReceived += (sender, e) => {
126 | errOutput += e.Data;
127 | };
128 | ps.Exited += exitedHandler != null ? exitedHandler : (sender, e) => {
129 | if (!String.IsNullOrEmpty(errOutput))
130 | {
131 | Log.wnmp_log_error("Failed: " + errOutput, progLogSection);
132 | errOutput = "";
133 | }
134 | };
135 | ps.EnableRaisingEvents = true;
136 |
137 | ps.BeginOutputReadLine();
138 | ps.BeginErrorReadLine();
139 | }
140 |
141 |
142 |
143 | public virtual void Start()
144 | {
145 | if(IsRunning())
146 | {
147 | return;
148 | }
149 | try {
150 | StartProcess(exeFile, startArgs);
151 | Log.wnmp_log_notice("Started " + programName, progLogSection);
152 | } catch (Exception ex) {
153 | Log.wnmp_log_error("Start: " + ex.Message, progLogSection);
154 | }
155 | }
156 |
157 | public virtual void Stop()
158 | {
159 | if(!IsRunning())
160 | {
161 | return;
162 | }
163 | if (killStop == false)
164 | StartProcess(exeFile, stopArgs);
165 | var processes = Process.GetProcessesByName(procName);
166 | foreach (var process in processes) {
167 | process.Kill();
168 | }
169 | Log.wnmp_log_notice("Stopped " + programName, progLogSection);
170 | }
171 |
172 | ///
173 | /// 杀死进程
174 | ///
175 | ///
176 | protected void KillProcess(string procName)
177 | {
178 | var processes = Process.GetProcessesByName(procName);
179 | foreach (var process in processes)
180 | {
181 | process.Kill();
182 | }
183 | }
184 |
185 |
186 |
187 | public void Restart()
188 | {
189 | this.Stop();
190 | this.Start();
191 | Log.wnmp_log_notice("Restarted " + programName, progLogSection);
192 | }
193 |
194 | ///
195 | /// 判断程序是否运行
196 | ///
197 | ///
198 | public virtual bool IsRunning()
199 | {
200 | var processes = Process.GetProcessesByName(procName);
201 | return (processes.Length != 0);
202 | }
203 |
204 | ///
205 | /// 设置初始参数
206 | ///
207 | public abstract void Setup();
208 | }
209 | }
210 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Programs/Mysql.cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.Tool;
2 | using System;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.ServiceProcess;
6 | using System.Text.RegularExpressions;
7 | using System.Windows;
8 |
9 | namespace SalamanderWnmp.Programs
10 | {
11 | class MysqlProgram : BaseProgram
12 | {
13 | private readonly ServiceController mysqlController = new ServiceController();
14 | public const string ServiceName = "mysql-salamander";
15 |
16 | public MysqlProgram()
17 | {
18 | mysqlController.MachineName = Environment.MachineName;
19 | mysqlController.ServiceName = ServiceName;
20 | }
21 |
22 | ///
23 | /// 移除服务
24 | ///
25 | public void RemoveService()
26 | {
27 | StartProcess("cmd.exe", stopArgs);
28 | }
29 |
30 | ///
31 | /// 安装服务
32 | ///
33 | public void InstallService()
34 | {
35 | StartProcess(exeFile, startArgs);
36 | }
37 |
38 | ///
39 | /// 获取my.ini中mysql的端口
40 | ///
41 | ///
42 | private static int GetIniMysqlListenPort()
43 | {
44 | string path = Common.APP_STARTUP_PATH + Common.Settings.MysqlDirName.Value + "/my.ini";
45 | Regex regPort = new Regex(@"^\s*port\s*=\s*(\d+)");
46 | Regex regMysqldSec = new Regex(@"^\s*\[mysqld\]");
47 | using (var sr = new StreamReader(path))
48 | {
49 | bool isStart = false;// 是否找到了"[mysqld]"
50 | string str = null;
51 | while ((str = sr.ReadLine()) != null)
52 | {
53 | if (isStart && regPort.IsMatch(str))
54 | {
55 | MatchCollection matches = regPort.Matches(str);
56 | foreach (Match match in matches)
57 | {
58 | GroupCollection groups = match.Groups;
59 | if (groups.Count > 1)
60 | {
61 | try
62 | {
63 | return Int32.Parse(groups[1].Value);
64 | }
65 | catch
66 | {
67 | return -1;
68 | }
69 | }
70 | }
71 |
72 | }
73 | // [mysqld]段开始
74 | if (regMysqldSec.IsMatch(str))
75 | {
76 | isStart = true;
77 | }
78 | }
79 | }
80 | return -1;
81 | }
82 |
83 |
84 | ///
85 | /// 服务是否存在
86 | ///
87 | ///
88 | public bool ServiceExists()
89 | {
90 | ServiceController[] services = ServiceController.GetServices();
91 | foreach (var service in services) {
92 | if (service.ServiceName == ServiceName)
93 | return true;
94 | }
95 | return false;
96 | }
97 |
98 | public override void Start()
99 | {
100 | if (IsRunning())
101 | return;
102 | try {
103 | if (!File.Exists(Common.APP_STARTUP_PATH + Common.Settings.MysqlDirName.Value + "/my.ini"))
104 | {
105 | Log.wnmp_log_error("my.ini file not exist", progLogSection);
106 | return;
107 | }
108 | int port = GetIniMysqlListenPort();// -1表示提取出错
109 | if (port != -1 && PortScanHelper.IsPortInUseByTCP(port))
110 | {
111 | Log.wnmp_log_error("Port " + port + " is used", progLogSection);
112 | return;
113 | }
114 | mysqlController.Start();
115 | Log.wnmp_log_notice("Started " + programName, progLogSection);
116 | } catch (Exception ex) {
117 | Log.wnmp_log_error("Start(): " + ex.Message, progLogSection);
118 | }
119 | }
120 |
121 | public override void Stop()
122 | {
123 | if(!IsRunning())
124 | {
125 | return;
126 | }
127 | try {
128 | mysqlController.Stop();
129 | mysqlController.WaitForStatus(ServiceControllerStatus.Stopped);
130 | Log.wnmp_log_notice("Stopped " + programName, progLogSection);
131 | } catch (Exception ex) {
132 | Log.wnmp_log_error("Stop(): " + ex.Message, progLogSection);
133 | }
134 | }
135 |
136 |
137 | ///
138 | /// 通过ServiceController判断服务是否在运行
139 | ///
140 | ///
141 | public override bool IsRunning()
142 | {
143 | mysqlController.Refresh();
144 | try
145 | {
146 | return mysqlController.Status == ServiceControllerStatus.Running;
147 | }
148 | catch
149 | {
150 | return false;
151 | }
152 | }
153 |
154 | public override void Setup()
155 | {
156 | this.exeFile = Common.APP_STARTUP_PATH + String.Format("{0}/bin/mysqld.exe", Common.Settings.MysqlDirName.Value);
157 | this.procName = "mysqld";
158 | this.programName = "MySQL";
159 | this.workingDir = Common.APP_STARTUP_PATH + Common.Settings.MysqlDirName.Value;
160 | this.progLogSection = Log.LogSection.WNMP_MARIADB;
161 | this.startArgs = "--install-manual " + MysqlProgram.ServiceName + " --defaults-file=\"" +
162 | Common.APP_STARTUP_PATH + String.Format("\\{0}\\my.ini\"", Common.Settings.MysqlDirName.Value);
163 | this.stopArgs = "/c sc delete " + MysqlProgram.ServiceName;
164 | this.killStop = true;
165 | this.confDir = "/mysql/";
166 | this.logDir = "/mysql/data/";
167 | }
168 |
169 | ///
170 | /// 打开MySQL Client命令行
171 | ///
172 | public static void OpenMySQLClientCmd()
173 | {
174 | Process ps = new Process();
175 | ps.StartInfo.FileName = Common.APP_STARTUP_PATH + String.Format("{0}/bin/mysql.exe", Common.Settings.MysqlDirName.Value);
176 | ps.StartInfo.Arguments = String.Format("-u{0} -p{1}", Common.Settings.MysqlClientUser.Value, Common.Settings.MysqlClientUserPass.Value);
177 | ps.StartInfo.UseShellExecute = false;
178 | ps.StartInfo.CreateNoWindow = false;
179 |
180 | ps.Start();
181 |
182 | }
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Programs/Nginx.cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.Tool;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Windows.Controls;
8 |
9 | namespace SalamanderWnmp.Programs
10 | {
11 | class NginxProgram : BaseProgram
12 | {
13 |
14 | public override void Setup()
15 | {
16 | this.exeFile = Common.APP_STARTUP_PATH + String.Format("{0}/nginx.exe", Common.Settings.NginxDirName.Value);
17 | this.procName = "nginx";
18 | this.programName = "Nginx";
19 | this.workingDir = Common.APP_STARTUP_PATH + Common.Settings.NginxDirName.Value;
20 | this.progLogSection = Log.LogSection.WNMP_NGINX;
21 | this.startArgs = "";
22 | this.stopArgs = "-s stop";
23 | this.killStop = false;
24 | this.confDir = "/conf/";
25 | this.logDir = "/logs/";
26 | }
27 |
28 | ///
29 | /// 打开命令行
30 | ///
31 | public static void OpenNginxtCmd()
32 | {
33 | Process ps = new Process();
34 | ps.StartInfo.FileName = "cmd.exe";
35 | ps.StartInfo.Arguments = "";
36 | ps.StartInfo.UseShellExecute = false;
37 | ps.StartInfo.CreateNoWindow = false;
38 | ps.StartInfo.WorkingDirectory = Common.APP_STARTUP_PATH + Common.Settings.NginxDirName.Value;
39 |
40 | ps.Start();
41 |
42 | }
43 |
44 |
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Programs/PHP.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using SalamanderWnmp.Tool;
3 | using System.Threading;
4 |
5 | namespace SalamanderWnmp.Programs
6 | {
7 | class PHPProgram : BaseProgram
8 | {
9 |
10 | private const string PHP_CGI_NAME = "php-cgi";
11 | private const string PHP_MAX_REQUEST = "PHP_FCGI_MAX_REQUESTS";
12 | private Object locker = new Object();
13 | private uint FCGI_NUM = 0;
14 | private bool watchPHPFCGI = true;
15 | private Thread watchThread;
16 |
17 | private void DecreaseFCGINum()
18 | {
19 | lock (locker)
20 | {
21 | FCGI_NUM--;
22 | }
23 | }
24 |
25 | private void IncreaseFCGINum()
26 | {
27 | lock (locker)
28 | {
29 | FCGI_NUM++;
30 | }
31 | }
32 |
33 |
34 | public PHPProgram()
35 | {
36 | if (Environment.GetEnvironmentVariable(PHP_MAX_REQUEST) == null)
37 | Environment.SetEnvironmentVariable(PHP_MAX_REQUEST, "300");
38 | }
39 |
40 | public override void Start()
41 | {
42 | if(!IsRunning() && PortScanHelper.IsPortInUseByTCP(Common.Settings.PHP_Port.Value))
43 | {
44 | Log.wnmp_log_error("Port " + Common.Settings.PHP_Port.Value + " is used", progLogSection);
45 | }
46 | else if(!IsRunning())
47 | {
48 | for (int i = 0; i < Common.Settings.PHPProcesses.Value; i++)
49 | {
50 | StartProcess(this.exeFile, this.startArgs, (s, args) =>
51 | {
52 | DecreaseFCGINum();
53 | });
54 | IncreaseFCGINum();
55 | }
56 | WatchPHPFCGINum();
57 | Log.wnmp_log_notice("Started " + programName, progLogSection);
58 | }
59 | }
60 |
61 | ///
62 | /// 异步查看php-cgi数量
63 | ///
64 | ///
65 | ///
66 | private void WatchPHPFCGINum()
67 | {
68 | watchPHPFCGI = true;
69 | watchThread = new Thread(() =>
70 | {
71 | while (watchPHPFCGI)
72 | {
73 | uint delta = Common.Settings.PHPProcesses.Value - FCGI_NUM;
74 | for (int i = 0; i < delta; i++)
75 | {
76 | StartProcess(this.exeFile, this.startArgs, (s, args) =>
77 | {
78 | DecreaseFCGINum();
79 | });
80 | IncreaseFCGINum();
81 | Console.WriteLine("restart a php-cgi");
82 | }
83 | }
84 | });
85 | watchThread.Start();
86 | }
87 |
88 | public void StopWatchPHPFCGINum()
89 | {
90 | watchPHPFCGI = false;
91 | }
92 |
93 | public override void Stop()
94 | {
95 | if (!IsRunning())
96 | {
97 | return;
98 | }
99 | StopWatchPHPFCGINum();
100 | KillProcess(PHP_CGI_NAME);
101 | Log.wnmp_log_notice("Stopped " + programName, progLogSection);
102 | }
103 |
104 | public override void Setup()
105 | {
106 | string phpDirPath = Common.APP_STARTUP_PATH + Common.Settings.PHPDirName.Value;
107 |
108 | this.exeFile = string.Format("{0}/php-cgi.exe", phpDirPath);
109 | this.procName = PHP_CGI_NAME;
110 | this.programName = "PHP";
111 | this.workingDir = phpDirPath;
112 | this.progLogSection = Log.LogSection.WNMP_PHP;
113 | this.startArgs = String.Format("-b 127.0.0.1:{0} -c {1}/php.ini", Common.Settings.PHP_Port.Value, phpDirPath);
114 | this.killStop = true;
115 | this.confDir = "/php/";
116 | this.logDir = "/php/logs/";
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Programs/Redis.cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.Tool;
2 | using System;
3 | using System.Diagnostics;
4 | using System.Windows;
5 |
6 | namespace SalamanderWnmp.Programs
7 | {
8 | class RedisProgram : BaseProgram
9 | {
10 | public override void Setup()
11 | {
12 | this.exeFile = Common.APP_STARTUP_PATH + String.Format("{0}/redis-server.exe", Common.Settings.RedisDirName.Value);
13 | this.procName = "redis-server";
14 | this.programName = "Redis";
15 | this.workingDir = Common.APP_STARTUP_PATH + Common.Settings.RedisDirName.Value;
16 | this.progLogSection = Log.LogSection.WNMP_REDIS;
17 | this.startArgs = "redis.windows.conf";
18 | this.stopArgs = "";
19 | this.killStop = true;
20 | this.confDir = "";
21 | this.logDir = "";
22 | }
23 |
24 | ///
25 | /// 打开MySQL Client命令行
26 | ///
27 | public static void OpenMySQLClientCmd()
28 | {
29 | Process ps = new Process();
30 | ps.StartInfo.FileName = Common.APP_STARTUP_PATH + String.Format("{0}/bin/mysql.exe", Common.Settings.MysqlDirName.Value);
31 | ps.StartInfo.Arguments = String.Format("-u{0} -p{1}", Common.Settings.MysqlClientUser.Value, Common.Settings.MysqlClientUserPass.Value);
32 | ps.StartInfo.UseShellExecute = false;
33 | ps.StartInfo.CreateNoWindow = false;
34 |
35 | ps.Start();
36 | }
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/SalamanderWnmp/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("SalamanderWnmp")]
11 | [assembly: AssemblyDescription("火蜥蜴制作,windows下用WPF制作的nginx,php,mysql集成环境")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("51nazi.com")]
14 | [assembly: AssemblyProduct("SalamanderWnmp")]
15 | [assembly: AssemblyCopyright("Salamander")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // 将 ComVisible 设置为 false 使此程序集中的类型
20 | // 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
21 | // 则将该类型上的 ComVisible 特性设置为 true。
22 | [assembly: ComVisible(false)]
23 |
24 | //若要开始生成可本地化的应用程序,请在
25 | // 中的 .csproj 文件中
26 | //设置 CultureYouAreCodingWith。 例如,如果您在源文件中
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.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace SalamanderWnmp.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", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | public 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 | public 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("SalamanderWnmp.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 | public static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// 查找类似 关于作者 的本地化字符串。
65 | ///
66 | public static string About {
67 | get {
68 | return ResourceManager.GetString("About", resourceCulture);
69 | }
70 | }
71 |
72 | ///
73 | /// 查找类似 添加连接 的本地化字符串。
74 | ///
75 | public static string AddConn {
76 | get {
77 | return ResourceManager.GetString("AddConn", resourceCulture);
78 | }
79 | }
80 |
81 | ///
82 | /// 查找类似 Wnmp 的本地化字符串。
83 | ///
84 | public static string AppName {
85 | get {
86 | return ResourceManager.GetString("AppName", resourceCulture);
87 | }
88 | }
89 |
90 | ///
91 | /// 查找类似 调色 的本地化字符串。
92 | ///
93 | public static string ChangeColor {
94 | get {
95 | return ResourceManager.GetString("ChangeColor", resourceCulture);
96 | }
97 | }
98 |
99 | ///
100 | /// 查找类似 编程面板 的本地化字符串。
101 | ///
102 | public static string CodePanel {
103 | get {
104 | return ResourceManager.GetString("CodePanel", resourceCulture);
105 | }
106 | }
107 |
108 | ///
109 | /// 查找类似 常见问题 的本地化字符串。
110 | ///
111 | public static string CommonQuestions {
112 | get {
113 | return ResourceManager.GetString("CommonQuestions", resourceCulture);
114 | }
115 | }
116 |
117 | ///
118 | /// 查找类似 #16a085 的本地化字符串。
119 | ///
120 | public static string DefaultThemeColor {
121 | get {
122 | return ResourceManager.GetString("DefaultThemeColor", resourceCulture);
123 | }
124 | }
125 |
126 | ///
127 | /// 查找类似 host文件 的本地化字符串。
128 | ///
129 | public static string Hosts {
130 | get {
131 | return ResourceManager.GetString("Hosts", resourceCulture);
132 | }
133 | }
134 |
135 | ///
136 | /// 查找类似 Http请求器 的本地化字符串。
137 | ///
138 | public static string HttpRequester {
139 | get {
140 | return ResourceManager.GetString("HttpRequester", resourceCulture);
141 | }
142 | }
143 |
144 | ///
145 | /// 查找类似 主目录 的本地化字符串。
146 | ///
147 | public static string MainDir {
148 | get {
149 | return ResourceManager.GetString("MainDir", resourceCulture);
150 | }
151 | }
152 |
153 | ///
154 | /// 查找类似 端口扫描器 的本地化字符串。
155 | ///
156 | public static string PortScaner {
157 | get {
158 | return ResourceManager.GetString("PortScaner", resourceCulture);
159 | }
160 | }
161 |
162 | ///
163 | /// 查找类似 Redis面板 的本地化字符串。
164 | ///
165 | public static string RedisPanel {
166 | get {
167 | return ResourceManager.GetString("RedisPanel", resourceCulture);
168 | }
169 | }
170 |
171 | ///
172 | /// 查找类似 设置 的本地化字符串。
173 | ///
174 | public static string Settings {
175 | get {
176 | return ResourceManager.GetString("Settings", resourceCulture);
177 | }
178 | }
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace SalamanderWnmp.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.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 | [global::System.Configuration.UserScopedSettingAttribute()]
27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
28 | [global::System.Configuration.DefaultSettingValueAttribute("0")]
29 | public long hMainWnd {
30 | get {
31 | return ((long)(this["hMainWnd"]));
32 | }
33 | set {
34 | this["hMainWnd"] = value;
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 0
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Properties/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
47 |
54 |
55 |
69 |
--------------------------------------------------------------------------------
/SalamanderWnmp/ReadMe.text:
--------------------------------------------------------------------------------
1 | /**************************Salamander制作**************************/
2 | 做这个小工具当然是自己开发用的
3 | 其中碰到了一些小问题,在此记录下咯
4 | 1. 手动安装mysql服务:
5 | mysqld --install mh-mysql --defaults-file="D:\software\wnmp-MH\mysql\my.ini"
6 | 其中mh-mysql为服务名,可以随便取
7 |
8 | 2. 启动服务
9 | net start mh-mysql
10 |
11 | 3.php-cgi如果单纯用命令php-cgi.exe -b 127.0.0.1:9000 -c your_php_path\php.ini会有自动退出问题
12 | 所有在程序中添加环境变量PHP_FCGI_MAX_REQUESTS
13 |
14 | 4. 命令启动nginx时,workingDirectory一定要设置为nginx的目录
15 |
16 | 5. 修改conf目录下nginx.conf中的localhost虚拟主机的root(网站根目录),改为某个目录(譬如D:/web_root)的绝对路径(使用/,使用\会出错)
17 |
18 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Resources/iconfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Resources/iconfont.ttf
--------------------------------------------------------------------------------
/SalamanderWnmp/Resources/logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Resources/logo.ico
--------------------------------------------------------------------------------
/SalamanderWnmp/Resources/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/Resources/logo.png
--------------------------------------------------------------------------------
/SalamanderWnmp/Tool/DispatcherHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading;
6 | using System.Windows.Threading;
7 |
8 | namespace SalamanderWnmp.Tool
9 | {
10 |
11 | public static class DispatcherHelper
12 | {
13 | public static Dispatcher UIDispatcher
14 | {
15 | get;
16 | private set;
17 | }
18 |
19 | private static int MainThreadId = Thread.CurrentThread.ManagedThreadId;
20 |
21 |
22 |
23 | public static void Initialize()
24 | {
25 | if (UIDispatcher != null)
26 | {
27 | return;
28 | }
29 |
30 | #if SILVERLIGHT
31 | UIDispatcher = Deployment.Current.Dispatcher;
32 | #else
33 | UIDispatcher = Dispatcher.CurrentDispatcher;
34 | #endif
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Tool/EnvironmentAutoConfig.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text.RegularExpressions;
6 |
7 | namespace SalamanderWnmp.Tool
8 | {
9 | ///
10 | /// 开发环境自动配置类
11 | ///
12 | class EnvironmentAutoConfig
13 | {
14 | private readonly static string nginxConfFile = Constants.APP_STARTUP_PATH + "nginx/conf/nginx.conf";
15 |
16 | private readonly static string phpConfFile = Constants.APP_STARTUP_PATH + "php/php.ini";
17 |
18 | private readonly static string mysqlConfFile = Constants.APP_STARTUP_PATH + "mysql/my.ini";
19 |
20 | ///
21 | /// 自动配置
22 | ///
23 | public static void Run()
24 | {
25 | ConfigNginx();
26 | ConfigPHP();
27 | ConfigMysql();
28 | }
29 |
30 | ///
31 | /// 配置Nginx
32 | ///
33 | private static void ConfigNginx()
34 | {
35 | if (File.Exists(nginxConfFile))
36 | {
37 | string txt = File.ReadAllText(nginxConfFile);
38 | Regex reg = new Regex(@"root D:/\*+;");
39 | File.WriteAllText(nginxConfFile, reg.Replace(txt, "root " + Constants.APP_STARTUP_PATH.Replace("\\", "/") + "nginx/html;", 1));
40 | Console.WriteLine("-----------------Nginx配置完成-----------------");
41 | }
42 | else
43 | {
44 | Console.WriteLine("Nginx配置文件没找到");
45 | }
46 | }
47 |
48 | ///
49 | /// 配置PHP
50 | ///
51 | private static void ConfigPHP()
52 | {
53 | if (File.Exists(phpConfFile))
54 | {
55 | string txt = File.ReadAllText(phpConfFile);
56 | Regex reg = new Regex("extension_dir = \"your_path" + @"\\" + "ext\"");
57 | string res = reg.Replace(txt,
58 | "extension_dir = \"" + Constants.APP_STARTUP_PATH + "php\\ext\"", 1);
59 | File.WriteAllText(phpConfFile, res);
60 | Console.WriteLine("-----------------PHP配置完成-----------------");
61 | }
62 | else
63 | {
64 | Console.WriteLine("php配置文件没找到");
65 | }
66 | }
67 |
68 | ///
69 | /// 配置Mysql
70 | ///
71 | private static void ConfigMysql()
72 | {
73 | if (File.Exists(mysqlConfFile))
74 | {
75 | string txt = File.ReadAllText(mysqlConfFile);
76 | Regex reg1 = new Regex(@"basedir=\*+");
77 | txt = reg1.Replace(txt, "basedir=" + Constants.APP_STARTUP_PATH.Replace("\\", "/")
78 | + "mysql", 1);
79 | // 第二个匹配
80 | Regex reg2 = new Regex(@"datadir=\*+/data");
81 | txt = reg2.Replace(txt, "datadir=" + Constants.APP_STARTUP_PATH.Replace("\\", "/")
82 | + @"mysql/data", 1);
83 | File.WriteAllText(mysqlConfFile, txt);
84 | Console.WriteLine("-----------------Mysql配置完成-----------------");
85 | }
86 | else
87 | {
88 | Console.WriteLine("mysql配置文件没找到");
89 | }
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Tool/HttpHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.IO.Compression;
5 | using System.Linq;
6 | using System.Net;
7 | using System.Text;
8 |
9 | namespace SalamanderWnmp.Tool
10 | {
11 | class HttpHelper
12 | {
13 | private HttpWebRequest request = null;
14 |
15 | private Encoding encoding = Encoding.UTF8;
16 |
17 | public HttpHelper(string url)
18 | {
19 | this.request = (HttpWebRequest)WebRequest.Create(url);
20 | }
21 |
22 | public WebRequest GetRequest()
23 | {
24 | return this.request;
25 | }
26 |
27 |
28 | ///
29 | /// 设置请求超时
30 | ///
31 | ///
32 | ///
33 | public HttpHelper SetTimeout(int timeout)
34 | {
35 | this.request.Timeout = timeout;
36 | return this;
37 | }
38 |
39 |
40 | ///
41 | /// 设置请求头
42 | ///
43 | ///
44 | ///
45 | public HttpHelper SetHeaders(Dictionary headers)
46 | {
47 | foreach(var header in headers)
48 | {
49 | this.request.Headers.Add(header.Key, header.Value);
50 | }
51 | return this;
52 | }
53 |
54 | ///
55 | /// 设置编码
56 | ///
57 | ///
58 | ///
59 | public HttpHelper SetEncoding(string encoding)
60 | {
61 | this.encoding = Encoding.GetEncoding(encoding);
62 | return this;
63 | }
64 |
65 | ///
66 | /// 设置Http请求的Body
67 | ///
68 | ///
69 | ///
70 | public HttpHelper SetBody(string body)
71 | {
72 | if (String.IsNullOrEmpty(body))
73 | return this;
74 | byte[] data = encoding.GetBytes(body);
75 | request.ContentLength = data.Length;
76 | Stream requestStream = request.GetRequestStream();
77 | requestStream.Write(data, 0, data.Length);
78 | requestStream.Close();
79 | return this;
80 | }
81 |
82 | private string SendRequest(string method)
83 | {
84 | this.request.Method = method;
85 | try
86 | {
87 | HttpWebResponse response = (HttpWebResponse)request.GetResponse();
88 | Stream respStream = null;
89 | if(response.ContentEncoding.ToLower().Contains("gzip"))
90 | {
91 | respStream = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress);
92 | }
93 | else if(response.ContentEncoding.ToLower().Contains("deflate"))
94 | {
95 | respStream = new DeflateStream(response.GetResponseStream(), CompressionMode.Decompress);
96 | }
97 | else
98 | {
99 | respStream = response.GetResponseStream();
100 | }
101 | using (StreamReader reader = new StreamReader(respStream, this.encoding))
102 | {
103 | return reader.ReadToEnd();
104 | }
105 | }
106 | catch (Exception ex)
107 | {
108 | return "";
109 | }
110 | }
111 |
112 |
113 |
114 | public string Get()
115 | {
116 | return this.SendRequest("GET");
117 | }
118 |
119 | public string Post()
120 | {
121 |
122 | return this.SendRequest("POST");
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Tool/IEProxySetting.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Runtime.InteropServices;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace IEProxyManagment
10 | {
11 |
12 | public class IEProxySetting
13 | {
14 | public static bool UnsetProxy()
15 | {
16 | return SetProxy(null, null);
17 | }
18 | public static bool SetProxy(string strProxy)
19 | {
20 | return SetProxy(strProxy, null);
21 | }
22 |
23 | public static bool SetProxy(string strProxy, string exceptions)
24 | {
25 | InternetPerConnOptionList list = new InternetPerConnOptionList();
26 |
27 | int optionCount = string.IsNullOrEmpty(strProxy) ? 1 : (string.IsNullOrEmpty(exceptions) ? 2 : 3);
28 | InternetConnectionOption[] options = new InternetConnectionOption[optionCount];
29 | // USE a proxy server ...
30 | options[0].m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS;
31 | options[0].m_Value.m_Int = (int)((optionCount < 2) ? PerConnFlags.PROXY_TYPE_DIRECT : (PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_PROXY));
32 | // use THIS proxy server
33 | if (optionCount > 1)
34 | {
35 | options[1].m_Option = PerConnOption.INTERNET_PER_CONN_PROXY_SERVER;
36 | options[1].m_Value.m_StringPtr = Marshal.StringToHGlobalAuto(strProxy);
37 | // except for these addresses ...
38 | if (optionCount > 2)
39 | {
40 | options[2].m_Option = PerConnOption.INTERNET_PER_CONN_PROXY_BYPASS;
41 | options[2].m_Value.m_StringPtr = Marshal.StringToHGlobalAuto(exceptions);
42 | }
43 | }
44 |
45 | // default stuff
46 | list.dwSize = Marshal.SizeOf(list);
47 | list.szConnection = IntPtr.Zero;
48 | list.dwOptionCount = options.Length;
49 | list.dwOptionError = 0;
50 |
51 |
52 | int optSize = Marshal.SizeOf(typeof(InternetConnectionOption));
53 | // make a pointer out of all that ...
54 | IntPtr optionsPtr = Marshal.AllocCoTaskMem(optSize * options.Length);
55 | // copy the array over into that spot in memory ...
56 | for (int i = 0; i < options.Length; ++i)
57 | {
58 | IntPtr opt = new IntPtr(optionsPtr.ToInt32() + (i * optSize));
59 | Marshal.StructureToPtr(options[i], opt, false);
60 | }
61 |
62 | list.options = optionsPtr;
63 |
64 | // and then make a pointer out of the whole list
65 | IntPtr ipcoListPtr = Marshal.AllocCoTaskMem((Int32)list.dwSize);
66 | Marshal.StructureToPtr(list, ipcoListPtr, false);
67 |
68 | // and finally, call the API method!
69 | int returnvalue = NativeMethods.InternetSetOption(IntPtr.Zero,
70 | InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION,
71 | ipcoListPtr, list.dwSize) ? -1 : 0;
72 | if (returnvalue == 0)
73 | { // get the error codes, they might be helpful
74 | returnvalue = Marshal.GetLastWin32Error();
75 | }
76 | // FREE the data ASAP
77 | Marshal.FreeCoTaskMem(optionsPtr);
78 | Marshal.FreeCoTaskMem(ipcoListPtr);
79 | if (returnvalue > 0)
80 | { // throw the error codes, they might be helpful
81 | throw new Win32Exception(Marshal.GetLastWin32Error());
82 | }
83 |
84 | return (returnvalue < 0);
85 | }
86 | }
87 |
88 | #region WinInet structures
89 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
90 | public struct InternetPerConnOptionList
91 | {
92 | public int dwSize; // size of the INTERNET_PER_CONN_OPTION_LIST struct
93 | public IntPtr szConnection; // connection name to set/query options
94 | public int dwOptionCount; // number of options to set/query
95 | public int dwOptionError; // on error, which option failed
96 | //[MarshalAs(UnmanagedType.)]
97 | public IntPtr options;
98 | };
99 |
100 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
101 | public struct InternetConnectionOption
102 | {
103 | static readonly int Size;
104 | public PerConnOption m_Option;
105 | public InternetConnectionOptionValue m_Value;
106 | static InternetConnectionOption()
107 | {
108 | InternetConnectionOption.Size = Marshal.SizeOf(typeof(InternetConnectionOption));
109 | }
110 |
111 | // Nested Types
112 | [StructLayout(LayoutKind.Explicit)]
113 | public struct InternetConnectionOptionValue
114 | {
115 | // Fields
116 | [FieldOffset(0)]
117 | public System.Runtime.InteropServices.ComTypes.FILETIME m_FileTime;
118 | [FieldOffset(0)]
119 | public int m_Int;
120 | [FieldOffset(0)]
121 | public IntPtr m_StringPtr;
122 | }
123 | }
124 | #endregion
125 |
126 | #region WinInet enums
127 | //
128 | // options manifests for Internet{Query|Set}Option
129 | //
130 | public enum InternetOption : uint
131 | {
132 | INTERNET_OPTION_PER_CONNECTION_OPTION = 75
133 | }
134 |
135 | //
136 | // Options used in INTERNET_PER_CONN_OPTON struct
137 | //
138 | public enum PerConnOption
139 | {
140 | INTERNET_PER_CONN_FLAGS = 1, // Sets or retrieves the connection type. The Value member will contain one or more of the values from PerConnFlags
141 | INTERNET_PER_CONN_PROXY_SERVER = 2, // Sets or retrieves a string containing the proxy servers.
142 | INTERNET_PER_CONN_PROXY_BYPASS = 3, // Sets or retrieves a string containing the URLs that do not use the proxy server.
143 | INTERNET_PER_CONN_AUTOCONFIG_URL = 4//, // Sets or retrieves a string containing the URL to the automatic configuration script.
144 |
145 | }
146 |
147 | //
148 | // PER_CONN_FLAGS
149 | //
150 | [Flags]
151 | public enum PerConnFlags
152 | {
153 | PROXY_TYPE_DIRECT = 0x00000001, // direct to net
154 | PROXY_TYPE_PROXY = 0x00000002, // via named proxy
155 | PROXY_TYPE_AUTO_PROXY_URL = 0x00000004, // autoproxy URL
156 | PROXY_TYPE_AUTO_DETECT = 0x00000008 // use autoproxy detection
157 | }
158 | #endregion
159 |
160 | internal static class NativeMethods
161 | {
162 | [DllImport("WinInet.dll", SetLastError = true, CharSet = CharSet.Auto)]
163 | [return: MarshalAs(UnmanagedType.Bool)]
164 | public static extern bool InternetSetOption(IntPtr hInternet, InternetOption dwOption, IntPtr lpBuffer, int dwBufferLength);
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Tool/Log.cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.Programs;
2 | using SalamanderWnmp.UI;
3 | using System;
4 | using System.IO;
5 | using System.Windows.Controls;
6 | using System.Windows.Documents;
7 | using System.Windows.Media;
8 |
9 | namespace SalamanderWnmp.Tool
10 | {
11 | ///
12 | /// Logs information and errors to a RichTextBox
13 | ///
14 | public static class Log
15 | {
16 | private static RichTextBox rtfLog;
17 |
18 | public enum LogSection
19 | {
20 | WNMP_MAIN = 0,
21 | WNMP_NGINX,
22 | WNMP_MARIADB,
23 | WNMP_PHP,
24 | WNMP_REDIS,
25 | }
26 | public static string LogSectionToString(LogSection logSection)
27 | {
28 | switch (logSection) {
29 | case LogSection.WNMP_MAIN:
30 | return "Wnmp Main";
31 | case LogSection.WNMP_NGINX:
32 | return "Wnmp Nginx";
33 | case LogSection.WNMP_MARIADB:
34 | return "Wnmp MySQL";
35 | case LogSection.WNMP_PHP:
36 | return "Wnmp PHP";
37 | case LogSection.WNMP_REDIS:
38 | return "Wnmp Redis";
39 | default:
40 | return "";
41 | }
42 | }
43 |
44 | private static void wnmp_log(string message, SolidColorBrush brush, LogSection logSection)
45 | {
46 | DispatcherHelper.UIDispatcher.Invoke(new Action(() =>
47 | {
48 | var SectionName = LogSectionToString(logSection);
49 | var DateNow = DateTime.Now.ToString();
50 | Run run1 = new Run(DateNow + " [");
51 | Run run2 = new Run() { Text = SectionName, Foreground = brush };
52 | Run run3 = new Run("] - " + message);
53 | var p = new Paragraph();
54 | p.Inlines.AddRange(new Run[] { run1, run2, run3 });
55 | rtfLog.Document.Blocks.Add(p);
56 | rtfLog.ScrollToEnd();
57 | }));
58 | }
59 | ///
60 | /// Log error
61 | ///
62 | public static void wnmp_log_error(string message, LogSection logSection)
63 | {
64 | wnmp_log(message, Brushes.Red, logSection);
65 | }
66 | ///
67 | /// Log information
68 | ///
69 | public static void wnmp_log_notice(string message, LogSection logSection)
70 | {
71 | wnmp_log(message, Brushes.DarkBlue, logSection);
72 | }
73 |
74 | public static void setLogComponent(RichTextBox logRichTextBox)
75 | {
76 | rtfLog = logRichTextBox;
77 | wnmp_log_notice("Initializing Control Panel", LogSection.WNMP_MAIN);
78 | wnmp_log_notice("Control Panel Version: " + Constants.CPVER, LogSection.WNMP_MAIN);
79 | wnmp_log_notice("Wnmp Version: " + Constants.APPVER, LogSection.WNMP_MAIN);
80 | wnmp_log_notice("Wnmp Directory: " + Constants.APP_STARTUP_PATH, LogSection.WNMP_MAIN);
81 | }
82 |
83 | ///
84 | /// 判断PHP,mysql,nginx是否在wnmp目录中
85 | ///
86 | public static void CheckForApps(BaseProgram nginx, BaseProgram mysql, BaseProgram php)
87 | {
88 | Log.wnmp_log_notice("Checking for applications", Log.LogSection.WNMP_MAIN);
89 | if (!Directory.Exists(nginx.workingDir))
90 | Log.wnmp_log_error("Error: Nginx Not Found", Log.LogSection.WNMP_NGINX);
91 |
92 | if (!Directory.Exists(mysql.workingDir))
93 | Log.wnmp_log_error("Error: Mysql Not Found", Log.LogSection.WNMP_MARIADB);
94 |
95 | if (!Directory.Exists(Common.APP_STARTUP_PATH + Common.Settings.PHPDirName.Value))
96 | Log.wnmp_log_error("Error: PHP Not Found", Log.LogSection.WNMP_PHP);
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Tool/PortScanHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Net;
5 | using System.Net.NetworkInformation;
6 | using System.Text;
7 | using System.Text.RegularExpressions;
8 |
9 | namespace SalamanderWnmp.Tool
10 | {
11 | class PortScanHelper
12 | {
13 |
14 | public class PortInfo
15 | {
16 | public string ProtocolType { get; set; }
17 |
18 | ///
19 | /// 占用端口
20 | ///
21 | public int Port { get; set; }
22 |
23 | ///
24 | /// 进程ID
25 | ///
26 | public int PID { get; set; }
27 |
28 | ///
29 | /// 程序名称
30 | ///
31 | public string ProcName { get; set; }
32 | }
33 |
34 | ///
35 | /// 获取端口占用情况
36 | ///
37 | ///
38 | public static List GetPortInfoList()
39 | {
40 | List portInfoList = new List();
41 | Process ps = new Process();
42 | // 设置命令行、参数
43 | ps.StartInfo.FileName = "netstat";
44 | ps.StartInfo.Arguments = "-ano";
45 | ps.StartInfo.UseShellExecute = false;
46 | ps.StartInfo.RedirectStandardInput = true;
47 | ps.StartInfo.RedirectStandardOutput = true;
48 | ps.StartInfo.RedirectStandardError = true;
49 | ps.StartInfo.CreateNoWindow = true;
50 | ps.Start();
51 | string result = ps.StandardOutput.ReadToEnd();
52 | string[] rows = Regex.Split(result, "\r\n", RegexOptions.IgnoreCase);
53 | foreach (var row in rows)
54 | {
55 | if(!string.IsNullOrEmpty(row))
56 | {
57 | string newRow = row.Trim();
58 | if(newRow.StartsWith("TCP") || newRow.StartsWith("UDP"))
59 | {
60 | string[] cols = Regex.Split(newRow, "\\s+");
61 | if (cols.Length >= 5)
62 | {
63 | int pid = Int32.Parse(cols[4]);
64 | string[] portStr = cols[1].Split(':');
65 | string procName = null;
66 | try
67 | {
68 | procName = Process.GetProcessById(pid).ProcessName;
69 | }
70 | catch
71 | {
72 | continue;
73 | }
74 | PortInfo info = new PortInfo
75 | {
76 | ProtocolType = cols[0],
77 | Port = Int32.Parse(portStr[portStr.Length - 1]),
78 | PID = pid,
79 | ProcName = Process.GetProcessById(pid).ProcessName
80 | };
81 | portInfoList.Add(info);
82 | }
83 | }
84 | }
85 | }
86 |
87 | return portInfoList;
88 | }
89 |
90 | ///
91 | /// 通过TCP监听列表判断端口是否被占
92 | ///
93 | ///
94 | ///
95 | public static bool IsPortInUseByTCP(int port)
96 | {
97 | bool inUse = false;
98 | IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
99 | IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();
100 | foreach (IPEndPoint endPoint in ipEndPoints)
101 | {
102 | if (endPoint.Port == port)
103 | {
104 | inUse = true;
105 | break;
106 | }
107 | }
108 | return inUse;
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Tool/ProxyHelper.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace SalamanderWnmp.Tool
9 | {
10 | class ProxyHelper
11 | {
12 |
13 | ///
14 | /// 获取正在使用的代理
15 | ///
16 | ///
17 | private static string GetProxyServer()
18 | {
19 | //打开注册表
20 | RegistryKey regKey = Registry.CurrentUser;
21 | string SubKeyPath = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
22 | RegistryKey optionKey = regKey.OpenSubKey(SubKeyPath, true); // 更改健值,设置代理,
23 | string actualProxy = optionKey.GetValue("ProxyServer").ToString();
24 | regKey.Close();
25 | return actualProxy;
26 | }
27 |
28 | private static bool GetProxyStatus()
29 | {
30 | //打开注册表
31 | RegistryKey regKey = Registry.CurrentUser;
32 | string SubKeyPath = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
33 | RegistryKey optionKey = regKey.OpenSubKey(SubKeyPath, true); // 更改健值,设置代理,
34 | int actualProxyStatus = Convert.ToInt32(optionKey.GetValue("ProxyEnable"));
35 | regKey.Close();
36 | return actualProxyStatus == 1 ? true : false;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Tool/RedisHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.ComponentModel;
5 | using System.IO;
6 | using System.Runtime.Serialization;
7 | using System.Runtime.Serialization.Formatters.Binary;
8 | using System.Text;
9 | using System.Windows;
10 |
11 | namespace SalamanderWnmp.Tool
12 | {
13 | ///
14 | /// Redis面板辅助类
15 | ///
16 | class RedisHelper
17 | {
18 | // redis连接配置文件
19 | private static readonly string CONN_FILE = Constants.APP_STARTUP_PATH + "redis_conns.dat";
20 |
21 | public enum NodeType
22 | {
23 | Connnection = 2,
24 | Database = 3,
25 | Key = 4
26 | }
27 |
28 | ///
29 | /// Redis连接配置
30 | ///
31 | [Serializable]
32 | public class RedisConnConfig
33 | {
34 | ///
35 | /// 连接名称
36 | ///
37 | public string ConnName { get; set; }
38 |
39 | ///
40 | /// 主机名
41 | ///
42 | public string Host { get; set; }
43 |
44 | ///
45 | /// 端口号
46 | ///
47 | public int Port { get; set; }
48 |
49 | ///
50 | /// 验证
51 | ///
52 | public string Auth { get; set; }
53 |
54 |
55 | ///
56 | /// 获取连接字符串
57 | ///
58 | ///
59 | public string GetConnectionStr()
60 | {
61 | return Host + ":" + Port + ",allowAdmin=true,connectTimeout=3000";
62 | }
63 |
64 | ///
65 | /// 主机加端口字符串
66 | ///
67 | ///
68 | public string GetHostAndPortStr()
69 | {
70 | return Host + ":" + Port;
71 | }
72 | }
73 |
74 | ///
75 | /// 节点类
76 | /// s
77 | public class Node: INotifyPropertyChanged
78 | {
79 | public event PropertyChangedEventHandler PropertyChanged;
80 |
81 | public void Notify(string propertyName)
82 | {
83 | this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
84 | }
85 |
86 | private string name;
87 | public string Name
88 | {
89 | get
90 | {
91 | return this.name;
92 | }
93 | set
94 | {
95 | this.name = value;
96 | this.Notify("Name");
97 | }
98 | }
99 |
100 | ///
101 | /// 节点类型
102 | ///
103 | public NodeType NodeType { get; set; }
104 |
105 | ///
106 | /// 节点存储的值
107 | ///
108 | public object Value { get; set; }
109 |
110 |
111 | private ObservableCollection nodes;
112 | ///
113 | /// 子节点指针
114 | ///
115 | public ObservableCollection Nodes
116 | {
117 | get
118 | {
119 | return this.nodes;
120 | }
121 | set
122 | {
123 | this.nodes = value;
124 | this.Notify("Nodes");
125 | }
126 | }
127 |
128 | }
129 |
130 | ///
131 | /// 获取连接配置列表
132 | ///
133 | /// List
134 | ///
135 | public static Dictionary GetConnList()
136 | {
137 | // 避免处理空流问题
138 | if (!File.Exists(CONN_FILE))
139 | return new Dictionary();
140 | FileStream fs = new FileStream(CONN_FILE, FileMode.Open);
141 | Dictionary conns = null;
142 | try
143 | {
144 | BinaryFormatter formatter = new BinaryFormatter();
145 | conns = (Dictionary)formatter.Deserialize(fs);
146 | if (conns == null)
147 | conns = new Dictionary();
148 | return conns;
149 | }
150 | catch (SerializationException ex)
151 | {
152 | MessageBox.Show("Failed to deserialize. Reason: " + ex.Message);
153 | return new Dictionary();
154 | }
155 | finally
156 | {
157 | fs.Close();
158 | }
159 | }
160 |
161 |
162 | ///
163 | /// 写入配置列表(序列化)
164 | ///
165 | ///
166 | public static void WriteConnList(Dictionary conns)
167 | {
168 | FileStream fs = new FileStream(CONN_FILE, FileMode.OpenOrCreate);
169 | BinaryFormatter formatter = new BinaryFormatter();
170 | try
171 | {
172 | formatter.Serialize(fs, conns);
173 | }
174 | catch (SerializationException ex)
175 | {
176 | Console.WriteLine("Failed to serialize. Reason: " + ex.Message);
177 | }
178 | finally
179 | {
180 | fs.Close();
181 | }
182 | }
183 |
184 | ///
185 | /// 生成顶级Node
186 | ///
187 | ///
188 | public static ObservableCollection BuildNodes(Dictionary ConnConfigList)
189 | {
190 | ObservableCollection nodes = new ObservableCollection();
191 | foreach (var item in ConnConfigList)
192 | {
193 | nodes.Add(new Node {
194 | Name = item.Key,
195 | NodeType = NodeType.Connnection,
196 | Value = item.Value,
197 | Nodes = new ObservableCollection()
198 | });
199 | }
200 | return nodes;
201 | }
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/SalamanderWnmp/Tool/ViewHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Media;
8 |
9 | namespace SalamanderWnmp.Tool
10 | {
11 | class ViewHelper
12 | {
13 | public static DependencyObject GetParentView(DependencyObject view)
14 | {
15 | return VisualTreeHelper.GetParent(view);
16 | }
17 |
18 |
19 | public static T FindVisualChild(DependencyObject obj) where T : DependencyObject
20 | {
21 | if (obj != null)
22 | {
23 | for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
24 | {
25 | DependencyObject child = VisualTreeHelper.GetChild(obj, i);
26 | if (child != null && child is T)
27 | {
28 | return (T)child;
29 | }
30 | T childItem = FindVisualChild(child);
31 | if (childItem != null) return childItem;
32 | }
33 | }
34 | return null;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/AboutWin.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | Author: Salamander
58 | QQ: 1906747819
59 | 源码 (欢迎star哦^_^)
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/AboutWin.xaml.cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.UserClass;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Windows.Documents;
6 | using System.Windows.Input;
7 | using System.Windows.Media;
8 | using System.Windows.Media.Imaging;
9 | using System.Windows.Shapes;
10 |
11 | namespace SalamanderWnmp.UI
12 | {
13 | ///
14 | /// AboutWindow.xaml 的交互逻辑
15 | ///
16 | public partial class AboutWin : WnmpUI.BaseWindow
17 | {
18 | public AboutWin()
19 | {
20 | InitializeComponent();
21 | }
22 |
23 |
24 | private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
25 | {
26 | Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
27 | e.Handled = true;
28 | }
29 |
30 | private void imgPortrait_MouseDown(object sender, MouseButtonEventArgs e)
31 | {
32 | Process.Start(new ProcessStartInfo("https://blog-cn.51lucy.com/"));
33 | e.Handled = true;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/AddRedisConnWin.xaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/AddRedisConnWin.xaml.cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.Configuration;
2 | using SalamanderWnmp.UserClass;
3 | using StackExchange.Redis;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Windows;
7 | using System.Windows.Input;
8 | using static SalamanderWnmp.Tool.RedisHelper;
9 |
10 | namespace SalamanderWnmp.UI
11 | {
12 | ///
13 | /// AddRedisConnWin.xaml 的交互逻辑
14 | ///
15 | public partial class AddRedisConnWin : WnmpUI.BaseWindow
16 | {
17 | ///
18 | /// 展示类型,0为添加Window,1为编辑Window
19 | ///
20 | public int ShowType { get; set; }
21 | private RedisConnConfig connData = new RedisConnConfig();
22 | private static ConnectionMultiplexer redisConn = null;
23 |
24 | public AddRedisConnWin()
25 | {
26 | InitializeComponent();
27 | if(ShowType == 1)
28 | {
29 | this.gridConn.DataContext = this.Tag as RedisConnConfig;
30 | }
31 | else
32 | {
33 | this.connData.Port = 6379; // 默认端口
34 | this.gridConn.DataContext = connData;
35 | }
36 | }
37 |
38 | ///
39 | /// 连接选项是否完整
40 | ///
41 | ///
42 | private bool isComplete()
43 | {
44 | if(String.IsNullOrEmpty(this.connData.ConnName))
45 | {
46 | MessageBox.Show("请填写连接名称");
47 | return false;
48 | }
49 | if (String.IsNullOrEmpty(this.connData.Host))
50 | {
51 | MessageBox.Show("请填写主机名");
52 | return false;
53 | }
54 | if (this.connData.Port <= 0)
55 | {
56 | MessageBox.Show("请输入端口");
57 | return false;
58 | }
59 | return true;
60 | }
61 |
62 | private void btnTestConn_Click(object sender, RoutedEventArgs e)
63 | {
64 | if(this.isComplete())
65 | {
66 | try
67 | {
68 | redisConn = ConnectionMultiplexer.Connect(this.connData.Host +
69 | ":" + this.connData.Port);
70 | MessageBox.Show("连接成功!");
71 | }
72 | catch(Exception ex)
73 | {
74 | MessageBox.Show("连接失败\r\n" + ex.Message);
75 | }
76 | }
77 | e.Handled = true;
78 | }
79 |
80 | private void btnAdd_Click(object sender, RoutedEventArgs e)
81 | {
82 | if (this.isComplete())
83 | {
84 | this.Tag = this.connData;
85 | this.Close();
86 | }
87 | e.Handled = true;
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/AuthorWin.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | Author: Salamander
50 | QQ: 1906747819
51 | 我的主页
52 | GitHub
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/AuthorWin.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Shapes;
14 |
15 | namespace SalamanderWnmp.UI
16 | {
17 | ///
18 | /// AboutWindow.xaml 的交互逻辑
19 | ///
20 | public partial class AuthorWindow : Window
21 | {
22 | public AuthorWindow()
23 | {
24 | InitializeComponent();
25 | }
26 |
27 | private void btn_Click(object sender, RoutedEventArgs e)
28 | {
29 | this.Close();
30 | e.Handled = true;
31 | }
32 |
33 | private void title_MouseDown(object sender, MouseButtonEventArgs e)
34 | {
35 | if (e.LeftButton == MouseButtonState.Pressed)
36 | {
37 | DragMove();
38 | }
39 | e.Handled = true;
40 | }
41 |
42 | private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
43 | {
44 | Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
45 | e.Handled = true;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/ChangeThemeColorWin.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/ChangeThemeColorWin.xaml.cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.UserClass;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 | using System.Windows.Documents;
9 | using System.Windows.Input;
10 | using System.Windows.Media;
11 |
12 | namespace SalamanderWnmp.UI
13 | {
14 | ///
15 | /// ChangeThemeColor.xaml 的交互逻辑
16 | ///
17 | public partial class ChangeThemeColorWin : WnmpUI.BaseWindow
18 | {
19 | ///
20 | /// 修改前的主题颜色
21 | ///
22 | private Brush originBrush = null;
23 |
24 | public ChangeThemeColorWin()
25 | {
26 | InitializeComponent();
27 | originBrush = Common.Settings.ThemeColor.Value;
28 | }
29 |
30 | private void cmdSet_Click(object sender, RoutedEventArgs e)
31 | {
32 | var defaultColor = (SolidColorBrush)new BrushConverter().ConvertFromString(Properties.Resources.DefaultThemeColor);
33 | Application.Current.Resources["ThemeColor"] = defaultColor;
34 | colorPicker.Color = defaultColor;
35 | e.Handled = true;
36 | }
37 |
38 | private void colorPicker_ColorChanged(object sender, RoutedPropertyChangedEventArgs e)
39 | {
40 | if (lblColor != null)
41 | lblColor.Text = "新的颜色是" + e.NewValue.ToString();
42 | Application.Current.Resources["ThemeColor"] = colorPicker.Color;
43 | }
44 |
45 | private void btnSave_Click(object sender, RoutedEventArgs e)
46 | {
47 | Common.Settings.ThemeColor.Value = colorPicker.Color;
48 | Common.Settings.UpdateSettings();
49 | originBrush = colorPicker.Color;
50 | this.Close();
51 | }
52 |
53 | private void btnExit_Click(object sender, RoutedEventArgs e)
54 | {
55 | Application.Current.Resources["ThemeColor"] = originBrush;
56 | this.Close();
57 | }
58 |
59 |
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/CodePanelWin.xaml:
--------------------------------------------------------------------------------
1 |
13 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | JavaScript
30 | PHP
31 | Python
32 | Go
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
47 |
48 |
51 |
54 |
57 |
58 |
59 |
62 |
65 |
68 |
71 |
74 |
77 |
78 |
81 |
84 |
85 |
86 |
87 |
88 |
89 | #
90 |
91 |
92 | ¶
93 |
94 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/HttpRequesterWin.xaml.cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.Tool;
2 | using SalamanderWnmp.UserClass;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Collections.ObjectModel;
6 | using System.IO;
7 | using System.Reflection;
8 | using System.Threading;
9 | using System.Windows;
10 | using System.Windows.Controls;
11 | using System.Windows.Input;
12 | using System.Windows.Navigation;
13 |
14 | namespace SalamanderWnmp.UI
15 | {
16 | ///
17 | /// HttpRequester.xaml 的交互逻辑
18 | ///
19 | public partial class HttpRequesterWin : WnmpUI.BaseWindow
20 | {
21 | public HttpRequesterWin()
22 | {
23 | InitializeComponent();
24 | rbtnTxt.IsChecked = true;
25 | cbMethod.ItemsSource = Enum.GetValues(typeof(RequestMethod));
26 | cbMethod.SelectedIndex = 0;
27 | cbHeaderName.ItemsSource = this.frequentHeaderNames;
28 | this.lbHeaders.ItemsSource = this.headers;
29 | }
30 |
31 | private LoadingWin winLoding = null;
32 | private HttpHelper helper = null;
33 | private ObservableCollection> headers = new ObservableCollection>();
34 |
35 | public enum RequestMethod
36 | {
37 | GET,
38 | POST,
39 | HEAD,
40 | TRACE,
41 | PUT,
42 | DELETE,
43 | OPTIONS,
44 | CONNECT
45 | }
46 |
47 | private string[] frequentHeaderNames = new string[]
48 | {
49 | "Content-Type",
50 | "Cookie",
51 | "Host",
52 | "Referer",
53 | "User-Agent",
54 | "Accept",
55 | "Accept-Charset",
56 | "Accept-Encoding",
57 | "Authorization",
58 | "From",
59 | "Upgrade"
60 | };
61 |
62 |
63 | private void btnSend_Click(object sender, RoutedEventArgs e)
64 | {
65 | if (!String.IsNullOrEmpty(txtURL.Text))
66 | {
67 |
68 | try
69 | {
70 | btnSend.IsEnabled = false;
71 | helper = new HttpHelper(txtURL.Text);
72 | winLoding = new LoadingWin();
73 | winLoding.Owner = this;
74 | new Thread(new ParameterizedThreadStart(SendRequest))
75 | .Start(cbMethod.SelectedItem);
76 | }
77 | catch(Exception ex)
78 | {
79 | MessageBox.Show(ex.Message);
80 | btnSend.IsEnabled = true;
81 | }
82 |
83 | }
84 | e.Handled = true;
85 | }
86 |
87 | ///
88 | /// 发送HTTP请求
89 | ///
90 | ///
91 | private void SendRequest(object method)
92 | {
93 | DispatcherHelper.UIDispatcher.Invoke(new Action(() =>
94 | {
95 | winLoding.Show();
96 | }));
97 | Thread.Sleep(1000);
98 | Dictionary maps = new Dictionary();
99 | foreach (var header in headers)
100 | {
101 | maps.Add(header.Key, header.Value);
102 | }
103 | helper.SetHeaders(maps);
104 | string res = null;
105 | switch ((RequestMethod)method)
106 | {
107 | case RequestMethod.GET:
108 | res = helper.Get();
109 | break;
110 | case RequestMethod.POST:
111 | helper.SetBody(txtBody.Text);
112 | res = helper.Post();
113 | break;
114 | }
115 | DispatcherHelper.UIDispatcher.Invoke(new Action(() => {
116 | txtRes.Text = res;
117 | wbRes.NavigateToString(res);
118 | }));
119 | DispatcherHelper.UIDispatcher.Invoke(new Action(() =>
120 | {
121 | winLoding.Close();
122 | btnSend.IsEnabled = true;
123 | }));
124 | }
125 |
126 |
127 | private void btnAddHeader_Click(object sender, RoutedEventArgs e)
128 | {
129 | string name = cbHeaderName.Text;
130 | string value = txtHeaderValue.Text;
131 | if (!String.IsNullOrEmpty(name) && !String.IsNullOrEmpty(value))
132 | {
133 | int index = -1;
134 | if(ExistSameKey(name, out index))
135 | {
136 | headers.RemoveAt(index);
137 | headers.Add(new KeyValuePair(name, value));
138 | }
139 | else
140 | {
141 | this.headers.Add(new KeyValuePair(name, value));
142 | }
143 | }
144 | e.Handled = true;
145 | }
146 |
147 | private void btnDeleteHeader_Click(object sender, RoutedEventArgs e)
148 | {
149 | if(lbHeaders.SelectedIndex >= 0)
150 | {
151 | headers.Remove((KeyValuePair)lbHeaders.SelectedItem);
152 | }
153 | e.Handled = true;
154 | }
155 |
156 | ///
157 | /// 是否存在相同的key
158 | ///
159 | ///
160 | ///
161 | ///
162 | private bool ExistSameKey(string key, out int index)
163 | {
164 | for(int i = 0; i < headers.Count; i++)
165 | {
166 | if (headers[i].Key == key)
167 | {
168 | index = i;
169 | return true;
170 | }
171 | }
172 | index = -1;
173 | return false;
174 | }
175 |
176 | private void WrapPanel_Checked(object sender, RoutedEventArgs e)
177 | {
178 | RadioButton btn = e.OriginalSource as RadioButton;
179 | if (btn.Name == "rbtnBroswer")
180 | {
181 | wbRes.Visibility = Visibility.Visible;
182 | txtRes.Visibility = Visibility.Hidden;
183 | }
184 | else
185 | {
186 | wbRes.Visibility = Visibility.Hidden;
187 | txtRes.Visibility = Visibility.Visible;
188 | }
189 | e.Handled = true;
190 | }
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/LoadingWin.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/LoadingWin.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Windows;
6 | using System.Windows.Controls;
7 | using System.Windows.Data;
8 | using System.Windows.Documents;
9 | using System.Windows.Input;
10 | using System.Windows.Media;
11 | using System.Windows.Media.Imaging;
12 | using System.Windows.Shapes;
13 |
14 | namespace SalamanderWnmp.UI
15 | {
16 | ///
17 | /// LoadingWin.xaml 的交互逻辑
18 | ///
19 | public partial class LoadingWin : WnmpUI.BaseWindow
20 | {
21 | public LoadingWin()
22 | {
23 | InitializeComponent();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/PortScanWin.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/PortScanWin.xaml.cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.Tool;
2 | using SalamanderWnmp.UserClass;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Diagnostics;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Windows;
10 | using System.Windows.Controls;
11 | using System.Windows.Data;
12 | using System.Windows.Documents;
13 | using System.Windows.Input;
14 | using System.Windows.Media;
15 | using System.Windows.Media.Imaging;
16 | using System.Windows.Shapes;
17 |
18 | namespace SalamanderWnmp.UI
19 | {
20 | ///
21 | /// PortScan.xaml 的交互逻辑
22 | ///
23 | public partial class PortScanWin : WnmpUI.BaseWindow
24 | {
25 | public PortScanWin()
26 | {
27 | InitializeComponent();
28 | }
29 |
30 | private void btnScan_Click(object sender, RoutedEventArgs e)
31 | {
32 | lvConditions.ItemsSource = PortScanHelper.GetPortInfoList();
33 | }
34 |
35 | private void GridViewColumnHeader_Click(object sender, RoutedEventArgs e)
36 | {
37 | if (e.OriginalSource is GridViewColumnHeader)
38 | {
39 | GridViewColumn clickedColumn = (e.OriginalSource as GridViewColumnHeader).Column;
40 | if (clickedColumn != null)
41 | {
42 | //Get binding property of clicked column
43 | string bindingProperty = (clickedColumn.DisplayMemberBinding as Binding).Path.Path;
44 | SortDescriptionCollection sdc = lvConditions.Items.SortDescriptions;
45 | ListSortDirection sortDirection = ListSortDirection.Ascending;
46 | if (sdc.Count > 0)
47 | {
48 | SortDescription sd = sdc[0];
49 | sortDirection = (ListSortDirection)((((int)sd.Direction) + 1) % 2);
50 | sdc.Clear();
51 | }
52 | sdc.Add(new SortDescription(bindingProperty, sortDirection));
53 | }
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/QuestionsWin.xaml.cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.UserClass;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Windows;
8 | using System.Windows.Controls;
9 | using System.Windows.Data;
10 | using System.Windows.Documents;
11 | using System.Windows.Input;
12 | using System.Windows.Media;
13 | using System.Windows.Media.Imaging;
14 | using System.Windows.Shapes;
15 |
16 | namespace SalamanderWnmp.UI
17 | {
18 | ///
19 | /// QuestionWin.xaml 的交互逻辑
20 | ///
21 | public partial class QuestionsWin : WnmpUI.BaseWindow
22 | {
23 | public QuestionsWin()
24 | {
25 | InitializeComponent();
26 | }
27 |
28 |
29 |
30 | private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
31 | {
32 | Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
33 | e.Handled = true;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/RedisWin.xaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
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 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UI/SettingWin.xaml.cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.Configuration;
2 | using SalamanderWnmp.UserClass;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Media.Imaging;
9 | using static SalamanderWnmp.Configuration.PHPConfigurationManager;
10 |
11 | namespace SalamanderWnmp.UI
12 | {
13 | ///
14 | /// SettingWindow.xaml 的交互逻辑
15 | ///
16 | public partial class SettingWin : WnmpUI.BaseWindow
17 | {
18 | private PHPConfigurationManager PHPConfigurationMgr = new PHPConfigurationManager();
19 | private Ini settingsCopy = new Ini();
20 |
21 |
22 | public SettingWin()
23 | {
24 | InitializeComponent();
25 | settingsCopy.ReadSettings();
26 | }
27 |
28 |
29 | private void Window_Loaded(object sender, RoutedEventArgs e)
30 | {
31 | gridRegular.DataContext = settingsCopy;
32 | gridMysql.DataContext = settingsCopy;
33 | PHPConfigurationMgr.LoadPHPExtensions(settingsCopy.PHPDirName.Value);
34 | lbPHPExt.ItemsSource = PHPConfigurationMgr.GetExtensions();
35 | txtTotal.DataContext = lbPHPExt;
36 | e.Handled = true;
37 | }
38 |
39 | private void btnSave_Click(object sender, RoutedEventArgs e)
40 | {
41 | Common.ChangeSettings(settingsCopy);
42 | Common.Settings.UpdateSettings();
43 | Common.Nginx.Setup();
44 | Common.Mysql.Setup();
45 | Common.PHP.Setup();
46 | this.Close();
47 | e.Handled = true;
48 | }
49 |
50 | private void btnSavePHPExt_Click(object sender, RoutedEventArgs e)
51 | {
52 | PHPConfigurationMgr.SavePHPIniOptions();
53 | this.Close();
54 | e.Handled = true;
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UserClass/ImageMenu.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 | using System.Windows.Controls;
9 | using System.Windows.Controls.Primitives;
10 | using System.Windows.Data;
11 | using System.Windows.Documents;
12 | using System.Windows.Input;
13 | using System.Windows.Media;
14 | using System.Windows.Media.Imaging;
15 | using System.Windows.Navigation;
16 | using System.Windows.Shapes;
17 |
18 | namespace SalamanderWnmp.UserClass
19 | {
20 |
21 | public class ImageMenu : ButtonBase
22 | {
23 | static ImageMenu()
24 | {
25 | DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageMenu), new FrameworkPropertyMetadata(typeof(ImageMenu)));
26 | }
27 |
28 |
29 | [Description("获取或设置图片")]
30 |
31 |
32 | public ImageSource MySource
33 | {
34 | get { return (ImageSource)GetValue(MySourceProperty); }
35 | set { SetValue(MySourceProperty, value); }
36 | }
37 |
38 | // Using a DependencyProperty as the backing store for MySource. This enables animation, styling, binding, etc...
39 | public static readonly DependencyProperty MySourceProperty =
40 | DependencyProperty.Register("MySource", typeof(ImageSource), typeof(ImageMenu));
41 |
42 |
43 |
44 |
45 |
46 | [Description("获取或设置文本")]
47 |
48 |
49 | public String MyText
50 | {
51 | get { return (String)GetValue(MyTextProperty); }
52 | set { SetValue(MyTextProperty, value); }
53 | }
54 |
55 | // Using a DependencyProperty as the backing store for MyText. This enables animation, styling, binding, etc...
56 | public static readonly DependencyProperty MyTextProperty =
57 | DependencyProperty.Register("MyText", typeof(String), typeof(ImageMenu));
58 |
59 |
60 |
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UserClass/NotificationAreaIcon.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Windows;
7 | using System.Windows.Input;
8 | using System.Windows.Markup;
9 | using System.Windows.Media;
10 | using Drawing = System.Drawing;
11 | using Forms = System.Windows.Forms;
12 |
13 | namespace SalamanderWnmp.UserClass
14 | {
15 | [ContentProperty("Text")]
16 | [DefaultEvent("MouseDoubleClick")]
17 | public class NotificationAreaIcon : FrameworkElement
18 | {
19 | Forms.NotifyIcon notifyIcon;
20 |
21 | public static readonly RoutedEvent MouseClickEvent = EventManager.RegisterRoutedEvent(
22 | "MouseClick", RoutingStrategy.Bubble, typeof(MouseButtonEventHandler), typeof(NotificationAreaIcon));
23 |
24 | public static readonly RoutedEvent MouseDoubleClickEvent = EventManager.RegisterRoutedEvent(
25 | "MouseDoubleClick", RoutingStrategy.Bubble, typeof(MouseButtonEventHandler), typeof(NotificationAreaIcon));
26 |
27 | public static readonly DependencyProperty IconProperty =
28 | DependencyProperty.Register("Icon", typeof(ImageSource), typeof(NotificationAreaIcon));
29 |
30 | public static readonly DependencyProperty TextProperty =
31 | DependencyProperty.Register("Text", typeof(string), typeof(NotificationAreaIcon));
32 |
33 | public static readonly DependencyProperty FormsContextMenuProperty =
34 | DependencyProperty.Register("MenuItems", typeof(List), typeof(NotificationAreaIcon), new PropertyMetadata(new List()));
35 |
36 | protected override void OnInitialized(EventArgs e)
37 | {
38 | base.OnInitialized(e);
39 |
40 | // Create and initialize the window forms notify icon based
41 | notifyIcon = new Forms.NotifyIcon();
42 | notifyIcon.Text = Text;
43 | if (!DesignerProperties.GetIsInDesignMode(this))
44 | {
45 | notifyIcon.Icon = FromImageSource(Icon);
46 | }
47 | notifyIcon.Visible = FromVisibility(Visibility);
48 |
49 | if (this.MenuItems != null && this.MenuItems.Count > 0)
50 | {
51 | notifyIcon.ContextMenu = new System.Windows.Forms.ContextMenu(this.MenuItems.ToArray());
52 | }
53 |
54 | notifyIcon.MouseDown += OnMouseDown;
55 | notifyIcon.MouseUp += OnMouseUp;
56 | notifyIcon.MouseClick += OnMouseClick;
57 | notifyIcon.MouseDoubleClick += OnMouseDoubleClick;
58 |
59 | Dispatcher.ShutdownStarted += OnDispatcherShutdownStarted;
60 | }
61 |
62 | private void OnDispatcherShutdownStarted(object sender, EventArgs e)
63 | {
64 | notifyIcon.Dispose();
65 | }
66 |
67 | private void OnMouseDown(object sender, Forms.MouseEventArgs e)
68 | {
69 | OnRaiseEvent(MouseDownEvent, new MouseButtonEventArgs(
70 | InputManager.Current.PrimaryMouseDevice, 0, ToMouseButton(e.Button)));
71 | }
72 |
73 | private void OnMouseUp(object sender, Forms.MouseEventArgs e)
74 | {
75 | OnRaiseEvent(MouseUpEvent, new MouseButtonEventArgs(
76 | InputManager.Current.PrimaryMouseDevice, 0, ToMouseButton(e.Button)));
77 | }
78 |
79 | private void OnMouseDoubleClick(object sender, Forms.MouseEventArgs e)
80 | {
81 | OnRaiseEvent(MouseDoubleClickEvent, new MouseButtonEventArgs(
82 | InputManager.Current.PrimaryMouseDevice, 0, ToMouseButton(e.Button)));
83 | }
84 |
85 | private void OnMouseClick(object sender, Forms.MouseEventArgs e)
86 | {
87 | OnRaiseEvent(MouseClickEvent, new MouseButtonEventArgs(
88 | InputManager.Current.PrimaryMouseDevice, 0, ToMouseButton(e.Button)));
89 | }
90 |
91 | private void OnRaiseEvent(RoutedEvent handler, MouseButtonEventArgs e)
92 | {
93 | e.RoutedEvent = handler;
94 | RaiseEvent(e);
95 | }
96 |
97 | public List MenuItems
98 | {
99 | get { return (List)GetValue(FormsContextMenuProperty); }
100 | set { SetValue(FormsContextMenuProperty, value); }
101 | }
102 |
103 | public ImageSource Icon
104 | {
105 | get { return (ImageSource)GetValue(IconProperty); }
106 | set { SetValue(IconProperty, value); }
107 | }
108 |
109 | public string Text
110 | {
111 | get { return (string)GetValue(TextProperty); }
112 | set { SetValue(TextProperty, value); }
113 | }
114 |
115 | public event MouseButtonEventHandler MouseClick
116 | {
117 | add { AddHandler(MouseClickEvent, value); }
118 | remove { RemoveHandler(MouseClickEvent, value); }
119 | }
120 |
121 | public event MouseButtonEventHandler MouseDoubleClick
122 | {
123 | add { AddHandler(MouseDoubleClickEvent, value); }
124 | remove { RemoveHandler(MouseDoubleClickEvent, value); }
125 | }
126 |
127 | #region Conversion members
128 |
129 | private static Drawing.Icon FromImageSource(ImageSource icon)
130 | {
131 | if (icon == null)
132 | {
133 | return null;
134 | }
135 | Uri iconUri = new Uri(icon.ToString());
136 | return new Drawing.Icon(Application.GetResourceStream(iconUri).Stream);
137 | }
138 |
139 | private static bool FromVisibility(Visibility visibility)
140 | {
141 | return visibility == Visibility.Visible;
142 | }
143 |
144 | private MouseButton ToMouseButton(Forms.MouseButtons button)
145 | {
146 | switch (button)
147 | {
148 | case Forms.MouseButtons.Left:
149 | return MouseButton.Left;
150 | case Forms.MouseButtons.Right:
151 | return MouseButton.Right;
152 | case Forms.MouseButtons.Middle:
153 | return MouseButton.Middle;
154 | case Forms.MouseButtons.XButton1:
155 | return MouseButton.XButton1;
156 | case Forms.MouseButtons.XButton2:
157 | return MouseButton.XButton2;
158 | }
159 | throw new InvalidOperationException();
160 | }
161 |
162 | #endregion Conversion members
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UserClass/SalamanderListBox.cs:
--------------------------------------------------------------------------------
1 | using SalamanderWnmp.Tool;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Windows.Controls;
7 | using System.Windows.Input;
8 |
9 | namespace SalamanderWnmp.UserClass
10 | {
11 | ///
12 | /// 带平滑滚动的ListBox
13 | ///
14 | class SalamanderListBox: ListBox
15 | {
16 | public SalamanderListBox()
17 | {
18 | this.AddHandler(ListBox.MouseWheelEvent, new MouseWheelEventHandler(list_MouseWheel), true);
19 | }
20 |
21 |
22 | private void list_MouseWheel(object sender, MouseWheelEventArgs e)
23 | {
24 | ItemsControl items = (ItemsControl)sender;
25 | ScrollViewer scroll = ViewHelper.FindVisualChild(items);
26 | if (scroll != null)
27 | {
28 | int d = e.Delta;
29 | if (d < 0)
30 | {
31 | scroll.LineRight();
32 | scroll.LineRight();
33 | }
34 | if (d > 0)
35 | {
36 | scroll.LineLeft();
37 | scroll.LineLeft();
38 | }
39 | scroll.ScrollToTop();
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UserComponent/ColorPicker.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
27 |
28 |
31 |
32 |
35 |
36 |
39 |
40 |
41 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UserComponent/ColorPicker.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 |
16 | namespace SalamanderWnmp.UserComponent
17 | {
18 | ///
19 | /// ColorPicker.xaml 的交互逻辑
20 | ///
21 | public partial class ColorPicker : System.Windows.Controls.UserControl
22 | {
23 | public ColorPicker()
24 | {
25 | InitializeComponent();
26 | SetUpCommands();
27 | }
28 |
29 | private void SetUpCommands()
30 | {
31 | // 设置命令关联,一般的方法
32 | CommandBinding binding = new CommandBinding(ApplicationCommands.Undo,
33 | UndoCommand_Executed, UndoCommand_CanExecute);
34 | this.CommandBindings.Add(binding);
35 | }
36 |
37 | // 存储之前的颜色
38 | private SolidColorBrush previousColor;
39 |
40 |
41 | private void UndoCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
42 | {
43 | ColorPicker colorPicker = (ColorPicker)sender;
44 | e.CanExecute = (colorPicker.previousColor != null);
45 | }
46 | private void UndoCommand_Executed(object sender, ExecutedRoutedEventArgs e)
47 | {
48 | // WPF冻结的问题
49 | if (previousColor.CanFreeze)
50 | {
51 | previousColor.Freeze();
52 | }
53 | ColorPicker colorPicker = (ColorPicker)sender;
54 | colorPicker.Color = (SolidColorBrush)colorPicker.previousColor;
55 | //e.Handled = true;
56 | }
57 |
58 | //依赖属性包装器,分别对应R,G,B,Alpha通道和Color颜色
59 | public byte Red
60 | {
61 | get { return (byte)GetValue(RedProperty); }
62 | set { SetValue(RedProperty, value); }
63 | }
64 | public byte Green
65 | {
66 | get { return (byte)GetValue(GreenProperty); }
67 | set { SetValue(GreenProperty, value); }
68 | }
69 |
70 | public byte Blue
71 | {
72 | get { return (byte)GetValue(BlueProperty); }
73 | set { SetValue(BlueProperty, value); }
74 | }
75 |
76 |
77 |
78 |
79 | public byte Alpha
80 | {
81 | get { return (byte)GetValue(AlphaProperty); }
82 | set { SetValue(AlphaProperty, value); }
83 | }
84 |
85 |
86 |
87 |
88 | public SolidColorBrush Color
89 | {
90 | get { return (SolidColorBrush)GetValue(ColorProperty); }
91 | set { SetValue(ColorProperty, value); }
92 | }
93 |
94 |
95 |
96 |
97 |
98 |
99 | public static readonly DependencyProperty RedProperty =
100 | DependencyProperty.Register("Red", typeof(byte), typeof(ColorPicker),
101 | new FrameworkPropertyMetadata(new PropertyChangedCallback(OnRGBAlphaChanged)));
102 |
103 |
104 | public static readonly DependencyProperty GreenProperty =
105 | DependencyProperty.Register("Green", typeof(byte), typeof(ColorPicker),
106 | new FrameworkPropertyMetadata(new PropertyChangedCallback(OnRGBAlphaChanged)));
107 |
108 |
109 | public static readonly DependencyProperty BlueProperty =
110 | DependencyProperty.Register("Blue", typeof(byte), typeof(ColorPicker),
111 | new FrameworkPropertyMetadata(new PropertyChangedCallback(OnRGBAlphaChanged)));
112 |
113 |
114 | public static readonly DependencyProperty AlphaProperty =
115 | DependencyProperty.Register("Alpha", typeof(byte), typeof(ColorPicker),
116 | new FrameworkPropertyMetadata(new PropertyChangedCallback(OnRGBAlphaChanged)));
117 |
118 |
119 | public static readonly DependencyProperty ColorProperty =
120 | DependencyProperty.Register("Color", typeof(SolidColorBrush), typeof(ColorPicker),
121 | new FrameworkPropertyMetadata(new PropertyChangedCallback(OnColorChanged)));
122 |
123 |
124 |
125 |
126 |
127 | // 关联的影响方法
128 | private static void OnRGBAlphaChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
129 | {
130 | ColorPicker colorPicker = (ColorPicker)sender;
131 | SolidColorBrush newColor = new SolidColorBrush(System.Windows.Media.Color.FromArgb(
132 | colorPicker.Alpha,colorPicker.Red,colorPicker.Green,colorPicker.Blue));
133 | colorPicker.Color = newColor;
134 | }
135 |
136 | private static void OnColorChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
137 | {
138 | ColorPicker colorPicker = (ColorPicker)sender;
139 |
140 | SolidColorBrush oldColor = (SolidColorBrush)e.OldValue;
141 | SolidColorBrush newColor = (SolidColorBrush)e.NewValue;
142 |
143 | colorPicker.Red = newColor.Color.R;
144 | colorPicker.Green = newColor.Color.G;
145 | colorPicker.Blue = newColor.Color.B;
146 | colorPicker.Alpha = Convert.ToByte(newColor.Color.ToString().Substring(1, 2),16);//变通方法而已
147 |
148 | colorPicker.previousColor = oldColor;
149 | colorPicker.OnColorChanged(oldColor, newColor);
150 | }
151 |
152 |
153 | // 路由事件
154 | public static readonly RoutedEvent ColorChangedEvent =
155 | EventManager.RegisterRoutedEvent("ColorChanged", RoutingStrategy.Bubble,
156 | typeof(RoutedPropertyChangedEventHandler), typeof(ColorPicker));
157 |
158 | public event RoutedPropertyChangedEventHandler ColorChanged
159 | {
160 | add { AddHandler(ColorChangedEvent, value); }
161 | remove { RemoveHandler(ColorChangedEvent, value); }
162 | }
163 |
164 | // 激发路由事件
165 | private void OnColorChanged(SolidColorBrush oldValue, SolidColorBrush newValue)
166 | {
167 | RoutedPropertyChangedEventArgs args = new RoutedPropertyChangedEventArgs(oldValue, newValue);
168 | args.RoutedEvent = ColorPicker.ColorChangedEvent;
169 | RaiseEvent(args);
170 | }
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UserComponent/Loading.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UserComponent/Loading.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Navigation;
14 | using System.Windows.Shapes;
15 |
16 | namespace SalamanderWnmp.UI
17 | {
18 | ///
19 | /// Loading.xaml 的交互逻辑
20 | ///
21 | public partial class Loading : UserControl
22 | {
23 | static Loading()
24 | {
25 | //重载默认样式
26 | DefaultStyleKeyProperty.OverrideMetadata(typeof(Loading), new FrameworkPropertyMetadata(typeof(Loading)));
27 | //DependencyProperty 注册 FillColor
28 | FillColorProperty = DependencyProperty.Register("FillColor",
29 | typeof(Color),
30 | typeof(Loading),
31 | new UIPropertyMetadata(Colors.DarkBlue,
32 | new PropertyChangedCallback(OnUriChanged))
33 | );
34 | //Colors.DarkBlue为控件初始化默认值
35 |
36 | }
37 | //属性变更回调函数
38 | private static void OnUriChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
39 | {
40 | //Border b = (Border)d;
41 | //MessageBox.Show(e.NewValue.ToString());
42 |
43 | }
44 | #region 自定义Fields
45 | // DependencyProperty属性定义 FillColorProperty=FillColor+Property组成
46 | public static readonly DependencyProperty FillColorProperty;
47 | #endregion
48 | //VS设计器属性支持
49 | [Description("背景色"), Category("个性配置"), DefaultValue("#FF668899")]
50 | public Color FillColor
51 | {
52 | //GetValue,SetValue为固定写法,此处一般不建议处理其他逻辑
53 | get { return (Color)GetValue(FillColorProperty); }
54 | set { SetValue(FillColorProperty, value); }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UserComponent/NumericControl.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
51 |
52 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/SalamanderWnmp/UserComponent/NumericControl.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using System.ComponentModel;
5 | using System.Windows;
6 | using System.Windows.Data;
7 | using System.Windows.Media;
8 | using System.Windows.Media.Animation;
9 | using System.Text.RegularExpressions;
10 | using System.Windows.Input;
11 | using System.Globalization;
12 | using System.Windows.Controls;
13 |
14 | namespace SalamanderWnmp.UserComponent
15 | {
16 | public partial class NumericControl : INotifyPropertyChanged
17 | {
18 |
19 | public NumericControl()
20 | {
21 | this.InitializeComponent();
22 | }
23 |
24 |
25 | public int Increment { get; set; }
26 | public int MaxValue { get; set; }
27 | public int MinValue { get; set; }
28 |
29 |
30 |
31 |
32 | ///
33 | /// 依赖属性
34 | ///
35 | [Description("获取或设置Value")]
36 |
37 |
38 | public int Value
39 | {
40 | get { return (int)GetValue(ValueProperty); }
41 | set { SetValue(ValueProperty, value); }
42 | }
43 |
44 | // Using a DependencyProperty as the backing store for MyText. This enables animation, styling, binding, etc...
45 | public static readonly DependencyProperty ValueProperty =
46 | DependencyProperty.Register("Value", typeof(int), typeof(NumericControl));
47 |
48 |
49 |
50 | private void UpButton_Click(object sender, RoutedEventArgs e)
51 | {
52 | int newValue = (Value + Increment);
53 | if (newValue > MaxValue)
54 | {
55 | Value = MaxValue;
56 | }
57 | else
58 | {
59 | Value = newValue;
60 | }
61 | }
62 |
63 | private void DownButton_Click(object sender, RoutedEventArgs e)
64 | {
65 | int newValue = (Value - Increment);
66 | if (newValue < MinValue)
67 | {
68 | Value = MinValue;
69 | }
70 | else
71 | {
72 | Value = newValue;
73 | }
74 | }
75 |
76 | private void ValueText_LostFocus(object sender, RoutedEventArgs e)
77 | {
78 | try
79 | {
80 | Value = int.Parse(ValueText.Text);
81 | }
82 | catch (Exception)
83 | {
84 | Value = 0;
85 | }
86 | }
87 |
88 |
89 | #region INotifyPropertyChanged Members
90 |
91 | public event PropertyChangedEventHandler PropertyChanged;
92 |
93 | public void NotifyPropertyChanged(string propertyName)
94 | {
95 | if (PropertyChanged != null)
96 | {
97 | PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
98 | }
99 | }
100 |
101 | #endregion
102 |
103 | private void ValueText_PreviewKeyDown(object sender, KeyEventArgs e)
104 | {
105 | if (e.Key == Key.Space)
106 | e.Handled = true;
107 |
108 | }
109 |
110 | private void ValueText_PreviewTextInput(object sender, TextCompositionEventArgs e)
111 | {
112 | int inputNum = 0;
113 | try
114 | {
115 | inputNum = int.Parse(e.Text);
116 | }
117 | catch (Exception)
118 | {
119 | e.Handled = true;
120 | }
121 | }
122 |
123 | private void ValueText_Pasting(object sender, DataObjectPastingEventArgs e)
124 | {
125 | // 取消粘贴
126 | e.CancelCommand();
127 | }
128 |
129 | private void ValueText_TextChanged(object sender, TextChangedEventArgs e)
130 | {
131 | TextBox textBox = sender as TextBox;
132 | TextChange[] change = new TextChange[e.Changes.Count];
133 | e.Changes.CopyTo(change, 0);
134 |
135 | int offset = change[0].Offset;
136 | if (change[0].AddedLength > 0)
137 | {
138 | int num = int.Parse(textBox.Text);
139 | if(num > MaxValue || num < MinValue)
140 | {
141 | textBox.Text = textBox.Text.Remove(offset, change[0].AddedLength);
142 | textBox.Select(offset, 0);
143 | }
144 | }
145 | }
146 | }
147 |
148 |
149 |
150 | [ValueConversion(typeof(double), typeof(string))]
151 | public class DoubleValueConverter : IValueConverter
152 | {
153 | #region IValueConverter Members
154 |
155 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
156 | {
157 | try
158 | {
159 | return value.ToString();
160 | }
161 | catch (Exception)
162 | {
163 | return "0";
164 | }
165 | }
166 |
167 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
168 | {
169 | //string myValue = (string)value;
170 | //return double.Parse(myValue);
171 | try
172 | {
173 | return int.Parse((string)value);
174 | }
175 | catch (Exception)
176 | {
177 | return 0;
178 | }
179 | }
180 |
181 | #endregion
182 | }
183 | }
--------------------------------------------------------------------------------
/SalamanderWnmp/XAML/Colors.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | 14
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | Microsoft YaHei
80 | 13
81 | 0.5
82 | 0.88
83 | 0.4
84 | yyyy年MM月dd日
85 | yyyy-MM-dd HH:mm:ss
86 |
87 |
--------------------------------------------------------------------------------
/SalamanderWnmp/XAML/FIcon.xaml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
12 |
--------------------------------------------------------------------------------
/SalamanderWnmp/XAML/RadioButton.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
46 |
47 |
48 |
57 |
58 |
59 |
83 |
84 |
--------------------------------------------------------------------------------
/SalamanderWnmp/XAML/TextBox.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
38 |
--------------------------------------------------------------------------------
/SalamanderWnmp/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | 0
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/SalamanderWnmp/logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/SalamanderWnmp/logo.ico
--------------------------------------------------------------------------------
/SalamanderWnmp/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/WnmpUI/BaseWindows.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using System.Text;
4 | using System.Windows;
5 | using System.Windows.Input;
6 | using System.Windows.Interop;
7 | using System.Windows.Media;
8 |
9 | namespace WnmpUI
10 | {
11 | public class BaseWindow : Window
12 | {
13 | public BaseWindow()
14 | {
15 | Style styleBase = Application.Current.Resources["BaseWindow"] as Style;
16 | if(styleBase != null)
17 | {
18 | this.Style = styleBase;
19 | }
20 | this.SourceInitialized += delegate (object sender, EventArgs e)
21 | {
22 | this._HwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource;
23 | };
24 | }
25 |
26 | protected const int WM_SYSCOMMAND = 0x112;
27 |
28 | ///
29 | /// 窗口句柄源
30 | ///
31 | protected HwndSource _HwndSource;
32 |
33 |
34 | #region 窗口事件函数
35 |
36 | ///
37 | /// 窗口移动事件
38 | ///
39 | ///
40 | ///
41 | protected void TitleBar_MouseMove(object sender, MouseEventArgs e)
42 | {
43 | if (e.LeftButton == MouseButtonState.Pressed)
44 | {
45 | this.DragMove();
46 | }
47 | e.Handled = true;
48 | }
49 |
50 | ///
51 | /// 关闭窗口事件
52 | ///
53 | ///
54 | ///
55 | protected virtual void btnClose_Click(object sender, RoutedEventArgs e)
56 | {
57 | this.Close();
58 | }
59 |
60 |
61 | ///
62 | /// 最小化窗口事件
63 | ///
64 | ///
65 | ///
66 | protected virtual void btnMinimize_Click(object sender, RoutedEventArgs e)
67 | {
68 | this.WindowState = WindowState.Minimized;
69 | e.Handled = true;
70 | }
71 |
72 | ///
73 | /// 显示WIndow并且将创建指定窗口的线程设置到前台
74 | ///
75 | protected void ShowWindowAndSetForeground()
76 | {
77 | ShowWindowAsync(_HwndSource.Handle, SW_SHOWNORMAL); // 显示
78 | SetForegroundWindow(_HwndSource.Handle);// 当到最前端
79 | }
80 |
81 | #endregion
82 |
83 | ///
84 | /// 设置目标窗体大小,位置
85 | ///
86 | /// 目标句柄
87 | /// 目标窗体新位置X轴坐标
88 | /// 目标窗体新位置Y轴坐标
89 | /// 目标窗体新宽度
90 | /// 目标窗体新高度
91 | /// 是否刷新窗体
92 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
93 | public static extern int MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool BRePaint);
94 |
95 |
96 | ///
97 | /// 返回指定窗口的边框矩形的尺寸。该尺寸以相对于屏幕坐标左上角的屏幕坐标给出
98 | ///
99 | /// 目标句柄
100 | ///
101 | ///
102 | [DllImport("user32.dll")]
103 | private static extern int GetWindowRect(IntPtr hwnd, out Rect lpRect);
104 |
105 | public struct Rect
106 | {
107 | public int Left;
108 | public int Top;
109 | public int Right;
110 | public int Bottom;
111 | }
112 |
113 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
114 | protected static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
115 |
116 |
117 | // API 常数定义
118 | protected const int SW_HIDE = 0;
119 | protected const int SW_SHOWNORMAL = 1;
120 | protected const int SW_MAXIMIZE = 3;
121 | protected const int SW_SHOWNOACTIVATE = 4;
122 | protected const int SW_SHOW = 5;
123 | protected const int SW_RESTORE = 9;
124 |
125 | ///
126 | /// 该函数设置由不同线程产生的窗口的显示状态
127 | ///
128 | /// 窗口句柄
129 | /// 指定窗口如何显示。查看允许值列表,请查阅ShowWlndow函数的说明部分
130 | /// 如果函数原来可见,返回值为非零;如果函数原来被隐藏,返回值为零
131 | [DllImport("User32.dll")]
132 | protected static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
133 |
134 | ///
135 | /// 该函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。
136 | /// 系统给创建前台窗口的线程分配的权限稍高于其他线程。
137 | ///
138 | /// 将被激活并被调入前台的窗口句柄
139 | /// 如果窗口设入了前台,返回值为非零;如果窗口未被设入前台,返回值为零
140 | [DllImport("User32.dll")]
141 | private static extern bool SetForegroundWindow(IntPtr hWnd);
142 |
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/WnmpUI/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("WnmpUI")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("WnmpUI")]
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("a3a1695d-1595-4e59-ae47-c4c8c02db6a3")]
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 |
--------------------------------------------------------------------------------
/WnmpUI/WnmpUI.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {A3A1695D-1595-4E59-AE47-C4C8C02DB6A3}
8 | Library
9 | Properties
10 | WnmpUI
11 | WnmpUI
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | ..\..\software\SalamanderWnmp\libs\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 | x64
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
59 |
--------------------------------------------------------------------------------
/support_img/alipay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/support_img/alipay.jpg
--------------------------------------------------------------------------------
/support_img/wxpay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pigLoveRabbit520/WinWnmp/3a4059f5471d05fb6a96e38ffede43909c200175/support_img/wxpay.jpg
--------------------------------------------------------------------------------