异常情况:
Cef.Initialize can only be called once per process. This is a limitation of the underlying CEF/Chromium framework.
You can change many (not all) settings at runtime through RequestContext.SetPreference.
See https://github.com/cefsharp/CefSharp/wiki/General-Usage#request-context-browser-isolation
Use Cef.IsInitialized to check if Cef.Initialize has already been called to avoid this exception.
If you are seeing this unexpectedly then you are likely calling Cef.Initialize after
you’ve created an instance of ChromiumWebBrowser, it must be called before the first instance is created.
翻译:每个进程只能调用一次Cef.Initialize。这是基础CEF/Chromium框架的限制。您可以在运行时通过RequestContext.SetPreference更改许多(而不是全部)设置。请参阅https://github.com/cefsharp/CefSharp/wiki/General-Usage#request-上下文浏览器隔离使用Cef.IsInitialize检查是否已调用Cef.Initialize以避免此异常。如果你意外地看到了这一点,那么你很可能正在调用Cef.Initialize。在创建ChromiumWebBrowser的实例后,必须在创建第一个实例之前调用它。
下面这段代码只能在同一个进程中,执行一次;
var cefSettingOp = new CefSettings()
{
CookieableSchemesExcludeDefaults = false,
PersistSessionCookies = true,
//WindowlessRenderingEnabled = true,
};
#if DEBUG
//http://localhost:9080 本地调试窗口
cefSettingOp.RemoteDebuggingPort = 9080;
#endif
Cef.Initialize(cefSettingOp, performDependencyCheck: true, browserProcessHandler: null);
主要将上面代码在静态构造函数执行一次即可;
解决:
using CefSharp.OffScreen;
using CefSharp;
using System.Text.RegularExpressions;
using System.Drawing;
using CefSharp.Handler;
namespace Web_rongmeiti_sys.PublishToRongMeiTi
{
/// <summary>
/// 登录处理
/// </summary>
/// 创建时间:2023-5-23 10:23:54。创建人:xxx
public class LoginHandler
{
static LoginHandler()
{
/* 异常情况:
Cef.Initialize can only be called once per process. This is a limitation of the underlying CEF/Chromium framework.
You can change many (not all) settings at runtime through RequestContext.SetPreference.
See https://github.com/cefsharp/CefSharp/wiki/General-Usage#request-context-browser-isolation
Use Cef.IsInitialized to check if Cef.Initialize has already been called to avoid this exception.
If you are seeing this unexpectedly then you are likely calling Cef.Initialize after
you've created an instance of ChromiumWebBrowser, it must be called before the first instance is created.
*/
//初始化Cef.Initialize在同一线程中,只准执行一次,否则报错
var cefSettingOp = new CefSettings()
{
CookieableSchemesExcludeDefaults = false,
PersistSessionCookies = true,
//WindowlessRenderingEnabled = true,
};
#if DEBUG
//http://localhost:9080 本地调试窗口
cefSettingOp.RemoteDebuggingPort = 9080;
#endif
Cef.Initialize(cefSettingOp, performDependencyCheck: true, browserProcessHandler: null);
}
/// <summary>
/// 验证码获取,模拟登录
/// </summary>
/// 创建时间:2023-6-21 16:16:43,
public static Result LoginCall(string account, string password)
{
cookieSb.Clear();
//1.账号密码登录,
//2.验证码图形识别
//string url = "https://gk.abm.kpc/login.html";
string url = MyConfigReader.GetConfigValue("iam_login_url");
//Result<string> result = HttpHandler.GetPageAsync(url, null).Result;
解析html
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
//HtmlAgilityPack
//HtmlWeb web = new HtmlWeb();
//var doc = web.LoadFromWebAsync(url).Result;
//var html = doc.ParsedText;
//var nodes = doc.DocumentNode.SelectNodes("//div[@id='news_list']/div/div[2]/h2/a");
ChromiumWebBrowser webBrowser = new ChromiumWebBrowser(url)
{
RequestHandler = new MyRequestHandler() { Cnpc_account = account }
//ResourceRequestHandlerFactory = new ResourceRequestHandler3()
};
webBrowser.FrameLoadEnd += WebBrowser_FrameLoadEnd;
//webBrowser.AddressChanged += WebBrowser_AddressChanged;
//等待内容完成加载
webBrowser.WaitForInitialLoadAsync().Wait();
//Task.Delay(500).Wait();
//tab切换到账号登录
//$("li[data-name=accountLogin]").click();
var taskTabJs = webBrowser.GetMainFrame().EvaluateScriptAsync("$(\"li[data-name=accountLogin]\").click();");
taskTabJs.Wait();
Task.Delay(500).Wait();
//点击触发生成验证码图片,执行页面中的js函数loadverifyimg()
//webBrowser.GetMainFrame().EvaluateScriptAsync("loadverifyimg()").Wait();
//获取验证码图片url
//$("img.checkImage").attr("src")
var jsResponse = webBrowser.GetMainFrame().EvaluateScriptAsync("$(\"img.checkImage\").attr(\"src\")");
jsResponse.Wait();
JavascriptResponse javascriptResponse = jsResponse.Result;
if (!javascriptResponse.Success || javascriptResponse.Result is null || string.IsNullOrWhiteSpace(javascriptResponse.Result.ToString()))
{
LogHelpter.AddLog("没有获取到验证码图片url", null, "jsError");
return new Result("登录失败");
}
获取页面html
//string html9 = webBrowser.GetSourceAsync().Result;
//验证码图片url
string imgVerifyUrl = javascriptResponse.Result.ToString();
//域名
string baseUrl = Regex.Match(url, "(https://|http://)[A-Za-z0-9.]+/").Value;
string imgUrl = baseUrl + imgVerifyUrl;
//下载验证码图片到本地保存
HttpClient client = new HttpClient();
var taskImg = client.GetByteArrayAsync(imgUrl);
taskImg.Wait();
string imgDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "imgVerify", DateTime.Now.ToString("yyyyMM"));
if (!System.IO.Directory.Exists(imgDir))
{
System.IO.Directory.CreateDirectory(imgDir);
}
//验证码图片
string fileNameImg = Path.Combine(imgDir, DateTime.Now.Ticks + ".jpg");
byte[] imageBytes = taskImg.Result;
//保存验证码图片到本地.jpg
using (MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
{
ms.Write(imageBytes, 0, imageBytes.Length);
var img = Image.FromStream(ms, true);
img.Save(fileNameImg, System.Drawing.Imaging.ImageFormat.Jpeg);
}
模拟登录
//string account = MyConfigReader.GetConfigValue("iam_login_account");
//string password = MyConfigReader.GetConfigValue("iam_login_password");
//账号、密码、验证码赋值js; 调用登录js方法
string jsLoginWork = $"$(\"#cnpc-input-userName\").val(\"{account}\");"
+ $"$(\"#cnpc-input-pwd\").val(\"{password}\");"
+ $"$(\".verifyCode\").val(\"{result}\");"
+ "userNameLogin();";
var jsLogin = webBrowser.GetMainFrame().EvaluateScriptAsync(jsLoginWork);
jsLogin.Wait();
JavascriptResponse jsLoginResponse = jsLogin.Result;
if (!jsLoginResponse.Success)
{
LogHelpter.AddLog("登录账号、密码赋值给输入框,登录模拟点击js", null, "jsError");
return new Result("登录失败");
}
//等待url变化后,加载的新页面,登录成功后进入https://gk.abm.kpc/index.html
var navHome = webBrowser.WaitForNavigationAsync();
navHome.Wait();
//等待内容完成加载
webBrowser.WaitForInitialLoadAsync().Wait();
查看登录后的代码
//string html25 = webBrowser.GetSourceAsync().Result;
webBrowser.Load(MyConfigReader.GetConfigValue("rongmeiti_url"));
//var jsLoginPfEip = webBrowser.GetMainFrame().EvaluateScriptAsync("window.location.href=\"https://gk.abm.kpc/\";");
//jsLoginPfEip.Wait();
//等待url变化后,加载的新页面,登录成功后进入https://gk.abm.kpc/index.html
var cnHome = webBrowser.WaitForNavigationAsync(timeout: TimeSpan.FromSeconds(30));
cnHome.Wait();
//等待内容完成加载
webBrowser.WaitForInitialLoadAsync().Wait();
//检察是否成功写了cookie文件,没有成功则一直阻塞线程,2023-6-27 16:16:28
int check_count = 0;
while (true)
{
if (check_count > 10)
{
LogHelpter.AddLog("一直获取不到cookie,处理异常", null, "identityCookie_while_error");
return new Result("登录失败");
}
string? identityCookie = AuthCookieHelpter.GetIdentityCookie(account);
if (!string.IsNullOrWhiteSpace(identityCookie))
{
LogHelpter.AddLog("成功写了cookie文件,account=" + account, null, "identityCookie_while");
break;
}
LogHelpter.AddLog("检察是否成功写了cookie文件...", null, "identityCookie_while");
check_count++;
Thread.Sleep(1000);
}
return new Result("登录成功", 200);
}
private static void WebBrowser_AddressChanged(object? sender, AddressChangedEventArgs e)
{
LogHelpter.AddLog(e.Address, null, "AddressChanged");
}
public static System.Text.StringBuilder cookieSb = new System.Text.StringBuilder();
private static void WebBrowser_FrameLoadEnd(object? sender, FrameLoadEndEventArgs e)
{
//获取谁在调用,cnpc账号
ChromiumWebBrowser webBrowser = sender as ChromiumWebBrowser;
var myRequestHandler = webBrowser.RequestHandler as MyRequestHandler;
string cnpc_account = myRequestHandler.Cnpc_account;
LogHelpter.AddLog(e.Url + " 状态=" + e.HttpStatusCode, null, "Log_FrameLoadEnd");
//cookie捕获
var cookieManager = Cef.GetGlobalCookieManager();
CookieVisitorHandle visitor = new CookieVisitorHandle();
visitor.OnCookie = cookie =>
{
string url = cookie.Domain + cookie.Path;
LogHelpter.AddLog($"path={url},{cookie.Name}={cookie.Value}", null, "getCookie");
//pf.eip.cnpc/api,.AspNetCore.CookiesC1
//pf.eip.cnpc/api,.AspNetCore.CookiesC2
if (url == "pf.eip.cnpc/api" && cookie.Name == ".AspNetCore.CookiesC1")
{
cookieSb.Append(cookie.Name + "=" + cookie.Value + ";");
if (cookie.Value.Length > 0)
{
LogHelpter.AddLog("登录成功", null, "FrameLoadEnd");
}
}
if (url == "pf.eip.cnpc/api" && cookie.Name == ".AspNetCore.CookiesC2")
{
cookieSb.Append(cookie.Name + "=" + cookie.Value + ";");
//保存cookie到本地文件
AuthCookieHelpter.SaveCookie(cnpc_account, cookieSb.ToString());
}
};
cookieManager.VisitAllCookies(visitor);
}
}
}