Tech feedback and support (技术支持) => 动态网中文技术支持区 => 主题发帖人为: TorHelper 于 九月 22, 2025, 11:58:52 上午

标题: TorHelper 发布
作者: TorHelper九月 22, 2025, 11:58:52 上午
https://torhelper.wordpress.com/
TorHelper 软件介绍
概述
在当今互联网环境中,隐私和安全性变得越来越重要。TorHelper 是一款专为保护用户在线隐私而设计的工具,旨在通过多种创新功能提升用户的匿名性和安全性。该软件结合了多条 Tor 链路的并行调度、代理穿越、随机网桥库的自动配置以及便携版 Chromium 浏览器的整合,为用户提供了一种高效、安全的上网体验。

主要特点
1. 多 Tor 链路并行调度
TorHelper 的一大亮点是其 多 Tor 链路并行调度 功能。传统的 Tor 网络通常依赖于单一链路进行数据传输,这可能导致速度缓慢和连接不稳定。TorHelper 通过并行调度多条 Tor 链路,显著提高了数据传输的速度和稳定性。用户可以在不同的链路之间快速切换,确保在任何情况下都能获得最佳的上网体验。

2. 支持代理穿越
在某些情况下,用户可能会面临网络限制或防火墙的阻碍。TorHelper 具备 代理穿越 功能,能够帮助用户绕过这些限制,顺利访问被封锁的网站和服务。无论是在学校、公司还是其他受限网络环境中,TorHelper 都能确保用户的自由上网。

3. 随机网桥库自动配置
为了进一步增强匿名性,TorHelper 提供了 随机网桥库自动配置 功能。用户可以选择不同的网桥,这些网桥会随机配置,以避免被检测和封锁。该功能不仅提高了连接的隐私性,还能有效防止网络监控和审查。用户无需手动配置网桥,软件会自动为其选择最佳的连接方式。

4. 整合便携 Chromium 浏览器
TorHelper 还整合了 便携版 Chromium 浏览器,使用户能够在不留下痕迹的情况下安全浏览网页。该浏览器经过特别优化,能够与 Tor 网络无缝连接,确保用户的所有在线活动都保持匿名。用户只需启动 TorHelper,即可自动打开便携版浏览器,享受安全、快速的上网体验。

使用场景
TorHelper 适用于多种场景,以下是一些典型的使用案例:

隐私保护:对于关注在线隐私的用户,TorHelper 提供了强大的匿名性,确保用户的身份和活动不被追踪。
访问受限内容:在某些国家或地区,特定网站和服务可能被封锁。TorHelper 使用户能够轻松访问这些受限内容,享受自由的互联网。
安全浏览:在公共 Wi-Fi 网络中,用户的在线活动容易受到攻击。使用 TorHelper,用户可以在不担心数据泄露的情况下安全浏览。
安装与配置
TorHelper 的安装过程简单直观。用户只需下载软件包,按照提示进行安装即可。安装完成后,用户可以根据自己的需求进行基本配置,包括选择链路、设置代理等。软件界面友好,适合各类用户,无论是技术专家还是普通用户,都能轻松上手。

未来发展
TorHelper 团队致力于不断优化和更新软件,以适应快速变化的网络环境。未来的版本将引入更多功能,如智能流量管理、用户行为分析等,以进一步提升用户体验和安全性。团队也欢迎用户的反馈和建议,以便更好地满足用户需求。

结论
TorHelper 是一款功能强大且易于使用的隐私保护工具,适合任何希望在互联网上保持匿名和安全的用户。通过多 Tor 链路并行调度、代理穿越、随机网桥库自动配置以及便携版 Chromium 浏览器的整合,TorHelper 为用户提供了一个全面的解决方案。无论是日常浏览、访问受限内容,还是保护个人隐私,TorHelper 都是您理想的选择。
标题: TorHelper 源代码
作者: torhelper九月 23, 2025, 03:04:30 上午
torhelper.exe 源码

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace Torhelper
{
    internal class Program
    {
        private static Dictionary<int, string> _processMap = new Dictionary<int, string>();
        private static List<string> torrclist = new List<string>();
        private static List<string> polipoconfiglist = new List<string>();
        private static List<string> awaitingDeletion = new List<string>();

        private static string iniconfigpath,
            proxyswitchpath,
            proxyswitchproxylistpath;

        private static string Torexepath, Torbridgedbpath, lyrebirdpath, webtunnelclientpath,
            Polipoexepath;

        private const int MF_BYCOMMAND = 0x00000000;
        private const int SC_CLOSE = 0xF060;
        private const int MF_GRAYED = 0x00000001;
        private static int deletetorcache = 0;

        [DllImport("user32.dll")]
        private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);

        [DllImport("user32.dll")]
        private static extern int EnableMenuItem(IntPtr hMenu, int uIDEnableItem, int uEnable);

        [DllImport("kernel32.dll")]
        private static extern IntPtr GetConsoleWindow();

        // 禁用 Ctrl+C 的 Win32 API
        [DllImport("kernel32.dll")]
        private static extern bool SetConsoleCtrlHandler(ConsoleCtrlHandler handler, bool add);

        // 定义控制台事件处理委托
        private delegate bool ConsoleCtrlHandler(CtrlType ctrlType);

        private enum CtrlType
        {
            CTRL_C_EVENT = 0,
            CTRL_BREAK_EVENT = 1,
            CTRL_CLOSE_EVENT = 2,
            CTRL_LOGOFF_EVENT = 5,
            CTRL_SHUTDOWN_EVENT = 6,
        }

        private static string proxytype = "https",
            proxyaddress = "127.0.0.1:8580";

        private static int torcount = 5,
            starttorport = 9050,
            startpolipoport = 8118;

        private static readonly string[] torrcpublic =
        {
            "SocksListenAddress 127.0.0.1",
            //"ExcludeNodes {cn},{hk},{sg},{pk},{th},{mo}",
            "ExcludeNodes {cn}",
            "ReachableDirAddresses *:80",
            "ReachableDirAddresses *:443",
            "ReachableORAddresses *:443",
            "ReachableORAddresses *:80",
            "ReachableORAddresses *:22",
            "ReachableORAddresses *:8443",
            "ReachableORAddresses *:3389",
            "ReachableORAddresses *:1080",
            "ReachableORAddresses *:445",
            "ReachableORAddresses *:3128",
            "ReachableORAddresses *:8080"
        };

        private static readonly string[] polipoconfigpublic =
        {
            "proxyAddress = \"127.0.0.1\"",
            "allowedClients = 127.0.0.1",
            "allowedPorts = 1-65535",
            "proxyName = \"localhost\"",
            "cacheIsShared = false",
            "socksProxyType = socks5",
            "chunkHighMark = 33554432",
            "diskCacheRoot = \"\"",
            "localDocumentRoot = \"\"",
            "disableLocalInterface = true",
            "disableConfiguration = true",
            "dnsUseGethostbyname = yes",
            "disableVia = true",
            "censoredHeaders = from,accept-language,x-pad,link",
            "censorReferer = maybe",
            "maxConnectionAge = 5m",
            "maxConnectionRequests = 120",
            "serverMaxSlots = 8",
            "serverSlots = 2",
            "tunnelAllowedPorts = 1-65535",
        };

        private static void Main()
        {
            IntPtr handle = GetConsoleWindow();
            if (handle != IntPtr.Zero)
            {
                IntPtr sysMenu = GetSystemMenu(handle, false);
                EnableMenuItem(sysMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
            }

            RegistryKey tweakMarketingKey = Registry.CurrentUser.CreateSubKey(
                @"Software\Tweak Marketing"
            );
            RegistryKey proxySwitchKey = tweakMarketingKey.CreateSubKey("Proxy Switch");
            RegistryKey registrationKey = proxySwitchKey.CreateSubKey("Registration");
            proxySwitchKey.SetValue("NumProxyErrors", 0001869f, RegistryValueKind.DWord);
            /*
            proxySwitchKey.SetValue("FileHash", "201622", RegistryValueKind.String);
            proxySwitchKey.SetValue("ListenPort", 0x00000c38, RegistryValueKind.DWord);
            proxySwitchKey.SetValue("Timeout", 0x00000002, RegistryValueKind.DWord);
            proxySwitchKey.SetValue("NumProxyErrors", 0x0000000a, RegistryValueKind.DWord);
            proxySwitchKey.SetValue("SavingPeriod", 0x00000003, RegistryValueKind.DWord);
            proxySwitchKey.SetValue("SocketBufSize", 0x00000002, RegistryValueKind.DWord);
            proxySwitchKey.SetValue("Switch", 0x00000000, RegistryValueKind.DWord);
            proxySwitchKey.SetValue("SwitchConnectionsValue", 0x00000005, RegistryValueKind.DWord);
            proxySwitchKey.SetValue("SwitchEverySecondsValue", 0x0000001e, RegistryValueKind.DWord);
            proxySwitchKey.SetValue("SwitchSecondsValue", 0x0000001e, RegistryValueKind.DWord);
            proxySwitchKey.SetValue("SwitchKBytesValue", 0x00000064, RegistryValueKind.DWord);
            proxySwitchKey.SetValue("BindRadio", 0x00000001, RegistryValueKind.DWord);
            proxySwitchKey.SetValue("BindInterface0", "127.0.0.1", RegistryValueKind.String);
            proxySwitchKey.SetValue("BindInterface1", "192.168.1.49", RegistryValueKind.String);
            proxySwitchKey.SetValue("IpMask0", "y127.0.0.1", RegistryValueKind.String);
            proxySwitchKey.SetValue("IpMask1", "y10.*.*.*", RegistryValueKind.String);
            proxySwitchKey.SetValue("IpMask2", "y172.16.0.0/12", RegistryValueKind.String);
            proxySwitchKey.SetValue("IpMask3", "y192.168.*.*", RegistryValueKind.String);
            proxySwitchKey.SetValue("FileOpenReplace", 0x00000000, RegistryValueKind.DWord);
            proxySwitchKey.SetValue("FileOpenNoDups", 0x00000000, RegistryValueKind.DWord);
            registrationKey.SetValue("Code", "KPS-82WLP-GKTF7MZ3CX", RegistryValueKind.String);

            // 关闭键
            registrationKey.Close();
            proxySwitchKey.Close();
            tweakMarketingKey.Close();
            */
            //注册 proxy switch
            string registryPath = @"Software\Tweak Marketing\Proxy Switch\Registration";
            string keyName = "Code";
            string keyValue = "KPS-82WLP-GKTF7MZ3CX";

            try
            {
                RegistryKey registryKey = Registry.CurrentUser.CreateSubKey(registryPath);

                registryKey.SetValue(keyName, keyValue);

                registryKey.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine("注册ProxySwitch时出错: " + ex.Message);
            }

            string currentDirectory = Directory.GetCurrentDirectory();
            // Data 目录用于存储tor 和 polipo的配置和Tor数据目录
            string dataDirectory = Path.Combine(currentDirectory, "Data");
            string chromecacheDirectory = Path.Combine(currentDirectory, "Cache");
            if (!Directory.Exists(chromecacheDirectory))
            {
                Directory.CreateDirectory(chromecacheDirectory);
            }
            string chromebindir = Path.Combine(currentDirectory, "App", "chrome-win");
            string chromebinpath = Path.Combine(
                currentDirectory,
                "App",
                "chrome-win",
                "chrome.exe"
            );
            if (!Directory.Exists(dataDirectory))
            {
                Directory.CreateDirectory(dataDirectory);
            }
            Torexepath = Path.Combine(currentDirectory, "App", "tor.exe");
            lyrebirdpath= Path.Combine(currentDirectory, "App", "Pluggable_Transports", "lyrebird.exe");
            webtunnelclientpath = Path.Combine(currentDirectory, "App", "Pluggable_Transports", "webtunnel-client.exe");
            Torbridgedbpath = Path.Combine(currentDirectory, "App", "bridges.txt");
            Polipoexepath = Path.Combine(currentDirectory, "App", "polipo.exe");
            string geiopath = Path.Combine(currentDirectory, "App", "geoip.txt");
            string geio6path = Path.Combine(currentDirectory, "App", "geoip6.txt");
            iniconfigpath = Path.Combine(currentDirectory, "config.ini");
            proxyswitchpath = Path.Combine(
                currentDirectory,
                "App",
                "Proxy Switch",
                "ProxySwitch.exe"
            );
            proxyswitchproxylistpath = Path.Combine(
                currentDirectory,
                "App",
                "Proxy Switch",
                "Proxies.psl"
            );
            //读取用户配置
            IniFiles myconf = new IniFiles(iniconfigpath);
            if (!File.Exists(iniconfigpath))
            {
                myconf.IniWriteValue("config", "proxytype", proxytype);
                myconf.IniWriteValue("config", "proxyaddress", proxyaddress);
                myconf.IniWriteValue("config", "torcount", torcount.ToString());
                myconf.IniWriteValue("config", "starttorport", starttorport.ToString());
                myconf.IniWriteValue("config", "startpolipoport", startpolipoport.ToString());
                myconf.IniWriteValue("config", "deletetorcache", deletetorcache.ToString());
            }
            else
            {
                proxytype = myconf.IniReadValue("config", "proxytype");
                proxyaddress = myconf.IniReadValue("config", "proxyaddress");
                torcount = Convert.ToInt32(myconf.IniReadValue("config", "torcount"));
                starttorport = Convert.ToInt32(myconf.IniReadValue("config", "starttorport"));
                startpolipoport = Convert.ToInt32(myconf.IniReadValue("config", "startpolipoport"));
                deletetorcache = Convert.ToInt32(myconf.IniReadValue("config", "deletetorcache"));
            }
            //检测配置文件中所有要使用到的端口是否被其它进程占用 如果是则要先结束占用端口的进程 0329 应该放到读取ini代码之后
            List<int> ourportlist = new List<int>();
            for (int index = 0; index < torcount; index++)
            {
                ourportlist.Add(starttorport + index);
                ourportlist.Add(startpolipoport + index);
            }
            ourportlist.Add(3128);
            foreach (int port in ourportlist)
            {
                if (IsPortInUse(port))
                {
                    int pid = GetProcessIdUsingPort(port);
                    if (pid != -1)
                    {
                        Console.WriteLine($"检测到占用设置端口的进程ID: {pid} 准备强行结束对应进程释放");
                        KillProcessById(pid);
                    }
                    else
                    {
                        //Console.WriteLine($"Torhelper中配置的端口{port}没有被占用");
                    }
                }
            }
            //写入 Proxies.psl
            if (File.Exists(proxyswitchproxylistpath))
            {
                File.Delete(proxyswitchproxylistpath);
            }
            string[] switchlist = new string[torcount];
            for (int i = startpolipoport; i < startpolipoport + torcount; i++)
            {
                string temp = "127.0.0.1:" + i.ToString() + ";0;0;1";
                switchlist[i - startpolipoport] = temp;
            }
            using (StreamWriter writer = new StreamWriter(proxyswitchproxylistpath, true)) // true 表示追加写入
            {
                foreach (string line in switchlist)
                {
                    writer.WriteLine(line);
                }
            }

            // 自动写 tor 和 polipo 配置文件模块

            for (int i = 0; i < torcount; i++)
            {
                var tordata = Path.Combine(dataDirectory, "Tor_" + i.ToString().PadLeft(2, '0'));
                var polipodata = Path.Combine(
                    dataDirectory,
                    "Polipo_" + i.ToString().PadLeft(2, '0')
                );
                awaitingDeletion.Add(tordata);
                awaitingDeletion.Add(polipodata);
                if (!Directory.Exists(tordata))
                {
                    Directory.CreateDirectory(tordata);
                }
                if (!Directory.Exists(polipodata))
                {
                    Directory.CreateDirectory(polipodata);
                }
                var torrcpath = Path.Combine(tordata, "torrc.txt");

                var polipopath = Path.Combine(polipodata, "polipo.conf");
                torrclist.Add(torrcpath);
                polipoconfiglist.Add(polipopath);

                List<string> torrctemp = torrcpublic.ToList();
                torrctemp.Add("DataDirectory " + tordata);
                torrctemp.Add("SocksPort " + (i + starttorport).ToString());
                torrctemp.Add("GeoIPFile " + geiopath);
                torrctemp.Add("GeoIPv6File " + geio6path);
                if (File.Exists(Torbridgedbpath))
                {
                    torrctemp.Add("UseBridges 1");
                    string[] bridgetemp = GetRandomLines(Torbridgedbpath, 12);//从App下bridges.txt 随机抽取10行网桥
                    foreach (string bridge in bridgetemp)
                    {
                        torrctemp.Add("Bridge " + bridge);
                    }
                    torrctemp.Add("ClientTransportPlugin obfs4 exec "+lyrebirdpath);
                    torrctemp.Add("ClientTransportPlugin webtunnel exec " + webtunnelclientpath);
                }
                else//如果不存在 bridge.txt 则根据ini的用户设定配置前置代理
                {
                    if (proxytype == "socks")
                    {
                        torrctemp.Add("Socks5Proxy " + proxyaddress);
                    }
                    else if (proxytype == "https")
                    {
                        torrctemp.Add("HttpProxy " + proxyaddress);
                        torrctemp.Add("HttpsProxy " + proxyaddress);
                    }
                }

                using (StreamWriter writer = new StreamWriter(torrcpath, true))
                {
                    foreach (string line in torrctemp)
                    {
                        writer.WriteLine(line);
                    }
                }
                StartTor(Torexepath, torrcpath);
                List<string> polipocfgtemp = polipoconfigpublic.ToList();
                polipocfgtemp.Add("proxyPort = " + (i + startpolipoport));
                polipocfgtemp.Add("socksParentProxy = 127.0.0.1:" + (i + starttorport));
                using (StreamWriter writer = new StreamWriter(polipopath, true))
                {
                    foreach (string line in polipocfgtemp)
                    {
                        writer.WriteLine(line);
                    }
                }

                StartPolipo(Polipoexepath, polipopath);
            }
            //启动 proxy switch
            if (File.Exists(proxyswitchpath))
            {
                try
                {
                    ProcessStartInfo startInfo = new ProcessStartInfo
                    {
                        FileName = proxyswitchpath,
                        WorkingDirectory = currentDirectory,
                        UseShellExecute = true,
                        CreateNoWindow = false,
                    };

                    Process process = Process.Start(startInfo);

                    _processMap.Add(process.Id, proxyswitchpath);
                    Console.WriteLine(
                        "ProxySwitch 代理调度机制已成功启动 请将浏览器和下载工具代理设置为 127.0.0.1:3128 使用"
                    );
                }
                catch (Exception ex)
                {
                    Console.WriteLine("启动 proxyProxySwitchswitch 时出错: " + ex.Message);
                }
            }
            else
            {
                Console.WriteLine("ProxySwitch.exe 不存在");
            }
            if (File.Exists(chromebinpath))
            {
                try
                {
                    ProcessStartInfo startInfo = new ProcessStartInfo
                    {
                        FileName = chromebinpath,
                        WorkingDirectory = chromebindir,
                        UseShellExecute = true,
                        CreateNoWindow = false,

                        Arguments =
                            $"--user-data-dir=\"{chromecacheDirectory}\" --no-default-browser-check --disable-logging --disable-breakpad --proxy-server=127.0.0.1:3128 --disk-cache-size=1 --disable-client-side-phishing-detection --disable-component-extensions-with-background-pages --disable-default-apps --disable-features=InterestFeedContentSuggestions --disable-features=Translate --no-first-run --disable-background-timer-throttling --disable-backgrounding-occluded-windows --disable-ipc-flooding-protection --disable-renderer-backgrounding --use-fake-device-for-media-stream --disable-external-intent-requests", //故意把disk-cache-size设置为1强制chrome缓存走内存 提升速度
                        WindowStyle = ProcessWindowStyle.Maximized,
                    };
                    using (var process = new Process { StartInfo = startInfo })
                    {
                        process.Start();
                        _processMap.Add(process.Id, proxyswitchpath);
                        Console.WriteLine("Chrome 浏览器已启动 可以安全畅游");
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("启动 Chrome 时出错: " + ex.Message);
                }
            }
            else
            {
                Console.WriteLine("Chrome.exe 不存在");
            }
            SetConsoleCtrlHandler(ConsoleCtrlHandler2, true);

            Console.WriteLine("输入 'exit' 退出程序...");

            while (true)
            {
                string input = Console.ReadLine();
                if (input != null && input.ToLower() == "exit")
                {
                    break;
                }
                else
                {
                    Console.WriteLine("无效输入,请输入 'exit' 退出程序。");
                }
            }

            Cleanup();
        }

        private static string[] GetRandomLines(string filePath, int numberOfLines)//20250328
        {
            string[] allLines = File.ReadAllLines(filePath);

            int availableLines = Math.Min(allLines.Length, numberOfLines);
            Random rnd = new Random();
            HashSet<int> selectedIndices = new HashSet<int>();

            while (selectedIndices.Count < availableLines)
            {
                int randomIndex = rnd.Next(0, allLines.Length);
                selectedIndices.Add(randomIndex);
            }

            string[] randomLines = new string[availableLines];
            int i = 0;
            foreach (int index in selectedIndices)
            {
                randomLines[i++] = allLines[index];
            }
            return randomLines;
        }

        private static void StartTor(string torpath, string configPath)
        {
            try
            {
                var process = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = torpath,
                        Arguments = string.Format("-f \"{0}\"", configPath),
                        UseShellExecute = false,
                        CreateNoWindow = true,
                    },
                };
                if (process.Start())
                {
                    _processMap.Add(process.Id, configPath);
                    Console.WriteLine("Tor 已启动进程 {0} : {1}", process.Id, configPath);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Tor 启动失败: {0}", ex.Message);
            }
        }

        private static void StartPolipo(string Polipopath, string configPath)
        {
            try
            {
                var process = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = Polipopath,
                        Arguments = string.Format("-c \"{0}\"", configPath),
                        UseShellExecute = false,
                        CreateNoWindow = true,
                    },
                };
                if (process.Start())
                {
                    _processMap.Add(process.Id, configPath);
                    Console.WriteLine("Polipo 已启动进程 {0} : {1}", process.Id, configPath);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Polipo 启动失败: {0}", ex.Message);
            }
        }

        private static bool ConsoleCtrlHandler2(CtrlType ctrlType)
        {
            if (
                ctrlType == CtrlType.CTRL_CLOSE_EVENT
                || ctrlType == CtrlType.CTRL_C_EVENT
                || ctrlType == CtrlType.CTRL_SHUTDOWN_EVENT
                || ctrlType == CtrlType.CTRL_BREAK_EVENT
                || ctrlType == CtrlType.CTRL_LOGOFF_EVENT
            )
            {
                Console.WriteLine("检测到软件被强行关闭或者退出 开始启动清理机制");
                Cleanup();
            }
            return false;
        }

        private static bool IsPortInUse(int port)
        {
            IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
            TcpConnectionInformation[] tcpConnInfoArray =
                ipGlobalProperties.GetActiveTcpConnections();

            return tcpConnInfoArray.Any(conn => conn.LocalEndPoint.Port == port);
        }

        private static int GetProcessIdUsingPort(int port)
        {
            var query = $"SELECT * FROM Win32_TCPIPPrinterPort WHERE PortNumber = {port}";
            using (var searcher = new ManagementObjectSearcher(query))
            {
                foreach (ManagementObject obj in searcher.Get())
                {
                    var pid = Convert.ToInt32(obj["ProcessID"]);
                    return pid;
                }
            }
            return -1;
        }

        private static void KillProcessById(int pid)
        {
            try
            {
                Process process = Process.GetProcessById(pid);
                Console.WriteLine(
                    $"正在结束占用端口的进程: {process.ProcessName} (PID: {pid}) "
                        + process.MainModule.ModuleName
                );
                process.Kill();
                process.WaitForExit();
                Console.WriteLine("进程已结束。");
            }
            catch (ArgumentException ex)
            {
                Console.WriteLine($"无法找到进程ID为 {pid} 的进程: {ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"结束进程时出错: {ex.Message}");
            }
        }

        private static void Cleanup()
        {
            foreach (var pid in new List<int>(_processMap.Keys))
            {
                try
                {
                    using (var process = Process.GetProcessById(pid))
                    {
                        if (
                            IsTargetProcess(process, _processMap[pid])
                            || process.MainModule.ModuleName.Contains("ProxySwitch.exe")
                        ) //|| process.MainModule.ModuleName.Contains("chrome")
                        {
                            KillProcessTree(pid);
                            Console.WriteLine("已终止进程 {0}", pid);
                        }
                    }
                }
                catch (ArgumentException)
                { /* 进程已退出 */
                }
                catch (Exception ex)
                {
                    Console.WriteLine("终止失败: {0}", ex.Message);
                }
            }
            foreach (var file in torrclist)
            {
                if (File.Exists(file))
                {
                    File.Delete(file);
                }
            }

            foreach (var file in polipoconfiglist)
            {
                if (File.Exists(file))
                {
                    File.Delete(file);
                }
            }
            if (deletetorcache == 1)
            {
                foreach (string dir in awaitingDeletion)
                {
                    if (Directory.Exists(dir))
                    {
                        Directory.Delete(dir, true);
                    }
                }
            }
        }

        private static bool IsTargetProcess(Process process, string expectedConfig)
        {
            try
            {
                var cmdLine = GetCommandLineWmi(process.Id);
                return cmdLine.Contains(string.Format("-c \"{0}\"", expectedConfig))
                    || cmdLine.Contains(string.Format("-f \"{0}\"", expectedConfig));
            }
            catch
            {
                return false;
            }
        }

        private static string GetCommandLineWmi(int processId)
        {
            using (
                var searcher = new ManagementObjectSearcher(
                    string.Format(
                        "SELECT CommandLine FROM Win32_Process WHERE ProcessId = {0}",
                        processId
                    )
                )
            )
            {
                foreach (ManagementObject mo in searcher.Get())
                {
                    if (mo["CommandLine"] != null) // 手动检查是否为 null
                    {
                        return mo["CommandLine"].ToString();
                    }
                    return ""; // 如果为 null,返回空字符串
                }
            }
            return "";
        }

        private static void KillProcessTree(int pid)
        {
            try
            {
                var searcher = new ManagementObjectSearcher(
                    string.Format(
                        "SELECT ProcessId FROM Win32_Process WHERE ParentProcessId={0}",
                        pid
                    )
                );
                foreach (ManagementObject mo in searcher.Get())
                {
                    int childPid = Convert.ToInt32(mo["ProcessId"]);
                    KillProcessTree(childPid);
                }

                using (var process = Process.GetProcessById(pid))
                {
                    if (!process.HasExited)
                    {
                        process.Kill();
                        process.WaitForExit(5000);
                    }
                }
            }
            catch
            { /* 忽略所有异常 */
            }
        }
    }
}

ini文件读取配置部分源码

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;

public class IniFiles
{
    public string inipath;

    [DllImport("Kernel32.dll")]
    private static extern int GetPrivateProfileString(string strAppName, string strKeyName, string strDefault, StringBuilder sbReturnString, int nSize, string strFileName);

    [DllImport("Kernel32.dll")]
    private extern static int GetPrivateProfileStringA(string strAppName, string strKeyName, string sDefault, byte[] buffer, int nSize, string strFileName);

    [DllImport("Kernel32.dll")]
    private static extern int GetPrivateProfileInt(string strAppName, string strKeyName, int nDefault, string strFileName);

    [DllImport("Kernel32.dll")]
    private extern static int GetPrivateProfileSectionNamesA(byte[] buffer, int iLen, string fileName);

    [DllImport("Kernel32.dll")]
    private static extern int GetPrivateProfileSection(string lpAppName, byte[] lpReturnedString, int nSize, string lpFileName);

    [DllImport("Kernel32.dll")]
    public static extern long WritePrivateProfileString(string strAppName, string strKeyName, string strKeyValue, string strFileName);

    [DllImport("Kernel32.dll")]
    public static extern long WritePrivateProfileSection(string strAppName, string strkeyandvalue, string strFileName);

    public IniFiles(string INIPath)
    {
        inipath = INIPath;
    }

    public IniFiles() { }

    public void IniWriteValue(string Section, string Key, string Value)
    {
        WritePrivateProfileString(Section, Key, Value, this.inipath);
    }

    public string IniReadValue(string Section, string Key)
    {
        StringBuilder temp = new StringBuilder(500);
        int i = GetPrivateProfileString(Section, Key, "", temp, 500, this.inipath);
        return temp.ToString();
    }

    public bool ExistINIFile()
    {
        return File.Exists(inipath);
    }

    public ArrayList ReadSections()
    {
        int bufferSize = 1024;
        byte[] buffer = new byte[bufferSize];
        int rel = GetPrivateProfileSectionNamesA(buffer, buffer.Length, this.inipath);

        if (rel > buffer.Length)
        {
            bufferSize = rel;
            buffer = new byte[bufferSize];
            rel = GetPrivateProfileSectionNamesA(buffer, buffer.Length, this.inipath);
        }

        int iCnt, iPos;
        ArrayList arrayList = new ArrayList();
        string tmp;

        if (rel > 0)
        {
            iCnt = 0;
            iPos = 0;

            for (iCnt = 0; iCnt < rel; iCnt++)
            {
                if (buffer[iCnt] == 0x00)
                {
                    tmp = Encoding.ASCII.GetString(buffer, iPos, iCnt - iPos).Trim();
                    iPos = iCnt + 1;
                    if (tmp != "")
                        arrayList.Add(tmp);
                }
            }
        }
        return arrayList;
    }
}
标题: 回复: TorHelper 发布
作者: torhelper九月 24, 2025, 06:01:52 上午
版主您好,wordpress的博客被莫名其妙封杀了,文件下载地址是https://www.mediafire.com/file/kyli5t4a21qngo8/TorHelper20250922.7z/file
如果方便,版主可以审核源码和压缩包后能否在动态网发布。
bridges.txt 里面可以修改成自己搜集的网桥库,即可实现自动调度实现高速冲浪。
标题: orHelper 网桥库更新方法
作者: torhelper十月 04, 2025, 06:21:17 下午
用户可以把自己在https://bridges.torproject.org/options 收集的网桥库替换 APP 目录下的bridges.txt,一行一个,多多益善。

当bridges.txt这个文件存在的时候,torhelper只会强制穿随机摄取的网桥,如果这个文件不存在,proxytype为https或者socks的时候,tor强制走前置代理。如果proxytype为https或者socks之外的任意字符并且bridges.txt不存在,Tor就是直连模式。