Program.cs
cs
builder.Services.AddSingleton<IBrowserHolder>(sp =>
{
var holder = new BrowserHolder(sp)
{
CurrentUrl = sp.GetRequiredService<IConfiguration>()["openUrl"]
};
return holder;
});
cs
public interface IBrowserHolder
{
IWebDriver GetOrCreate(); // 每次登录按钮触发时调它
string? CurrentUrl { get; set; } // 需要打开的地址
}
cs
public class BrowserHolder : IBrowserHolder, IDisposable
{
private readonly IServiceProvider _sp;
private IWebDriver? _driver;
private readonly object _lock = new();
public string? CurrentUrl { get; set; }
public BrowserHolder(IServiceProvider sp) => _sp = sp;
public IWebDriver GetOrCreate()
{
lock (_lock)
{
// 如果窗口已关,则释放旧实例
if (_driver != null && !_driver.IsAlive())
{
_driver.Quit();
_driver.Dispose();
_driver = null;
}
if (_driver == null)
{
_driver = BuildDriver();
if (!string.IsNullOrEmpty(CurrentUrl))
_driver.Navigate().GoToUrl(CurrentUrl);
}
else if (!string.IsNullOrEmpty(CurrentUrl))
{
// 窗口还在,但想再跳一次同一地址(可选)
_driver.Navigate().GoToUrl(CurrentUrl);
}
return _driver;
}
}
private IWebDriver BuildDriver()
{
var cfg = _sp.GetRequiredService<IConfiguration>();
var logger = _sp.GetRequiredService<ILogger<BrowserHolder>>();
var options = new ChromeOptions();
options.PageLoadStrategy = PageLoadStrategy.None;
// options.AddArgument("--headless=new"); //无头模式可在没有可视化桌面的时候开启
options.AddArgument("--disable-gpu");
options.AddArgument("--no-sandbox");
options.AddArgument("--disable-dev-shm-usage");
options.AddArgument("--disable-extensions");
options.AddArgument("--disable-infobars");
options.AddArgument("--window-size=1920,1080");
options.AddArgument("--ignore-certificate-errors");
options.AddArgument("--start-maximized");
if (!string.IsNullOrEmpty(cfg["googleUrl"]))
options.BinaryLocation = cfg["googleUrl"];
var service = ChromeDriverService.CreateDefaultService(cfg["chromedriverUrl"], "chromedriver");
service.Port = int.Parse(cfg["googlePort"]);
service.EnableVerboseLogging = true;
service.LogPath = "chromedriver.log";
logger.LogInformation("正在启动 ChromeDriver ...");
if (!string.IsNullOrWhiteSpace(cfg["chromedriverUrl"]))
{
return new ChromeDriver(service, options);
}
else
{
return new ChromeDriver( options);
}
}
public void Dispose()
{
_driver?.Quit();
_driver?.Dispose();
}
应用
cs
private readonly IBrowserHolder _browser;
public IndexModel(ILogger<IndexModel> logger, IBrowserHolder browser, IConfiguration configuration)
{
_logger = logger;
_browser = browser;
}
public IActionResult OnPost()
{
try
{
var driver = _browser.GetOrCreate();
return Page();
}
catch (Exception ex)
{
throw;
}
}
javascript
//Windows 本地测试环境
"googleUrl": "", // 空着程序会自己去找默认路径
"chromedriverUrl": "", // 空着程序会自己去找默认路径
"googlePort": 9520
具体模拟点击代码略。。。
以上代码在windows环境下安装了谷歌浏览器可直接运行
在Ubuntu环境中,需要做如下配置:
- net core 环境安装 (*)
wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install -y dotnet-runtime-6.0
sudo apt-get install -y dotnet-sdk-6.0
2.安装谷歌浏览器(*)
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome-stable_current_amd64.deb || sudo apt -f -y install
查看版本
google-chrome --version
下载对应版本的ChromeDriver
解压并移动到系统路径:(路径需要在代码里面配置的)
unzip chromedriver-linux64.zip
sudo mv chromedriver-linux64/chromedriver /usr/local/bin/
赋予执行权限:(没有权限后面可能调用不了谷歌)
sudo chmod +x /usr/local/bin/chromedriver
3.将发布文件先用U盘拷贝到系统
3.1 创建文件夹
sudo mkdir -p /var/www/myapp
sudo cp -r ~/var/www/myapp/* /var/www/myapp/
3.2.把目录所有者改成你自己
sudo chown -R USER:USER /var/www/myapp
4.创建 systemd 服务文件(*)
sudo nano /etc/systemd/use/WebApplication1.service -- WebApplication1自己换成其他的名称
service配置内容
Unit
Description=My .NET Core Web App
After=network.target
Service
Environment=DISPLAY=:0
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/dotnet /var/www/myapp/WebApplication1.dll --urls "http://*:5000"
Restart=always
RestartSec=10
SyslogIdentifier=WebApplication1
Environment=ASPNETCORE_ENVIRONMENT=Production
Install
WantedBy=multi-user.target
Environment=DISPLAY=:0 是一定需要的,不然到时候打开不了浏览器
配置图形启动器
echo $DISPLAY
export DISPLAY=:0
启动服务程序
systemctl --user daemon-reload
systemctl --user enable --now WebApplication1.service
loginctl enable-linger $USER # 允许后台常驻(开机启动)
这里有一个大坑 千万不要用sudo 启动服务 如:
sudo systemctl daemon-reload
sudo systemctl enable WebApplication1
sudo systemctl start WebApplication1
如果用sudo会无法拿到配置Environment=DISPLAY=:0 导致无法打开浏览器
写入权限:(根据实际情况看是否需要)
sudo mkdir -p /var/www/myapp/logs
sudo chown www-data:www-data /var/www/myapp/logs
sudo chmod g+w /var/www/myapp/logs
5.添加use 对目录的权限(不添加程序无法运行) (*)
sudo chown -R USER:USER /var/www/myapp
如果里面曾经 root 跑过日志、sqlite,一起改
sudo find /var/www/myapp -type f -exec chmod u+rw {} \;
6.设置固定IP (可选)
6.1.查看网卡名称
ip link show
6.2. 查看当前 enp1s0 的 IP 配置
ip addr show enp1s0
6.3. 查看当前网关
ip route show default
6.4.查看当前DNS
resolvectl status
6.5.输入配置(严格按照缩进)
/etc/netplan/01-netcfg.yaml
Let NetworkManager manage all devices on this system
network:
version: 2
renderer: NetworkManager
ethernets:
enp1s0: # 你的网卡名称
dhcp4: no
addresses: [192.168.20.200/24] # IP地址和子网掩码
routes:
- to: default
via: 192.168.20.1 # 网关
nameservers:
addresses: [192.168.20.10] # 你的 DNS 服务器
search: [fbo.cn] # DNS 搜索域
6.6.验证语法
sudo netplan generate
如果出现提示:
WARNING **: 13:56:55.030: Permissions for /etc/netplan/01-network-manager-all.yaml are too open. Netplan configuration should NOT be accessible by others.
警告文件权限问题
修复:
sudo chmod 600 /etc/netplan/01-network-manager-all.yaml
6.7.应用配置
sudo netplan apply
6.8检查 IP 地址是否改变
ip addr show enp1s0