I have added a CEF control into a WinForm. And I have added an invokeCapture method that is expected to capture the screen shot of the entire page of the CEF. It works fine when first invoking. But errors are encountered since second invoking and more, which the message is "Generated MessageID 100002 doesn't match returned Message Id 100001". How can I capture screen shot more than once?
I have copied the screenshot function code from https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Example/DevTools/DevToolsExtensions.cs to my project and renamed the namespace of it to winformcefdemo.CefSharp.Example.
The variable lastMessageId of the class DevToolsClient, in which class CaptureScreenshot executes ExecuteDevToolsMethodAsync in order to run command "Page.CaptureScreenshot", is private and there are either no getter nor setter to it. It seems to be annoying. The method ExecuteDevToolsMethodAsync would want to compare the message ID of what the method ExecuteDevToolsMethod returns to the automatically increased message ID of the DevToolsClient itself. The DevtoolsClient in the method CaptureScreenShotAsPng is what browser.GetDevToolsClient() returns (in the line 36 of the link above). And I have also checked the implementation of the method GetDevToolsClient. It is also using DevToolsClient devToolsClient = new DevToolsClient(browser); in CefSharp.DevToolsExtensions.
private async void invokeCapture()
{
try
{
byte[] result = await winformcefdemo.CefSharp.Example.DevTools.DevToolsExtensions.CaptureScreenShotAsPng(browser);
// task.Start();
// byte[] result = task.Result;
SaveFileDialog dialog = new SaveFileDialog();
DialogResult dresult = dialog.ShowDialog();
if (dresult == DialogResult.OK)
{
string path = dialog.FileName;
try
{
File.WriteAllBytes(path, result);
MessageBox.Show(path + " saved success");
} catch (Exception e)
{
MessageBox.Show(path + "Unknown error occurred when saving to file: " + e.Message);
}
}
}
catch (Exception ee)
{
MessageBox.Show("Unknown error occurred when capturing: " + ee.Message);
}
}
Solved in Chinese community of CSDN
Use no DevToolsExtensions. Use PageClient Instead. DevToolsExtensions does have issues that are not solved.
And PageClient should be defined globally. Do not define it in the method.
# Source: https://bbs.csdn.net/topics/398544662
CefSharp.DevTools.Page.PageClient pageClien= null;
private async void invokeCapture()
{
if(pageClien==null)
{
pageClien = webBrowser.GetBrowser().GetDevToolsClient().Page;
}
var result = await pageClien.CaptureScreenshotAsync();
if (result.Data != null)
{
MemoryStream ms = new MemoryStream(result.Data);
ms.Write(result.Data, 0, result.Data.Length);
SaveFileDialog dialog = new SaveFileDialog();
dialog.Filter = "PNG Picture (*.PNG)|*.PNG";
DialogResult dresult = dialog.ShowDialog();
if (dresult == DialogResult.OK)
{
string path = dialog.FileName;
try
{
File.WriteAllBytes(path, result);
MessageBox.Show(path + " saved success");
} catch (Exception e)
{
MessageBox.Show(path + "Unknown error occurred when saving to file: " + e.Message);
}
}
}
}
Related
I was working on my windows form program, and i saw that the login function (linked to a simple button) freeze my application. I searched on internet and i found how to create a task, but i'm not sure about how it works ...
That's my login function, how can i correctly translate it into a task?
string sURL = url + "/login";
string result = null;
await Task.Run(() =>
{
try
{
result = Web_api.MakeRequest("POST", sURL); //return null if there is some error
}
catch(Exception ex)
{
Debug.WriteLine("[frmLogin] --> result: " + result);
}
});
if(result != null)
{
try
{
Login_response accepted = JsonConvert.DeserializeObject<Login_response>(result);
Debug.WriteLine("[frm_Login] --> accepted: " + accepted);
if (accepted.login)
{
//throw new Exception();
Debug.WriteLine("[frm_login]: result " + result);
frmMain frm = new frmMain(); //calling the new form
frm.Show(); //new form is show-up
this.Hide(); //log-in form hide
frm.FormClosed += Frm_FormClosed; //close the form
}
}
//if server is down, or the id or password is wrong
catch (Exception ex)
{
lblLoginError.Visible = true; //pop-up the error label
pbLogin.Visible = false; //hide the progress-bar
this.Style = MetroFramework.MetroColorStyle.Red; //changing the color of the form
Debug.WriteLine("Exception: " + ex);
}
}
else
{
lblLoginError.Visible = true; //pop-up the error label
pbLogin.Visible = false; //hide the progress-bar
this.Style = MetroFramework.MetroColorStyle.Red; //changing the color of the form
}
EDIT: i provided a real (and working) soluction and i followed all the suggestion in the comments ... do you think this could be acceptable?
Execute any potentially long-running code on a background thread using a Task:
private async void btnLogin_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtUser.Text.Trim()) || string.IsNullOrEmpty(txtPassword.Text.Trim()))
{
MessageBox.Show("You must insert a valid user/password format", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
//Progress bar start
pbLogin.Visible = true; // BUT THIS PROGRESS BAR I STACK DUE TO STATIC DEFINITON OF LOGIN
//Getting ID + Password
User.username = txtUser.Text;
User.password = txtPassword.Text;
string sURL = Web_api.url + "/login";
try
{
Login_response accepted = await Task.Run(() =>
{
//the following code gets executed on a background thread...
string result = Web_api.MakeRequest("POST", sURL);
Login_response accepted = JsonConvert.DeserializeObject<Login_response>(result);
Debug.WriteLine("[frm_Login] --> accepted: " + accepted);
return accepted;
});
//...and here you are back on the UI thread once the task has completed
if (accepted.login)
{
//throw new Exception();
Debug.WriteLine("[frm_login]: result " + result);
frmMain frm = new frmMain(); //calling the new form
frm.Show(); //new form is show-up
this.Hide(); //log-in form hide
frm.FormClosed += Frm_FormClosed; //close the form
}
}
//if server is down, or the id or password is wrong
catch (Exception ex)
{
lblLoginError.Visible = true; //pop-up the error label
pbLogin.Visible = false; //hide the progress-bar
this.Style = MetroFramework.MetroColorStyle.Red; //changing the color of the form
Debug.WriteLine("Exception: " + ex);
}
}
Event handlers always return void. They are an exception to the rule that says that an async method always should return a Task or a Task<T>.
You can create an async void method. It is actually the correct way to implement async callbacks for events such as button click.
First, let's make an asynchronous login method :
public async Task LoginAsync()
{
try
{
var stream = await _http.GetStreamAsync($"{baseUrl}/login");
var response = await JsonSerializer.DeserializeAsync<LoginResponse>(stream);
if (!response.login)
{
throw new BusinessException<LoginError>(LoginError.LoginDenied);
}
}
catch (HttpRequestException ex)
{
throw new BusinessException<LoginError>(LoginError.LoginFailed, ex);
}
}
Now we implement an asynchronous button callback:
private async void btnLogin_Click(object sender, EventArgs e)
{
try
{
await authentication.LoginAsync().ConfigureAwait(false);
// handle login success here
}
catch (BusinessException<LoginError> ex) when (ex.Error == LoginError.LoginDenied)
{
// handle login denied here
}
catch (BusinessException<LoginError> ex) when (ex.Error == LoginError.LoginFailed)
{
// handle connection failed here
}
}
If you want the LoginAsync() method to do some UI operations (for instance showing a form), you will need to use ConfigureAwait(true). Otherwise, there is a risk that part of the method is executed on a different thread and UI operations will fail.
I am trying to save, modified changes in an existing powerpoint file loaded from disk. i was successfully able to open the file.
While tried to save edited (already existing) powerpoint file using saveas method, exception is observed.
private void adxPowerPointAppEvents1_PresentationBeforeSave(object sender, ADXHostBeforeActionEventArgs e)
{
try
{
PowerPoint.Presentation pre = e.HostObject as
PowerPoint.Presentation;
// cancel this operation
e.Cancel = true;
//save
pre.SaveAs(pre.Name,
PowerPoint.PpSaveAsFileType.ppSaveAsDefault,Office.MsoTriState.msoTrue);
MessageBox.Show("you will not see me due to exception");
}
catch(Exception e){}
}
When code is executed, enter image description here
The approach used in msword and msexcel were not working.
If there would be either approach to save the edited file, kindly help me ..
Got solution for this problem...
Like in word, excel we can't make save() operation... Powerpoint throws an exception if we call save or saveas from the same event handler(function).Accordingly, you must call SaveAs outside of that event handler, after PowerPoint invokes it.
private void adxPowerPointAppEvents_PresentationBeforeSave(object sender, ADXHostBeforeActionEventArgs e)
{
PowerPoint.Presentation pre = e.HostObject as PowerPoint.Presentation;
try
{
if (pre.Saved == Microsoft.Office.Core.MsoTriState.msoFalse)
{
e.Cancel = true;
GCHandle handle = GCHandle.Alloc(pre.FullName);
IntPtr parameter = (IntPtr)handle;
this.SendMessage(MESSAGE_SAVE_PPT, parameter, IntPtr.Zero);
pre.Saved = Microsoft.Office.Core.MsoTriState.msoTrue;
}
}
catch(Exception ex)
{
Log.Info("Exception while saving powerpoint : " + ex.StackTrace);
MessageBox.Show(ex.Message);
}
return;
}
private void AddinModule_OnSavePowerPointMessage(object sender, AddinExpress.MSO.ADXSendMessageEventArgs e)
{
if (e.Message == MESSAGE_SAVE_PPT)
{
PowerPoint.Presentation ppPre = null;
try
{
GCHandle handle = (GCHandle)e.WParam;
String fullName = (handle.Target as String);
ppPre = PowerPointApp.Presentations[fullName];
if (ppPre != null)
{
ppPre.Saved = Microsoft.Office.Core.MsoTriState.msoTrue;
//ppPre.SaveAs(ppPre.FullName, PowerPoint.PpSaveAsFileType.ppSaveAsDefault, Microsoft.Office.Core.MsoTriState.msoTrue);
ppPre.Save();
Log.Info("Value of pre.name " + ppPre.Name);
}
}
catch (Exception exSavePpt)
{
Log.Info("Exception while saving powerpoint : " + exSavePpt.StackTrace);
}
}
}
Actually, in AddinModule_OnSavePowerPointMessage(), We should not pass COM objects which would create com exception. So instead that we should pass presentation name(ppt.fullname) and create com reference pointing to same object in the second method. So, without any trouble now i could save ppt files...
I have this code in my application that allows user to download the newest version of the application. When the application download is finished, it opens a prompt if user wants to open the file location to see the file.
However, the tool launches two Message boxes instead of only once. I'm not sure if I'm missing something.
private void BTN_GNV_MouseUp(object sender, MouseButtonEventArgs e)
{
string URLDir = "http://shard.combatkingz.com/downloads/";
string URLName = "DayZ Config Tweak tool v" + Properties.Settings.Default.AvailableVersion + ".exe";
string URLFull = "";
using (WebClient DLWC = new WebClient())
{
URLFull = URLDir + URLName;
GlobalVars.DLPath = System.Environment.CurrentDirectory + "\\" + URLName;
try
{
DLWC.DownloadFileAsync(new Uri(URLFull), GlobalVars.DLPath);
DLWC.DownloadProgressChanged += DLWC_DownloadProgressChanged;
}
catch
{
MessageBox.Show("There was an error downloading the file.", GlobalVars.APPNAME, MessageBoxButton.OK, MessageBoxImage.Error);
#if DEBUG
#else
AddDownloadToDB("Failed");
#endif
}
}
}
void DLWC_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
PB_GNV.Width = (BTN_GNV.Width / 100) * e.ProgressPercentage;
if (PB_GNV.Width == BTN_GNV.Width && e.TotalBytesToReceive == e.BytesReceived)
{
MessageBoxResult nav = MessageBox.Show("New version downloaded. Do you want to navigate to the folder?", GlobalVars.APPNAME, MessageBoxButton.YesNo, MessageBoxImage.Error);
if (nav == MessageBoxResult.Yes)
{
string argument = #"/select, " + #GlobalVars.DLPath;
System.Diagnostics.Process.Start("explorer.exe", argument);
#if DEBUG
#else
AddDownloadToDB("Success");
#endif
}
}
}
I suspect that the DownloadProgressChanged event is firing on receiving the last byte and on the file completed. Using the DownloadFileCompleted event should resolve the problem.
This is a code that I wrote for my open button ... but I have error on "DisplayErrorMessage" part.
What should I write instead? or how can I define it in order not to have the error again.
protected void btnOpen_Click(object sender, EventArgs e)
{
txtFileName.Text = txtFileName.Text.Trim();
if (txtFileName.Text == string.Empty)
{
string strErrorMessage = "you did Not specify file for opening!";
DisplayErrorMessage(strErrorMessage);
}
string strFileName = txtFileName.Text;
string strRootRelativePath = "~/app_data/pageContent";
string strRootRelativePathName =
string.Format("{0}/{1}", strRootRelativePath, strFileName);
string strPathName = Server.MapPath(strRootRelativePathName);
System.IO.StreamReader ostreamReader = null;
try
{
ostreamReader = new System.IO.StreamReader(strPathName, System.Text.Encoding.UTF8);
litPageMessages.Text = ostreamReader.ReadToEnd();
}
catch (Exception ex)
{
litPageMessages.Text = ex.Message;
}
finally
{
if (ostreamReader != null)
{
ostreamReader.Dispose();
ostreamReader= null;
}
}
}
If you want to alert your error message in the browser, you could do the following.
Add a class file in your App_Code folder, say Helpers.cs
Then, open it and add the following code:
public class Helpers
{
public static void DisplayErrorMessage(Page page, string msg)
{
string script = "<script>alert('" + msg + "');</script>";
if (!page.ClientScript.IsStartupScriptRegistered("MyAlertMsgHandler"))
page.ClientScript.RegisterStartupScript(page.GetType(), "MyAlertMsgHandler", script);
}
}
Lately, call this method from your code behind like this:
Helpers.DisplayErrorMessage(this.Page, "Error message details.");
Either create a function which takes message in the parameter and use MessageBox.Show() method to Display the error message.
or
Just Call MessageBox.Show( this, strErrorMessage ) instead of DisplayErrorMessage(strErrorMessage);
Try This...
void DisplayErrorMessage(string msg)
{
string script = "<script>alert('" + msg + "');</script>";
if (!Page.IsStartupScriptRegistered("myErrorScript"))
{
Page.ClientScript.RegisterStartupScript("myErrorScript", script);
}
}
I'm building a FTP application for Windows Phone 8, and want to save the downloaded songs from the isolated storage to the media library. I check if the file exists in isostore, and it returns true, but when I'm using the SaveSong method it always throws an exception. Here is the code sample:
private async void contextMenuItem1_Click(object sender, RoutedEventArgs e)
{
string fileName = (sender as MenuItem).DataContext.ToString();
MediaLibrary library = null;
......
else if (fileName.EndsWith(".mp3") || fileName.EndsWith(".wav") || fileName.EndsWith(".aac"))
{
IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication();
if (myIsolatedStorage.FileExists(fileName))
{
library = new MediaLibrary();
StorageFile localFile = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
if (localFile != null)
{
//MessageBox.Show("StorageFile is: " + localFile.Name);
try
{
library.SaveSong(new Uri(localFile.Name, UriKind.RelativeOrAbsolute), null, SaveSongOperation.CopyToLibrary);
//MediaLibraryExtensions.SaveSong(media, new Uri(fileName, UriKind.RelativeOrAbsolute), null, SaveSongOperation.CopyToLibrary);
}
catch (InvalidOperationException ex)
{
MessageBox.Show("Exception caught: " + ex.Message);
}
}
}
else
MessageBox.Show("File does not exist in isostore");
}
}
I wolud be very grateful if anybody could help me, thx.
If your file name or file path is null then this exception comes.Also please verify ID_CAP_MEDIALIB_AUDIO capability added or not.
FYI