How to delete folder after MediaElement in WPF play file - wpf

I am testing MediaElement in WPF.
but frequently Directory.Delete function show error.
I don't know Why the error occurs.
MediaElement mediatest = new MediaElement();
mediatest.LoadedBehavior = MediaState.Manual;
root.Children.Add(mediatest);
mediatest.BeginInit();
mediatest.Source = null;
mediatest.Source = new Uri(MediaSrc);
mediatest.EndInit();.
mediatest.Play();
stop()
mediatest.Stop();
mediatest.Close();
mediatest.Source = null;
mediatest = null;
root.Children.Clear();
System.IO.Directory.Delete(System.IO.Path.Combine(Environment.CurrentDirectory, #"sound"), true);

Try to use instead of Directory.Delete the following method:
public static void DeleteDirectory(string target_dir)
{
string[] files = Directory.GetFiles(target_dir);
string[] dirs = Directory.GetDirectories(target_dir);
foreach (string file in files)
{
File.SetAttributes(file, FileAttributes.Normal);
File.Delete(file);
}
foreach (string dir in dirs)
{
DeleteDirectory(dir);
}
Directory.Delete(target_dir, false);
}

I tried it, but the same issue appear. and I am trying to check it.
mediatest.Stop();
mediatest.Close();
mediatest.Source = null;
mediatest = null;
root.Children.Clear();
GC.Collect();
but the same issue appear again.
and then I changed source following
GC.Collect();
Thread.Sleep(500);
now I didn't see an error so far.

Related

FileSystemStorage isDirectory returns false for a directory

I am trying to write a file browser in CN1 to let the user select a profile picture for upload.
I tried using the FileSystemStorage's isDirectory() method, but it is returning false for a directory.
Code:
private void displayFiles(final Container c, String root)
{
c.removeAll();
FileSystemStorage fs = FileSystemStorage.getInstance();
try {
String files[] = fs.listFiles(root);
for(final String file: files)
{
System.out.println(file+"-->"+fs.isDirectory(file));
if(fs.isDirectory(file))
{
Button b = new Button("Folder::"+file);
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
displayFiles(c, file);
}
});
c.addComponent(b);
}else
{
Container c1 = new Container(new BoxLayout(BoxLayout.X_AXIS));
Label l = new Label("File::"+file);
CheckBox cb = new CheckBox();
c1.addComponent(l);
c1.addComponent(cb);
c.addComponent(c1);
}
}
} catch (IOException ex) {
}
c.revalidate();
}
Output:
CN1Log__$-->false
CN1Preferences-->false
Cookies-->false
data-->false
FaceBookAccesstmp652635968-->false
folder1-->false
folder2-->false
HELLOCN1FS-->false
myFileName-->false
token-->false
Screenshot of the emulator:
Screenshot of the explorer
The behavior is same on the phone as well
Could this be a bug ?
Is there something that I am not doing correctly ?
Thanks
You need to use the full path for the file:
if(fs.isDirectory(root + file))

Loading Images in background while not locking the files

My application loads a lot of images in a BackgroundWorker to stay usable. My Image control is bound to a property named "ImageSource". If this is null it's loaded in the background and raised again.
public ImageSource ImageSource
{
get
{
if (imageSource != null)
{
return imageSource;
}
if (!backgroundImageLoadWorker.IsBusy)
{
backgroundImageLoadWorker.DoWork += new DoWorkEventHandler(bw_DoWork);
backgroundImageLoadWorker.RunWorkerCompleted +=
new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
backgroundImageLoadWorker.RunWorkerAsync();
}
return imageSource;
}
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
bitmap = new BitmapImage();
bitmap.BeginInit();
try
{
bitmap.CreateOptions = BitmapCreateOptions.DelayCreation;
bitmap.DecodePixelWidth = 300;
MemoryStream memoryStream = new MemoryStream();
byte[] fileContent = File.ReadAllBytes(imagePath);
memoryStream.Write(fileContent, 0, fileContent.Length);
memoryStream.Position = 0;
bitmap.StreamSource = memoryStream;
}
finally
{
bitmap.EndInit();
}
bitmap.Freeze();
e.Result = bitmap;
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
BitmapSource bitmap = e.Result as BitmapSource;
if (bitmap != null)
{
Dispatcher.CurrentDispatcher.BeginInvoke(
(ThreadStart)delegate()
{
imageSource = bitmap;
RaisePropertyChanged("ImageSource");
}, DispatcherPriority.Normal);
}
}
This is all well so far but my users can change the images in question. They choose a new image in an OpenDialog, the old image file is overwritten with the new and ImageSource is raised again which loads the new image with the same filename again:
public string ImagePath
{
get { return imagePath; }
set
{
imagePath= value;
imageSource = null;
RaisePropertyChanged("ImageSource");
}
}
On some systems the overwriting of the old file results in an exception:
"a generic error occured in GDI+" and "The process cannot access the file..."
I tried a lot of things like loading with BitmapCreateOptions.IgnoreImageCache and BitmapCacheOption.OnLoad. This raised Exceptions when loading them:
Key cannot be null.
Parameter name: key
If I try this without the BackgroundWorker on the UI thread it works fine. Am I doing something wrong? Isn't it possible to load the images in the background while keeping the files unlocked?
Well, it seems all of the above works. I simplified the example for the question and somehow on the way lost the problem.
The only difference I could see in my code is that the loading of the image itself was delegated to a specific image loader class which somehow created the problem. When I removed this dependency the errors disappeared.

How can I save and open a file in winForms?

I have this application where I use windowsForm and UserControl to draw some diagrams. After I am done I want to save them or I want to open an existing file that I created before and keep working on the diagram. So, I want to use the save and open dialog File to save or open my diagrams.
EDIT:
this is what i have :
//save the object to the file
public bool ObjectToFile(Object model, string FileName)
{
try
{
System.IO.MemoryStream _MemoryStream = new System.IO.MemoryStream();
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter _BinaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
_BinaryFormatter.Serialize(_MemoryStream, model);
byte[] _ByteArray = _MemoryStream.ToArray();
System.IO.FileStream _FileStream = new System.IO.FileStream(FileName, System.IO.FileMode.Create, System.IO.FileAccess.Write);
_FileStream.Write(_ByteArray.ToArray(), 0, _ByteArray.Length);
_FileStream.Close();
_MemoryStream.Close();
_MemoryStream.Dispose();
_MemoryStream = null;
_ByteArray = null;
return true;
}
catch (Exception _Exception)
{
Console.WriteLine("Exception caught in process: {0}", _Exception.ToString());
}
return false;
}
//load the object from the file
public Object FileToObject(string FileName)
{
try
{
System.IO.FileStream _FileStream = new System.IO.FileStream(FileName, System.IO.FileMode.Open, System.IO.FileAccess.Read);
System.IO.BinaryReader _BinaryReader = new System.IO.BinaryReader(_FileStream);
long _TotalBytes = new System.IO.FileInfo(FileName).Length;
byte[] _ByteArray = _BinaryReader.ReadBytes((Int32)_TotalBytes);
_FileStream.Close();
_FileStream.Dispose();
_FileStream = null;
_BinaryReader.Close();
System.IO.MemoryStream _MemoryStream = new System.IO.MemoryStream(_ByteArray);
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter _BinaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
_MemoryStream.Position = 0;
return _BinaryFormatter.Deserialize(_MemoryStream);
}
catch (Exception _Exception)
{
Console.WriteLine("Exception caught in process: {0}", _Exception.ToString());
}
return null;
}
and now I want to do this but it's not working
public void save()
{
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "txt files (*.txt)|*.txt";
saveFileDialog1.FilterIndex = 2;
saveFileDialog1.RestoreDirectory = true;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
if (saveFileDialog1.OpenFile() != null)
{
ObjectToFile(model, saveFileDialog1.FileName);
}
}
}
but if I try without the fileDialog and i just use
ObjectToFile(model, "d:\\objects.txt");
this works. And I want to save it where I want and with my own name.
Check out the SaveFileDialog and OpenFileDialog classes. They are pretty similar, and can be used like this:
using(SaveFileDialog sfd = new SaveFileDialog()) {
sfd.Filter = "Text Files|*.txt|All Files|*.*";
if(sfd.ShowDialog() != DialogResult.OK) {
return;
}
ObjectToFile(sfd.FileName);
}
The mechanics of actually saving your file are, obviously, outside the scope of this answer.
Edit: I've updated my answer to reflect the new information in your post.

Delete image file used by XAML

I'm trying to delete a Image file in WPF, but WPF locks the file.
<Image Source="C:\person.gif" x:Name="PersonImage">
<Image.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete..." x:Name="DeletePersonImageMenuItem" Click="DeletePersonImageMenuItem_Click"/>
</ContextMenu>
</Image.ContextMenu>
</Image>
And the Click handler just looks like this:
private void DeletePersonImageMenuItem_Click(object sender, RoutedEventArgs e)
{
System.IO.File.Delete(#"C:\person.gif");
}
But, when I try to delete the file it is locked and cannot be removed.
Any tips on how to delete the file?
My application Intuipic deals with this by using a custom converter that frees the image resource. See the code here.
Using code behind, you can use the cache option BitmapCacheOption.OnLoad:
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bi.UriSource = new Uri(PathToImage);
bi.EndInit();
PersonImage.Source = bi;
Because I struggled to find it, I will add that if you want to replace the deleted image dynamically, you need to add the argument BitmapCreateOptions.IgnoreImageCache.
First Remove it from the PersonImage control then delete the image. Hope that will help.
As you have assigned to the control in source, and remove it without unassigning the control source.
PersonImage.Source = null;
System.IO.File.Delete(#"C:\person.gif");
hope that will help.
The most easiest way to do this will be, creating a temporary copy of your image file and using it as a source.. and then at end of your app, deleting all temp files..
static List<string> tmpFiles = new List<string>();
static string GetTempCopy(string src)
{
string copy = Path.GetTempFileName();
File.Copy(src, copy);
tmpFiles.Add(copy);
return copy;
}
static void DeleteAllTempFiles()
{
foreach(string file in tmpFiles)
{
File.Delete(file);
}
}
Image caching in WPF also can be configured to do this, but for some reason my various attempts failed and we get unexpected behaviour like not being able to delete or refresh the image etc, so we did this way.
Do not attach the physical file to the object.
BitmapImage bmp;
static int filename = 0;
static string imgpath = "";
private void saveButton_Click(object sender, RoutedEventArgs e)
{
try
{
filename = filename + 1;
string locimagestored = Directory.GetParent(Assembly.GetExecutingAssembly().Location).ToString();
locimagestored = locimagestored + "\\StoredImage\\";
imgpath = locimagestored + filename + ".png";
webCameraControl.GetCurrentImage().Save(imgpath);
Bitmap bitmap = new Bitmap(#imgpath);
IntPtr hBitmap = bitmap.GetHbitmap();
ImageSource wpfBitmap = Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); ;
if (filename == 1)
{
imgSavedOnline0.Source = wpfBitmap;
bitmap.Dispose();
}
else if (filename == 2)
{
imgSavedOnline1.Source = wpfBitmap;
bitmap.Dispose();
}
else if (filename == 3)
{
imgSavedOnline2.Source = wpfBitmap;
bitmap.Dispose();
}
else if (filename == 4)
{
imgSavedOnline3.Source = wpfBitmap;
bitmap.Dispose();
}
System.IO.DirectoryInfo di2 = new DirectoryInfo(locimagestored);
foreach (FileInfo file in di2.GetFiles())
{
file.Delete();
}
}
catch (Exception ex)
{
textBox1.Text = ex.Message;
}
}

BitmapFrame in another thread

I am using a WPF BackgroundWorker to create thumbnails. My worker function looks like:
private void work(object sender, DoWorkEventArgs e)
{
try
{
var paths = e.Argument as string[];
var boxList = new List<BoxItem>();
foreach (string path in paths)
{
if (!string.IsNullOrEmpty(path))
{
FileInfo info = new FileInfo(path);
if (info.Exists && info.Length > 0)
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.DecodePixelWidth = 200;
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.UriSource = new Uri(info.FullName);
bi.EndInit();
var item = new BoxItem();
item.FilePath = path;
MemoryStream ms = new MemoryStream();
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bi));
encoder.Save(ms);
item.ThumbNail = ms.ToArray();
ms.Close();
boxList.Add(item);
}
}
}
e.Result = boxList;
}
catch (Exception ex)
{
//nerver comes here
}
}
When this function is finished and before the BackgroundWorker "Completed" function is started, I can see on the output window on Vs2008, that a exception is generated. It looks like:
A first chance exception of type 'System.NotSupportedException' occurred in PresentationCore.dll
The number of exceptions generates equals the number of thumbnails to be generated.
Using "trial and error" method I have isolated the problem to:
BitmapFrame.Create(bi)
Removing that line (makes my function useless) also removes the exception.
I have not found any explanation to this, or a better method to create thumbnails in a background thread.
Lasse, I believe the problem arises because you are performing actions outside of the UI thread that need to be done within the UI thread. Creating UI elements (BitmapImage, BitmapFrame) and adding to UI Containers, I believe, should be done on the UI thread. (Someone correct me if I'm wrong here).
There are a few ways to create those elements on the UI thread without blocking the application for an excessive period of time. The easiest is probably using the BackgroundWorker's ProgressChanged event. ProgressChanged is invoked on the UI thread, which makes it perfect for this situation.
You can use the worker's ProgressChanged event and pass it the path needed to load a thumbnail in the UserState argument.
Thanks for your input. It made start to look for another solutions and I come up with this.
try
{
var paths = e.Argument as string[];
var boxList = new List<BoxItem>();
foreach (string path in paths)
{
using (Image photoImg = Image.FromFile(path))
{
int newWidth = 200;
int width = newWidth;
int height = (photoImg.Height * newWidth) / photoImg.Width;
var thumbnail = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage((System.Drawing.Image)thumbnail))
{
g.DrawImage(photoImg, 0, 0, width, height);
using (var ms = new System.IO.MemoryStream())
{
var item = new BoxItem();
item.FilePath = path;
thumbnail.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
item.ThumbNail = ms.ToArray();
boxList.Add(item);
}
}
}
}
e.Result = boxList;
}
catch (Exception exp)
{
}
Not using any UI elements .. and works nicely.
Thanks.
//lasse

Resources