netchx/netch · error · MessageException

Failed to copy wintun.dll to system directory: {e.Message}

Error message

Failed to copy wintun.dll to system directory: {e.Message}

What it means

Thrown by TUNController.CheckDriver when File.Copy(bin\wintun.dll -> %SystemRoot%\System32\wintun.dll, overwrite:true) raised an exception. The hashes differed (so a copy was needed) but the copy itself failed; e.Message is appended. This blocks TUN mode because tun_init needs the system-resident wintun.dll.

Source

Thrown at Netch/Controllers/TUNController.cs:152

            string binDriver = Path.Combine(Global.NetchDir, Constants.WintunDllFile);
            string sysDriver = $@"{Environment.SystemDirectory}\wintun.dll";

            var binHash = Utils.Utils.Sha256CheckSumAsync(binDriver).Result;
            var sysHash = Utils.Utils.Sha256CheckSumAsync(sysDriver).Result;
            Log.Information("Built-in  wintun.dll Hash: {Hash}", binHash);
            Log.Information("Installed wintun.dll Hash: {Hash}", sysHash);
            if (binHash == sysHash)
                return;

            try
            {
                Log.Information("Copy wintun.dll to System Directory");
                File.Copy(binDriver, sysDriver, true);
            }
            catch (Exception e)
            {
                Log.Error(e, "Copy wintun.dll failed");
                throw new MessageException($"Failed to copy wintun.dll to system directory: {e.Message}");
            }
        }

        #region Route

        private void SetupRouteTable()
        {
            Global.MainForm.StatusText(i18N.Translate("Setup Route Table Rule"));

            var tunNetworkInterface = NetworkInterfaceUtils.Get(_tun.InterfaceIndex);
            // Server Address
            if (_serverRemoteAddress != null)
                RouteUtils.CreateRoute(_outbound.FillTemplate(_serverRemoteAddress.ToString(), 32));

            // Global Bypass IPs
            RouteUtils.CreateRouteFill(_outbound, _tunConfig.BypassIPs);

            // rule

View on GitHub (pinned to 9d99eb1c5a)

Solutions

  1. Relaunch Netch as administrator.
  2. Close any other VPN/TUN client that may have wintun.dll loaded, then retry.
  3. Stop the current Netch TUN mode fully (StopAsync frees tun2socks which unloads wintun) before retrying Start.
  4. Add an antivirus/tamper-protection exclusion for the Netch directory and System32\wintun.dll.
  5. Manually copy bin\wintun.dll to %SystemRoot%\System32\wintun.dll from an elevated shell if the in-app copy keeps failing.
Defensive patterns

Strategy: try-catch

Validate before calling

// Only attempt the copy when elevated and the target isn't locked.
if (!HasAdminRights())
    throw new MessageException("Updating wintun.dll requires administrator privileges.");
string sys = $"{Environment.SystemDirectory}\\wintun.dll";
if (File.Exists(sys))
    try { File.OpenWrite(sys).Dispose(); } catch { /* locked */ throw new MessageException("wintun.dll is locked; stop TUN mode first."); }

Try / catch

try { /* TUNController.CheckDriver copy */ }
catch (MessageException ex) when (ex.Message.StartsWith("Failed to copy wintun.dll"))
{
    // ex.Message has the inner exception; most common fix is elevation or stopping other VPNs.
    SuggestRunAsAdminOrCloseOtherVPN(ex.Message);
}

Prevention

When it happens

Trigger: Netch not running elevated so it cannot write System32\wintun.dll; an existing wintun.dll is loaded/locked by a running TUN session or another VPN; antivirus blocks the write; disk full; Windows Resource Protection or Controlled Folder Access blocking System32 writes.

Common situations: User didn't run as admin; another app (WireGuard, another Netch instance, a VPN client) holds wintun.dll loaded; Defender tamper protection blocks it.

Related errors


AI-assisted analysis of netchx/netch@9d99eb1c5a (2026-08-13). Data as JSON: /api/errors/6579562036402d87. Report an issue: GitHub.