首页 > 其他分享 >远程桌面一键登录 winform

远程桌面一键登录 winform

时间:2024-06-20 21:59:19浏览次数:11  
标签:string Windows 一键 System Forms 远程桌面 using new winform

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>

RDPRemoteLoginPro\Form1.Designer.cs

namespace RDPRemoteLoginPro
{
    partial class Form1
    {
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        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
            // 
            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
            // 
            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
            // 
            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
            // 
            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
            // 
            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
            // 
            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
            // 
            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
            // 
            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
            // 
            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;
            // 
            // Form1
            // 
            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;
    }
}


RDPRemoteLoginPro\Form1.resx

<?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>

RDPRemoteLoginPro\Form1.cs

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();
        }

        /// <summary>
        /// 执行命令行命令
        /// </summary>
        /// <param name="cmd"></param>
        /// <returns></returns>
        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; //获取RDP模板字符串
            //用DataProtection加密密码,并转化成二进制字符串
            var pwstr = BitConverter.ToString(
                DataProtection.ProtectData(Encoding.Unicode.GetBytes(PasswordTextBox.Text), "")
            );
            pwstr = pwstr.Replace("-", "");
            //替换模板里面的关键字符串,生成当前的drp字符串
            var NewStr = TemplateStr
                .Replace("{#address}", AddressComboBox.Text)
                .Replace("{#username}", UsernameTextBox.Text)
                .Replace("{#password}", pwstr);
            //将drp保存到文件,并放在程序目录下,等待使用
            _filename = NameTextBox.Text + "0" + ".rdp";
            StreamWriter sw = new StreamWriter(_filename);
            sw.Write(NewStr);
            sw.Close();
            //利用CMD命令调用MSTSC
            ProcCmd("mstsc -admin " + _filename);

            this.ShowInTaskbar = true;
            this.WindowState = FormWindowState.Minimized; //使当前窗体最小化
        }

        private void AddressComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            // 获取 ComboBox 实例
            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);
            // 将json字符串转换为Server对象
            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);
                // 将json字符串转换为Server对象
                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)
            {
                // 读取json文件内容
                string jsonContent = File.ReadAllText(_configPath);
                // 将json字符串转换为Server对象
                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;
        }

        /// <summary>
        /// 加密数据
        /// </summary>
        /// <param name="data">要加密的明文数据</param>
        /// <param name="name">有意义的描述,此描述会加到加密后的数据中</param>
        /// <param name="dwFlags">flags的位标志</param>
        /// <returns></returns>
        private static byte[] ProtectData(byte[] data, string name, CryptProtectDataFlags dwFlags)
        {
            byte[] cipherText = null;

            // copy data into unmanaged memory
            //DATA_BLOB结构,用于CryptProtectData参数
            DPAPI.DATA_BLOB din = new DPAPI.DATA_BLOB();
            din.cbData = data.Length;

            //Marshal类的作用:提供了一个方法集,这些方法用于分配非托管内存、复制非托管内存块、将托管类型转换为非托管类型,
            //此外还提供了在与非托管代码交互时使用的其他杂项方法。 
            //为din.pbData分配内存
            din.pbData = Marshal.AllocHGlobal(din.cbData);

            //InPtr结构:用于表示指针或句柄的平台特定类型
            //分配内存错误,抛出内存不足异常
            //IntPtr.Zero:一个只读字段,代表已初始化为零的指针或句柄
            if (din.pbData.Equals(IntPtr.Zero))
                throw new OutOfMemoryException("Unable to allocate memory for buffer.");

            //将data数组中的数据复制到pbData内存指针中
            Marshal.Copy(data, 0, din.pbData, din.cbData);

            //声明DPAPI类的DATA_BLOB公共结构类型
            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数据元素大小为dout.cbData
                    cipherText = new byte[dout.cbData];
                    //从dout.pbData内存指针指向的内容拷贝到byte数组cipherText中
                    Marshal.Copy(dout.pbData, cipherText, startIndex, dout.cbData);
                    //从内存中释放指针指向的数据I
                    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
            {
                // 如果din.pbData非空,则释放din.pbData使用的内存
                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; // = Marshal.SizeOf(typeof(CRYPTPROTECT_PROMPTSTRUCT))
            public int dwPromptFlags; // = 0
            public IntPtr hwndApp; // = IntPtr.Zero
            public string szPrompt; // = null
        }
    }


    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
    {
        /// <summary>  
        /// window form show count  
        /// </summary>  
        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);

        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            //Application.EnableVisualStyles();
            //Application.SetCompatibleTextRenderingDefault(false);
            //Application.Run(new Form1());

            Process instance = RunningInstance();
            if (instance == null)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }
            else
            {
                HandleRunningInstance(instance);
            }
        }

        /// <summary>  
        /// application repeat start  
        /// </summary>  
        public static void ApplicationRepeatStart()
        {
            Process instance = RunningInstance();
            if (instance != null)
            {
                HandleRunningInstance(instance);
            }
        }

        /// <summary>  
        /// Running process instance  
        /// </summary>  
        /// <returns>the running process</returns>  
        public static Process RunningInstance()
        {
            Process current = Process.GetCurrentProcess();
            Process[] processes = Process.GetProcessesByName(current.ProcessName);
            ////Loop through the running processes in with the same name  
            foreach (Process process in processes)
            {
                ////Ignore the current process  
                if (process.Id != current.Id)
                {
                    ////Make sure that the process is running from the exe file.  
                    if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)
                    {
                        ////Return the other process instance.  
                        return process;
                    }
                }
            }
            ////No other instance was found, return null.  
            return null;
        }

        /// <summary>  
        /// handle running instance  
        /// </summary>  
        /// <param name="instance">the running process</param>  
        public static void HandleRunningInstance(Process instance)
        {
            ////Make sure the window is not minimized or maximized  
            ShowWindowAsync(instance.MainWindowHandle, WS_SHOWNORMAL);
            
            ////Set the real instance to foreground window  
            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}

标签:string,Windows,一键,System,Forms,远程桌面,using,new,winform
From: https://www.cnblogs.com/zhuoss/p/18252661

相关文章

  • 远程桌面提示"你的凭据不工作"解决方案
    这几天遇到用户名密码正确,但是使用远程桌面提示“你的凭据不工作”的问题,尝试了下面连接提到的方法,均未解决。https://www.cnblogs.com/wmxblog/p/17540648.html经过查找资料,发现是CredSSP的问题,有两个方案来解决这个问题。编辑远程桌面文件打开远程桌面,设置好信息以后,将其另......
  • Linux一键DD纯净系统
    默认密码:MoeClub.org重装为CentOS:以下命令中的-c后面为CentOS版本号,-v后面为64位/32位,可根据需求进行替换。#CentOS6.1064位:bash<(wget--no-check-certificate-qO-'https://www.moeelf.com/attachment/LinuxShell/InstallNET.sh')-c6.10-v64-a#CentOS6.......
  • Stable Diffusion【应用篇】【艺术写真】:一个让影楼倒闭的SD插件,使用InstantID插件一
    大家好,我是AIGC阿道夫。最近收到不少网友关于AI写真方面的留言,希望能写一些关于AI写真方面的文章。个人关注AI写真有一段时间了,网上也看到了不少写的文章教程和案例,作为一个AI绘画的狂热爱好者,自然也少不了去操作实践一下,关于AI写真,后面我会作为专题来写一系列的文章,把自己......
  • CentOS 7 配置 VNC 远程桌面连接
    文章目录前言1.图形化桌面配置VNC远程连接1.1.安装VNC服务1.2.临时启用VNC远程连接1.2.1.单终端启用VNC远程连接1.2.2.多终端启用VNC远程连接1.3.开机自启动VNC服务实现远程连接1.3.1.设置以root用户身份远程连接1.3.2.设置以普通用户身份远程连接2.最小化......
  • Tailor:一键式视频智能处理,轻松打造精彩视频!
    TailorTailor是令人惊叹的视频编辑神器!其人脸和语音剪辑精准无比,人脸识别能锁定人物画面,语音捕捉和裁剪独具魅力。视频生成方面,口播生成赋予图像灵魂,字幕生成准确契合,色彩生成让黑白鲜活,音频生成创造无限可能。优化上,背景更换如入奇幻世界,流畅度与清晰度也极佳。Tailor......
  • 小鲤AI志愿填报助手:一键探索最适合你的大学专业
    背景每年六月,随着高考的落幕,一个新的挑战随之而来——如何在全国范围内的激烈竞争中抢占一席之地。今年,超过1300万的学生参加了这场决定未来命运的考试,每一个人都希望能进入心仪的大学,学习理想的专业。然而,选择的过程并不简单,错综复杂的分数线、众多的院校和专业以及地域和预......
  • 一键解锁多场景新玩法,TRTC上新虚拟背景功能,开通即用省时省心!
    在视频通话、直播带货、线上会议等众多实时互动场景中,虚拟背景这一功能已然深入人心。通过虚拟背景功能,用户可以模糊视频画面的背景,从而突出主体,获得更沉浸、专注的画面观感,也可以直接替换背景,通过更换图片来适应不同场景的背景需要。这样既可以保护自身隐私,同时也避免了杂乱......
  • 教你一招,一键学会NAS磁盘“净身出户”的好方法!
    在毕业季这个充满离别与新的开始的时刻,空气中似乎也弥漫着一种“断舍离”的氛围。就在这个特殊的季节里,我们迎来了618购物节,各种诱人的优惠活动如雨后春笋般涌现。铁威马618优惠不断!T系列部分低至六折!  在这个热闹的购物季中,有一位即将毕业的小伙伴向我提出了一个困扰他的......
  • OpenStack一键安装部署与配置(全网最详细)
    一,安装环境准备(步骤比较多,建议搭建合理利用虚拟机快照)下载Linux操作系统CentOS7.9镜像:http://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/CentOS-7-x86_64-DVD-2009.iso;1.创建在VMware中创建实验用的虚拟机实例。CPU2x2,(开启虚拟化引擎),内存4G以上,硬盘80G,NAT网络模式......
  • 禁止启动多个winform项目进程程序.exe
    1,在winform项目中 Program.cs文件里添加usingSystem;usingSystem.Collections.Generic;usingSystem.Diagnostics;usingSystem.Linq;usingSystem.Threading.Tasks;usingSystem.Windows.Forms;namespaceSMProjectSysetm{internalstaticclassProgram......