I am trying to incorporate a browser into a console application using CefSharp Offscreen with dotnet core.
Is it possible to view the web page inside the Chromium browser this way?
In the code below (largely taken from their Offscreen github example) I am trying to display a simple HTML page (later it'll be React or Angular but for now HTML is fine).
In their code they l;oad up a webpage in Chromium and take a picture of it, I want to be able to view the webpae that it takes a screenshot of.
public static void Start()
{
//Only required for PlatformTarget of AnyCPU
AppDomain.CurrentDomain.AssemblyResolve += Resolver;
Console.WriteLine("apply cef settings");
CefSettings settings = new CefSettings();
settings.RegisterScheme(new CefCustomScheme
{
SchemeName = "localfolder",
SchemeHandlerFactory = new FolderSchemeHandlerFactory(
rootFolder: #"..\..\..\..\html",
defaultPage: "index.html"
)
});
Cef.Initialize(settings, performDependencyCheck: false, browserProcessHandler: null);
CefSharpSettings.ShutdownOnExit = true;
Console.WriteLine("load web page");
ChromeBrowser = new ChromiumWebBrowser("localfolder://cefsharp/");
Console.ReadKey();
Cef.Shutdown();
}
Related
I have an Windows Form Application which utilises CefSharp.
A while ago I used a chunk of code that saves the state of the browser such as login details etc so that the user does not have to log in multiple times.
This is the code I used:
private static bool _hasRun;
CefSettings settings = new CefSettings();
if (!_hasRun)
{
Cef.Initialize(new CefSettings { CachePath = "MyCachePath", PersistSessionCookies = true });
}
_hasRun = true;
string cache_dir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + #"\CEF";
settings.CachePath = cache_dir;
settings.CefCommandLineArgs.Add("persist_session_cookies", "1");
string link = Domain;
chrome = new ChromiumWebBrowser(link);
this.tabPage2.Controls.Add(chrome);
chrome.Dock = DockStyle.Fill;
This code runs fine in my old application but when using this on my most recent app I receive this error message:
Any suggestions?
You must provide a full path.
non-absolute: "MyCachepath"
absolute: "C:\users\username\documents\MyCachepath"
why did it work in older projects?
Some project types and versions automaticallly translate an relative path into an absolute path like so:
environment.CurrentDirectory + #"\MyCachepath"
var settings = new CefSettings();
// Initialize cef with the provided settings
settings.CachePath = "C:/Users/Anoni/Source/Repos/WindowsFormsApp1/bin/Debug/Cache";
Cef.Initialize(settings);
// Create a browser component
chromeBrowser = new ChromiumWebBrowser("https://www.reddit.com/r/Turkishleft/");
// Add it to the form and fill it to the form window.
this.Controls.Add(chromeBrowser);
chromeBrowser.Dock = DockStyle.Fill;
string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
settings.RemoteDebuggingPort = 8088;
These are my CefSharp settings. As you can see, CefSharp stores my cache in "C:/Users/Anoni/Source/Repos/WindowsFormsApp1/bin/Debug/Cache". But i want it to store cache wherever the application starts from. For example, if app start from "D:/", I want it to save cache in "D:/Cache". How can i make that happen?
Found it. Line of code should be
settings.CachePath = Application.StartupPath + "/Cache";
I am updating my browser app to support Windows Phone 8.1 and I noticed the MSGestureHoldevent is not raised.
To reproduce this error,
Download the MS Mini-browser Sample.
Upgrade the project to WP8.1 project in Visual Studio 2013 and add IsScriptEnabled="True".
Run the project on WP8.1 emulator or device
Navigate to this touch and mouse example.
Scroll down to the Sample 1: handling the hold gesture section and click the IE11 users test.
Notice that MSGestureHold is not working.
However the project is working when tested in
Default Windows Phone Internet Explorer app for WP8 and WP8.1
WebBrowser control in WP8 app.
Is this a bug?
I guess this is the WebBrowser control's bug.
I test several gesture events with WebBrowser control for WP8.1, such as pointerdown,MSGestureHold,MSGestureChange,and MSGestureTap.
Finally, pointerdown, MSGestureChange and MSGestureTap can be triggered normally,except MSGestureHold.
So I guess this is a bug.
This code works fine in webview for WPhone 8.1 apps :
var init = function(){
var myState = // context
var target = // DOM variable target
var msg = new MSGesture();
msg.target = target;
target.addEventListener("MSGestureHold", function (evt) { buttonTactileListener.apply(myState, [evt, msg]); }, false);
target.addEventListener("pointerdown", function (evt) { buttonTactileListener.apply(myState, [evt, msg]); }, false);
target.addEventListener("MSGestureEnd", function (evt) { buttonTactileListener.apply(myState, [evt, msg]); }, false);
}
var buttonTactileListener = function (evt, msgesture) {
var myState = this;
if (evt.type == "pointerdown") {
msgesture.addPointer(evt.pointerId);
return;
}
if (evt.type == "MSGestureHold") {
///do something
return;
}
if (evt.type == "MSGestureEnd") {
// renew instance of handler
msgesture = new MSGesture();
msgesture.target = evt.target;
return;
}
}
I'm working on a web browser where the default search engine is Google until the user clicks on the Yahoo (or another search engine) button. The problem is, after you start a new session, it opens with Google again. How to you save that?
I'm aware how to save settings with Properties.Settings.Default.Save(); however it doesn't seem to work with a click event. (Where the code is to change the search engine)
I'm using GeckoFX. Code for the Yahoo setting is:
goo.Enabled = true;
y.Enabled = false;
bin.Enabled = true;
ba.Enabled = true;
ya.Enabled = true;
sear.Text = "Yahoo!";
And is performed with:
if (y.Enabled == false)
{
W.Navigate("search.yahoo.com/search?p=" + q.Text);
W.Select();
}
I need to use the WinForms WebBrowser control in an ASP.NET application in order to take screenshots of webpages.
I'd much rather run it in a console app, and communicate to the app via the ASP.NET application, but it's not my call, I've been told it has to run as part of the website.
It all pretty much works apart from every call to navigate starts fresh with a new session, it's like the cookies aren't being persisted. As an experiment, I changed my IIS application pool to run as me rather than NETWORK_SERVICE, and it all works fine. So it's something strange about it running as network service.
I'm guessing that the network service account doesn't have the permissions to keep track of the ASP.NET_SessionId cookie and the auth cookie, but both these are non-persistent cookies, so I don't know why that would be.
Here is some simplified code so you can get the gist of what I'm doing. There is a bunch of logging and storing of images that I cut out, so it's not complete code. Basically a developer/tester/admin can run this code once (task kicked off via webpage), it will generate bitmaps of every page in the system, they can release a new version of the website and then run it again, it will tell you the differences (new pages, pages removed, pages changed).
public void Run()
{
var t = new Thread(RunThread);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
private void RunThread()
{
try
{
using (var browser = new WebBrowser())
{
browser.DocumentCompleted += BrowserDocumentCompleted;
if (!VisitPage(browser, "special page that sets some session flags for testing - makes content predictable")))
throw new TestRunException("Unable to disable randomness");
foreach (var page in pages)
{
VisitPage(browser, page);
}
}
}
// An unhandled exception in a background thread in ASP.NET causes the app to be recycled, so catch everything here
catch (Exception)
{
Status = TestStatus.Aborted;
}
}
private bool VisitPage(WebBrowser browser, string page)
{
finishedEvent.Reset();
var timeout = false;
stopwatch = new Stopwatch();
browser.Navigate(page);
stopwatch.Start();
while (!timeout && !finishedEvent.WaitOne(0))
{
Application.DoEvents();
if (stopwatch.ElapsedMilliseconds > 10000)
timeout = true;
}
Application.DoEvents();
if (timeout)
{
if (resource != null)
ShopData.Shop.LogPageCrawlTestLine(testRunID, resource, sequence++, (int)stopwatch.ElapsedMilliseconds, null);
}
browser.Stop();
return !timeout;
}
private void BrowserDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
try
{
var browser = (WebBrowser)sender;
var width = browser.Document.Body.ScrollRectangle.Width;
var height = browser.Document.Body.ScrollRectangle.Height;
var timeTaken = (int)stopwatch.ElapsedMilliseconds;
if ((width == 0) || (height == 0))
{
return;
}
browser.Width = width;
browser.Height = height;
byte[] buffer;
using (var bitmap = new Bitmap(width, height))
using (var memoryStream = new MemoryStream())
{
browser.DrawToBitmap(bitmap, new Rectangle(0, 0, width, height));
bitmap.Save(memoryStream, ImageFormat.Bmp);
buffer = memoryStream.ToArray();
}
// stores image
}
finally
{
finishedEvent.Set();
}
}
So in summary:
The above code is started by a ASP.NET page and it runs in the backgound
It works fine if I run it in an IIS application pool set to run as a proper user
If I run it in an IIS application pool as NETWORK_SERVICE then every navigate has a new session, rather than persisting a session for the lifetime of the WebBrowser.
I can get it working fine outside of ASP.NET, but that is not an option for me currently, it has to run inside this ASP.NET application.
//Update
On the advice of my colleague I'm using impersonation in the background thread where I'm creating the WebBrowser, running as a local user. This works fine and I'm pretty happy with this solution. He's a stackoverflow user so I'll let him post the answer and get the credit :)
Using impersonation in the background thread would allow the WebBrowser to run as a user with permissions to run IE and thus store cookies, instead of it running as the Application Pool user (NETWORK_SERVICE).
You can setup the Impersonation in the web.config or programatically to restrict it to a specific thread.
not offcially supported due to its usage of WinInet. see http://support.microsoft.com/kb/238425 for limitations of WinInet in a service.
Do you see the session cookie in the requests coming from the WebBrowser control? I cannot find anything on how this control is supposed to handle cookies - if it ignores them you would get the behavior you are describing