I am deploying my app to Windows 7, Windows 10, and Linux. At one point I am using OpenFileDialog to allow to user to pick a file path. This is working in Windows 10 and Linux, but when run in Windows 7, an ArgumentException is being thrown.
I've tried looking into the exception by displaying the exception message, which is "Value does not fall within expected range." I am not sure what this means. It works fine in Windows 10 so I don't know why it wouldn't work the same here.
I have a method GetPath() that gets the selected path using OpenFileDialog and a button clicked event that calls GetPath() and sets the result to a local variable.
public async Task<string> GetPath()
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filters.Add(new FileDialogFilter() { Name = "Csv", Extensions = { "csv" } });
string[] result = await dialog.ShowAsync(this); //sets opened file to a stream
string stream = string.Join(" ", result); //converts string[] to string
return stream; //returns path to selected file
}
private async void MasterBrowse_Clicked(object sender, RoutedEventArgs args)
{
string getPath = string.Empty;
try
{
getPath = await GetPath();
}
catch (ArgumentException e)
{
await MessageBox.Show(this, "Make sure to select a file before continuing\n" + "Exception: " + e.Message, "Error: incorrect file", MessageBox.MessageBoxButtons.Ok);
}
}
Expected:
GetPath() should OpenFileDialog and save the selected path as a string, then return it. MasterBrowse_Clicked() should get the returned string.
Actual:
ArgumentException thrown when OpenFileDialog.ShowAsync() is called.
Related
I wrote a simple app that monitors BLE advertisements. When the app receives an advertisement it calls BluetoothLEDevice.FromBluetoothAddressAsync() and if that call returns a non null value GetGattServicesAsync() is called (see code below). Occasionally GetGattServicesAsync() will throw a "Value does not fall within the expected range."
private async void WatcherAdvertisementReceivedAsync(Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementWatcher sender,
BluetoothLEAdvertisementReceivedEventArgs args)
{
using var device = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress);
if (device == null)
return;
try
{
var gatt = await device.GetGattServicesAsync();
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
I'm trying to export files to the public external storage of an Android phone in Xamarin, for a backup DB. However, in the last version of Android phones (11.0 - API30), one can't opt-out of scoped storage using the property android:requestLegacyExternalStorage="true" of the <application> tag in the manifest.xml.
I made sure that the permissions READ_EXTERNAL_STORAGE & WRITE_EXTERNAL_STORAGE are granted before trying to create the file. Still, when trying to create a file, a System.UnauthorizedAccessException exception is thrown.
/* file 1: */
// ....
private async void Export_Tapped (object sender, EventArgs e) {
// check if permission for writing in external storage is given
bool canWrite = await FileSystem.ExternalStoragePermission_IsGranted ();
if (!canWrite) {
// request permission
canWrite = await FileSystem.ExternalStoragePermission_Request ();
if (!canWrite) {
// alert user
return;
}
}
// find the directory to export the db to, based on the platform
string fileName = "backup-" + DateTime.Now.ToString ("yyMMddThh:mm:ss") + ".db3";
string directory = FileSystem.GetDirectoryForDatabaseExport (); // returns "/storage/emulated/0/Download"
string fullPath = Path.Combine (directory, fileName);
// copy db to the directory
bool copied = false;
if (directory != null)
copied = DBConnection.CopyDatabase (fullPath);
if (copied)
// alert user
else
// alert user
}
// ....
/* file 2: */
class DBConnection
{
private readonly string dbPath;
// ....
public bool CopyDatabase(string path)
{
byte[] dbFile = File.ReadAllBytes(dbPath);
File.WriteAllBytes(path, dbFile); // --> this is where the exception is thrown <--
return true;
}
// ....
}
So the question stands: how does one write a new file to the public external storage of an Android device with an API level of 29 or more?
All the resources I have found so far, maybe you can gather more information than I did:
https://forums.xamarin.com/discussion/179999/access-denied-to-external-storage
(regarding private external storage) https://forums.xamarin.com/discussion/171039/saving-files-to-external-storage
https://learn.microsoft.com/en-us/xamarin/android/platform/files/external-storage?tabs=windows
https://developer.android.com/about/versions/11/privacy/storage#permissions
Try This , I use a dependency service to call this method in Native Android and save files like docx and pdf from their by byte array.
public async Task<bool> CreateFile(string fileName, byte[] docBytes, string fileType)
{
try
{
Java.IO.File file = new Java.IO.File(Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath, fileName + fileType);
OutputStream os = new FileOutputStream(file);
os.Write(docBytes);
os.Close();
}
catch
{
return false;
}
return true;
}
The path you use is incorrect, please try the following file path .
Context context = Android.App.Application.Context;
var filePath = context.GetExternalFilesDir(Android.OS.Environment.DirectoryDocuments);
Refer to https://forums.xamarin.com/discussion/comment/422501/#Comment_422501 .
I am unable to cleanup the temporary file after the user uploads a file using
MultipartFormDataStreamProvider. I get "access to the path '...' is denied". However, it can delete old temporary files.
I based my cleanup on the example given here MultipartFormDataStreamProvider Cleanup.
I checked the windows identity and it has Read&Execute/read/write access to the folder. I think, something has locked by the file somehow, but I can't tell what. I tried moving the delete to the end and adding a sleep, but neither helped.
What is the correct way to cleanup these files? I need to do it immediately after I am done using the file. There really should be a setting so it does it for you.
[HttpPost]
[Route("UploadFile")]
public async Task<HttpResponseMessage> UploadFile(string toolToken,
int Publication_ID,
string externalKey,
int dataTypeID,
int toolProject_ID,
string cngDesc)
{
Logger logger = LogManager.GetCurrentClassLogger();
logger.Info("application pool user - " + System.Security.Principal.WindowsIdentity.GetCurrent().Name);
try
{
string tempDir = Config.ServerTempDataDir; // is ~/App_Data";
var provider = new MultipartFormDataStreamProvider(tempDir); //using this instead of ReadAsMultipartAsync because of memory constraints
await Request.Content.ReadAsMultipartAsync(provider);
MultipartFileData file = provider.FileData.FirstOrDefault(); //only one file is sent
if (file != null)
{
var dir = Path.GetDirectoryName(file.LocalFileName);
string begStr = Path.GetFileName(file.LocalFileName).Substring(0, 8);
//will do something with file
//delete file this fails every time, access denied
try
{
File.Delete(file.LocalFileName);
}
catch (Exception e)
{
logger.Error("Cleanup Failed" + e.Message);
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e.Message);
}
//delete any lingering files - this works
foreach (var curFilePath in Directory.GetFiles(dir, begStr + "*"))
{
if (File.GetCreationTime(curFilePath) < (DateTime.Now.AddHours(-3)))
{
try
{
File.Delete(curFilePath);
}
catch { }
}
}
}
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content.Headers.ContentType = new MediaTypeWithQualityHeaderValue(#"application/json");
return response;
}
catch (Exception e)
{
logger.Error("Upload File Exception" + e.Message);
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e.Message);
}
Our network guys had Read&Execute/read/write access but did not have "modify" access on the App_Data folder.
I want to show the error message on the other page. I got the NullReferenceException, but the query string is set on the page which has error. Would someone tell me what is wrong with my code?
catch (Exception ex)
{
//Dispatcher.BeginInvoke(new Action(() =>MessageBox.Show(ex.StackTrace,"Error!",MessageBoxButton.OK)));
string query=#"/ErrorPage.xaml?msg=" + ex.StackTrace.ToString() ;
Dispatcher.BeginInvoke(new Action(() =>this.NavigationService.Navigate(new Uri(query, UriKind.Relative))));
}
There is the code for showing the error message when the page is loaded on other page
public ErrorPage()
{
InitializeComponent();
string msg = NavigationContext.QueryString["msg"].ToString();
lstMessage.Items.Add(msg);
}
I should put my code into the MainPage_Load method. It works.
public ErrorPage()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
MessageBoxResult result = MessageBox.Show(CMSPhoneApp.App.GlobalVariables.strNofifyEmailSubject,
"Report Error", MessageBoxButton.OKCancel);
if (result == MessageBoxResult.OK)
{
//according to the serach it works on real devices (not on the emulator)
//the reason the EmailComposer not pop up because can't set up an email account on the emulator
EmailComposeTask emailcomposer = new EmailComposeTask();
emailcomposer.To = CMSPhoneApp.App.GlobalVariables.reportAddress;
emailcomposer.Subject = CMSPhoneApp.App.GlobalVariables.strNofifyEmailSubject;
emailcomposer.Body = CMSPhoneApp.App.GlobalVariables.errorMsg;
emailcomposer.Show();
}
else
{
App.GoBack();
}
}
I have tried hundreds of times to find errors for this piece of codes.
It only works through WIFI, but When I switch off WIFI on my phone, and run the app again, this app just shut down automatically, which means it thrown an exception.
The app is simple, I used WebClint() to download HTML source and parsed it with HTML Agility Pack, then added them to a list, foreach the list to creat each news object.
I have tried catch the exception stacktrace and bind it to a texblock, It said some of ArgumentOutOfRange exception and Genericlist(int32 index)???
I have no idea about it, It was fine in wifi, but not in 3G network. Can anyone help?
public partial class MainPage : PhoneApplicationPage
{
string srcHTML;
HtmlNode UrlNode;
ObservableCollection<News> newsList = new ObservableCollection<News>();
List<HtmlNode> headlines;
HtmlDocument hd;
News n;
// Constructor
public MainPage()
{
InitializeComponent();
}
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
WebClient webClenet = new WebClient();
webClenet.Encoding = new HtmlAgilityPack.Gb2312Encoding();
webClenet.DownloadStringAsync(new Uri("http://www.6park.com/news/multi1.shtml", UriKind.RelativeOrAbsolute));
webClenet.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClenet_DownloadStringCompleted);
}
private void webClenet_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
srcHTML = e.Result;
GetHeadlinePage(srcHTML);
}
private void GetHeadlinePage(string srcHTML)
{
hd = new HtmlDocument();
hd.LoadHtml(srcHTML);
try
{
UrlNode = hd.DocumentNode.ChildNodes[1].ChildNodes[3].ChildNodes[8].ChildNodes["tr"].ChildNodes["td"].ChildNodes["ul"];
headlines = UrlNode.Descendants("a").ToList();
foreach (var headline in headlines)
{
if (headline.Attributes["href"].Value.Contains("6park"))
{
n = new News();
n.NewsTitle = headline.InnerText;
n.NewsUrl = headline.Attributes["href"].Value;
n.NewsDetails = headline.NextSibling.InnerText.Replace("- ", "新闻来源:") + headline.NextSibling.NextSibling.InnerText + headline.NextSibling.NextSibling.NextSibling.InnerText;
newsList.Add(n);
}
}
}
catch (Exception ex)
{
//NewsSource.Text = ex.StackTrace + "\n" + ex.Message;
}
NewslistBox.ItemsSource = newsList;
//NewsHeadlineWebBrowser.NavigateToString(ConvertExtendedASCII(headNews));
}
}
I'd debug the value passed to GetHeadlinePage().
I'd suspect that the response is different based on the network or the request is timing out or you're getting some other error.
I'd assume that the call to LoadHtml() is failing as this isn't inside any exception handling/trapping and you've not validating the value passed to it.