OneDrive file only uploads when app is terminated - c#

I'm having a problem uploading a file to OneDrive from a universal app that I can't understand or figure out how to debug. I used this guide to go through the process of getting file IDs and such and it worked great until a few hours ago.
Now I can get folder and file ids, so I assume that I am still successfully connecting to OneDrive and my internet connection is still working. But when I step into the BackgroundUploadAsync the thread or whatever that was was executing before never returns. In the code below, the message "Uploading new file to OneDrive..." never disappears.
Strangely, while it is uploading I can refresh my OneDrive folder on ie and I'll never see what I'm trying to upload. But once I stop the debugger, or terminate the app on the phone, I can instantly refresh and the file will be there.
Here is the method for uploading:
public async Task UploadToOneDrive(string folderID, string localFileName)
{
try
{
StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(localFileName);
string fileName = "backup-" + DateTime.Now.ToString("dd-MM") + ".db";
await file.CopyAsync(ApplicationData.Current.LocalFolder, fileName, NameCollisionOption.ReplaceExisting);
file = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
await connectClient.BackgroundUploadAsync(folderID,
fileName, file, OverwriteOption.Overwrite);
}
catch (LiveConnectException)
{
MessageDialog m = new MessageDialog("Could not connect to to OneDrive. Cloud sync will be stopped.");
m.ShowAsync();
}
catch (LiveAuthException)
{
MessageDialog m = new MessageDialog("Error authenticating OneDrive service. Please try cloud sync again later.");
m.ShowAsync();
}
catch (Exception ex)
{
MessageDialog m = new MessageDialog("Unknown exception occurred.\n\nError:{0}", ex.Message);
m.ShowAsync();
}
}
And here is the sync process
public async Task sync()
{
var sb = StatusBar.GetForCurrentView();
sb.ProgressIndicator.Text = "Syncing with OneDrive...";
await sb.ProgressIndicator.ShowAsync();
string cloudFolderID = await syncManager.CreateOrGetOneDriveFolderID("GlucoseCalculator", "Documents/");
string cloudFileID = await syncManager.GetFileID(DataManager.sqlFileName, "Documents/GlucoseCalculator/");
try
{
if (cloudFileID != null)
{
if (!(await dbManager.DoesFileExist(DataManager.sqlFileName)))
{
sb.ProgressIndicator.Text = "Downloading file from OneDrive...";
await syncManager.DownloadFromOneDrive(cloudFileID, DataManager.sqlFileName);
goto BREAK;
}
DateTime cloudLastEditDateTime = DateTime.Parse(await syncManager.GetFileProperty(cloudFileID, "updated_time"));
DateTime localLastEditDateTime = ApplicationData.Current.LocalFolder.GetFileAsync(DataManager.sqlFileName).GetResults().GetBasicPropertiesAsync().GetResults().DateModified.DateTime;
if (cloudLastEditDateTime > localLastEditDateTime)
{
sb.ProgressIndicator.Text = "Downloading file from OneDrive...";
await syncManager.DownloadFromOneDrive(cloudFileID, DataManager.sqlFileName);
}
else if (cloudLastEditDateTime < localLastEditDateTime)
{
sb.ProgressIndicator.Text = "Uploading file to OneDrive...";
await syncManager.UploadToOneDrive(cloudFolderID, DataManager.sqlFileName);
}
}
else if (cloudFileID == null)
{
sb.ProgressIndicator.Text = "Uploading new file to OneDrive...";
await syncManager.UploadToOneDrive(cloudFolderID, DataManager.sqlFileName);
}
}
catch (Exception)
{
sb.ProgressIndicator.Text = "Cloud synchronization failed.";
sb.ProgressIndicator.HideAsync();
return;
}
sb.ProgressIndicator.Text = "Synchronization complete!";
BREAK:;
await sb.ProgressIndicator.HideAsync();
}

Most likely, you are creating some object that implements IDisposible, but it is not in a using block. Maybe the StorageFile.

Related

How to handle UnauthorizedAccessException in asynchronous code?

Catching an UnauthorizedAccessException works fine, but it doesn't when I make the File.WriteAllBytes -> await Task.Run(() => File.WriteAllBytes(Path + vid.FullName, vid.GetBytes()));
When I do this the exception doesn't get caught. What's the best way to catch this exception, so that the MessageBox shows? Thanks.
(NOTE: This code is clearly a YouTube converter, but it is for my own personal use)
public async Task ConvertVideoAndDownloadToFolder(string link, string MP3Name = null)
{
try
{
var youtube = YouTube.Default;
var vid = await Task.Run(() => youtube.GetVideo(link));
await Task.Run(() => File.WriteAllBytes(Path + vid.FullName, vid.GetBytes()));
var inputFile = new MediaFile { Filename = Path + vid.FullName };
MediaFile outputFile;
//Creates mp4 and mp3
if (String.IsNullOrEmpty(MP3Name)) { outputFile = new MediaFile { Filename = $"{Path + vid.FullName}.mp3" }; }
//only creates MP4
else { outputFile = new MediaFile { Filename = $"{MP3Name}.mp3" }; }
using (var engine = new Engine())
{
await Task.Run(() => engine.GetMetadata(inputFile));
await Task.Run(() => engine.Convert(inputFile, outputFile));
}
}
catch (Exception ex)
{
if(ex is UnauthorizedAccessException)
{
MessageBox.Show($"Can't write on '{Path}' as it is protected.\rPlease choose another folder. ", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
else if(ex is ArgumentException)
{
MessageBox.Show($"'{link}' is not a valid YouTube link, \rMake sure the video still works, or check the link for typos. ", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
else
{
throw;
}
}
}
In Asynchronous programming it is very easy for exceptions to be swallowed as they typically run on another thread. This needs to be carefully managed
AggregateException stores all the exceptions that happen in different threads and therefore you do not lose any exception
catch (AggregateException aex)
{
foreach(var ex in aex.InnerExceptions) //This will consolidate t
{
Console.WriteLine(ex.Message);
}
}
Reference

Xamarin computer vision

I am trying to create a Xamarin application using Azure computer vision API, I got the API key and endpoint URL whenever i click a picture and set in image view and then describe image function not working and i am not getting output captions, my code is below:
private async void Button_Clicked(object sender, EventArgs e)
{
await CrossMedia.Current.Initialize();
try
{
if(!CrossMedia.Current.IsTakePhotoSupported&&!CrossMedia.Current.IsPickPhotoSupported)
{
await DisplayAlert("INFO", "CAMERA NOT AVAILABEL", "OK");
}
else
{
var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory="Images",
Name="test.jpg"
});
if (file==null)
{
await DisplayAlert("ERROR", "FILE NOT FOUND", "OK");
return;
}
img.Source = ImageSource.FromStream(() =>
{
var stream = file.GetStream();
return stream;
});
var visionapi = new ComputerVisionClient(new ApiKeyServiceClientCredentials(""));
visionapi.Endpoint = "";
var desc = await visionapi.DescribeImageInStreamAsync(file.GetStream());
foreach (var tag in desc.Captions)
{
cap.Text = cap.Text + "\n" + tag;
}
}
}
catch(Exception )
{
await DisplayAlert("", "ERROR", "OK");
}
}
DescribeImageInStreamAsync functon is not working it is moving into catch block after few minutes with the below error:
Microsoft.Azure.CognitiveServices.Vision.ComputerVisionErrororException: Operation returned an invalid status code 'Not Found'
Exception

Download txt file from google drive in windows phone 8.1

I'm doing a windows phone project, and need to download a text file from the internet and read its content.
This is what I have tried (but it didn't work)
private async Task pobierz()
{
string source = "https://drive.google.com/file/d/0BzgKBwKyU4oORkxxSlVITGswb1E/view?usp=sharing";
string LocalName = "hej.txt";
var srce = new Uri(source, UriKind.Absolute);
// var destinationFile =await KnownFolders.PicturesLibrary.CreateFileAsync()
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(#"ms-appx:///Assets/hej.txt"));
var downloader = new BackgroundDownloader();
DownloadOperation download = downloader.CreateDownload(srce,file);
}
Please see https://msdn.microsoft.com/en-us/library/windows/apps/xaml/jj152726.aspx?f=255&MSPPError=-2147217396 for detailed description of how to use the BackgroundDownloader.
You need to implement and call the following method:
private async void HandleDownloadAsync(DownloadOperation download, bool start)
{
try
{
// Store the download so we can pause/resume.
activeDownloads.Add(download);
Progress<DownloadOperation> progressCallback = new Progress<DownloadOperation>(DownloadProgress);
if (start)
{
// Start the download and attach a progress handler.
await download.StartAsync().AsTask(cts.Token, progressCallback);
}
else
{
// The download was already running when the application started, re-attach the progress handler.
await download.AttachAsync().AsTask(cts.Token, progressCallback);
}
ResponseInformation response = download.GetResponseInformation();
Log(String.Format("Completed: {0}, Status Code: {1}", download.Guid, response.StatusCode));
}
catch (TaskCanceledException)
{
Log("Download cancelled.");
}
catch (Exception ex)
{
LogException("Error", ex);
}
finally
{
activeDownloads.Remove(download);
}
}

The process cannot access the file because it is being used by another process

I am running a program where a file gets uploaded to a folder in IIS,and then is processed to extract some values from it. I use a WCF service to perform the process, and BackgroundUploader to upload the file to IIS. However, after the upload process is complete, I get the error "The process cannot access the file x because it is being used by another process." Based on similar questions asked here, I gathered that the file concerned needs to be in a using statement. I tried to modify my code to the following, but it didn't work, and I am not sure if it is even right.
namespace App17
{
public sealed partial class MainPage : Page, IDisposable
{
private CancellationTokenSource cts;
public void Dispose()
{
if (cts != null)
{
cts.Dispose();
cts = null;
}
GC.SuppressFinalize(this);
}
public MainPage()
{
this.InitializeComponent();
cts = new CancellationTokenSource();
}
public async void Button_Click(object sender, RoutedEventArgs e)
{
try
{
Uri uri = new Uri(serverAddressField.Text.Trim());
FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add("*");
StorageFile file = await picker.PickSingleFileAsync();
using (var stream = await file.OpenAsync(FileAccessMode.Read))
{
GlobalClass.filecontent = file.Name;
GlobalClass.filepath = file.Path;
BackgroundUploader uploader = new BackgroundUploader();
uploader.SetRequestHeader("Filename", file.Name);
UploadOperation upload = uploader.CreateUpload(uri, file);
await HandleUploadAsync(upload, true);
stream.Dispose();
}
}
catch (Exception ex)
{
string message = ex.ToString();
var dialog = new MessageDialog(message);
await dialog.ShowAsync();
Log(message);
}
}
private void CancelAll(object sender, RoutedEventArgs e)
{
Log("Canceling all active uploads");
cts.Cancel();
cts.Dispose();
cts = new CancellationTokenSource();
}
private async Task HandleUploadAsync(UploadOperation upload, bool start)
{
try
{
Progress<UploadOperation> progressCallback = new Progress<UploadOperation>(UploadProgress);
if (start)
{
await upload.StartAsync().AsTask(cts.Token, progressCallback);
}
else
{
// The upload was already running when the application started, re-attach the progress handler.
await upload.AttachAsync().AsTask(cts.Token, progressCallback);
}
ResponseInformation response = upload.GetResponseInformation();
Log(String.Format("Completed: {0}, Status Code: {1}", upload.Guid, response.StatusCode));
cts.Dispose();
}
catch (TaskCanceledException)
{
Log("Upload cancelled.");
}
catch (Exception ex)
{
string message = ex.ToString();
var dialog = new MessageDialog(message);
await dialog.ShowAsync();
Log(message);
}
}
private void Log(string message)
{
outputField.Text += message + "\r\n";
}
private async void LogStatus(string message)
{
var dialog = new MessageDialog(message);
await dialog.ShowAsync();
Log(message);
}
private void UploadProgress(UploadOperation upload)
{
BackgroundUploadProgress currentProgress = upload.Progress;
MarshalLog(String.Format(CultureInfo.CurrentCulture, "Progress: {0}, Status: {1}", upload.Guid,
currentProgress.Status));
double percentSent = 100;
if (currentProgress.TotalBytesToSend > 0)
{
percentSent = currentProgress.BytesSent * 100 / currentProgress.TotalBytesToSend;
}
MarshalLog(String.Format(CultureInfo.CurrentCulture,
" - Sent bytes: {0} of {1} ({2}%), Received bytes: {3} of {4}", currentProgress.BytesSent,
currentProgress.TotalBytesToSend, percentSent, currentProgress.BytesReceived, currentProgress.TotalBytesToReceive));
if (currentProgress.HasRestarted)
{
MarshalLog(" - Upload restarted");
}
if (currentProgress.HasResponseChanged)
{
MarshalLog(" - Response updated; Header count: " + upload.GetResponseInformation().Headers.Count);
}
}
private void MarshalLog(string value)
{
var ignore = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
Log(value);
});
}
}
}
After this is done, the file name is sent to a WCF service which will access and process the uploaded file to extract certain values. It is at this point I receive the error. I would truly appreciate some help.
public async void Extract_Button_Click(object sender, RoutedEventArgs e)
{
ServiceReference1.Service1Client MyService = new ServiceReference1.Service1Client();
string filename = GlobalClass.filecontent;
string filepath = #"C:\Users\R\Documents\Visual Studio 2015\Projects\WCF\WCF\Uploads\"+ filename;
bool x = await MyService.ReadECGAsync(filename, filepath);
}
EDIT: Code before I added the using block
try
{
Uri uri = new Uri(serverAddressField.Text.Trim());
FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add("*");
StorageFile file = await picker.PickSingleFileAsync();
GlobalClass.filecontent = file.Name;
GlobalClass.filepath = file.Path;
BackgroundUploader uploader = new BackgroundUploader();
uploader.SetRequestHeader("Filename", file.Name);
UploadOperation upload = uploader.CreateUpload(uri, file);
await HandleUploadAsync(upload, true);
}
When you work with stream writers you actually create a process, which you can close it from task manager. And after stream.Dispose() put stream.Close().
This should solve your problem.
You should also close the stream that writes the file to disk (look at your implementation of CreateUpload).
i got such error in DotNet Core 2 using this code:
await file.CopyToAsync(new FileStream(fullFileName, FileMode.Create));
counter++;
and this is how I managed to get rid of message (The process cannot access the file x because it is being used by another process):
using (FileStream DestinationStream = new FileStream(fullFileName, FileMode.Create))
{
await file.CopyToAsync(DestinationStream);
counter++;
}

how to browse and upload files in Windows Phone App

How to upload a file in windows phone i mean which controls are used to browse the files (phone Content) are they pre-defined for windows phone or do we need to create manually. Browsing them and uploading them .
you can try the MSDN way
Make sure that the user has consented to the required scope, and then create an upload
Handle pending uploads when the app restarts.
private async void Upload()
{
try
{
// Ensure that the user has consented to the wl.skydrive and wl.skydrive_update scopes.
var authClient = new LiveAuthClient();
var authResult = await authClient.LoginAsync(new string[] { "wl.skydrive", "wl.skydrive_update" });
if (authResult.Session != null)
{
var liveConnectClient = new LiveConnectClient(authResult.Session);
// Upload to OneDrive.
LiveUploadOperation uploadOperation = await liveConnectClient.CreateBackgroundUploadAsync(
uploadPath, fileName, uploadInputStream, OverwriteOption.Rename);
LiveOperationResult uploadResult = await uploadOperation.StartAsync();
HandleUploadResult(uploadResult);
}
}
catch (LiveAuthException ex)
{
// Handle errors.
}
catch(LiveConnectException ex)
{
// Handle errors.
}
}
var pendingOperations = await LiveConnectClient.GetCurrentBackgroundUploadsAsync();
foreach(LiveDownloadOperation pendingOperation in pendingOperations)
{
try
{
var opResult = await pendingOperation.AttachAsync();
// Handle results.
}
catch
{
// Handle errors.
}
}

Categories