├── .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 | [![Build Status](https://travis-ci.org/slimphp/Slim.svg?branch=develop)](https://travis-ci.org/slimphp/Slim) 4 | [![Coverage Status](https://coveralls.io/repos/slimphp/Slim/badge.svg)](https://coveralls.io/r/slimphp/Slim) 5 | [![License](https://poser.pugx.org/slim/slim/license)](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 | 修改php目录 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 | 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 | 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 --------------------------------------------------------------------------------