RDPRemoteLoginPro\RDPRemoteLoginPro.csproj
| <Project Sdk="Microsoft.NET.Sdk"> |
| <PropertyGroup> |
| <TargetFramework>net8.0-windows</TargetFramework> |
| <OutputType>WinExe</OutputType> |
| <AssemblyName>MstscOneClick</AssemblyName> |
| <GenerateAssemblyInfo>false</GenerateAssemblyInfo> |
| <UseWindowsForms>true</UseWindowsForms> |
| <ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets> |
| </PropertyGroup> |
| <ItemGroup> |
| <PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> |
| <PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" /> |
| <PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.0" /> |
| </ItemGroup> |
| </Project> |
| namespace RDPRemoteLoginPro |
| { |
| partial class Form1 |
| { |
| |
| |
| |
| private System.ComponentModel.IContainer components = null; |
| |
| |
| |
| |
| |
| protected override void Dispose(bool disposing) |
| { |
| if (disposing && (components != null)) |
| { |
| components.Dispose(); |
| } |
| base.Dispose(disposing); |
| } |
| |
| #region Windows 窗体设计器生成的代码 |
| |
| |
| |
| |
| |
| private void InitializeComponent() |
| { |
| label1 = new System.Windows.Forms.Label(); |
| label2 = new System.Windows.Forms.Label(); |
| UsernameTextBox = new System.Windows.Forms.TextBox(); |
| label3 = new System.Windows.Forms.Label(); |
| PasswordTextBox = new System.Windows.Forms.TextBox(); |
| button1 = new System.Windows.Forms.Button(); |
| AddressComboBox = new System.Windows.Forms.ComboBox(); |
| label4 = new System.Windows.Forms.Label(); |
| NameTextBox = new System.Windows.Forms.TextBox(); |
| SuspendLayout(); |
| |
| |
| |
| label1.AutoSize = true; |
| label1.Location = new System.Drawing.Point(34, 35); |
| label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); |
| label1.Name = "label1"; |
| label1.Size = new System.Drawing.Size(56, 20); |
| label1.TabIndex = 0; |
| label1.Text = "IP地址:"; |
| label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; |
| label1.Click += label1_Click; |
| |
| |
| |
| label2.AutoSize = true; |
| label2.Location = new System.Drawing.Point(34, 153); |
| label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); |
| label2.Name = "label2"; |
| label2.Size = new System.Drawing.Size(58, 20); |
| label2.TabIndex = 0; |
| label2.Text = "用户名:"; |
| label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; |
| |
| |
| |
| UsernameTextBox.Location = new System.Drawing.Point(122, 153); |
| UsernameTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); |
| UsernameTextBox.Name = "UsernameTextBox"; |
| UsernameTextBox.Size = new System.Drawing.Size(223, 27); |
| UsernameTextBox.TabIndex = 1; |
| |
| |
| |
| label3.AutoSize = true; |
| label3.Location = new System.Drawing.Point(34, 217); |
| label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); |
| label3.Name = "label3"; |
| label3.Size = new System.Drawing.Size(55, 20); |
| label3.TabIndex = 0; |
| label3.Text = "密 码:"; |
| label3.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; |
| |
| |
| |
| PasswordTextBox.Location = new System.Drawing.Point(122, 212); |
| PasswordTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); |
| PasswordTextBox.Name = "PasswordTextBox"; |
| PasswordTextBox.Size = new System.Drawing.Size(223, 27); |
| PasswordTextBox.TabIndex = 1; |
| PasswordTextBox.UseSystemPasswordChar = true; |
| |
| |
| |
| button1.Location = new System.Drawing.Point(122, 303); |
| button1.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); |
| button1.Name = "button1"; |
| button1.Size = new System.Drawing.Size(112, 38); |
| button1.TabIndex = 2; |
| button1.Text = "连接"; |
| button1.UseVisualStyleBackColor = true; |
| button1.Click += button1_Click; |
| |
| |
| |
| AddressComboBox.FormattingEnabled = true; |
| AddressComboBox.Location = new System.Drawing.Point(122, 35); |
| AddressComboBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); |
| AddressComboBox.Name = "AddressComboBox"; |
| AddressComboBox.Size = new System.Drawing.Size(223, 28); |
| AddressComboBox.TabIndex = 3; |
| AddressComboBox.SelectedIndexChanged += AddressComboBox_SelectedIndexChanged; |
| |
| |
| |
| label4.AutoSize = true; |
| label4.Location = new System.Drawing.Point(34, 92); |
| label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); |
| label4.Name = "label4"; |
| label4.Size = new System.Drawing.Size(55, 20); |
| label4.TabIndex = 0; |
| label4.Text = "名 称:"; |
| label4.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; |
| |
| |
| |
| NameTextBox.Location = new System.Drawing.Point(122, 92); |
| NameTextBox.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); |
| NameTextBox.Name = "NameTextBox"; |
| NameTextBox.Size = new System.Drawing.Size(223, 27); |
| NameTextBox.TabIndex = 1; |
| |
| |
| |
| AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); |
| AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; |
| ClientSize = new System.Drawing.Size(384, 380); |
| Controls.Add(AddressComboBox); |
| Controls.Add(button1); |
| Controls.Add(PasswordTextBox); |
| Controls.Add(label3); |
| Controls.Add(NameTextBox); |
| Controls.Add(label4); |
| Controls.Add(UsernameTextBox); |
| Controls.Add(label2); |
| Controls.Add(label1); |
| FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; |
| Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); |
| MaximizeBox = false; |
| MinimizeBox = false; |
| Name = "Form1"; |
| StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; |
| Text = "MSTSC神器"; |
| Load += Form1_Load; |
| ResumeLayout(false); |
| PerformLayout(); |
| } |
| |
| #endregion |
| |
| private System.Windows.Forms.Label label1; |
| private System.Windows.Forms.Label label2; |
| private System.Windows.Forms.TextBox UsernameTextBox; |
| private System.Windows.Forms.Label label3; |
| private System.Windows.Forms.TextBox PasswordTextBox; |
| private System.Windows.Forms.Button button1; |
| private System.Windows.Forms.ComboBox AddressComboBox; |
| private System.Windows.Forms.Label label4; |
| private System.Windows.Forms.TextBox NameTextBox; |
| } |
| } |
| |
| |
| <?xml version="1.0" encoding="utf-8"?> |
| <root> |
| <!-- |
| Microsoft ResX Schema |
| |
| Version 2.0 |
| |
| The primary goals of this format is to allow a simple XML format |
| that is mostly human readable. The generation and parsing of the |
| various data types are done through the TypeConverter classes |
| associated with the data types. |
| |
| Example: |
| |
| ... ado.net/XML headers & schema ... |
| <resheader name="resmimetype">text/microsoft-resx</resheader> |
| <resheader name="version">2.0</resheader> |
| <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> |
| <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> |
| <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> |
| <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> |
| <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> |
| <value>[base64 mime encoded serialized .NET Framework object]</value> |
| </data> |
| <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> |
| <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> |
| <comment>This is a comment</comment> |
| </data> |
| |
| There are any number of "resheader" rows that contain simple |
| name/value pairs. |
| |
| Each data row contains a name, and value. The row also contains a |
| type or mimetype. Type corresponds to a .NET class that support |
| text/value conversion through the TypeConverter architecture. |
| Classes that don't support this are serialized and stored with the |
| mimetype set. |
| |
| The mimetype is used for serialized objects, and tells the |
| ResXResourceReader how to depersist the object. This is currently not |
| extensible. For a given mimetype the value must be set accordingly: |
| |
| Note - application/x-microsoft.net.object.binary.base64 is the format |
| that the ResXResourceWriter will generate, however the reader can |
| read any of the formats listed below. |
| |
| mimetype: application/x-microsoft.net.object.binary.base64 |
| value : The object must be serialized with |
| : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter |
| : and then encoded with base64 encoding. |
| |
| mimetype: application/x-microsoft.net.object.soap.base64 |
| value : The object must be serialized with |
| : System.Runtime.Serialization.Formatters.Soap.SoapFormatter |
| : and then encoded with base64 encoding. |
| |
| mimetype: application/x-microsoft.net.object.bytearray.base64 |
| value : The object must be serialized into a byte array |
| : using a System.ComponentModel.TypeConverter |
| : and then encoded with base64 encoding. |
| --> |
| <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> |
| <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> |
| <xsd:element name="root" msdata:IsDataSet="true"> |
| <xsd:complexType> |
| <xsd:choice maxOccurs="unbounded"> |
| <xsd:element name="metadata"> |
| <xsd:complexType> |
| <xsd:sequence> |
| <xsd:element name="value" type="xsd:string" minOccurs="0" /> |
| </xsd:sequence> |
| <xsd:attribute name="name" use="required" type="xsd:string" /> |
| <xsd:attribute name="type" type="xsd:string" /> |
| <xsd:attribute name="mimetype" type="xsd:string" /> |
| <xsd:attribute ref="xml:space" /> |
| </xsd:complexType> |
| </xsd:element> |
| <xsd:element name="assembly"> |
| <xsd:complexType> |
| <xsd:attribute name="alias" type="xsd:string" /> |
| <xsd:attribute name="name" type="xsd:string" /> |
| </xsd:complexType> |
| </xsd:element> |
| <xsd:element name="data"> |
| <xsd:complexType> |
| <xsd:sequence> |
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> |
| <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> |
| </xsd:sequence> |
| <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> |
| <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> |
| <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> |
| <xsd:attribute ref="xml:space" /> |
| </xsd:complexType> |
| </xsd:element> |
| <xsd:element name="resheader"> |
| <xsd:complexType> |
| <xsd:sequence> |
| <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> |
| </xsd:sequence> |
| <xsd:attribute name="name" type="xsd:string" use="required" /> |
| </xsd:complexType> |
| </xsd:element> |
| </xsd:choice> |
| </xsd:complexType> |
| </xsd:element> |
| </xsd:schema> |
| <resheader name="resmimetype"> |
| <value>text/microsoft-resx</value> |
| </resheader> |
| <resheader name="version"> |
| <value>2.0</value> |
| </resheader> |
| <resheader name="reader"> |
| <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
| </resheader> |
| <resheader name="writer"> |
| <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> |
| </resheader> |
| </root> |
| using System; |
| using System.Collections.Generic; |
| using System.ComponentModel; |
| using System.Data; |
| using System.Diagnostics; |
| using System.Drawing; |
| using System.IO; |
| using System.Linq; |
| using System.Text; |
| using System.Windows.Forms; |
| using RDPRemoteLoginPro; |
| |
| namespace RDPRemoteLoginPro |
| { |
| public partial class Form1 : Form |
| { |
| private string _filename; |
| |
| private string _address; |
| private string _linkName; |
| private string _username; |
| private string _password; |
| |
| public Form1() |
| { |
| InitializeComponent(); |
| } |
| |
| private void button1_Click(object sender, EventArgs e) |
| { |
| Connect(); |
| SaveConfig(); |
| } |
| |
| |
| |
| |
| |
| |
| void ProcCmd(String cmd) |
| { |
| Process p = new Process(); |
| p.StartInfo.FileName = "cmd.exe"; |
| p.StartInfo.UseShellExecute = false; |
| p.StartInfo.RedirectStandardInput = true; |
| p.StartInfo.RedirectStandardOutput = true; |
| p.StartInfo.RedirectStandardError = true; |
| p.StartInfo.CreateNoWindow = true; |
| p.Start(); |
| p.StandardInput.WriteLine(cmd); |
| p.StandardInput.WriteLine("exit"); |
| } |
| |
| |
| private void Form1_Load(object sender, EventArgs e) |
| { |
| AddressComboBox.Select(); |
| LoadConfig(); |
| } |
| |
| private void LoadConfig() |
| { |
| List<Server> servers = ConfigHelper.GetServers(); |
| if (servers.Count == 0) |
| { |
| AddressComboBox.Text = "请输入IP地址"; |
| UsernameTextBox.PlaceholderText = "计算机名称"; |
| PasswordTextBox.PlaceholderText = "用户名"; |
| NameTextBox.PlaceholderText = "请输入密码"; |
| } |
| else |
| { |
| List<string> serverIps = servers.Select(x => x.ServerIp).ToList(); |
| foreach (string ip in serverIps) |
| { |
| AddressComboBox.Items.Add(ip); |
| } |
| AddressComboBox.SelectedIndex = 0; |
| |
| UsernameTextBox.Text = servers.First().User; |
| PasswordTextBox.Text = servers.First().Password; |
| NameTextBox.Text = servers.First().LinkName; |
| } |
| |
| |
| } |
| |
| private void SaveConfig() |
| { |
| |
| ConfigHelper.AddAndUpdateServer( |
| new Server |
| { |
| ServerIp = AddressComboBox.Text, |
| LinkName = NameTextBox.Text, |
| User = UsernameTextBox.Text, |
| Password = PasswordTextBox.Text, |
| }); |
| } |
| |
| private void Connect() |
| { |
| if ( |
| string.IsNullOrEmpty(AddressComboBox.Text) |
| || string.IsNullOrEmpty(UsernameTextBox.Text) |
| || string.IsNullOrEmpty(PasswordTextBox.Text) |
| || string.IsNullOrEmpty(NameTextBox.Text.Trim()) |
| ) |
| { |
| |
| MessageBox.Show(@"请检查配置!"); |
| return; |
| } |
| |
| |
| |
| var TemplateStr = RDPRemoteLoginPro.Properties.Resources.TemplateRDP; |
| |
| var pwstr = BitConverter.ToString( |
| DataProtection.ProtectData(Encoding.Unicode.GetBytes(PasswordTextBox.Text), "") |
| ); |
| pwstr = pwstr.Replace("-", ""); |
| |
| var NewStr = TemplateStr |
| .Replace("{#address}", AddressComboBox.Text) |
| .Replace("{#username}", UsernameTextBox.Text) |
| .Replace("{#password}", pwstr); |
| |
| _filename = NameTextBox.Text + "0" + ".rdp"; |
| StreamWriter sw = new StreamWriter(_filename); |
| sw.Write(NewStr); |
| sw.Close(); |
| |
| ProcCmd("mstsc -admin " + _filename); |
| |
| this.ShowInTaskbar = true; |
| this.WindowState = FormWindowState.Minimized; |
| } |
| |
| private void AddressComboBox_SelectedIndexChanged(object sender, EventArgs e) |
| { |
| |
| ComboBox comboBox = sender as ComboBox; |
| if (comboBox != null) |
| { |
| |
| string serverIp = (string)comboBox.SelectedItem; |
| var server = ConfigHelper.GetServerByIp(serverIp.Trim()); |
| NameTextBox.Text = server.LinkName; |
| UsernameTextBox.Text = server.User; |
| PasswordTextBox.Text = server.Password; |
| } |
| } |
| |
| private void label1_Click(object sender, EventArgs e) |
| { |
| |
| } |
| } |
| } |
| |
RDPRemoteLoginPro\ConfigHelper.cs
| using Newtonsoft.Json; |
| using System; |
| using System.Collections.Generic; |
| using System.Configuration; |
| using System.IO; |
| using System.Linq; |
| using System.Text.RegularExpressions; |
| using System.Xml; |
| using System.Xml.Linq; |
| |
| |
| namespace RDPRemoteLoginPro |
| { |
| public static class ConfigHelper |
| { |
| |
| static string _configPath = @"serverData.json"; |
| |
| static List<Server> _servers = new List<Server>(); |
| |
| static ConfigHelper() |
| { |
| if (!File.Exists(_configPath)) |
| { |
| string jsonString = JsonConvert.SerializeObject(_servers); |
| File.WriteAllText(_configPath, jsonString); |
| } |
| } |
| |
| public static List<Server> GetServers() |
| { |
| string jsonContent = File.ReadAllText(_configPath); |
| |
| List<Server> serversInfos = |
| JsonConvert.DeserializeObject<List<Server>>(jsonContent) |
| ?? throw new Exception("server is null"); |
| _servers.AddRange(serversInfos); |
| return _servers; |
| } |
| public static Server GetServerByIp(string ip) |
| { |
| if (_servers.Count == 0) |
| { |
| string jsonContent = File.ReadAllText(_configPath); |
| |
| List<Server> serversInfos = |
| JsonConvert.DeserializeObject<List<Server>>(jsonContent) |
| ?? throw new Exception("server is null"); |
| _servers.AddRange(serversInfos); |
| } |
| Server server = _servers.Where(x => x.ServerIp == ip).First(); |
| return server; |
| } |
| |
| |
| public static void AddAndUpdateServer(Server server) |
| { |
| if (_servers.Count == 0) |
| { |
| |
| string jsonContent = File.ReadAllText(_configPath); |
| |
| List<Server> serversInfos = |
| JsonConvert.DeserializeObject<List<Server>>(jsonContent) |
| ?? throw new Exception("server is null"); |
| _servers.AddRange(serversInfos); |
| } |
| |
| bool isExist = _servers.Exists(x => x.ServerIp == server.ServerIp); |
| if (isExist) |
| { |
| Server server1 = _servers.Where(x => x.ServerIp == server.ServerIp).First(); |
| server1.LinkName = server.LinkName; |
| server1.User = server.User; |
| server1.Password = server.Password; |
| } |
| else |
| { |
| _servers.Add(server); |
| } |
| |
| string jsonString = JsonConvert.SerializeObject(_servers); |
| |
| File.WriteAllText(_configPath, jsonString); |
| } |
| |
| |
| } |
| |
| |
| } |
| |
RDPRemoteLoginPro\DataProtection.cs
| using System; |
| using System.Runtime.InteropServices; |
| using System.Text; |
| using System.Security; |
| |
| namespace RDPRemoteLoginPro |
| { |
| [Serializable()] |
| public sealed class DataProtection |
| { |
| [Flags()] |
| public enum CryptProtectPromptFlags |
| { |
| CRYPTPROTECT_PROMPT_ON_UNPROTECT = 0x01, |
| CRYPTPROTECT_PROMPT_ON_PROTECT = 0x02, |
| CRYPTPROTECT_PROMPT_RESERVED = 0x04, |
| CRYPTPROTECT_PROMPT_STRONG = 0x08, |
| CRYPTPROTECT_PROMPT_REQUIRE_STRONG = 0x10 |
| } |
| |
| [Flags()] |
| public enum CryptProtectDataFlags |
| { |
| CRYPTPROTECT_UI_FORBIDDEN = 0x01, |
| CRYPTPROTECT_LOCAL_MACHINE = 0x04, |
| CRYPTPROTECT_CRED_SYNC = 0x08, |
| CRYPTPROTECT_AUDIT = 0x10, |
| CRYPTPROTECT_NO_RECOVERY = 0x20, |
| CRYPTPROTECT_VERIFY_PROTECTION = 0x40, |
| CRYPTPROTECT_CRED_REGENERATE = 0x80 |
| } |
| |
| #region 加密数据 |
| public static string ProtectData(string data, string name) |
| { |
| return ProtectData(data, name, |
| CryptProtectDataFlags.CRYPTPROTECT_UI_FORBIDDEN | CryptProtectDataFlags.CRYPTPROTECT_LOCAL_MACHINE); |
| } |
| |
| public static byte[] ProtectData(byte[] data, string name) |
| { |
| return ProtectData(data, name, |
| CryptProtectDataFlags.CRYPTPROTECT_UI_FORBIDDEN | CryptProtectDataFlags.CRYPTPROTECT_LOCAL_MACHINE); |
| } |
| |
| public static string ProtectData(string data, string name, CryptProtectDataFlags flags) |
| { |
| byte[] dataIn = Encoding.Unicode.GetBytes(data); |
| byte[] dataOut = ProtectData(dataIn, name, flags); |
| |
| if (dataOut != null) |
| return (Convert.ToBase64String(dataOut)); |
| else |
| return null; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| private static byte[] ProtectData(byte[] data, string name, CryptProtectDataFlags dwFlags) |
| { |
| byte[] cipherText = null; |
| |
| |
| |
| DPAPI.DATA_BLOB din = new DPAPI.DATA_BLOB(); |
| din.cbData = data.Length; |
| |
| |
| |
| |
| din.pbData = Marshal.AllocHGlobal(din.cbData); |
| |
| |
| |
| |
| if (din.pbData.Equals(IntPtr.Zero)) |
| throw new OutOfMemoryException("Unable to allocate memory for buffer."); |
| |
| |
| Marshal.Copy(data, 0, din.pbData, din.cbData); |
| |
| |
| DPAPI.DATA_BLOB dout = new DPAPI.DATA_BLOB(); |
| |
| try |
| { |
| |
| bool cryptoRetval = DPAPI.CryptProtectData(ref din, name, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, dwFlags, ref dout); |
| |
| |
| if (cryptoRetval) |
| { |
| int startIndex = 0; |
| |
| cipherText = new byte[dout.cbData]; |
| |
| Marshal.Copy(dout.pbData, cipherText, startIndex, dout.cbData); |
| |
| DPAPI.LocalFree(dout.pbData); |
| } |
| else |
| { |
| |
| int errCode = Marshal.GetLastWin32Error(); |
| StringBuilder buffer = new StringBuilder(256); |
| |
| Win32Error.FormatMessage(Win32Error.FormatMessageFlags.FORMAT_MESSAGE_FROM_SYSTEM, IntPtr.Zero, errCode, 0, buffer, buffer.Capacity, IntPtr.Zero); |
| } |
| } |
| finally |
| { |
| |
| if (!din.pbData.Equals(IntPtr.Zero)) |
| Marshal.FreeHGlobal(din.pbData); |
| } |
| |
| |
| return cipherText; |
| } |
| #endregion |
| |
| |
| |
| |
| internal static void InitPromptstruct(ref DPAPI.CRYPTPROTECT_PROMPTSTRUCT ps) |
| { |
| ps.cbSize = Marshal.SizeOf(typeof(DPAPI.CRYPTPROTECT_PROMPTSTRUCT)); |
| ps.dwPromptFlags = 0; |
| ps.hwndApp = IntPtr.Zero; |
| ps.szPrompt = null; |
| } |
| } |
| |
| |
| [SuppressUnmanagedCodeSecurityAttribute()] |
| internal class DPAPI |
| { |
| [DllImport("crypt32")] |
| public static extern bool CryptProtectData(ref DATA_BLOB dataIn, string szDataDescr, IntPtr optionalEntropy, IntPtr pvReserved, |
| IntPtr pPromptStruct, DataProtection.CryptProtectDataFlags dwFlags, ref DATA_BLOB pDataOut); |
| |
| [DllImport("crypt32")] |
| public static extern bool CryptUnprotectData(ref DATA_BLOB dataIn, StringBuilder ppszDataDescr, IntPtr optionalEntropy, |
| IntPtr pvReserved, IntPtr pPromptStruct, DataProtection.CryptProtectDataFlags dwFlags, ref DATA_BLOB pDataOut); |
| |
| [DllImport("Kernel32.dll")] |
| public static extern IntPtr LocalFree(IntPtr hMem); |
| |
| [StructLayout(LayoutKind.Sequential)] |
| public struct DATA_BLOB |
| { |
| public int cbData; |
| public IntPtr pbData; |
| } |
| |
| [StructLayout(LayoutKind.Sequential)] |
| public struct CRYPTPROTECT_PROMPTSTRUCT |
| { |
| public int cbSize; |
| public int dwPromptFlags; |
| public IntPtr hwndApp; |
| public string szPrompt; |
| } |
| } |
| |
| |
| internal class Win32Error |
| { |
| [Flags()] |
| public enum FormatMessageFlags : int |
| { |
| FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x0100, |
| FORMAT_MESSAGE_IGNORE_INSERTS = 0x0200, |
| FORMAT_MESSAGE_FROM_STRING = 0x0400, |
| FORMAT_MESSAGE_FROM_HMODULE = 0x0800, |
| FORMAT_MESSAGE_FROM_SYSTEM = 0x1000, |
| FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x2000, |
| FORMAT_MESSAGE_MAX_WIDTH_MASK = 0xFF, |
| } |
| |
| [DllImport("Kernel32.dll")] |
| public static extern int FormatMessage(FormatMessageFlags flags, IntPtr source, int messageId, int languageId, |
| StringBuilder buffer, int size, IntPtr arguments); |
| } |
| } |
| |
RDPRemoteLoginPro\Server.cs
| using System; |
| using System.Collections.Generic; |
| using System.Linq; |
| using System.Text; |
| using System.Threading.Tasks; |
| |
| namespace RDPRemoteLoginPro |
| { |
| public class Server |
| { |
| public string ServerIp { get; set; } |
| public string LinkName { get; set; } |
| public string User { get; set; } |
| public string Password { get; set; } |
| } |
| } |
| |
RDPRemoteLoginPro\RDPRemoteLoginPro.csproj.user
| <?xml version="1.0" encoding="utf-8"?> |
| <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
| <PropertyGroup /> |
| <ItemGroup> |
| <Compile Update="Form1.cs"> |
| <SubType>Form</SubType> |
| </Compile> |
| </ItemGroup> |
| </Project> |
RDPRemoteLoginPro\RDPRemoteLoginPro.sln
| |
| Microsoft Visual Studio Solution File, Format Version 12.00 |
| # Visual Studio 15 |
| VisualStudioVersion = 15.0.28010.2048 |
| MinimumVisualStudioVersion = 10.0.40219.1 |
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RDPRemoteLoginPro", "RDPRemoteLoginPro.csproj", "{F14DB645-6273-48E7-8CBD-E823A27BD9DC}" |
| EndProject |
| Global |
| GlobalSection(SolutionConfigurationPlatforms) = preSolution |
| Debug|Any CPU = Debug|Any CPU |
| Release|Any CPU = Release|Any CPU |
| EndGlobalSection |
| GlobalSection(ProjectConfigurationPlatforms) = postSolution |
| {F14DB645-6273-48E7-8CBD-E823A27BD9DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
| {F14DB645-6273-48E7-8CBD-E823A27BD9DC}.Debug|Any CPU.Build.0 = Debug|Any CPU |
| {F14DB645-6273-48E7-8CBD-E823A27BD9DC}.Release|Any CPU.ActiveCfg = Release|Any CPU |
| {F14DB645-6273-48E7-8CBD-E823A27BD9DC}.Release|Any CPU.Build.0 = Release|Any CPU |
| EndGlobalSection |
| GlobalSection(SolutionProperties) = preSolution |
| HideSolutionNode = FALSE |
| EndGlobalSection |
| GlobalSection(ExtensibilityGlobals) = postSolution |
| SolutionGuid = {66A1728E-08D1-488F-864D-EDCD804E34F1} |
| EndGlobalSection |
| EndGlobal |
| |
RDPRemoteLoginPro\Program.cs
| using System; |
| using System.Collections.Generic; |
| using System.Diagnostics; |
| using System.Linq; |
| using System.Reflection; |
| using System.Runtime.InteropServices; |
| using System.Windows.Forms; |
| using RDPRemoteLoginPro; |
| |
| namespace RDPRemoteLoginPro |
| { |
| static class Program |
| { |
| |
| |
| |
| private const int WS_SHOWNORMAL = 1; |
| |
| [DllImport("User32.dll")] |
| private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow); |
| [DllImport("User32.dll")] |
| private static extern bool SetForegroundWindow(IntPtr hWnd); |
| [DllImport("kernel32.dll")] |
| private static extern IntPtr LoadLibrary(string sLibName); |
| |
| |
| |
| |
| [STAThread] |
| static void Main() |
| { |
| |
| |
| |
| |
| Process instance = RunningInstance(); |
| if (instance == null) |
| { |
| Application.EnableVisualStyles(); |
| Application.SetCompatibleTextRenderingDefault(false); |
| Application.Run(new Form1()); |
| } |
| else |
| { |
| HandleRunningInstance(instance); |
| } |
| } |
| |
| |
| |
| |
| public static void ApplicationRepeatStart() |
| { |
| Process instance = RunningInstance(); |
| if (instance != null) |
| { |
| HandleRunningInstance(instance); |
| } |
| } |
| |
| |
| |
| |
| |
| public static Process RunningInstance() |
| { |
| Process current = Process.GetCurrentProcess(); |
| Process[] processes = Process.GetProcessesByName(current.ProcessName); |
| |
| foreach (Process process in processes) |
| { |
| |
| if (process.Id != current.Id) |
| { |
| |
| if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName) |
| { |
| |
| return process; |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| |
| |
| |
| |
| public static void HandleRunningInstance(Process instance) |
| { |
| |
| ShowWindowAsync(instance.MainWindowHandle, WS_SHOWNORMAL); |
| |
| |
| SetForegroundWindow(instance.MainWindowHandle); |
| } |
| } |
| } |
| |
RDPRemoteLoginPro\Resources\TemplateRDP.txt
| screen mode id:i:2 |
| use multimon:i:0 |
| desktopwidth:i:1600 |
| desktopheight:i:900 |
| session bpp:i:32 |
| winposstr:s:0,3,0,0,800,600 |
| compression:i:1 |
| keyboardhook:i:2 |
| audiocapturemode:i:0 |
| videoplaybackmode:i:1 |
| connection type:i:2 |
| networkautodetect:i:1 |
| bandwidthautodetect:i:1 |
| displayconnectionbar:i:1 |
| enableworkspacereconnect:i:0 |
| disable wallpaper:i:1 |
| allow font smoothing:i:0 |
| allow desktop composition:i:0 |
| disable full window drag:i:1 |
| disable menu anims:i:1 |
| disable themes:i:0 |
| disable cursor setting:i:0 |
| bitmapcachepersistenable:i:1 |
| audiomode:i:1 |
| redirectprinters:i:1 |
| redirectcomports:i:0 |
| redirectsmartcards:i:1 |
| redirectclipboard:i:1 |
| redirectposdevices:i:0 |
| autoreconnection enabled:i:1 |
| authentication level:i:2 |
| prompt for credentials:i:0 |
| negotiate security layer:i:1 |
| remoteapplicationmode:i:0 |
| alternate shell:s: |
| shell working directory:s: |
| gatewayhostname:s: |
| gatewayusagemethod:i:4 |
| gatewaycredentialssource:i:4 |
| gatewayprofileusagemethod:i:0 |
| promptcredentialonce:i:0 |
| use redirection server name:i:0 |
| rdgiskdcproxy:i:0 |
| kdcproxyname:s: |
| drivestoredirect:s: |
| redirectdirectx:i:1 |
| full address:s:{#address} |
| username:s:{#username} |
| password 51:b:{#password} |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!