添加系统托盘和菜单项:
- 显示/隐藏界面
- ToolTipText显示已拨链接的名字和获取的IP地址
- 针对每一个链接的连接/断开操作
- 断开所有链接
- 退出程序
App.Config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
<appSettings>
<!--存在多个路由条目时,使用分号连接,以拨号服务器地址为键名-->
<add key="1.1.1.1" value="192.168.2.0 MASK 255.255.255.0 DIALIP"/>
<add key="2.2.2.2" value="192.168.3.0 MASK 255.255.255.0 DIALIP"/>
<add key="site1.example.com" value="192.168.0.0 MASK 255.255.255.0 DIALIP"/>
<add key="3.example.com" value="192.168.8.0 MASK 255.255.255.0 DIALIP"/>
</appSettings>
</configuration>
EntrySimple
/// <summary>
/// 一个简化的拨号连接对象
/// </summary>
public class EntrySimple
{
public string IP
{
get
{
try
{
var ip = NetworkInterface.GetAllNetworkInterfaces().Where(i => i.Name == Name).FirstOrDefault().GetIPProperties().UnicastAddresses[0].Address.ToString();
if (string.IsNullOrEmpty(ip)) return "-";
return ip;
}
catch (Exception)
{
return "-";
}
}
}
/// <summary>
/// 拨号连接名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 拨号服务器地址
/// </summary>
public string PhoneNumber { get; set; }
/// <summary>
/// 是否EAP认证,根据此项决定使用哪个程序拨号
/// </summary>
public bool TypeEAP { get; set; }
/// <summary>
/// 路由条目
/// </summary>
public List<string> Routes { get; set; }
/// <summary>
/// 获取这个拨号条目对应的连接,未拨号时将返回null
/// </summary>
RasConnection Connection => RasConnection.GetActiveConnections().FirstOrDefault(c => c.EntryName == Name);
public EntrySimple(string name, string phoneNumber, bool eap)
{
TypeEAP = eap;
Name = name;
PhoneNumber = phoneNumber;
Routes = new();
}
/// <summary>
/// 拨号功能,先拨号,再添加路由
/// </summary>
public void Connect()
{
if (Connection is null)
{
if (TypeEAP)
{
Process.Start(
new ProcessStartInfo("rasdial")
{
Arguments = Name,
WindowStyle = ProcessWindowStyle.Hidden
}).WaitForExit();
}
else
{
Process.Start("rasphone", $"-d {Name}").WaitForExit();
}
var ip = IP;
if (ip != "-")
{//查询拨号连接获取到的地址
foreach (var route in Routes)
{
string strRoute = route.Replace("DIALIP", IP);
Process.Start(new ProcessStartInfo("cmd") { Arguments = $"/c ROUTE ADD {strRoute}" }).WaitForExit();
}
}
}
}
/// <summary>
/// 是否处于连接状态
/// </summary>
public bool IsConnected => Connection != null;
/// <summary>
/// 挂断
/// </summary>
public void HangUp() => Connection?.HangUp();
}
Form1
public partial class Form1 : Form
{
public Point Position;
readonly Dictionary<string, EntrySimple> DictEntries = new();
readonly RasPhoneBook phoneBook = new();
public Form1()
{
InitializeComponent();
listEntries.MultiSelect = false;
//打开默认电话簿(这个对象包含了所有拨号连接)
phoneBook.Open(RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.User));
Timer timer = new();
timer.Interval = 3000;
timer.Tick += (s, e) => EnumEntries(false);
timer.Start();
}
private void BtnQuit_Click(object sender, EventArgs e) => ExitApp();
private void Form1_Shown(object sender, EventArgs e) => EnumEntries();
private void EnumEntries(bool showmsg = true)
{
int selectedIndex = -1;
if (listEntries.SelectedItems.Count > 0) selectedIndex = listEntries.SelectedItems[0].Index;
if (showmsg) WriteMessage("开始检测本地拨号连接");
listEntries.Clear();
DictEntries.Clear();
menuTrayEntries.DropDownItems.Clear();
List<string> trayTips = new();
var connections = RasConnection.GetActiveConnections();
foreach (var entry in phoneBook.Entries)
{//遍历电话簿里所有连接
entry.Options.PreviewUserPassword = false;//不弹出登录窗口
entry.Options.RemoteDefaultGateway = false;//不使用远程网关
entry.NetworkProtocols.IPv6 = false;//不用IPV6
entry.Update();//不管之前如何,一定重新设置这几项,并保存
var item = listEntries.Items.Add(entry.Name, connections.Any(c => c.EntryName == entry.Name) ? 1 : 2);
var entrySimple = new EntrySimple(entry.Name, entry.PhoneNumber, entry.Options.RequireEap);
try
{//配置文件里不一定存在这个服务器的路由条目
entrySimple.Routes = ConfigurationManager.AppSettings[entry.PhoneNumber.ToLower()].
Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList();
}
catch (Exception) { }
var menuTrayEntry = new ToolStripMenuItem() { Text = entry.Name, Checked = connections.Any(c => c.EntryName == entry.Name) };
menuTrayEntry.Click += (s, o) =>
{
if (entrySimple.IsConnected)
{
WriteMessage($"挂断 {entry.Name}", date: true);
entrySimple.HangUp();
}
else
{
WriteMessage($"开始连接到 {entry.Name}", date: true);
entrySimple.Connect();
}
};
menuTrayEntries.DropDownItems.Add(menuTrayEntry);
item.Tag = entrySimple;
DictEntries[entry.PhoneNumber.ToLower()] = entrySimple;
if (entrySimple.IsConnected) trayTips.Add($"【{entrySimple.Name}】\r\n{entrySimple.IP}");
}
//如果先前选中了某个项,刷新后仍然尝试选择它
if (trayTips.Count > 0)
{
notiIcon.Text = $"已连接\r\n{string.Join("\r\n", trayTips)}";
}
else
{
notiIcon.Text = "";
}
if (selectedIndex >= 0 && selectedIndex < listEntries.Items.Count) listEntries.Items[selectedIndex].Selected = true;
if (showmsg) WriteMessage("所有连接检测完成");
}
private void LblTitle_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left) Location = new Point(Location.X + e.X - Position.X, Location.Y + e.Y - Position.Y);
}
private void LblTitle_MouseDown(object sender, MouseEventArgs e) => Position = e.Location;
private void ListEntries_SelectedIndexChanged(object sender, EventArgs e)
{
if (listEntries.SelectedItems.Count > 0)
{
ShowInfo(listEntries.SelectedItems[0].Tag as EntrySimple);
}
else
{
txtInfo.Clear();
}
}
private void ShowInfo(EntrySimple entry) =>
txtInfo.Text =
$"{entry.Name} - [{(entry.IsConnected ? "Connected" : "DisConnected")}] \r\n" +
$"Server:\t{entry.PhoneNumber}\r\n" +
$"Routes:\r\n{string.Join("\r\n", entry.Routes)}";
private void WriteMessage(string msg, bool date = true, bool msgbox = false)
{
string result = date ? DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") : "";
txtLogs.AppendText($"{result} {msg}\r\n");
if (msgbox) MessageBox.Show(msg);
}
private void BtnMin_Click(object sender, EventArgs e) => WindowState = FormWindowState.Minimized;
private void ListEntries_MouseDoubleClick(object sender, MouseEventArgs e)
{//双击时,拨号,或挂断连接
ListViewHitTestInfo info = listEntries.HitTest(e.X, e.Y);
if (info.Item != null)
{
if (listEntries.SelectedItems.Count > 0)
{
var entry = listEntries.SelectedItems[0].Tag as EntrySimple;
if (entry.IsConnected)
{
entry.HangUp();
WriteMessage($"挂断 {entry.Name}", date: true);
}
else
{
entry.Connect();
WriteMessage($"开始连接到 {entry.Name}", date: true);
}
}
}
}
private void MnuInit_Click(object sender, EventArgs e) => EnumEntries();
private void MnuDisconnectAll_Click(object sender, EventArgs e) => DisconnectAll();
private void MnuTrayDisconnectAll_Click(object sender, EventArgs e) => DisconnectAll();
private void MenuTrayQuit_Click(object sender, EventArgs e) => ExitApp();
private void MenuTrayEntries_Click(object sender, EventArgs e) => WindowState = FormWindowState.Normal;
private void NotiIcon_MouseDoubleClick(object sender, MouseEventArgs e) => ShowWindow();
private void BtnHide_Click(object sender, EventArgs e) => HideWindow();
private void MenuTrayShow_Click(object sender, EventArgs e)
{
if (menuTrayShow.Text.Contains("隐藏"))
{
HideWindow();
}
else
{
ShowWindow();
}
}
private void ShowWindow()
{
Show();
menuTrayShow.Text = "隐藏(&H)";
WindowState = FormWindowState.Normal;
}
private void HideWindow()
{
notiIcon.Visible = true;
menuTrayShow.Text = "显示(&S)";
Hide();
}
private void ExitApp()
{
notiIcon.Dispose();
Environment.Exit(0);
}
private void DisconnectAll()
{
WriteMessage("断开所有连接");
RasConnection.GetActiveConnections().ToList().ForEach(c => c.HangUp());
}
}