I am using following code to create a file in isolated storage
mystorage = IsolatedStorageFile.GetUserStoreForApplication();
if (mystorage.FileExists(scanName))
{
mystorage.DeleteFile(scanName);
}
WriteableBitmap wb = new WriteableBitmap(canImage, null);
using (MemoryStream stream = new MemoryStream())
{
wb.SaveJpeg(stream, (int)canImage.Width, (int)canImage.Height, 0, 100);
using (IsolatedStorageFileStream local = new IsolatedStorageFileStream(scanName, FileMode.Create, mystorage))
{
local.Write(stream.GetBuffer(), 0, stream.GetBuffer().Length);
}
}
if (MessageBox.Show("Scan updated successfully") == MessageBoxResult.OK)
{
App.isTransformRequest = false;
NavigationService.Navigate(new Uri("/View/EditDocument.xaml?paramList=" + App.currentName, UriKind.RelativeOrAbsolute));
}
this code works fine. But I want to detect weather the file is completely created or not, and after that only I want to display the success message. The way I am currently working somtimes displays the success message before the complete creation of the file, I want the message to be displayed only after the file is created completely, ie the stream is written completely.
Using the BeginWrite Method of the IsolatedStorageFileStream (msdn) you can regsiter a ActionCallback to continue with the redirection options in your UI.
Please note, if your callback shows a MessageBox in the UI-Thread, you have to sync the ThreadContext using the Dispatcher (msdn)
Related
I am currently working on a project using the Windows Runtime and I have run into a roadblock, this was something that was always very easy to do and I feel very frustrated for not getting this right.
I have been sitting for hours and I just cannot seem to get it right. I get the "Access is denied error", also in some variations of my code when I did click on the button, nothing happened. I feel like the answer is staring me right in the face. Here is the code:
private async void btnDtlsSaveChanges(object sender, TappedRoutedEventArgs e)
{
StorageFile del = await Package.Current.InstalledLocation
.GetFileAsync("UserDetails.txt");
await del.DeleteAsync();
StorageFile file = await Package.Current.InstalledLocation.CreateFileAsync
("UserDetails.txt", CreationCollisionOption.OpenIfExists);
using (StreamWriter writer =
new StreamWriter(await file.OpenStreamForWriteAsync()))
{
await writer.WriteLineAsync("Hello World");
}
}
I also tried using ReplaceExisting instead of OpenIfExists:
StorageFile file = await Package.Current.InstalledLocation.CreateFileAsync
("UserDetails.txt", CreationCollisionOption.ReplaceExisting);
using (StreamWriter writer = new StreamWriter(await file.OpenStreamForWriteAsync()))
{
await writer.WriteLineAsync("Hello World");
}
I have tried in several ways, all leading down the same track, and I have looked at every related question on stack overflow, nothing is getting me there.
Any help would be greatly appreciated, thanks in advance.
EDIT: (Solved) Me in my stupidity and the learning of a new technology did not actually realise that there is a difference between the LocalStorage and the actual installed location, thanks to Rob Caplan for guiding me in the right direction.
You get access denied because apps don't have write access to Package.Current.InstalledLocation.
For write access you need to use your application data folders such as Windows.Storage.ApplicationData.Current.LocalFolder
If you want to ship your app with an initial data file and then update the app with user data at runtime you can copy it from InstalledLocation to LocalFolder on first run.
See App data (Windows Runtime apps) and Accessing app data with the Windows Runtime (Windows Runtime apps)
I don't know why you are using await, but the following code should be able to clear the file content for you
using (StreamWriter sw = new StreamWriter("UserDetails.txt", false))
{
sw.WriteLine("Hello world");
}
I used a button for it to test
After Clicking the button the file will be empty.
You need to use using FileMode.Create, It will create a new file or overwrite it.
private void button1_Click(object sender, EventArgs e)
{
using (FileStream NewFileStream = new FileStream(#"C:\Users\Crea\Documents\TCP.txt", FileMode.Create))
{ }
//using (StreamWriter sw = new StreamWriter(#"C:\Users\Crea\Documents\TCP.txt", true))
// {
// sw.WriteLine("Hello");
// }
}
I think it should go somewhere in the OpenReadCompleted event but nothing I have tried is working. The code below includes the portion where if the file already exists, it will Play, which works. But I would like it to also play automatically after initially downloading.
audioStream = IsolatedStorageFile.GetUserStoreForApplication().OpenFiledata.SavePath,FileMode.Open, FileAccess.Read, FileShare.Read);
AudioPlayer.SetSource(audioStream);
AudioPlayer.Play();
}
else
{
WebClient client = new WebClient();
client.OpenReadCompleted += (senderClient, args) =>
{
using (IsolatedStorageFileStream fileStream = IsolatedStorageFile.GetUserStoreForApplication().CreateFile(data.SavePath))
{
args.Result.Seek(0, SeekOrigin.Begin);
args.Result.CopyTo(fileStream);
}
};
client.OpenReadAsync(new Uri(data.FilePath));
}
I could have swore I tried this earlier and it didn't work. Here was my solution. Added AudioPlayer code after args like so:
using (IsolatedStorageFileStream fileStream = IsolatedStorageFile.GetUserStoreForApplication).CreateFile(data.SavePath))
{
args.Result.Seek(0, SeekOrigin.Begin);
args.Result.CopyTo(fileStream);
AudioPlayer.SetSource(fileStream);
AudioPlayer.Play();
I'm trying to implement a lockscreen background application on Windows Phone 8 using C#. The idea is that when a user clicks a button, PhotoChooserTask is initiated. When he picks a photo from his media library, it's copied to isolated storage and then set as a lockscreen background.
The problem is that Windows Phone requires a unique name for each new lockscreen picture, so the solution has to be the following:
The user selects a photo from the library
2.1 If the current lockscreen picture EndsWith("_A.jpg") the chosen photo is copied to the isolated storage as photobackground_B.jpg and is set as lockscreen background
2.2. Otherwise, if the current lockscreen picture doesn't meet the EndsWith("_A.jpg") condition, then the chosen photo is copied to the isolated storage as photobackground_A.jpg and is set as lockscreen background.
Thus, the A/B switching logic is implemented so that each new lockscreen background has a unique name.
However, my code does not work.In particular the following line throws an exception:
Windows.Phone.System.UserProfile.LockScreen.SetImageUri(new Uri("ms-appdata:///Local/photobackground_A.jpg", UriKind.Absolute));
What seems to be the problem?
P.S. I'm completely new to programming, so I would also greately appreciate an explanation and a proper code sample. Thanks!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using Microsoft.Phone.Tasks;
using Day2Demo.Resources;
using System.Windows.Media;
using System.IO;
using System.IO.IsolatedStorage;
using Microsoft.Xna.Framework.Media;
namespace Day2Demo
{
public partial class MainPage : PhoneApplicationPage
{
PhotoChooserTask photoChooserTask;
// Constructor
public MainPage()
{
InitializeComponent();
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
private async void button1_Click(object sender, RoutedEventArgs e)
{
//check if current app provided the lock screen image
if (!Windows.Phone.System.UserProfile.LockScreenManager.IsProvidedByCurrentApplication)
{
//current image not set by current app ask permission
var permission = await Windows.Phone.System.UserProfile.LockScreenManager.RequestAccessAsync();
if (permission == Windows.Phone.System.UserProfile.LockScreenRequestResult.Denied)
{
//no permission granted so return without setting the lock screen image
return;
}
}
photoChooserTask = new PhotoChooserTask();
photoChooserTask.Completed += new EventHandler<PhotoResult>(photoChooserTask_Completed);
photoChooserTask.Show();
}
void photoChooserTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
var currentImage = Windows.Phone.System.UserProfile.LockScreen.GetImageUri();
if (currentImage.ToString().EndsWith("_A.jpg"))
{
var contents = new byte[1024];
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var local = new IsolatedStorageFileStream("photobackground_B.jpg", FileMode.Create, store))
{
int bytes;
while ((bytes = e.ChosenPhoto.Read(contents, 0, contents.Length)) > 0)
{
local.Write(contents, 0, bytes);
}
}
Windows.Phone.System.UserProfile.LockScreen.SetImageUri(new Uri("ms-appdata:///Local/photobackground_B.jpg", UriKind.Absolute));
}
}
else
{
var contents = new byte[1024];
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var local = new IsolatedStorageFileStream("photobackground_A.jpg", FileMode.Create, store))
{
int bytes;
while ((bytes = e.ChosenPhoto.Read(contents, 0, contents.Length)) > 0)
{
local.Write(contents, 0, bytes);
}
}
Windows.Phone.System.UserProfile.LockScreen.SetImageUri(new Uri("ms-appdata:///Local/photobackground_A.jpg", UriKind.Absolute));
}
}
}
}
}
}
Here are some suggestions for you:
You may be overcomplicating the matter of naming the file. First, I'd say if the app is the current lock screen manager, delete the existing lock screen image, then create a new image name using Guid.NewGuid. Guids are guaranteed to be unique upon generation so you'll never run into a naming collision here.
You're using antiquated storage APIs that may lock your UI and cause it to become non-responsive. There are new async file storage APIs provided in Windows Phone 8 and it might help to familiarize yourself with them in the future. The code sample provided will give you a start.
The URI you're ultimately going to provide is likely most easily generated by giving the OS a system-relative file path (i.e. C:\) and that's easily accessible from the StorageFile.Path Property.
Modify your event handler to something along the lines of the following code and see how you fare. You will need to add a using directive to import the System.IO namespace to use the OpenStreamForWriteAsync Extension:
private async void photoChooserTask_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
// Load the image source into a writeable bitmap
BitmapImage bi = new BitmapImage();
bi.SetSource(e.ChosenPhoto);
WriteableBitmap wb = new WriteableBitmap(bi);
// Buffer the photo content in memory (90% quality; adjust parameter as needed)
byte[] buffer = null;
using (var ms = new System.IO.MemoryStream())
{
int quality = 90;
e.ChosenPhoto.Seek(0, SeekOrigin.Begin);
// TODO: Crop or rotate here if needed
// Resize the photo by changing parameters to SaveJpeg() below if desired
wb.SaveJpeg(ms, wb.PixelWidth, wb.PixelHeight, 0, quality);
buffer = ms.ToArray();
}
// Save the image to isolated storage with new Win 8 APIs
var isoFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
var nextImageName = Guid.NewGuid() + ".jpg";
var newImageFile = await isoFolder.CreateFileAsync(nextImageName, Windows.Storage.CreationCollisionOption.FailIfExists);
using (var wfs = await newImageFile.OpenStreamForWriteAsync())
{
wfs.Write(buffer, 0, buffer.Length);
}
// Use the path property of the StorageFile to set the lock screen URI
Windows.Phone.System.UserProfile.LockScreen.SetImageUri(new Uri(newImageFile.Path, UriKind.Absolute));
}
}
Thanks lthibodeaux for the awesome idea) Everything worked except for the SetImageUri line.
This one seems to do the business: Windows.Phone.System.UserProfile.LockScreen.SetImageUri(new Uri("ms-appdata:///Local/" + nextImageName, UriKind.Absolute))
Thanks again!
I've read about a thousand similar posts, and have followed the general advice but am still running into the issue. Here's my scenario:
I'm working on a Windows Phone 8 app that, when the user saves, serializes all of their data into XML then uses CreateFile to store it. The problem that I'm facing is that if a user hits save several times consecutively, IsolatedStorageException:Operation Not Permitted is thrown (I'm guessing that the serialization takes long enough that the file is still being used when I attempt to access it a second time). When save is tapped the second time, is there a way for me to abort the previous action, free up the isolated storage file, and initiate the new save? Or is there a better solution?
Here's the code for my Save method (the exception occurs on the isoStore.CreateFile(filename) line):
using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = isoStore.CreateFile(filename))
{
XmlSerializer xml = new XmlSerializer(GetType());
xml.Serialize(stream, this);
}
}
Any help would be amazing, as I've been stuck here for weeks.
Thanks,
Ben:
You could go with something like this.
private async Task Save(string fileName)
{
Button.IsEnabled = false;
await Task.Run(() =>
{
using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = isoStore.CreateFile(filename))
{
XmlSerializer xml = new XmlSerializer(GetType());
xml.Serialize(stream, this);
}
}
});
Button.IsEnabled = true;
}
Why not disable the 'save' button when clicked then enable it again once the serialization completes?
Using DOTNET 3.5 . I have a app which shows load a flash movie in form, using this code
axShockwaveFlash1 = new AxShockwaveFlashObjects.AxShockwaveFlash()
axShockwaveFlash1.LoadMovie(0, Form1.currentGame);
The problem is that whenever I make a changes in the flash hosted in our application and try to refresh the to see the changes, the new changes is 'messed' up. to be more specific , it seems that the background and some controls of the previous flash still remain, 'spoiling' the new flash that is loaded. why?
Using the following methods before loading the second flash video makes no difference
axShockwaveFlash1.Refresh();
axShockwaveFlash1.Stop();
I tried other methods, it doesn't work for me. Here is what I did to achieve the desired result.
private void btnReload_Click(object sender, EventArgs e)
{
byte[] fileContent = File.ReadAllBytes(Application.StartupPath + #"\yourflashfile.swf");
if (fileContent != null && fileContent.Length > 0)
{
using (MemoryStream stm = new MemoryStream())
{
using (BinaryWriter writer = new BinaryWriter(stm))
{
/* Write length of stream for AxHost.State */
writer.Write(8 + fileContent.Length);
/* Write Flash magic 'fUfU' */
writer.Write(0x55665566);
/* Length of swf file */
writer.Write(fileContent.Length);
writer.Write(fileContent);
stm.Seek(0, SeekOrigin.Begin);
/* 1 == IPeristStreamInit */
//Same as LoadMovie()
this.axShockwaveFlash1.OcxState = new AxHost.State(stm, 1, false, null);
}
}
fileContent = null;
GC.Collect();
}
}
I copied the core code somewhere in SO but I don't remember the source.
Have you tried loading an "empty" flash video before loading your new video?
e.g.
axShockwaveFlash1.LoadMovie(0,"");
I'm sure that I encountered a similar problem and resolved it this way.
Try this.
Make a blank swf. "Blank.swf" load it first and then re-load your game.
axShockwaveFlash1.LoadMovie(0,"Blank.swf");
axShockwaveFlash1.Play();
axShockwaveFlash1.LoadMovie(0, Form1.currentGame);
axShockwaveFlash1.Play();
Ensure you give the correct path for the Blank.swf.