Cefsharp Winforms app shows blank browser - cefsharp

I have a WinForms based cefsharp app that was working. I updated the NuGet packages for CefSharp (to 75.1.142.0) and now the browser only shows blank on start up. The log file says:
[1029/115545.989:WARNING:resource_bundle.cc(952)] unable to find resource: 164
[1029/115546.193:ERROR:viz_main_impl.cc(170)] Exiting GPU process due to errors during initialization
[1029/115546.210:WARNING:gpu_process_host.cc(1205)] The GPU process has crashed 1 time(s)
Is there a way to get more detailed debug info?

EDIT: OK - Stupid me! Updating the packages doesn't update the files in my custom locations (obviously!). Fix that, and everything is sweet!
I found an answer, but I'm not sure why it should be. I commented out the setting of the paths in the CefSharpSettings (as below) and now it works?
private static void LoadForm(string[] args)
{
// Alternate file locations
string browser = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"CEFSharp\CefSharp.BrowserSubprocess.exe");
string locales = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"CEFSharp\locales\");
string res = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"CEFSharp\");
string cache = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"CEFSharp\cache\");
// Initialise CEF
CefSharpSettings.SubprocessExitIfParentProcessClosed = true;
CefSharp.CefSharpSettings.LegacyJavascriptBindingEnabled = true;
CefSettings settings = new CefSettings();
settings.CachePath = cache;
settings.MultiThreadedMessageLoop = true;
settings.ExternalMessagePump = false;
settings.RemoteDebuggingPort = 8088;
settings.CefCommandLineArgs.Add("proxy-auto-detect", "true");
settings.LogFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, #"CEFSharp\Debug.log");
//settings.BrowserSubprocessPath = browser;
//settings.LocalesDirPath = locales;
//settings.ResourcesDirPath = res;
settings.DisableGpuAcceleration();
Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
Application.Run(new ImportForm(args));
}

Related

EPPLUS package works fine locally but returns Internal server error when deployed to azure server

I have my web api that uploads and reads an excel file from the client app and then afterwards saves the data into the database, the application works perfect on locally server but the problem comes when the application is deployed to azure server it returns error 500 internal server error therefore i don't understand why this happens and and don't know how i can track to understand what might be the cause below are my code blocks.
My Interface Class
public interface UploadExcelInterface
{
Task UploadMultipleClients(Client obj);
}
My Service Implementation
public class UploadExcelService : UploadExcelInterface
{
private readonly DbContext _connect;
private readonly IHttpContextAccessor httpContextAccessor;
public UploadExcelService(DbContext _connect, IHttpContextAccessor httpContextAccessor)
{
this._connect = _connect;
this.httpContextAccessor = httpContextAccessor;
}
public async Task UploadMultipleClients(Client obj)
{
var file = httpContextAccessor.HttpContext.Request.Form.Files[0];
if (file != null && file.Length > 0)
{
var folderName = Path.Combine("Datas", "ClientUPloads");
var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), folderName);
var fileName = Guid.NewGuid() + ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
var fullPath = Path.Combine(pathToSave, fileName);
var clientsList = new List<Client>();
using (var fileStream = new FileStream(fullPath, FileMode.Create))
{
await file.CopyToAsync(fileStream);
FileInfo excelFile = new FileInfo(Path.Combine(pathToSave, fileName));
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using (ExcelPackage package = new ExcelPackage(excelFile))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
var rowcount = worksheet.Dimension.Rows;
for (int row = 2; row <= rowcount; row++)
{
var Names = (worksheet.Cells[row,2].Value ?? string.Empty).ToString().Trim();
var Address = (worksheet.Cells[row,3].Value ?? string.Empty).ToString().Trim();
var Title = (worksheet.Cells[row,4].Value ?? string.Empty).ToString().Trim();
var Product = (worksheet.Cells[row,5].Value ?? string.Empty).ToString().Trim();
var Order = (worksheet.Cells[row,6].Value ?? string.Empty).ToString().Trim();
var Email = (worksheet.Cells[row,7].Value ?? string.Empty).ToString().Trim();
var Price = (worksheet.Cells[row,8].Value ?? string.Empty).ToString().Trim();
clientsList.Add(new Client
{
Names = Names,
Address = Address,
Title = Title,
Product = Product,
Order = Order,
Email = Email,
Price = Price,
}
}
//adding clients into the database
foreach (Client client in clientsList)
{
var exist = _connect.client.Any(x => x.Email == client.Email);
if (!exist)
{
await _connect.client.AddAsync(client);
}
}
await _connect.SaveChangesAsync();
}
}
}
My Controller Class
[HttpPost]
public async Task UploadMultipleClients([FromForm] Client obj)
{
await uploadExcelInterface.UploadMultipleClients(obj);
}
}
Please any help regarding this error that am getting from the server, and addition on that is it possible to get the data from the excel file without uploading it to server if yes how? because i tried adding the file to memory stream an reading it from memory but it appers not work, any suggestions thanks.
My answer may not help you solve the problem directly, but it can locate the error step by step. After we fix the error, we should be able to solve the problem in this thread.
Suggestions
Please make sure you have inclue EPPlus library in your deploy content.
Enabling ASP.NET Core stdout log (Windows Server)
Azure App Service - Configure Detailed Error Logging
Why
After tested, I am sure azure webapp can support EPPlus. For 500 error, as we don't have a more specific error message to refer to, we can't quickly locate the problem. Following the suggested method, you will surely see some useful information.
E.g:
The class library of EPPlus was not found.
Folders such as Datas are not created.
The database connection string, the test environment and the production environment may be different.
...

JxBrowser not connecting

I am having troubles to make the jxbrowser work outside of the development environment. When I run it in eclipse it works fine, but when I compile it and run the screen doesn't seems to load. Here is the code that I'm using:
browser = new Browser();
com.teamdev.jxbrowser.chromium.swing.BrowserView view = new com.teamdev.jxbrowser.chromium.swing.BrowserView(browser);
javax.swing.JFrame frame = new javax.swing.JFrame();
frame.add(view, java.awt.BorderLayout.CENTER);
frame.setSize(800, 450);
frame.setVisible(true);
browser.loadURL(Main.class.getResource("/assets/engine.html").toExternalForm());
> When I run from eclipse <
> When I compile and run <
Am I missing something?
If your HTML resource "/assets/engine.html" is located inside the RPGItems.jar after build, the path to it will not be resolved properly by the Chromium engine by default. To be able to load resources located inside JAR archive you must register custom ProtocolHandler with the following implementation:
BrowserContext browserContext = browser.getContext();
ProtocolService protocolService = browserContext.getProtocolService();
protocolService.setProtocolHandler("jar", new ProtocolHandler() {
#Override
public URLResponse onRequest(URLRequest request) {
try {
URLResponse response = new URLResponse();
URL path = new URL(request.getURL());
InputStream inputStream = path.openStream();
DataInputStream stream = new DataInputStream(inputStream);
byte[] data = new byte[stream.available()];
stream.readFully(data);
response.setData(data);
String mimeType = getMimeType(path.toString());
response.getHeaders().setHeader("Content-Type", mimeType);
return response;
} catch (Exception ignored) {}
return null;
}
});
The getMimeTypemethod here returns appropriate mime type for the given resource extension:
private static String getMimeType(String path) {
if (path.endsWith(".html")) {
return "text/html";
}
if (path.endsWith(".css")) {
return "text/css";
}
if (path.endsWith(".js")) {
return "text/javascript";
}
return "text/html";
}
Once you register ProtocolHandler and define what mime types are supported, you can load resources from JAR archive using standard Java and JxBrowser API:
browser.loadURL(Main.class.getResource("/assets/engine.html").toString());

OpenStack Rackspace Cloud Files .net SDK

I am trying to save an XML file to a non CDN Container from Sydney:
public void Save(XDocument document)
{
using (MemoryStream ms = new MemoryStream())
{
document.Save(ms);
ms.Position = 0;
RackspaceCloudIdentity identity = new RackspaceCloudIdentity { Username = "username", APIKey = "xxxxxxxxxxx", CloudInstance = CloudInstance.Default };
CloudFilesProvider provider = new CloudFilesProvider(identity);
provider.CreateObject("XMLFiles", ms, "xmlFile1.xml", region: "syd");
}
}
For a 1MB file, it takes about 50 seconds to upload (very long).
And, trying to download the file back, returns an empty result:
public void Read()
{
RackspaceCloudIdentity identity = new RackspaceCloudIdentity { Username = "username", APIKey = "xxxxxxxxxxx", CloudInstance = CloudInstance.Default };
CloudFilesProvider provider = new CloudFilesProvider(identity);
using (MemoryStream ms = new MemoryStream())
{
provider.GetObject("XMLFiles", "xmlFile1.xml", ms, region: "syd");
// ms.Length is 0
}
}
I am doing something wrong?
Ugh. I introduced this bug in commit 799f37c (first released in v1.1.3.0). I'm looking into the best workaround right now.
Edit: There is no workaround, but I filed issue #116 for the issue, and after the pull request for it is merged, we'll release version 1.1.3.1 of the library to correct the problem.
Are you able to access your control panel at mycloud.rackspace.com?
I used my control panel to upload an XML file, then used your code, above, to download the XML file. It worked fine.
I'm going now use the upload code you posted.
Just wanted you to know I'm looking into this.

ChromeDriver console application hide

I have created a player which will automate chrome using selenium and ChromeDriver in C#. It's working fine.
Issue what I am facing is, when it creates an object for ChromDriver, it will start ChromeDriver application, which gets pop up and then Chrome will load. It's perfect as that application is loading that chrome for me.
Is there anyway, that I can open that ChromeDriver hidden?
Modifying source code in WebDriver\DriverService.cs is not necessary for this in latest WebDriver. You just need to instantiate ChromeDriverService and set HideCommandPromptWindow to true and then instantiate ChromeDriver by that service and ChromeOptions. I am giving C# code example below
var chromeDriverService = ChromeDriverService.CreateDefaultService();
chromeDriverService.HideCommandPromptWindow = true;
return new ChromeDriver(chromeDriverService, new ChromeOptions());
No, there is no way to hide the console window of the chromedriver.exe in the .NET bindings without modifying the bindings source code. This is seen as a feature of the bindings, as it makes it very easy to see when your code hasn't correctly cleaned up the resources of the ChromeDriver, since the console window remains open. In the case of some other languages, if your code does not properly clean up the instance of ChromeDriver by calling the quit() method on the WebDriver object, you can end up with a zombie chromedriver.exe process running on your machine.
Yes, you need modify source code in WebDriver\DriverService.cs in Start(); add:
this.driverServiceProcess.StartInfo.CreateNoWindow = true;
This is possible now, using the headless option. Might not have been available then.
Running Chrome Headless
Translated into C#, you can do this:
ChromeOptions options = new ChromeOptions();
options.AddArgument("headless");
ChromeDriver driver = new ChromeDriver(options);
Now the browser window is invisible, while the rest of the program stays the same.
As an update to this question. Yes, you can hide command prompt window in Selenium 2.40.0 and up. Please note that hiding command prompt window is not recommended but you can do it. As the question refers to C# you do it with the next code:
ChromeDriver
var driverService = ChromeDriverService.CreateDefaultService();
driverService.HideCommandPromptWindow = true;
var driver = new ChromeDriver(driverService, new ChromeOptions());
InternetExplorerDriver
var driverService = InternetExplorerDriverService.CreateDefaultService();
driverService.HideCommandPromptWindow = true;
var driver = new InternetExplorerDriver(driverService, new InternetExplorerOptions());
PhantomJSDriver
var driverService = PhantomJSDriverService.CreateDefaultService();
driverService.HideCommandPromptWindow = true;
var driver = new PhantomJSDriver(driverService);
drv.Manage().Window.Position = new Point(3000, 3000);
will fix your problem.
I did this using c#, but like JimEvan's repply, I had some problems with "zombies chromedrivers and cmd zombies". After doing "headless mode" and "hiding" the prompt window.
Don't forget to close your chrome driver instance correcly.
To solve this, doing a little google how kill some process, I kill these two process, before open another chrome driver again :
static void Main(string[] args)
{
ChromeDriverService _chromeDriverService;
ChromeOptions _chromeOptions;
IWebDriver _driver;
//set ChromeDriverService, to hide prompt widow
_chromeDriverService = ChromeDriverService.CreateDefaultService("YOUR CHROME DRIVER PATH HERE");
_chromeDriverService.HideCommandPromptWindow = true;
//set ChromeOptions, to hide ChromeDriver
_chromeOptions = new ChromeOptions();
_chromeOptions.AddArguments("headless");
_driver = ChromeDriver(_chromeDriverService, _chromeOptions);
//do your things...
}
//call this method before run your chrome driver, to close some ghost chromeDriver or prompt window
private static void CloseGhostsChromeDriver()
{
Process[] cmd = Process.GetProcessesByName("cmd");
Process[] chromeDriver = Process.GetProcessesByName("chromedriver");
Process[] workers = chromeDriver.Concat(cmd).ToArray();
foreach (Process worker in workers)
{
worker.Kill();
worker.WaitForExit();
worker.Dispose();
}
}
In updated version of ChromeDriver you don't need to edit the source code just with:
var driverService = ChromeDriverService.CreateDefaultService();
driverService.HideCommandPromptWindow = true;
If you want to hide the console that is opened when launching chrome, firefox, etc.. you will need a helper class like this:
static class WindowsUtils
{
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
// Delegate to filter which windows to include
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
/// <summary> Get the text for the window pointed to by hWnd </summary>
public static string GetWindowText(IntPtr hWnd)
{
int size = GetWindowTextLength(hWnd);
if (size > 0)
{
var builder = new StringBuilder(size + 1);
GetWindowText(hWnd, builder, builder.Capacity);
return builder.ToString();
}
return String.Empty;
}
/// <summary> Find all windows that match the given filter </summary>
/// <param name="filter"> A delegate that returns true for windows
/// that should be returned and false for windows that should
/// not be returned </param>
public static IEnumerable<IntPtr> FindWindows(EnumWindowsProc filter)
{
IntPtr found = IntPtr.Zero;
List<IntPtr> windows = new List<IntPtr>();
EnumWindows(delegate (IntPtr wnd, IntPtr param)
{
if (filter(wnd, param))
{
// only add the windows that pass the filter
windows.Add(wnd);
}
// but return true here so that we iterate all windows
return true;
}, IntPtr.Zero);
return windows;
}
/// <summary> Find all windows that contain the given title text </summary>
/// <param name="titleText"> The text that the window title must contain. </param>
public static IEnumerable<IntPtr> FindWindowsWithText(string titleText)
{
return FindWindows(delegate (IntPtr wnd, IntPtr param)
{
return GetWindowText(wnd).Contains(titleText);
});
}
}
An then you can create your Selenium driver like this (also hidding the Firefox window).. If you want to use Chrome only have to do some minor changes... I prefreer Firefox because Chrome sometimes don't work with headless option:
FirefoxOptions options = new FirefoxOptions();
options.SetPreference("permissions.default.image", 2); //prevent download images
options.AddArguments(new string[] { "--headless", "'--disable-gpu'" }); //no window, no gpu
driver = new FirefoxDriver(options);
WindowsUtils.ShowWindow(WindowsUtils.FindWindowsWithText("geckodriver.exe").FirstOrDefault(), 0); //0 to hide, 1 to show
This solution will help you. Please note that hiding command prompt window is not recommended.
ChromeDriver
var driverService = ChromeDriverService.CreateDefaultService();
driverService.HideCommandPromptWindow = true;
var driver = new ChromeDriver(driverService, new ChromeOptions());
I know this isn't what you want but it could help if used in certain situations.
Writing driver.quit() will terminate the chrome window and the terminal it has open.

ASP.NET- using System.IO.File.Delete() to delete file(s) from directory inside wwwroot?

I have a ASP.NET SOAP web service whose web method creates a PDF file, writes it to the "Download" directory of the applicaton, and returns the URL to the user. Code:
//Create the map images (MapPrinter) and insert them on the PDF (PagePrinter).
MemoryStream mstream = null;
FileStream fs = null;
try
{
//Create the memorystream storing the pdf created.
mstream = pgPrinter.GenerateMapImage();
//Convert the memorystream to an array of bytes.
byte[] byteArray = mstream.ToArray();
//return byteArray;
//Save PDF file to site's Download folder with a unique name.
System.Text.StringBuilder sb = new System.Text.StringBuilder(Global.PhysicalDownloadPath);
sb.Append("\\");
string fileName = Guid.NewGuid().ToString() + ".pdf";
sb.Append(fileName);
string filePath = sb.ToString();
fs = new FileStream(filePath, FileMode.CreateNew);
fs.Write(byteArray, 0, byteArray.Length);
string requestURI = this.Context.Request.Url.AbsoluteUri;
string virtPath = requestURI.Remove(requestURI.IndexOf("Service.asmx")) + "Download/" + fileName;
return virtPath;
}
catch (Exception ex)
{
throw new Exception("An error has occurred creating the map pdf.", ex);
}
finally
{
if (mstream != null) mstream.Close();
if (fs != null) fs.Close();
//Clean up resources
if (pgPrinter != null) pgPrinter.Dispose();
}
Then in the Global.asax file of the web service, I set up a Timer in the Application_Start event listener. In the Timer's ElapsedEvent listener I look for any files in the Download directory that are older than the Timer interval (for testing = 1 min., for deployment ~20 min.) and delete them. Code:
//Interval to check for old files (milliseconds), also set to delete files older than now minus this interval.
private static double deleteTimeInterval;
private static System.Timers.Timer timer;
//Physical path to Download folder. Everything in this folder will be checked for deletion.
public static string PhysicalDownloadPath;
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
deleteTimeInterval = Convert.ToDouble(System.Configuration.ConfigurationManager.AppSettings["FileDeleteInterval"]);
//Create timer with interval (milliseconds) whose elapse event will trigger the delete of old files
//in the Download directory.
timer = new System.Timers.Timer(deleteTimeInterval);
timer.Enabled = true;
timer.AutoReset = true;
timer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimedEvent);
PhysicalDownloadPath = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + "Download";
}
private static void OnTimedEvent(object source, System.Timers.ElapsedEventArgs e)
{
//Delete the files older than the time interval in the Download folder.
var folder = new System.IO.DirectoryInfo(PhysicalDownloadPath);
System.IO.FileInfo[] files = folder.GetFiles();
foreach (var file in files)
{
if (file.CreationTime < DateTime.Now.AddMilliseconds(-deleteTimeInterval))
{
string path = PhysicalDownloadPath + "\\" + file.Name;
System.IO.File.Delete(path);
}
}
}
This works perfectly, with one exception. When I publish the web service application to inetpub\wwwroot (Windows 7, IIS7) it does not delete the old files in the Download directory. The app works perfect when I publish to IIS from a physical directory not in wwwroot. Obviously, it seems IIS places some sort of lock on files in the web root. I have tested impersonating an admin user to run the app and it still does not work. Any tips on how to circumvent the lock programmatically when in wwwroot? The client will probably want the app published to the root directory.
Your problem may be related to the fact that IIS reloads the Web Service Application if the directory or files contained in the main folder changes.
Try creating / deleting files in a temporary folder which is outside the root folder of your application (be aware of permissions on the folder to allow IIS to read/write files).
Instead of writing directly to the file system, why not use isolated storage?
http://msdn.microsoft.com/en-us/library/system.io.isolatedstorage.isolatedstorage.aspx
This should solve any location or permission based issues that you are having
I forgot to come back and answer my question.
I had to give the IIS_IUSRS group Modify permissions to the directory where I was reading/writing files.
Thanks to all those who answered.

Resources