询问者
LaunchFileAsync 失败可能是什么原因?

问题
-
最近出现了与 LaunchFileAsync 有关的问题,而且出现了电脑和手机表现不一致的情况。(这真是令人尴尬)(说好的大统一呢)
异常表现:
首先,这是我的 APP 的某一页的内容
(由于大小限制,图片显示不全,在 http://bbs.wfun.com/forum.php?mod=viewthread&tid=910240&page=1&extra=#post_14396209 发表了同样的帖子)
在导航到这一页时,OnNavigatedTo 会执行读取文件操作:
//StorageFolder filesFolder, filesCacheFolder; 和 object apm; 定义在全局变量中 //filesFolder 存储高清原图,filesCacheFolder 存储略缩图,横向200px,纵向由原图纵横比决定,每张约107KB //AddedPhotosManager 是我自己写的一个类 apm = e.Parameter; filesFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("photos", CreationCollisionOption.OpenIfExists); filesCacheFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("photosCache", CreationCollisionOption.OpenIfExists); //传递参数是空的代表未加载过 if (apm == null) { apm = new AddedPhotosManager(); IReadOnlyList<StorageFile> fileOL = await filesFolder.GetFilesAsync(); IReadOnlyList<StorageFile> fileCacheOL = await filesCacheFolder.GetFilesAsync(); string sum = fileOL.Count.ToString(); Image im, im2; for (int i = 0; i < fileOL.Count; i++) { //粗暴的文字提示 progressText.Text = "即将完成(" + (i + 1).ToString() + "/" + sum + ")\n在此应用关闭前仅加载一次,除非你在此期间使用共享或文件关联的方式添加了新的图片。"; //在全局变量的 Lis t中添加文件以便接下来的管理(主要是“删除”) ((AddedPhotosManager)apm).filesList.Add(fileOL[i]); ((AddedPhotosManager)apm).filesCacheList.Add(fileCacheOL[i]); //根据 107 KB 的缩略图从 StorageFile 生成 Image im = await AddedPhotosManager.getImage(fileCacheOL[i]); //也添加到全局变量中以便在页面导航时传递该变量,实现“在此应用关闭前仅加载一次” ((AddedPhotosManager)apm).imagesList.Add(im); //另生成一个新的 Image 以便重复添加到 GridView 中 im2 = new Image(); im2.Height = im.Height; im2.Width = im.Width; im2.Source = im.Source; im2.Stretch = Stretch.UniformToFill; photosGridView.Items.Add(im2); selectAllAppBarButton.Visibility = Visibility.Visible; } } //已加载过图片 else { Image i2; foreach (Image i in ((AddedPhotosManager)apm).imagesList) { i2 = new Image(); i2.Height = i.Height; i2.Width = i.Width; i2.Source = i.Source; i2.Stretch = Stretch.UniformToFill; photosGridView.Items.Add(i2); selectAllAppBarButton.Visibility = Visibility.Visible; } }
这些文件点击“打开”的时候都是正常的。文件信息里显示的文件夹也正常,是此应用的本地文件夹。
bool x = await Launcher.LaunchFileAsync(((AddedPhotosManager)apm).filesList[photosGridView.SelectedIndex]); //如果打开失败 if (!x) { //launchFailed是一个做得很像 MessageDialogue 的 Flyout launchFailedStackPanel.Width = mainGrid.ActualWidth - 44; //将其拉伸到与应用窗口一样宽 launchFailed.ShowAt(Frame); }
点击右下角的“+”,添加图片:
FileOpenPicker picker = new FileOpenPicker(); picker.CommitButtonText = "添加"; picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary; picker.ViewMode = PickerViewMode.Thumbnail; picker.FileTypeFilter.Add(".jpg"); picker.FileTypeFilter.Add(".jpeg"); picker.FileTypeFilter.Add(".png"); StorageFile file2, file3; Image i, i2; IReadOnlyList<StorageFile> flist = await picker.PickMultipleFilesAsync(); int x = 0; string sum = flist.Count.ToString(); foreach (StorageFile file in flist) { //粗暴的文字提示 x++; progressText.Text = "正在复制并缓存第" + x.ToString() + "张图片(共"+ sum +")…\n这可能需要较长时间。"; //复制此文件到应用本地文件夹 //fileDisplayName是int变量,其作用是当用户保存第一张图片时命名为0.jpg/.jpeg/.png,第二张图片时命名为1.jpg/.jpeg/.png,以此类推。我省略了与其有关的保存/读取代码。 file2 = await file.CopyAsync(filesFolder, fileDisplayName.ToString() + file.FileType); //添加到全局变量的 List 里面 ((AddedPhotosManager)apm).filesList.Add(file2); //获取缩略图并同时保存,详细代码在下一个框内 file3 = await AddedPhotosManager.getThumbNail(file2); ((AddedPhotosManager)apm).filesCacheList.Add(file3); i = await AddedPhotosManager.getImage(file3); ((AddedPhotosManager)apm).imagesList.Add(i); i2 = new Image(); i2.Height = i.Height; i2.Width = i.Width; i2.Source = i.Source; i2.Stretch = Stretch.UniformToFill; photosGridView.Items.Add(i2); selectAllAppBarButton.Visibility = Visibility.Visible; selectAllAppBarButton.IsChecked = false; fileDisplayName++; }
internal static async Task<StorageFile> getThumbNail(StorageFile file) { StorageFolder cacheFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("photosCache", CreationCollisionOption.OpenIfExists); ImageProperties x = await file.Properties.GetImagePropertiesAsync(); uint lim = 0; //将其横向像素设置为 200 if (x.Height < x.Width) { lim = 200; } else { lim = 200 * x.Height / x.Width; } StorageItemThumbnail c = await file.GetThumbnailAsync(ThumbnailMode.PicturesView, lim, ThumbnailOptions.ResizeThumbnail); Windows.Storage.Streams.Buffer buf = new Windows.Storage.Streams.Buffer(Convert.ToUInt32(c.Size)); IBuffer ibu = await c.ReadAsync(buf, buf.Capacity, InputStreamOptions.None); //保存到 filesCacheFolder 并返回该文件 StorageFile f = await cacheFolder.CreateFileAsync(file.Name, CreationCollisionOption.ReplaceExisting); using (IRandomAccessStream strm = await f.OpenAsync(FileAccessMode.ReadWrite, StorageOpenOptions.None)) { await strm.WriteAsync(ibu); } return f; }
此文件在电脑上正常打开,并且左侧显示的文件夹路径也正常,说明 StorageFile 应该没搞错,没把用户本来的文件错误地当成应用本地的文件。(我曾经怀疑是不是把 file 而不是 file2 添加到 List 里了。)但是在手机上不能打开。
MSDN 官方解释:
此 API 也对它可生成的文件类型有若干限制。很多包含可执行代码的文件类型,例如 .exe、.msi 和 .js 文件,在启动时都被阻止。恶意文件会修改系统,此限制可保护用户免受可能存在的恶意文件的危害。
可是我 Launch 的都是一些 png,jpg,jpeg 这些人畜无害的文件啊,这是什么原因?- 已编辑 MIC 2014 2016年4月2日 14:54