Hello I tried looking through questions that may have my answer but none of them did.
I am doing web automation testing and trying to take a screenshot of when an error occurs and save it to a file in another folder.
My program has a 30 second timeout when searching for elements on the page. If after 30 seconds no element is found, it takes a SS, reloads the page, and tries again.
The first screenshot works fine. But on the second run through, it tries to save another screenshot to the folder and I get this incredibly vague error that is seemingly caused by a hundred different things, so I'm not quite sure what the problem is.
Here's my code:
public void takeScreenShot()
{
string ssPath = _persistencePath += "\\Errors";
string currTime = DateTime.Now.ToString(#"MMM-ddd-d-HH.mm");
Screenshot ss = ((ITakesScreenshot)_driver).GetScreenshot();
try
{
ss.SaveAsFile(ssPath + "\\ERROR-" + currTime + ".png", System.Drawing.Imaging.ImageFormat.Png);
ssCount = 0;
}
catch (System.Runtime.InteropServices.ExternalException)
{
ssCount++;
//error occurs here
ss.SaveAsFile(ssPath + "\\ERROR-" + currTime + "(" + ssCount + ")" + ".png", System.Drawing.Imaging.ImageFormat.Png);
}
I initially thought the issue was that it was trying to save a file of the same name, because if the error happens during the same minute then the file name is the same. So that's why I added that catch block, in an attempt to change the name if it occurs in the same minute. But that didn't fix it.
Again I tried searching all over and couldn't find an answer. Any help is greatly appreciated.
Well, if anyone's curious I solved it. Turns out I'm just an idiot.
string ssPath = _persistencePath += "\\Errors";
this line was appending another \Errors to the target path on the second run though. thus invalidating the path, because \Errors\Errors didn't exist.
Thanks to everyone who commented/tried to help!
The Screenshot class doesn't dispose of the image resource properly, so it may be a bug in the Selenium framework. A work-around is to do it yourself:
public void takeScreenShot()
{
string ssPath = System.IO.Path.Combine(_persistencePath, #"\Errors");
string currTime = DateTime.Now.ToString(#"MMM-ddd-d-HH.mm");
string fileName = System.IO.Path.Combine(ssPath, #"\ERROR-" + currTime + ".png");
Screenshot ss = ((ITakesScreenshot)_driver).GetScreenshot();
using (MemoryStream ms = new MemoryStream(ss.AsByteArray))
using (Image screenShotImage = Image.FromStream(ms))
{
Bitmap cp = new Bitmap(screenShotImage);
cp.Save(filename, ImageFormat.Png);
cp.Dispose();
}
}
No assurance that this will fix it, but at least you can be reasonable assured that the resources are disposed of properly.
Note requires you to reference System.Drawing.dll in the project.
Edit another workaround posted.
Finally i did it!
check out this, just write completed PATHNAME,
pathname+filename+extension: #"C:\folderWithPermission\test.bmp"
JUST TAKE FOLDER WITH WRITE PERMISSIONS, was like o.0
here's the method
public DriverExecutor CaptureScreen(string filename)
{
Screenshot shot = this.myRemoteWebDriver.GetScreenshot();
MemoryStream ms;
Image imgShot;
Bitmap bitmap;
try
{
using (ms = new MemoryStream(shot.AsByteArray))
using (imgShot = Image.FromStream(ms))
using (bitmap = new Bitmap(imgShot))
{
bitmap.Save(filename, ImageFormat.Bmp);
}
}catch(Exception err){}
return this;
}
NOTE: im asssuming what remoteDriver was rightly instanced and encapsulated on a own object , i hope this help you all ^^
Related
today, I've run into a bit of a problem.
The image object you can see below keeps giving me an outofmemory exception
as I iterate through the list of files.
I'm trying to make a list of resolutions of each image.
I've tried disposing it to remove the object from memory but that doesn't seem to work....
List<string> temp = new List<string>();
Image img;
foreach(string s in fileArray)
{
img = Image.FromFile(s);
temp.Add(img.Width.ToString() + "x" + img.Height.ToString());
img.Dispose();
}
Glad that you got the problem figured out!
FYI: Whenever you are utilizing a type that wraps unmanaged resources, you will want to use a using block. Details:
https://msdn.microsoft.com/en-us/library/yh598w02.aspx
Here is your sample re-written with the using (and var instead of explicitly defined types)
var temp = new List<string>();
foreach(var s in fileArray)
using(var img = Image.FromFile(s))
{
temp.Add(img.Width.ToString() + "x" + img.Height.ToString());
}
I desperately need help with an issue I am having while trying load an image or unload an image using ASP/C#. The problem I am having is the first time I run the code and Load the image into the thumbnail, I have no problem but the minute I try to remove the picture or load a second or third image, it takes very very long to hit the event and I get an Out of Memory error. I think something is getting locked and takes a while to get unlocked but I am not sure.
Here is the code I am using:
protected void btnUploadImgPicture1_ServerClick(object sender, EventArgs e)
{
using (filePicture1)
{
if (filePicture1.PostedFile.FileName != "")
{
imageUtil = new ImageUtility();
string realPhysicalPath = Path.Combine(Server.MapPath("~/upload/"), filePicture1.PostedFile.FileName);
filePicture1.PostedFile.SaveAs(realPhysicalPath);
//imgVehiclePicture1.Src = realPhysicalPath;
using (imgVehiclePicture1)
{
imgVehiclePicture1.Attributes["src"] = imageUtil.getBase64String(realPhysicalPath);
Session.Add("Image1", realPhysicalPath);
imageUtil = null;
}
}
}
}
public string getBase64String(string path)
{
Image img = Image.FromFile(path);
byte[] imageBytes = imageToByteArray(img);
string base64String = Convert.ToBase64String(imageBytes, 0, imageBytes.Length);
return "data:image/png;base64," + base64String;
}
I am using this code on 3 times for 3 different events and then I am using similar code to remove the selected image from the upload.
What is ImageUtility? If it implements IDisposable then you might want to try explicitly disposing it instead of setting the variable to null. Even better if you can wrap it inside of a using block.
am using url for downloading images and save the current user login path but occurse error is
a generic error occurred in gdi+.
becouse i think system geting path of this format :-C:\\Users\\admin\\Pictures
but i want C:\Users\admin\Pictures
so please solve my problems to stackoverflow team
am using a this code and geting a error....
string userpath=Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
string Sourceurl = url;
userpath += id;
userpath += ".jpg";
Bitmap varBmp = (Bitmap)Bitmap.FromStream(WebRequest.Create(url).GetResponse().GetResponseStream());
Bitmap newBitmap = new Bitmap(varBmp);
varBmp.Dispose();
varBmp = null;
//do something
newBitmap.Save(userpath, ImageFormat.Png);
shimpi mahesh
pune.
Try using Path.Combine as in
string userpath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "123" + ".jpg");
To view the value correctly don't rely on mouse over, that shows the escaped string, to see the reality use the magnify icon near the value, a new window will appear.
Hi i have the following Function:
private void CreateRoomImage(string path)
{
Directory.CreateDirectory(path);
var file = "";
foreach (PanelView panelView in pv)
{
var RoomImage = GetRaumImageName(panelView.Title);
file = path + GetImageFile(RoomImage);
if (File.Exists(file))
{
File.Delete(file);
}
using (var img = GetRaumImage(panelView.Title, panelView))
{
ImageWriter imgWriter = new ImageWriter(ImageFormat.Bmp);
imgWriter.Save(img, file);
}
}
}
My Problem is that everytime i try to Delete the existing File my programm is throwing an exception:
The process can not access the file because it is being used by another process
Is there a solution for this Problem? How can i delete the existing image?
It seems like this could be a weird race condition where the file.exists hasn't released the resource and it is trying to delete prior to release. I would probably try something along these lines.
try
{
File.Delete(file);
}
catch
{
//File does not exist or another error occurred.
}
I found it on my Own.
In PageLoad i use thet "file" also. I forgot to dispose the Image:
foreach (PanelView panel in pv)
{
path = Request.PhysicalPath.Substring(0, Request.PhysicalPath.LastIndexOf('\\') + 1) + subPath + "\\" + GetRaumImageName(panel.Title);
bitMap = new Bitmap(path + ".bmp");
b0 = BmpToMonochromConverter.CopyToBpp(bitMap, 1);
// bounce.updateInterface.UpdateProductImage(b0, panel.Panel.PRODUCT_ID, "", ref update_Handle);
bitMap.Dispose();
}
Anyway thanks for help!
Why delete file in the first place? Can't you make it overwrite the existing file if it already exists?
Another thing you can do is to pause the thread for like 400ms until OS does it's thing and files are completely deleted and all streams closed.
Alright it has come to this. I searched this website among many others and no one can seem to give me a straight answer so I'm going to try just asking outright. Been on this issue for about a solid 3 days and I can't afford to waste any more time on it.
Goal: The app I am building is in WPF and is going to be used as a bug tracker for a project my design team and I will be undertaking soon. Since we are going to be building a game in C++ most of the errors that occur will have a visual element to them so I inlcuded functionality to provide an image of the error in question when the user adds a bug to the list. I then take that image and save it to a local directory (for testing). Now the image path in the Error object points to a path that leads to the local directory. This functionality has been tested and works fine. My problem showes up when I want to delete a bug from the list. I am getting that very infamous "IO Exception" saying that the image I want to delete is being used by another process.
So Far: At first I tried very elegant solutions, but as with all things you get to a point where you just want to see if you can get the thing to even work at all. So I am at the point where most of the code I am using is experimental and radical. So please when looking at it note that the code being used is out of desperation, so any "simple" solutions have probably already been tried (I did research this a lot becuase I hate having to do this). Things i can think of off the top of my head are the obsurd amount of disposes and forced garbage collections being called so please to not comment on the negative nature of this practice, I am well aware :).
The Code
Saving image to local directory
public void OnBrowseClick()
{
Microsoft.Win32.OpenFileDialog openBox = new Microsoft.Win32.OpenFileDialog();
// Show dialog box to user and grab output
Nullable<bool> result = openBox.ShowDialog();
if (result == true)
{
// Create temp variable to hold local path string
string localPath = Directory.GetCurrentDirectory();
// Grab the extension of the specified file path
string extension = openBox.FileName.Substring(openBox.FileName.LastIndexOf("\\"));
// Add extension to local path
localPath += extension;
// Create local copy of image at given file path (being ridiculous at this point)
using (Stream stream = new FileStream(openBox.FileName, FileMode.Open, FileAccess.ReadWrite))
{
using (Bitmap bmp = LoadImage(stream))
{
using (Bitmap temp = (Bitmap)bmp.Clone())
{
temp.Save(localPath);
temp.Dispose();
}
bmp.Dispose();
}
stream.Dispose();
}
// Set the URL in the image text box (UI stuff)
LocalError.ImagePath = localPath;
}
}
The following is the LoadImage function that is used in the function above
private Bitmap LoadImage(Stream stream)
{
Bitmap retval = null;
using (Bitmap bitmap = new Bitmap(stream))
{
retval = new Bitmap(bitmap.Width, bitmap.Height, bitmap.PixelFormat);
using (Graphics gdi = Graphics.FromImage(retval))
{
gdi.DrawImageUnscaled(bitmap, 0, 0);
gdi.Flush();
gdi.Dispose();
bitmap.Dispose();
}
}
// Garbage collection here to be safe
GC.WaitForPendingFinalizers();
GC.Collect();
return retval;
}
And finally we come to where I try to delete the image
public void OnDeleteClick()
{
// Ask user to make sure they want to delete selected item(s)
MessageBoxResult result = MessageBox.Show("Are you sure you want to delete selected item(s) from the list?",
"Delete", MessageBoxButton.YesNo);
if (result == MessageBoxResult.Yes)
{
for( int i = 0; i < Parent.ErrorListControl.ErrorDataGrid.SelectedItems.Count; ++i)
{
// Get path to image
string path = (Parent.ErrorListControl.ErrorDataGrid.SelectedItems[i] as Error).ImagePath;
// Even tried calling garbage collection here!!!!!
System.GC.WaitForPendingFinalizers();
System.GC.Collect();
File.Delete(path);
// Remove the error from the error list
Parent.ErrorListVM.ErrorList.Remove((Error)Parent.ErrorListControl.ErrorDataGrid.SelectedItems[i]);
// Decrement counter because we altered the list while in a loop
i--;
}
}
}
Notes: If anyone would like me to explain anything further or if you need to know something I left out please just ask I will get back to you ASAP! Any suggestions are helpful at this point I have absolutley no idea what I am doing wrong. I generally only program in a C++ environment so I tend to manage my own memory this whole "garbage collection" thing is really throwing a wrench in our project! (Off topic note: I do not know why I am not getting any color highlighting so I apologize to anyone who takes the time to read this).
Here's a simple way to do what you want. In this example, I'm using Path.GetTempFileName() to generate a random file name in the local user's temp directory. If you don't need to persist the files then it's a good place to store them temporarily. Also, the user could theoretically import two files with the same name. So you want to use some kind of random filename generation or other mechanism to avoid conflicts.
private void browseButton_Click(object sender, RoutedEventArgs e)
{
var openFileDialog = new Microsoft.Win32.OpenFileDialog();
if (openFileDialog.ShowDialog(this) == true)
{
using (Bitmap originalImage = new Bitmap(openFileDialog.FileName))
{
string tempFileName = System.IO.Path.GetTempFileName();
originalImage.Save(tempFileName);
// LocalError.LocalPath
LocalPath = tempFileName;
}
}
}
private void deleteButton_Click(object sender, RoutedEventArgs e)
{
if (File.Exists(LocalPath))
{
File.Delete(LocalPath);
}
}
Although a simple File.Copy should suffice as long as you have the right paths, I was just providing a solution that matched your question.
EDIT:
Actually the current directory does not seem to be changed by the OpenFileDialog. I could swear that it did at some point. So I don't think this is your problem. Regardless, this code still works for me and you shouldn't require anything more complicated than this.
EDIT #2:
It seems the lock is actually caused by the image being databound to the view and presumably locked by the BitmapSource. You should be able to create it without locking the file. Generally, this is slower so don't do it this way unless you need to be able to modify or delete the file.
bitmapSource = new BitmapImage();
bitmapSource.BeginInit();
bitmapSource.CacheOption = BitmapCacheOption.OnLoad;
bitmapSource.CreateOption = BitmapCreateOptions.IgnoreImageCache;
bitmapSource.UriSource = new Uri(ImagePath, UriKind.Absolute);
bitmapSource.EndInit();
Since your LoadImage method does simple copy of the image, why not use File.Copy(source, dest) and avoid all the bitmaps, drawings, etc? Your goal might be to modify local bitmap after it's created, but it can still be done after copy.
Also, when using the using block, explicit .Dispose() is not required, as using block does it for you:
using (var obj = new SomeDisposableObject())
{
// code here
// obj.Dispose(); <-- not needed, since...
} // ...at this point obj.Dispose is called automatically.