You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET环境下Selenium部署生产环境后Chrome进程无法启动

ASP.NET Web API部署后Selenium无法启动Chrome进程的解决方法

问题描述

本地运行ASP.NET Web API中使用Selenium WebDriver的代码正常,但部署到生产环境后提示无法创建Chrome进程。已将对应版本的WebDriver.exe部署至wwwroot,也尝试过更新Selenium、复制chrome.exe到wwwroot并指定二进制路径,但问题仍未解决。

相关代码

ChromeOptions options = new ChromeOptions();
           
options.AddArgument("--no-sandbox");
options.AddArgument("--headless");
options.AddArgument("--ignore-ssl-errors=true");
options.AddArgument("--ignore-certificate-errors");
options.AddArgument("--window-size=1920x1080");
options.AddArgument("--disable-gpu");
options.AddUserProfilePreference("download.default_directory", "Downloads");
options.AddUserProfilePreference("download.prompt_for_download", false);
options.AddUserProfilePreference("safebrowsing.enabled", false);
 
string chromeDriverPath = @"C:\Users\Gentrit\source\repos\Azon\Azon\bin\Debug\net8.0";

using (var driver = new ChromeDriver(_hostingEnvironment.WebRootPath, options)){
    // 错误在此处抛出,无法创建chrome进程
}

完整错误信息

[Error] Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer: Connection ID "18014398527467168636", Request ID "4000237f-0004-fa00-b63f-84710c7967bb": An unhandled exception was thrown by the application.
OpenQA.Selenium.WebDriverException: unknown error: Failed to create Chrome process.at OpenQA.Selenium.WebDriver.UnpackAndThrowOnError(Response errorResponse, String commandToExecute)at OpenQA.Selenium.WebDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)at OpenQA.Selenium.WebDriver.StartSession(ICapabilities desiredCapabilities)at OpenQA.Selenium.WebDriver..ctor(ICommandExecutor executor, ICapabilities capabilities)at OpenQA.Selenium.Chromium.ChromiumDriver..ctor(ChromiumDriverService service, ChromiumOptions options, TimeSpan commandTimeout)at OpenQA.Selenium.Chrome.ChromeDriver..ctor(ChromeDriverService service, ChromeOptions options, TimeSpan commandTimeout)at OpenQA.Selenium.Chrome.ChromeDriver..ctor(String chromeDriverDirectory, ChromeOptions options, TimeSpan commandTimeout)at OpenQA.Selenium.Chrome.ChromeDriver..ctor(String chromeDriverDirectory, ChromeOptions options)at Azon.Controllers.HomeController.UploadImageAsync(IFormFile image) in C:\Users\Gentrit\source\repos\Azon\Azon\Controllers\HomeController.cs:line 100at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)at Program.<<<Main>$>b__0_10>d.MoveNext() in C:\Users\Gentrit\source\repos\Azon\Azon\Program.cs:line 151--- End of stack trace from previous location ---at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)at Microsoft.AspNetCore.Session.SessionMiddleware.Invoke(HttpContext context)at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()

排查与解决步骤

1. 修正ChromeDriver路径配置

代码中chromeDriverPath是本地调试路径,生产环境完全无效。需确保初始化ChromeDriver时传入的路径下存在对应版本的chromedriver.exe,并避免硬编码本地路径:

// 构建Web根目录下的driver路径
string chromeDriverPath = Path.Combine(_hostingEnvironment.WebRootPath, "drivers");
// 确保目录存在,避免路径不存在报错
Directory.CreateDirectory(chromeDriverPath);

2. 补充服务器适配的Chrome启动参数

生产环境多为无桌面的服务器环境,需添加更多适配参数:

ChromeOptions options = new ChromeOptions();
options.AddArgument("--no-sandbox");
options.AddArgument("--headless=new"); // 新版无头模式兼容性更强
options.AddArgument("--ignore-ssl-errors=true");
options.AddArgument("--ignore-certificate-errors");
options.AddArgument("--window-size=1920x1080");
options.AddArgument("--disable-gpu");
options.AddArgument("--disable-dev-shm-usage"); // 解决共享内存不足问题
options.AddArgument("--remote-debugging-port=9222"); // 避免端口冲突
options.AddArgument("--no-first-run"); // 跳过首次运行配置
options.AddArgument("--disable-extensions"); // 禁用扩展减少启动负载

// 下载路径改为绝对路径,避免相对路径在生产环境失效
string downloadPath = Path.Combine(_hostingEnvironment.ContentRootPath, "Downloads");
Directory.CreateDirectory(downloadPath);
options.AddUserProfilePreference("download.default_directory", downloadPath);
options.AddUserProfilePreference("download.prompt_for_download", false);
options.AddUserProfilePreference("safebrowsing.enabled", false);

3. 明确指定Chrome二进制文件路径

若生产环境未全局安装Chrome,需指定完整的chrome.exe路径(需部署Chrome完整目录,而非仅单个exe文件):

// 假设Chrome部署在Web根目录的Chrome文件夹下
string chromeBinaryPath = Path.Combine(_hostingEnvironment.WebRootPath, "Chrome", "chrome.exe");
options.BinaryLocation = chromeBinaryPath;

4. 检查应用程序池权限

  • 确保IIS应用程序池的运行账户(如ApplicationPoolIdentity或自定义账户)拥有:
    • chromedriver.exe和Chrome目录的读取权限
    • 下载目录的写入权限
    • 创建进程的权限(需在服务器本地安全策略中配置)
  • 测试阶段可临时将应用程序池切换为LocalSystem验证权限问题,生产环境需使用权限最小化的自定义账户。

5. 验证版本匹配性

确保Chrome版本与ChromeDriver版本完全对应,可通过代码输出版本信息排查:

// 输出ChromeDriver版本
Console.WriteLine($"ChromeDriver Version: {ChromeDriverService.CreateDefaultService().DriverVersion}");

6. 启用ChromeDriver日志定位问题

配置日志输出,查看具体启动失败原因:

var service = ChromeDriverService.CreateDefaultService(chromeDriverPath);
service.LogPath = Path.Combine(_hostingEnvironment.ContentRootPath, "chromedriver.log");
service.EnableVerboseLogging = true;

using (var driver = new ChromeDriver(service, options))
{
    // 业务逻辑代码
}

查看生成的chromedriver.log,里面会包含Chrome启动失败的具体细节(如文件缺失、权限不足、依赖缺失等)。

7. 检查服务器依赖项

Windows服务器运行Chrome需确保安装:

  • 对应版本的Visual C++ Redistributable Packages
  • .NET Framework 4.8或更高版本(适配旧版ChromeDriver)
  • 关闭或配置安全软件(防火墙、杀毒软件)允许Chrome和ChromeDriver运行

内容的提问来源于stack exchange,提问作者Gentrit Cunaj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 11:02:34