Windows网络XX修改和删除,dotnet程序
Windows网络XX修改和删除,dotnet程序
把这些丢进Visual Studio编译即可
只有两个文件
存哪:注册表
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles{GUID}
ProfileName = "网络 6"
Category = 0(0=公用,1=专用,2=域)
读哪:Network List Service(服务名 netprofm)
该服务开机/网络变化时读取上述注册表,按网络指纹(网关 MAC、SSID 等)匹配已知配置文件;匹配不到就新建,自动命名为"网络 N"
设置界面和 Get-NetConnectionProfile 都是通过它的 COM 接口(INetworkListManager)读取,不直接读注册表
一句话:数据在注册表,读取由 netprofm 服务负责。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net472</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<LangVersion>5</LangVersion>
<ApplicationIcon>app.ico</ApplicationIcon>
</PropertyGroup>
</Project>using System;
using System.Collections.Generic;
using System.Drawing;
using System.Security.Principal;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;
namespace NetProfileEdit
{
public class ProfileValue
{
public string Name;
public RegistryValueKind Kind;
public object Data;
}
public class MainForm : Form
{
const string BasePath = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles";
static readonly string[] CatText = { "公用", "专用", "域" };
// 值名翻译(中文(原名))
static readonly Dictionary<string, string> ValCn = new Dictionary<string, string>
{
{ "ProfileName", "配置文件名" },
{ "Category", "类别" },
{ "Description", "描述" },
{ "NameType", "名称类型" },
{ "Managed", "是否托管" },
{ "DateCreated", "创建日期" },
{ "DateLastConnected", "最后连接日期" },
{ "CategoryType", "类别类型" },
{ "NameSourceTag", "名称来源" }
};
// 值的注释说明(右侧"说明"列)
static readonly Dictionary<string, string> ValDesc = new Dictionary<string, string>
{
{ "ProfileName", "网络显示名称(可改)" },
{ "Category", "0=公用 1=专用 2=域" },
{ "Description", "备注描述(可改)" },
{ "NameType", "连接类型: 6=有线 23=无线 53/41=VPN" },
{ "Managed", "是否被策略管理: 0=否 1=是" },
{ "DateCreated", "创建时间(显示=转换后(原始值))" },
{ "DateLastConnected", "最后连接时间(显示=转换后(原始值))" },
{ "CategoryType", "类别判定来源(系统自动维护)" },
{ "NameSourceTag", "名称来源(系统自动维护)" }
};
readonly Dictionary<string, List<ProfileValue>> _profiles = new Dictionary<string, List<ProfileValue>>();
readonly List<string> _order = new List<string>(); // 行号 -> GUID
string _curGuid;
bool _loading;
bool _selAll;
readonly TextBox _txtPath;
readonly SplitContainer _split;
readonly DataGridView _tblLeft; // 左侧:信息表格(带勾选框)
readonly DataGridView _grid; // 右侧:选中项键值
readonly Label _status;
readonly Button _btnRead, _btnSel, _btnDel;
static string DispName(string regName)
{
string cn;
return ValCn.TryGetValue(regName, out cn) ? cn + "\n(" + regName + ")" : regName;
}
static string TypeDisp(RegistryValueKind k)
{
switch (k)
{
case RegistryValueKind.String: return "字符串(String)";
case RegistryValueKind.DWord: return "双字(DWord)";
case RegistryValueKind.Binary: return "二进制(Binary)";
case RegistryValueKind.ExpandString: return "可扩展字符串(ExpandString)";
case RegistryValueKind.QWord: return "四字(QWord)";
default: return k.ToString();
}
}
static string NumDisp(string field, int n)
{
if (field == "Category")
{
if (n >= 0 && n <= 2) return CatText[n] + "(" + n + ")";
}
else if (field == "NameType")
{
if (n == 6) return "有线(6)";
if (n == 23) return "无线(23)";
if (n == 41) return "VPN(41)";
if (n == 53) return "VPN/虚拟网卡(53)";
}
else if (field == "Managed")
{
return n == 0 ? "否(0)" : "是(1)";
}
else if (field == "CategoryType")
{
if (n >= 0 && n <= 2) return CatText[n] + "(" + n + ")";
}
return n.ToString();
}
// 二进制日期(SYSTEMTIME) -> 转换值(原始hex)
static string BinDisp(string name, byte[] b)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (byte x in b) sb.Append(x.ToString("x2")).Append(' ');
string hex = sb.ToString().TrimEnd();
if ((name == "DateCreated" || name == "DateLastConnected") && b.Length >= 16)
{
ushort y = BitConverter.ToUInt16(b, 0);
ushort mo = BitConverter.ToUInt16(b, 2);
ushort d = BitConverter.ToUInt16(b, 6);
ushort h = BitConverter.ToUInt16(b, 8);
ushort mi = BitConverter.ToUInt16(b, 10);
ushort s = BitConverter.ToUInt16(b, 12);
if (y >= 1601 && mo >= 1 && mo <= 12 && d >= 1 && d <= 31)
{
try
{
DateTime dt = new DateTime(y, mo, d, h, mi, s);
return dt.ToString("yyyy-MM-dd HH:mm:ss") + "\n(" + hex + ")";
}
catch { }
}
}
return hex;
}
static string GetDesc(string name)
{
string d;
return ValDesc.TryGetValue(name, out d) ? d : "";
}
public MainForm()
{
Text = "网络配置文件编辑器 (NetworkList Profiles)";
ClientSize = new Size(780, 520);
MinimumSize = new Size(640, 420);
StartPosition = FormStartPosition.CenterScreen;
try { Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath); } catch { }
var lbl = new Label { Text = "位置:", Location = new Point(10, 12), AutoSize = true };
_txtPath = new TextBox
{
Text = "HKEY_LOCAL_MACHINE\\" + BasePath,
ReadOnly = true,
Location = new Point(48, 9),
Size = new Size(660, 23),
Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right
};
_btnRead = new Button { Text = "读取", Location = new Point(48, 42), Size = new Size(80, 28) };
_btnSel = new Button { Text = "全选", Location = new Point(138, 42), Size = new Size(80, 28) };
_btnDel = new Button { Text = "删除", Location = new Point(228, 42), Size = new Size(80, 28) };
var h1 = new Label { Text = "网络列表(勾选后删除)", Location = new Point(10, 78), AutoSize = true };
var h2 = new Label
{
Text = "键值(双击数据列编辑,退出即写入;仅 配置文件名/描述 可改)",
Location = new Point(370, 78),
AutoSize = true
};
// ---------- 分隔容器: 左右可拖动 ----------
_split = new SplitContainer
{
Location = new Point(10, 96),
Size = new Size(760, 400),
SplitterWidth = 6,
Anchor = AnchorStyles.Top | AnchorStyles.Bottom
| AnchorStyles.Left | AnchorStyles.Right
};
_split.SplitterDistance = 350;
// ---------- 左侧表格(第一列为勾选框) ----------
_tblLeft = new DataGridView
{
Dock = DockStyle.Fill,
AllowUserToAddRows = false,
RowHeadersVisible = false,
MultiSelect = true,
SelectionMode = DataGridViewSelectionMode.FullRowSelect,
ReadOnly = false
};
_tblLeft.ColumnHeadersDefaultCellStyle.WrapMode = DataGridViewTriState.True;
_tblLeft.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
_tblLeft.ColumnHeadersHeight = 42;
var colChk = new DataGridViewCheckBoxColumn { Name = "check", HeaderText = "选", Width = 40 };
_tblLeft.Columns.Add(colChk);
_tblLeft.Columns.Add("ProfileName", "网络名称\n(ProfileName)");
_tblLeft.Columns.Add("Description", "描述\n(Description)");
_tblLeft.Columns.Add("Category", "类别\n(Category)");
_tblLeft.Columns.Add("NameType", "类型\n(NameType)");
_tblLeft.Columns.Add("GUID", "唯一标识\n(GUID)");
_tblLeft.Columns["ProfileName"].ReadOnly = true;
_tblLeft.Columns["Description"].ReadOnly = true;
_tblLeft.Columns["Category"].ReadOnly = true;
_tblLeft.Columns["NameType"].ReadOnly = true;
_tblLeft.Columns["GUID"].ReadOnly = true;
_tblLeft.SelectionChanged += delegate { if (!_loading) FillGrid(); };
_split.Panel1.Controls.Add(_tblLeft);
// ---------- 右侧键值网格(含说明列,固定行高) ----------
_grid = new DataGridView
{
Dock = DockStyle.Fill,
AllowUserToAddRows = false,
RowHeadersVisible = false,
EditMode = DataGridViewEditMode.EditProgrammatically
};
_grid.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
_grid.RowTemplate.Height = 46; // 固定两行高度,不自动撑高
_grid.ColumnHeadersDefaultCellStyle.WrapMode = DataGridViewTriState.True;
_grid.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
_grid.ColumnHeadersHeight = 40;
_grid.Columns.Add("名称", "名称\n(Name)");
_grid.Columns.Add("类型", "类型\n(Type)");
_grid.Columns.Add("数据", "数据\n(Data)");
_grid.Columns.Add("说明", "说明\n(Note)");
for (int i = 0; i < 4; i++) _grid.Columns[i].ReadOnly = true;
_grid.Columns[0].Width = 110;
_grid.Columns[1].Width = 120;
_grid.Columns[2].Width = 210;
_grid.Columns[3].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
_grid.CellDoubleClick += delegate (object s, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0 || e.ColumnIndex != 2) return;
string n = Convert.ToString(_grid.Rows[e.RowIndex].Tag);
if (n == "ProfileName" || n == "Description")
_grid.BeginEdit(true);
};
_grid.CellEndEdit += delegate (object s, DataGridViewCellEventArgs e) { CommitCell(e.RowIndex); };
_split.Panel2.Controls.Add(_grid);
_status = new Label
{
Location = new Point(10, 502),
Size = new Size(760, 23),
Text = "就绪",
Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right
};
_btnRead.Click += delegate { ReadProfiles(); };
_btnSel.Click += delegate { ToggleSelectAll(); };
_btnDel.Click += delegate { DeleteProfile(); };
Controls.AddRange(new Control[] { lbl, _txtPath, _btnRead, _btnSel, _btnDel, h1, h2,
_split, _status });
ReadProfiles();
}
// ================= 全选 / 全不选(作用于勾选框) =================
void ToggleSelectAll()
{
if (_tblLeft.Rows.Count == 0) return;
_loading = true;
bool val = !_selAll;
foreach (DataGridViewRow r in _tblLeft.Rows) r.Cells["check"].Value = val;
_selAll = val;
_btnSel.Text = _selAll ? "全不选" : "全选";
_loading = false;
}
static ProfileValue Find(List<ProfileValue> vals, string name)
{
foreach (ProfileValue v in vals) if (v.Name == name) return v;
return null;
}
// ================= 读取 =================
void ReadProfiles()
{
_loading = true;
_profiles.Clear(); _order.Clear(); _curGuid = null;
_tblLeft.Rows.Clear(); _grid.Rows.Clear();
_selAll = false; _btnSel.Text = "全选";
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(BasePath, false))
{
if (key == null) { MessageBox.Show("无法打开注册表键"); return; }
foreach (string guid in key.GetSubKeyNames())
{
var vals = new List<ProfileValue>();
using (RegistryKey sk = key.OpenSubKey(guid))
{
if (sk == null) continue;
foreach (string n in sk.GetValueNames())
vals.Add(new ProfileValue { Name = n, Kind = sk.GetValueKind(n), Data = sk.GetValue(n) });
}
_profiles[guid] = vals; _order.Add(guid);
ProfileValue pn = Find(vals, "ProfileName");
ProfileValue ds = Find(vals, "Description");
ProfileValue nt = Find(vals, "NameType");
ProfileValue ct = Find(vals, "Category");
_tblLeft.Rows.Add(false,
pn != null ? Convert.ToString(pn.Data) : guid,
ds != null ? Convert.ToString(ds.Data) : "",
ct != null ? NumDisp("Category", Convert.ToInt32(ct.Data)) : "",
nt != null ? NumDisp("NameType", Convert.ToInt32(nt.Data)) : "",
guid);
}
}
_loading = false;
_tblLeft.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
_status.Text = string.Format("已读取 {0} 项", _profiles.Count);
}
// ================= 左侧选中 -> 右侧键值 =================
void FillGrid()
{
if (_tblLeft.CurrentRow == null) return;
_grid.EndEdit();
_grid.Rows.Clear();
int i = _tblLeft.CurrentRow.Index;
if (i >= _order.Count) return;
_curGuid = _order[i];
foreach (ProfileValue v in _profiles[_curGuid])
{
string txt;
if (v.Kind == RegistryValueKind.DWord)
txt = NumDisp(v.Name, Convert.ToInt32(v.Data));
else if (v.Kind == RegistryValueKind.Binary)
txt = BinDisp(v.Name, (byte[])v.Data); // 日期类: 转换值(原始hex)
else
txt = Convert.ToString(v.Data);
bool editable = (v.Name == "ProfileName" || v.Name == "Description");
int r = _grid.Rows.Add(DispName(v.Name), TypeDisp(v.Kind), txt, GetDesc(v.Name));
_grid.Rows[r].Tag = v.Name;
_grid.Rows[r].Cells[2].ReadOnly = !editable;
}
AdjustGridColumns();
}
// ================= 右侧键值表格列宽自适应 =================
void AdjustGridColumns()
{
if (_grid.Columns.Count < 4) return;
// 先恢复为自动,让 AutoResizeColumns 能按内容测量
for (int c = 0; c < 4; c++)
_grid.Columns[c].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
_grid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.DisplayedCells);
// 名称、类型、说明: 内容自适应,但设上下限
ClampWidth(_grid.Columns[0], 100, 180); // 名称
ClampWidth(_grid.Columns[1], 110, 170); // 类型
ClampWidth(_grid.Columns[3], 120, 260); // 说明
// 数据列: 给足空间(日期类两行显示,hex 串较长)
_grid.Columns[2].Width = 240;
// 剩余宽度交给说明列填充,避免右侧留白
_grid.Columns[3].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
_grid.Columns[3].MinimumWidth = 120;
}
static void ClampWidth(DataGridViewColumn col, int min, int max)
{
if (col.Width < min) col.Width = min;
else if (col.Width > max) col.Width = max;
}
// ================= 编辑退出 -> 立即写注册表 =================
void CommitCell(int rowIndex)
{
if (_curGuid == null || rowIndex < 0) return;
string name = Convert.ToString(_grid.Rows[rowIndex].Tag);
if (name != "ProfileName" && name != "Description") return;
string val = Convert.ToString(_grid.Rows[rowIndex].Cells[2].Value) ?? "";
if (name == "ProfileName" && val.Trim().Length == 0)
{
_status.Text = "ProfileName 不能为空,已还原";
FillGrid(); return;
}
try
{
using (RegistryKey sk = Registry.LocalMachine.OpenSubKey(BasePath + "\\" + _curGuid, true))
{
if (sk == null) throw new Exception("无写入权限");
sk.SetValue(name, val, RegistryValueKind.String);
}
ProfileValue pv = Find(_profiles[_curGuid], name);
if (pv != null) pv.Data = val;
int row = _order.IndexOf(_curGuid);
if (row >= 0) _tblLeft.Rows[row].Cells[name].Value = val;
_status.Text = "已写入: " + name + " = " + val;
}
catch (Exception ex)
{
MessageBox.Show("写入失败:\n" + ex.Message);
FillGrid();
}
}
// ================= 删除(按勾选行,支持批量) =================
void DeleteProfile()
{
var guids = new List<string>();
var names = new StringBuilder();
int shown = 0;
foreach (DataGridViewRow row in _tblLeft.Rows)
{
object v = row.Cells["check"].Value;
if (!(v is bool) || !(bool)v) continue;
int i = row.Index;
if (i >= _order.Count) continue;
guids.Add(_order[i]);
if (shown < 8) { names.AppendLine(Convert.ToString(row.Cells["ProfileName"].Value)); shown++; }
}
if (guids.Count == 0) { MessageBox.Show("请先在左侧勾选要删除的行"); return; }
string tip = "确定删除 " + guids.Count + " 项?\n" + names + (guids.Count > 8 ? "..." : "");
if (MessageBox.Show(tip, "删除", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes) return;
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(BasePath, true))
{
if (key == null) { MessageBox.Show("无权限"); return; }
foreach (string g in guids) key.DeleteSubKey(g, false);
}
_status.Text = "已删除 " + guids.Count + " 项";
ReadProfiles();
}
}
static class Program
{
[STAThread]
static void Main()
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
bool admin = new WindowsPrincipal(id).IsInRole(WindowsBuiltInRole.Administrator);
if (!admin)
{
if (MessageBox.Show("需要管理员权限写入注册表。\n以管理员身份重新运行?", "权限",
MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
string exe = System.Reflection.Assembly.GetExecutingAssembly().Location;
try { System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(exe) { Verb = "runas", UseShellExecute = true }); }
catch { }
}
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
try { Application.Run(new MainForm()); }
catch (Exception ex) { MessageBox.Show(ex.ToString(), "启动失败"); }
}
}
} 




