问下关于删除文件报拒绝访问的

山****花 UID.2951546
2018-04-12 发表

主要是想实现更换背景图的功能,已经按要求放appdata/local上了,但是问题是:只能添加背景图片,但是在删除、覆盖的时候就会提示拒绝访问(System.UnauthorizedAccessException: '拒绝访问。 (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))')
因为看别人写的storagefile.deleteasync()就能删除,但是却出现了这个。
还有更奇怪的,就是文件可以改名,但是就是不能删除跟覆盖
源代码(工程本来做的就是vb的,下面有个自己转的c#代码): <code> Dim bkg As ImageBrush = New ImageBrush()
Dim localpath As StorageFolder = ApplicationData.Current.LocalFolder
Dim fileopen As New FileOpenPicker()
fileopen.FileTypeFilter.Add(".jpg")
fileopen.FileTypeFilter.Add(".png")
fileopen.FileTypeFilter.Add(".bmp")
Dim sfile As StorageFile = Await fileopen.PickSingleFileAsync()
If sfile IsNot Nothing Then
Dim checkname As StorageFile
If Mainpage.Background IsNot Nothing Then
Dim deletefile As StorageFile
Mainpage.Background = Nothing
checkname = Await StorageFile.GetFileFromPathAsync(localpath.Path + "\bkg.jpg")
Await checkname.RenameAsync("del.jpg", NameCollisionOption.ReplaceExisting)
deletefile = Await StorageFile.GetFileFromPathAsync(localpath.Path + "\del.jpg")
Await deletefile.DeleteAsync(StorageDeleteOption.PermanentDelete)'<--这里出错
End If
checkname = Await sfile.CopyAsync(localpath, "bkg.jpg", NameCollisionOption.ReplaceExisting)
bkg.ImageSource = New BitmapImage(New Uri("ms-appdata:///local/bkg.jpg", UriKind.Absolute))
bkg.Stretch = Stretch.UniformToFill
bkg.Opacity = 0.5
Mainpage.Background = bkg
maingrid.Background = Nothing
main_topbar.Background.Opacity = 0.5
mainsplit.PaneBackground.Opacity = 0.7
End If</code>


如果不明白转个c#版的(太长就只写了一部分): <code>imagebrush bkg=new imagebrush();
storagefolder localpath=applicationdata.current.localfolder;
fileopenpicker fileopen=new fileopenpicker();
fileopen.filetypefilter.add(".jpg");
fileopen.filetypefilter.add(".png");
fileopen.filetypefilter.add(".bmp");
storagefile sfile=await fileopen.picksinglefileasync();
if(sfile!=null)
{
storagefile checkname;
if (mainpage.background!=null)
{
storagefile deletefile;
mainpage.background=null;
ckeckname=await storagefile.getfilefrompathasync(localpath.path+"\\bkg.jpg");
await checkname.renameasync("del.jpg",namecollisionoption.replaceexisting);
deletefile=await storagefile.getfilefrompathasync(localpath.path+"\\del.jpg");
await deletefile.deleteasync(storagedeleteoption.permanentdelete);//换过来报错应该是这里的
}
checkname=await sfile.copyasync(localpath,"bkg.jpg",namecollisionoption.replaceexisting);
......
}</code>

敬告:
为防止不可控的内容风险,本站已关闭新用户注册,新贴的发表及评论;
你现在看到的内容只是互联网用户曾经发表的言论快照,仅用于老用户留存纪念,且仅与科技行业相关,全部内容不代表本站观点及立场;
本站重新开放前已针对包括用户隐私、版权保护、信息安全、国家政策在内的各种互联网法律法规要求,执行了隐患内容的自查、屏蔽和删除;
本站目前所属个人主体,未有任何盈利安排与计划,且与原WFUN.COM所属公司不存在任何关联关系;
如果本帖内容或者相关资源侵犯到您的合法权益,或者您认为存在问题,那么请您务必点此举报或投诉!
全部回复:
asizel UID.631132
2018-04-12 使用 Lumia 1520 回复

撸过 帮顶 不懂

山****花 UID.2951546
2018-04-12 回复

唉,没人回答啊,只能粗暴解决了: <code> Private Async Sub use_background_Click(sender As Object, e As RoutedEventArgs)
Dim localpath As StorageFolder = ApplicationData.Current.LocalFolder
Dim tmppath As StorageFolder = ApplicationData.Current.TemporaryFolder
Dim fileopen As New FileOpenPicker()
fileopen.FileTypeFilter.Add(".jpg")
fileopen.FileTypeFilter.Add(".png")
fileopen.FileTypeFilter.Add(".bmp")
Dim sfile As StorageFile = Await fileopen.PickSingleFileAsync()
If sfile IsNot Nothing Then
Dim filetoken As String = Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(sfile)
Dim checkname As StorageFile
Dim delfile As StorageFile = Await localpath.GetFileAsync("bkg.jpg")
If setbkg_frompath = True Or delfile IsNot Nothing Then
Await delfile.MoveAsync(tmppath, "del.jpg", NameCollisionOption.GenerateUniqueName)'<--把旧文件扔到临时文件,重复与否也算了
setbkg_frompath = False
End If
'Await error_dlg.ShowAsync()
'filetoken = Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(sfile)
checkname = Await sfile.CopyAsync(localpath, "bkg.jpg", NameCollisionOption.ReplaceExisting)
set_bkg()
setbkg_frompath = True
End If
End Sub</code>

箭士 UID.2864780
2018-04-12 回复

好像挺厉害

山****花 UID.2951546
2018-04-12 回复

继续试了下,看来还是没办法的样子,在手机端依然会触发“System.UnauthorizedAccessException: '拒绝访问。 (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))'”
但电脑端就很顺利。看来这个问题还是要解决啊

tmp00000 UID.995403
2018-04-13 回复

可能是文件被占用了

tmp00000 UID.995403
2018-04-13 回复

你可以这样:先把要删除的文件挪到临时文件夹,然后把新文件加到 AppLocalData 里面,将 ImageSource 设置成新文件。每次应用启动的时候检查上次那个临时文件在不在。如果在就删掉。

tmp00000 UID.995403
2018-04-13 回复

原因是 Image 控件的内存管理机制是引用计数,就像 VB6 里面一样。那个旧图片 BitmapSource 虽然引用计数从 Image.Source 属性设置为 Nothing 之后减少了,但是它还在 Image 控件的位图缓存里面被引用着。这样就有可能删不掉。所以说必须挪到临时文件里面在下次启动的时候删除或者等系统自动删除。

TonyDeng UID.2870126
2018-04-13 使用 Lumia 950 回复

本帖最后由 TonyDeng 于 2018-4-13 20:58 编辑

不能刪除和覆蓋,是因爲文件被打開了,共享狀態下是不能刪除和覆蓋。你在PC 上可以但在手機上不可以,是有點怪,我沒測試過。如果要變通辦法,大致是這樣:先把背景圖換了,然後刪除或覆蓋原先的圖,再換回來。 傳統的做法,需要關閉資源,各種close,才能刪除或覆蓋的,需要查資料怎樣關閉資源。

tmp00000 UID.995403
2018-04-13 回复

QuoteTonyDeng 发表于 2018-4-13 20:55
不能刪除和覆蓋,是因爲文件被打開了,共享狀態下是不能刪除和覆蓋。你在PC 上可以但在手機上不可以,是有 ...


那个资源是释放不掉的,除非把引用计数置 0。用反射可以看出那是 COM Object。

TonyDeng UID.2870126
2018-04-13 使用 Lumia 950 回复

Quotetmp00000 发表于 2018-4-13 21:08
那个资源是释放不掉的,除非把引用计数置 0。用反射可以看出那是 COM Object。 ...


引用計數自己不能改的,非零的話一定有地方在用,要麽檢查是否有複製引用多了拷貝,類似失效指針那種編程失誤。

tmp00000 UID.995403
2018-04-13 回复

用 .NET 语言做 UWP 涉及到 COM 对象的互操作问题。引用计数是 UWP 的运行库内部实现用到的概念,在 .NET 这边只要注意使用 COM 对象的时候别循环引用就行。在没有明显的循环引用的代码中(比如说这次楼主发的代码),图片文件没关掉就是 UWP 的运行库中使用那个图片文件的对象引用计数在 Mainpage.Background = Nothing 那行代码之后还不是 0。这个时候文件被占用只能当作运行库的限制处理,也就是我说到的把需要删除的文件挪到临时文件夹,并下次启动时清理。

TonyDeng UID.2870126
2018-04-13 使用 Lumia 950 回复

本帖最后由 TonyDeng 于 2018-4-13 21:42 编辑

問題恐怕出在異步庫函數上,自己這邊關了,別的不能控制的部分沒關。置null是沒有關閉資源的,把另一個對象引用過來而已,原先在用的那個實體還處於打開狀態。A引用B,後來A改引用C,然而原先的B還處於被引用狀態。

山****花 UID.2951546
2018-04-14 回复

***链接停止解析*** ***链接停止解析***

感谢两位指导,不过今天试了下,看来手机还是比较无解,连重命名都不行。
也试了取消引用(直接将imagebrush/bitmapimage设置为nothing/null),不过还是占着。

至于在使用之前进行清理,倒是可行的,文件可以正常删除

这里居然出现了平台区别实在是奇怪...

TonyDeng UID.2870126
2018-04-14 使用 Lumia 950 回复

你用什麽開發環境?

山****花 UID.2951546
2018-04-14 回复

Quote***链接停止解析***
你用什麽開發環境?


sdk...10240的,宿主...17643

另外试了下把背景图片以stream的方式读进内存貌似可以解决(可以覆盖),只是还要测一下

山****花 UID.2951546
2018-04-14 回复

本帖最后由 山形まり花 于 2018-4-14 13:31 编辑

解决: <code> Public Shared Async Sub set_bkg(ByVal sender As Page)
Dim bkg As ImageBrush = New ImageBrush()
Dim bkg2 As BitmapImage = New BitmapImage()
Dim file As StorageFile = Await ApplicationData.Current.LocalFolder.GetFileAsync("bkg.jpg")
Using ms As IRandomAccessStream = Await file.OpenAsync(FileAccessMode.Read)
bkg2.SetSource(ms)
End Using
'bkg.ImageSource = (New Uri("ms-appdata:///local/bkg.jpg", UriKind.Absolute)) <--这句为原来的
bkg.ImageSource = bkg2'<--改为从stream读取
bkg.Stretch = Stretch.UniformToFill
bkg.Opacity = 0.5
sender.Background = bkg
End Sub</code>

相应的c# <code>public async static void set_bkg(Page sender)
{
ImageBrush bkg = new ImageBrush();
BitmapImage bkg2 = new BitmapImage();
StorageFile file = await ;
using (IRandomAccessStream ms = await ApplicationData.Current.LocalFolder.GetFileAsync("bkg.jpg"))
{
bkg2.SetSource(ms);
}
//bkg.ImageSource = (new Uri("ms-appdata:///local/bkg.jpg", UriKind.Absolute)) <--这句为原来的
bkg.ImageSource = bkg2;
bkg.Stretch = Stretch.UniformToFill;
bkg.Opacity = 0.5;
sender.Background = bkg;
}</code>

再次感谢 @tmp00000 @TonyDeng 两位指出的文件占用问题,试了怎么都释放不了之后就试着把文件读取出来,放在stream上,然后直接引用stream的值之后就可以随意换文件了

TonyDeng UID.2870126
2018-04-14 回复

Quote山形まり花 发表于 2018-4-14 13:00
解决:



是一个解决办法,虽然代码多了一些,也占用内存,但较为灵活。不过还是没有解决原先的疑问,有机会最好找到原因,照原理推,应该就是资源占用造成,必须关闭,这报错与文件共享打开无法删除和覆盖是同一个信息,根源是一样的。

tmp00000 UID.995403
2018-04-14 回复

QuoteTonyDeng 发表于 2018-4-14 13:32
是一个解决办法,虽然代码多了一些,也占用内存,但较为灵活。不过还是没有解决原先的疑问,有机会最好找 ...


说不定是 WP 的 UWP 运行库内部实现有 Bug,循环引用了。PC 端修复了那个 Bug。遇到这种限制就要换个办法实现了。

tmp00000 UID.995403
2018-04-14 回复

Quote山形まり花 发表于 2018-4-14 13:00
解决:



这个代码有个小问题。应用挂起之后还原有一定几率导致当前缓存的图片丢失。14393 那阵子我见到过这样的问题,自从 15063 后就无法复现了。

TonyDeng UID.2870126
2018-04-14 使用 Lumia 950 回复

Quotetmp00000 发表于 2018-4-14 17:22
说不定是 WP 的 UWP 运行库内部实现有 Bug,循环引用了。PC 端修复了那个 Bug。遇到这种限制就要换个办法 ...


有可能的。他用10240,用最新的框架試試?

artfly08 UID.2900999
2018-05-11 使用 Lumia 830 回复

不清楚

artfly08 UID.2900999
2018-06-26 使用 Lumia 950 XL 回复

有时候应用也卸载不了

本站使用Golang构建,点击此处申请开源鄂ICP备18029942号-4联系站长投诉/举报