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(), "启动失败"); }
        }
    }
}

标签: none

添加新评论