using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net.NetworkInformation; // Thêm thư viện này để sử dụng Ping
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace RE_Smart_Terminal
{
public partial class Form1 : Form
{
private SerialPort serialPort;
private bool serialConnected = false;
private TcpClient telnetClient;
private NetworkStream telnetStream;
private bool telnetConnected = false;
private List<string> commandHistory = new List<string>();
private int historyIndex = -1;
private string settingFile = "Setting.ini";
public Form1()
{
InitializeComponent();
cbPort.DropDownStyle = ComboBoxStyle.DropDownList;
cbBaud.DropDownStyle = ComboBoxStyle.DropDown;
cbIp.DropDownStyle = ComboBoxStyle.DropDown;
cbBaud.Items.AddRange(new string[] { "9600", "19200", "38400", "57600",
"115200" });
cbBaud.Text = "115200";
cbIp.Items.Add("192.168.1.1");
cbIp.Text = "192.168.1.1";
cbPort.Items.AddRange(SerialPort.GetPortNames());
btnSend.Click += BtnSend_Click;
txtSend.KeyDown += TxtSend_KeyDown;
btnConnectSerial.Click += BtnConnectSerial_Click;
btnStopSerial.Click += BtnStopSerial_Click;
btnConnectTelnet.Click += BtnConnectTelnet_Click; // Sử dụng lại sự
kiện này
btnStopTelnet.Click += BtnStopTelnet_Click;
txtTerminal.ReadOnly = false;
txtTerminal.KeyDown += TxtTerminal_KeyDown;
groupBox1.DoubleClick += GroupBox_DoubleClick;
groupBox2.DoubleClick += GroupBox_DoubleClick;
groupBox3.DoubleClick += GroupBox_DoubleClick;
groupBox4.DoubleClick += GroupBox_DoubleClick;
this.Load += Form1_Load;
}
// --- Save Log ---
private void btnSaveLog_Click(object sender, EventArgs e)
{
using (SaveFileDialog sfd = new SaveFileDialog())
{
sfd.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";
sfd.FileName = "terminal_log.txt";
if (sfd.ShowDialog() == DialogResult.OK)
{
File.WriteAllText(sfd.FileName, txtTerminal.Text);
MessageBox.Show("Log đã được lưu vào:\n" + sfd.FileName,
"Save Log",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
}
}
// --- GroupBox Rename ---
private void GroupBox_DoubleClick(object sender, EventArgs e)
{
if (sender is GroupBox gb)
{
string newText = InputDialog.Show("Đổi tên GroupBox", "Nhập tên mới
cho nhóm:", gb.Text);
if (!string.IsNullOrWhiteSpace(newText))
{
gb.Text = newText;
SaveGroupBoxNames(settingFile);
}
}
}
private void LoadGroupBoxNames(string filePath)
{
if (!File.Exists(filePath)) return;
var lines = File.ReadAllLines(filePath);
foreach (var line in lines)
{
if (line.StartsWith("Group1=")) groupBox1.Text =
line.Substring("Group1=".Length).Trim();
if (line.StartsWith("Group2=")) groupBox2.Text =
line.Substring("Group2=".Length).Trim();
if (line.StartsWith("Group3=")) groupBox3.Text =
line.Substring("Group3=".Length).Trim();
if (line.StartsWith("Group4=")) groupBox4.Text =
line.Substring("Group4=".Length).Trim();
}
}
private void SaveGroupBoxNames(string filePath)
{
List<string> newLines = new List<string>();
if (File.Exists(filePath))
{
var lines = File.ReadAllLines(filePath).ToList();
bool inGroupBox = false;
foreach (var line in lines)
{
if (line.Trim().Equals("[GroupBox]",
StringComparison.OrdinalIgnoreCase))
{
inGroupBox = true;
continue;
}
if (inGroupBox && line.StartsWith("[") && line.EndsWith("]"))
{
inGroupBox = false;
}
if (!inGroupBox)
{
newLines.Add(line);
}
}
}
List<string> groupBoxSection = new List<string>
{
"[GroupBox]",
"Group1=" + groupBox1.Text,
"Group2=" + groupBox2.Text,
"Group3=" + groupBox3.Text,
"Group4=" + groupBox4.Text,
""
};
newLines.InsertRange(0, groupBoxSection);
File.WriteAllLines(filePath, newLines);
}
// --- Load Button Config ---
private void Form1_Load(object sender, EventArgs e)
{
LoadGroupBoxNames(settingFile);
LoadButtonConfig(settingFile);
}
private void LoadButtonConfig(string filePath)
{
if (!File.Exists(filePath))
{
AppendTerminal($"\x1b[31m[ERROR]\x1b[0m Không tìm thấy file
{filePath}\n");
return;
}
string[] lines = File.ReadAllLines(filePath);
string currentButton = "";
string tenNut = "";
List<string> commands = new List<string>();
foreach (string line in lines)
{
if (line.StartsWith("[Button"))
{
if (!string.IsNullOrEmpty(currentButton) && commands.Count > 0)
ApplyButtonConfig(currentButton, tenNut, commands);
currentButton = line.Trim('[', ']');
tenNut = "";
commands = new List<string>();
}
else if (line.StartsWith("TenNutBam="))
{
tenNut = line.Substring("TenNutBam=".Length).Trim();
}
else if (line.StartsWith("Command"))
{
string cmd = line.Substring(line.IndexOf('=') + 1).Trim();
if (!string.IsNullOrEmpty(cmd))
commands.Add(cmd);
}
}
if (!string.IsNullOrEmpty(currentButton) && commands.Count > 0)
ApplyButtonConfig(currentButton, tenNut, commands);
}
private void ApplyButtonConfig(string buttonName, string tenNut,
List<string> commands)
{
var btn = this.Controls.Find(buttonName, true).FirstOrDefault() as
Button;
if (btn != null)
{
btn.Text = tenNut;
btn.Tag = commands;
btn.Click -= ButtonConfig_Click;
btn.Click += ButtonConfig_Click;
AppendTerminal($"\x1b[32m[OK]\x1b[0m Gán {buttonName} -> {tenNut}\
n");
}
else
{
AppendTerminal($"\x1b[31m[ERROR]\x1b[0m Không tìm thấy {buttonName}
trên form\n");
}
}
private void ButtonConfig_Click(object sender, EventArgs e)
{
if (sender is Button btn && btn.Tag is List<string> commands)
{
foreach (string cmd in commands)
{
SendCommand(cmd + "\r\n");
}
commandHistory.Add(string.Join(" ; ", commands));
historyIndex = -1;
}
}
// --- Send Command ---
private void BtnSend_Click(object sender, EventArgs e) =>
SendFromTxtSend();
private void TxtSend_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter && !e.Control)
{
e.SuppressKeyPress = true;
SendFromTxtSend();
}
else if (e.KeyCode == Keys.Enter && e.Control)
{
int pos = txtSend.SelectionStart;
txtSend.Text = txtSend.Text.Insert(pos, Environment.NewLine);
txtSend.SelectionStart = pos + Environment.NewLine.Length;
e.SuppressKeyPress = true;
}
else if (e.KeyCode == Keys.Up)
{
if (commandHistory.Count > 0 && historyIndex < commandHistory.Count
- 1)
{
historyIndex++;
txtSend.Text = commandHistory[commandHistory.Count - 1 -
historyIndex];
txtSend.SelectionStart = txtSend.Text.Length;
}
e.Handled = true;
}
else if (e.KeyCode == Keys.Down)
{
if (historyIndex > 0)
{
historyIndex--;
txtSend.Text = commandHistory[commandHistory.Count - 1 -
historyIndex];
}
else
{
historyIndex = -1;
txtSend.Clear();
}
txtSend.SelectionStart = txtSend.Text.Length;
e.Handled = true;
}
}
private void SendFromTxtSend()
{
string cmd = txtSend.Text;
if (string.IsNullOrWhiteSpace(cmd))
{
SendCommand("\r\n");
}
else
{
SendCommand(cmd + "\r\n");
commandHistory.Add(cmd);
historyIndex = -1;
txtSend.Clear();
}
}
private void TxtTerminal_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter && !e.Control)
{
e.SuppressKeyPress = true;
int lastLineIndex =
txtTerminal.GetLineFromCharIndex(txtTerminal.SelectionStart);
string lastLine = txtTerminal.Lines[lastLineIndex];
SendCommand(lastLine + "\r\n");
commandHistory.Add(lastLine);
historyIndex = -1;
}
}
private void SendCommand(string cmd)
{
try
{
AppendTerminal($"\x1b[33m{cmd.Trim()}\x1b[0m\n");
if (serialConnected && serialPort != null && serialPort.IsOpen)
{
serialPort.Write(cmd);
}
else if (telnetConnected && telnetStream != null &&
telnetStream.CanWrite)
{
byte[] buffer = Encoding.ASCII.GetBytes(cmd);
telnetStream.Write(buffer, 0, buffer.Length);
}
else
{
AppendTerminal("\x1b[31m[ERROR]\x1b[0m Chưa kết nối thiết bị!\
n");
}
}
catch (Exception ex)
{
AppendTerminal("\x1b[31m[LỖI SEND]\x1b[0m " + ex.Message + "\n");
}
}
// --- Serial ---
private void BtnConnectSerial_Click(object sender, EventArgs e)
{
if (cbPort.SelectedItem == null)
{
MessageBox.Show("Hãy chọn COM Port!");
return;
}
if (serialConnected || telnetConnected)
{
AppendTerminal("\x1b[31m[ERROR]\x1b[0m Đã có một kết nối đang hoạt
động. Vui lòng ngắt kết nối trước.\n");
return;
}
try
{
serialPort = new SerialPort(cbPort.SelectedItem.ToString(),
int.Parse(cbBaud.Text));
serialPort.DataReceived += (s, ev) =>
{
string data = serialPort.ReadExisting();
AppendTerminal(data);
};
serialPort.Open();
serialConnected = true;
AppendTerminal($"\x1b[32m[COM CONNECTED]\x1b[0m
{serialPort.PortName} @ {serialPort.BaudRate}\n");
btnConnectTelnet.Enabled = false;
btnStopTelnet.Enabled = false;
cbIp.Enabled = false;
}
catch (Exception ex)
{
MessageBox.Show("Lỗi COM: " + ex.Message);
}
}
private void BtnStopSerial_Click(object sender, EventArgs e)
{
if (serialPort != null && serialPort.IsOpen)
{
serialPort.Close();
serialConnected = false;
AppendTerminal("\x1b[33m[COM DISCONNECTED]\x1b[0m\n");
btnConnectTelnet.Enabled = true;
btnStopTelnet.Enabled = true;
cbIp.Enabled = true;
}
}
// --- Telnet ---
private bool CheckPing(string ipAddress)
{
try
{
Ping pinger = new Ping();
PingReply reply = pinger.Send(ipAddress, 1000);
if (reply.Status == IPStatus.Success)
{
AppendTerminal($"\x1b[32m[PING OK]\x1b[0m Ping thành công
{ipAddress} (tốc độ: {reply.RoundtripTime}ms)\n");
return true;
}
else
{
AppendTerminal($"\x1b[31m[PING FAILED]\x1b[0m Không ping được
{ipAddress}. Trạng thái: {reply.Status}\n");
return false;
}
}
catch (Exception ex)
{
AppendTerminal($"\x1b[31m[PING ERROR]\x1b[0m Lỗi khi ping
{ipAddress}: {ex.Message}\n");
return false;
}
}
// Đã hợp nhất các chức năng vào hàm này
private void BtnConnectTelnet_Click(object sender, EventArgs e)
{
string ipAddress = cbIp.Text;
if (telnetConnected || serialConnected)
{
AppendTerminal("\x1b[31m[ERROR]\x1b[0m Đã có một kết nối đang hoạt
động. Vui lòng ngắt kết nối trước.\n");
return;
}
if (!CheckPing(ipAddress))
{
return;
}
try
{
telnetClient = new TcpClient(ipAddress, 23);
telnetStream = telnetClient.GetStream();
telnetConnected = true;
AppendTerminal($"\x1b[32m[TELNET CONNECTED]\x1b[0m Kết nối thành
công đến {ipAddress}\n");
var reader = new System.Threading.Thread(() =>
{
byte[] buffer = new byte[1024];
int bytes;
while (telnetConnected && telnetStream.CanRead && (bytes =
telnetStream.Read(buffer, 0, buffer.Length)) > 0)
{
string data = Encoding.ASCII.GetString(buffer, 0, bytes);
AppendTerminal(data);
}
});
reader.IsBackground = true;
reader.Start();
btnConnectSerial.Enabled = false;
btnStopSerial.Enabled = false;
cbPort.Enabled = false;
cbBaud.Enabled = false;
}
catch (Exception ex)
{
MessageBox.Show("Lỗi Telnet: " + ex.Message);
AppendTerminal($"\x1b[31m[TELNET ERROR]\x1b[0m Không thể kết nối
đến {ipAddress}. Vui lòng kiểm tra lại địa chỉ IP hoặc cổng.\n");
}
}
private void BtnStopTelnet_Click(object sender, EventArgs e)
{
if (telnetConnected)
{
telnetConnected = false;
telnetStream?.Close();
telnetClient?.Close();
AppendTerminal("\x1b[33m[TELNET DISCONNECTED]\x1b[0m\n");
btnConnectSerial.Enabled = true;
btnStopSerial.Enabled = true;
cbPort.Enabled = true;
cbBaud.Enabled = true;
}
}
// --- ANSI Terminal ---
private void AppendTerminal(string text)
{
if (txtTerminal.InvokeRequired)
{
txtTerminal.Invoke(new Action(() =>
AppendAnsiText(txtTerminal, text)));
}
else
{
AppendAnsiText(txtTerminal, text);
}
}
private void AppendAnsiText(RichTextBox box, string text)
{
var regex = new Regex(@"\x1B\[(\d+)(;\d+)?m");
int lastIndex = 0;
foreach (Match m in regex.Matches(text))
{
if (m.Index > lastIndex)
{
box.AppendText(text.Substring(lastIndex, m.Index - lastIndex));
}
string[] codes = m.Value.Replace("\x1B[", "").Replace("m",
"").Split(';');
foreach (string codeStr in codes)
{
if (int.TryParse(codeStr, out int code))
{
switch (code)
{
case 0: box.SelectionColor = Color.White;
box.SelectionFont = new Font("Consolas", box.Font.Size, FontStyle.Regular); break;
case 1: box.SelectionFont = new Font("Consolas",
box.Font.Size, FontStyle.Bold); break;
case 4: box.SelectionFont = new Font("Consolas",
box.Font.Size, FontStyle.Underline); break;
case 30: box.SelectionColor = Color.Black; break;
case 31: box.SelectionColor = Color.Red; break;
case 32: box.SelectionColor = Color.Green; break;
case 33: box.SelectionColor = Color.Yellow; break;
case 34: box.SelectionColor = Color.Blue; break;
case 35: box.SelectionColor = Color.Magenta; break;
case 36: box.SelectionColor = Color.Cyan; break;
case 37: box.SelectionColor = Color.White; break;
default: box.SelectionColor = Color.White; break;
}
}
}
lastIndex = m.Index + m.Length;
}
if (lastIndex < text.Length)
{
box.AppendText(text.Substring(lastIndex));
}
// Luôn cuộn xuống cuối cùng
box.SelectionStart = box.Text.Length;
box.ScrollToCaret();
}
private void btnConnectTelnet_Click_1(object sender, EventArgs e)
{
// Hàm này trống. Có thể bạn đã tạo nhầm sự kiện. Hãy xóa hàm này và sử
dụng btnConnectTelnet_Click đã sửa ở trên.
}
private void button41_Click(object sender, EventArgs e)
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.Arguments = "/K ping 192.168.1.1 -t";
try
{
Process.Start(psi);
}
catch (Exception ex)
{
MessageBox.Show("Lỗi khi chạy lệnh: " + ex.Message, "Lỗi",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void button42_Click(object sender, EventArgs e)
{
// Tên của card mạng bạn muốn kích hoạt.
// Tên của card mạng bạn muốn kích hoạt.
// Thay thế "Ethernet" bằng tên card mạng của bạn.
string interfaceName = "Ethernet";
try
{
// Tạo một đối tượng ProcessStartInfo để chạy lệnh netsh.
ProcessStartInfo psi = new ProcessStartInfo("netsh", $"interface
set interface \"{interfaceName}\" enable");
// Thiết lập UseShellExecute để chạy với quyền quản trị viên.
psi.UseShellExecute = true;
// Cần quyền Admin để thực hiện lệnh này.
psi.Verb = "runas";
// Khởi động Process.
Process.Start(psi);
MessageBox.Show($"Đã gửi lệnh kích hoạt card mạng:
{interfaceName}", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"Lỗi: Không thể kích hoạt card mạng.\nChi tiết:
{ex.Message}\n\nĐảm bảo ứng dụng chạy với quyền quản trị viên.", "Lỗi",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void button42_Click_1(object sender, EventArgs e)
{
try
{
AppendTerminal("\x1b[36m[INFO]\x1b[0m Đang mở Network
Connections...");
// Sử dụng ProcessStartInfo để cấu hình rõ ràng
ProcessStartInfo startInfo = new ProcessStartInfo
{
FileName = "control.exe",
Arguments = "ncpa.cpl",
UseShellExecute = true,
Verb = "open", // Mở bình thường, không cần admin
WindowStyle = ProcessWindowStyle.Normal
};
using (Process process = new Process())
{
process.StartInfo = startInfo;
process.Start();
// Đợi một chút để process khởi động
process.WaitForExit(1000);
}
AppendTerminal("\x1b[32m[SUCCESS]\x1b[0m Đã gửi yêu cầu mở Network
Connections");
}
catch (Win32Exception winEx)
{
AppendTerminal($"\x1b[31m[ERROR]\x1b[0m Lỗi Windows:
{winEx.Message}");
MessageBox.Show($"Lỗi hệ thống: {winEx.Message}\n\nCó thể do chính
sách bảo mật.",
"Lỗi", MessageBoxButtons.OK,
MessageBoxIcon.Warning);
}
catch (Exception ex)
{
AppendTerminal($"\x1b[31m[ERROR]\x1b[0m {ex.Message}");
// Thử cách khác nếu cách trên thất bại
TryAlternativeMethod();
}
}
private void TryAlternativeMethod()
{
try
{
AppendTerminal("\x1b[36m[INFO]\x1b[0m Thử phương pháp thay
thế...");
// Cách 2: Sử dụng rundll32
Process.Start("rundll32.exe", "shell32.dll,Control_RunDLL
ncpa.cpl");
AppendTerminal("\x1b[32m[SUCCESS]\x1b[0m Đã thử mở bằng rundll32");
}
catch (Exception ex2)
{
AppendTerminal($"\x1b[31m[ERROR]\x1b[0m Cũng thất bại:
{ex2.Message}");
ShowManualInstructions();
}
}
private void ShowManualInstructions()
{
AppendTerminal("\x1b[33m[HƯỚNG DẪN THỦ CÔNG]\x1b[0m");
AppendTerminal("\x1b[33m1. Nhấn Win + R\x1b[0m");
AppendTerminal("\x1b[33m2. Gõ: ncpa.cpl\x1b[0m");
AppendTerminal("\x1b[33m3. Nhấn Enter\x1b[0m");
AppendTerminal("\x1b[33m4. Hoặc: control.exe ncpa.cpl\x1b[0m");
MessageBox.Show("Không thể mở tự động. Vui lòng mở thủ công:\n\n" +
"1. Nhấn Windows + R\n" +
"2. Gõ: ncpa.cpl\n" +
"3. Nhấn Enter",
"Hướng dẫn mở thủ công",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
private void button42_Click_2(object sender, EventArgs e)
{
try
{
// Chạy lệnh shell để mở hộp thoại "Run" của Windows.
// Đây là cách chính xác nhất để thực hiện tác vụ này.
Process.Start("explorer.exe", "shell:::{2559a1f5-21d7-11d4-bdf9-
00104bd364f8}");
}
catch (Exception ex)
{
MessageBox.Show("Lỗi khi mở hộp thoại Run: " + ex.Message, "Lỗi",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void button42_Click_3(object sender, EventArgs e)
{
try
{
string filePath = "setting.ini";
// Kiểm tra file có tồn tại không
if (!File.Exists(filePath))
{
MessageBox.Show("File setting.ini không tồn tại!", "Lỗi",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// Mở file với trình soạn thảo mặc định
Process.Start(new ProcessStartInfo
{
FileName = filePath,
UseShellExecute = true
});
// Ghi log thành công
AppendTerminal("\x1b[32m[SUCCESS]\x1b[0m Đã mở file setting.ini");
}
catch (Exception ex)
{
MessageBox.Show($"Lỗi khi mở file: {ex.Message}", "Lỗi",
MessageBoxButtons.OK, MessageBoxIcon.Error);
AppendTerminal($"\x1b[31m[ERROR]\x1b[0m Không thể mở setting.ini:
{ex.Message}");
}
}
}
// --- InputDialog Class ---
public class InputDialog : Form
{
private TextBox textBox;
private Button btnOK;
private Button btnCancel;
public string InputText => textBox.Text;
public InputDialog(string title, string prompt, string defaultText = "")
{
this.Text = title;
this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.StartPosition = FormStartPosition.CenterParent;
this.ClientSize = new Size(300, 130);
this.MinimizeBox = false;
this.MaximizeBox = false;
Label lblPrompt = new Label()
{
Text = prompt,
AutoSize = true,
Location = new Point(10, 10)
};
this.Controls.Add(lblPrompt);
textBox = new TextBox()
{
Text = defaultText,
Location = new Point(10, 35),
Width = 270
};
this.Controls.Add(textBox);
btnOK = new Button()
{
Text = "OK",
DialogResult = DialogResult.OK,
Location = new Point(125, 75),
Width = 70
};
this.Controls.Add(btnOK);
btnCancel = new Button()
{
Text = "Cancel",
DialogResult = DialogResult.Cancel,
Location = new Point(205, 75),
Width = 70
};
this.Controls.Add(btnCancel);
this.AcceptButton = btnOK;
this.CancelButton = btnCancel;
}
public static string Show(string title, string prompt, string defaultText =
"")
{
using (var dialog = new InputDialog(title, prompt, defaultText))
{
return dialog.ShowDialog() == DialogResult.OK ? dialog.InputText :
defaultText;
}
}
}
}