PAYATHON 2026

Selenium C# WPF 程序的 release 版本为何在重命名或移动后报错?

排障赵师傅

遇到这类错误,先检查部署文件是否完整,以及重命名后配置文件是否仍与程序匹配。只复制 Release 目录中的 .exe,通常无法运行依赖 Selenium 的 WPF 程序。在开发项目中安装了 NuGet 包,也不代表目标文件夹或另一台计算机上已经有了运行所需的依赖。

目前还缺少项目的目标框架和实际复制的文件清单,无法确定具体原因。原输出目录可以运行,移动后却找不到 WebDriver,应优先检查部署时是否漏了文件;重命名后出现 System.Text.Json 版本错误,则要检查配置文件,尤其是 .NET Framework 的绑定重定向。

为什么安装了 NuGet 包,运行时仍然找不到程序集?

NuGet 包版本和程序集版本是两个概念。例如,项目安装的包是:

Selenium.WebDriver 4.31.0

异常中的程序集标识却可能是:

WebDriver, Version=4.0.0.0, Culture=neutral, PublicKeyToken=null

这不表示程序正在寻找 Selenium.WebDriver 4.0.0 这个 NuGet 包。包名、包版本和 DLL 内部的程序集标识不必相同,不能仅凭这条异常决定降级哪个包。

System.Text.Json 也一样。异常中的 Version=8.0.0.0 是程序集版本。安装 System.Text.Json 9.0.4 后能否满足该引用,取决于目标框架、实际部署的 DLL,以及运行时的版本解析规则。

错误中的:

or one of its dependencies

表示缺少的也可能是该程序集依赖的其他文件。因此,即使目标目录中有 WebDriver.dll,也要检查它的依赖是否齐全。

为什么在 bin 目录运行正常,移动后就失败?

构建输出通常包括主程序、依赖 DLL、配置文件和其他运行所需的文件。程序在原目录中能找到这些文件,只移动 .exe 时,它们不会自动跟过去。

.NET Framework 程序的输出目录可能类似:

MyApp.exe
MyApp.exe.config
WebDriver.dll
WebDriver.Support.dll
System.Text.Json.dll
其他依赖文件……

具体文件以项目的实际构建结果为准,不要只按这份示例挑选几个 DLL。

现代 .NET 的 WPF 项目还可能包含:

MyApp.exe
MyApp.dll
MyApp.deps.json
MyApp.runtimeconfig.json
其他依赖文件……

其中,.exe 可能只是启动宿主,主程序代码在对应的 .dll 中。因此,不能把默认构建出的 .exe 直接当作可独立运行的文件。

先复制完整目录,确认是不是漏文件

  1. 清理并重新生成 Release。
  2. 将实际输出目录中的全部文件和子目录复制到一个空文件夹。
  3. 保持文件名和目录结构不变,从新文件夹启动程序。

如果完整复制后可以运行,就需要修正打包或复制流程。如果仍然失败,再检查:

  • 目标目录中的 WebDriver.dll 等文件是否来自本次构建。
  • 是否有手工添加的 DLL 引用未随构建输出复制。
  • 是否存在硬编码的开发机路径。
  • 程序是否误以为相对路径总是以程序所在目录为起点。
  • 新目录中是否混入了旧版本的 DLL 或配置文件。

使用传统程序集引用的项目,可以检查引用属性中的 Copy Local 是否为 True。使用 PackageReference 的项目,应检查还原、构建和发布结果,不要靠手工复制少数 DLL 来替代正常部署。

重命名为什么可能引发 System.Text.Json 版本错误?

.NET Framework:检查 exe.config 是否仍然匹配

.NET Framework 应用的配置文件通常随可执行文件命名:

MyApp.exe
MyApp.exe.config

如果只将程序改成:

RenamedApp.exe

却保留:

MyApp.exe.config

运行时通常就不会把原配置文件作为新程序的应用配置,其中的程序集绑定重定向也可能随之失效。

如果程序此前依靠绑定重定向,将旧的 System.Text.Json 引用解析到已部署的版本,重命名后就可能因此出现版本加载错误。需要查看实际生成的配置文件,才能确认是否属于这种情况。

对于支持自动绑定重定向的 .NET Framework 桌面项目,可以在 .csproj 中检查或启用:

<PropertyGroup>
  <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
  <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>

重新构建后,确认输出的 MyApp.exe.config 中包含所需的重定向,并将它一起部署。检查时要看构建输出中的配置文件,不能只看源代码目录中的 App.config。

bindingRedirect 需要按实际情况配置,不要直接照抄。其中的 newVersion 应对应实际 DLL 的程序集版本,同时还要确认相关依赖兼容。

现代 .NET:通过项目配置修改名称

现代 .NET 的依赖解析机制不同,不能套用 .NET Framework 的绑定重定向方案。

需要更改程序名称时,建议先修改项目的程序集名称,再重新构建或发布:

<PropertyGroup>
  <AssemblyName>RenamedApp</AssemblyName>
</PropertyGroup>

随后部署重新生成的整套文件,不要靠批量重命名 .dll、.deps.json 等文件来猜测运行时需要的名称。

根据目标框架选择发布方式

打开 .csproj,查看 TargetFramework 或 TargetFrameworkVersion,再选择相应的处理方法。

.NET Framework 项目

部署完整构建输出,或使用适合该项目的安装、发布方式,同时确认目标计算机已安装应用要求的 .NET Framework。

检查以下内容:

  • 所有运行时依赖是否已经输出。
  • 应用名.exe.config 是否存在且名称匹配。
  • 绑定重定向是否指向实际部署的程序集。
  • 程序是否依赖开发机上的绝对路径。

现代 .NET 的 --self-contained 发布选项不适用于传统 .NET Framework 项目。

现代 .NET WPF 项目

优先部署发布目录。面向 Windows x64 的现代 .NET WPF 项目可以使用:

dotnet publish .\MyApp.csproj -c Release -r win-x64 --self-contained true -o .\publish

将 MyApp.csproj 替换为实际项目文件,并根据目标计算机选择运行时标识。发布后,复制整个 publish 目录,保留子目录结构。

--self-contained true 会随应用部署所需的 .NET 运行时,但不会自动把应用、浏览器和所有外部资源合并成一个文件。单文件发布需要另外配置,建议先确认普通发布的程序可以移动到其他目录运行,再考虑单文件发布。

不要靠降级到有漏洞的版本解决加载问题

安装较早的 System.Text.Json 后能够运行,只能说明这次依赖组合满足了当时的加载要求,不能据此认定旧版本适合长期使用。

先查清以下问题:

  1. 哪个直接或间接依赖引用了 System.Text.Json。
  2. 输出目录实际包含哪个版本的 DLL。
  3. 是否存在旧构建文件或失效的绑定重定向。
  4. 当前目标框架是否支持准备使用的包版本。

确认后,再选择与目标框架兼容、且已修复相关漏洞的依赖组合。仅凭 Version=8.0.0.0 这段程序集标识,无法判断某个 NuGet 补丁版本是否存在漏洞,应以具体包版本对应的漏洞提示为准。

代码中应先保留完整异常信息

目前的代码只显示 ex.Message,会丢失堆栈和内部异常。排查时可以暂时改成:

catch (Exception ex)
{
    MessageBox.Show(
        ex.ToString(),
        "启动失败",
        MessageBoxButton.OK,
        MessageBoxImage.Error);

    result = string.Empty;
}

也可以查看程序目录和当前工作目录:

string appDirectory = AppContext.BaseDirectory;
string workingDirectory = System.IO.Directory.GetCurrentDirectory();

两者不一定相同。读取随程序部署的文件时,可以使用:

string filePath = System.IO.Path.Combine(
    AppContext.BaseDirectory,
    "settings.json");

这段代码只用于修正应用自身的文件路径,不能代替 DLL 部署。排查当前错误也不需要改写网页操作逻辑。

如果 .NET Framework 项目在完整复制后仍然加载失败,可以使用 Fuslogvw.exe 查看程序集绑定日志,确认运行时尝试加载的版本和搜索位置。

还要区分 WebDriver.dll 与 chromedriver.exe、msedgedriver.exe、geckodriver.exe:前者是 Selenium 的 .NET 程序集,后者是浏览器驱动进程。当前的 Could not load file or assembly 'WebDriver...' 应先按程序集部署问题处理。程序集成功加载后,再排查浏览器驱动启动、浏览器安装和 Selenium Manager 所需文件等问题。

备注:内容仅供参考。