关于结构化存储问题(IStorage) (200分)

  • 主题发起人 主题发起人 KN
  • 开始时间 开始时间
K

KN

Unregistered / Unconfirmed
GUEST, unregistred user!
我是想用IStorage.OpenStorage这个打开子流,我为什么只能打开到2级子存储以后,下面的都打不开了,注意:我是修改了3级下的子流或更下面的子流才出现这样的情况,但是我修该2级以上的子流都不会出错。它打不开的原因是HResult返回值STG_E_ACCESSDENIED,它的意思是Insufficient permissions to open storage object.
请大虾们指教,很急啊,谢谢!
 
不懂,学习
 
1.叙述不清,如何打开,参数是什么. ...
2.返回值的意思是没有存取权限.
3.可能的问题是OpenStorage 有个打开模式的参数设置问题,建议你首先新建一个工程,单独进行结构化存储的测试。
4.IStorage.OpenStorage这个打开的不是子流而是子存储. IStorage相当于文件夹/IStream相当于文件
 
TO:zjan521
我的Mode是 STGM_READWRITE or STGM_SHARE_EXCLUSIVE
我把问题再说清楚一点,我现在有结构为:
A
C(A下子存储)
D(C下子存储)
B
我打开子存储都是用以上的模式,我在C下建立子存储,退回到A后可以打开所有子存储,但是我在D下建立子存储再退回到A就不能把A打开了,但是可以打开同级的B以及B下的所有子存储,打开A的返回值就是STG_E_ACCESSDENIED
 
以上的问题我已经解决了。
我现在正在学习结构化存储,我回从现在开始把我遇到的问题发上来,解决问题的方法也发上来,这不仅使大家了解结构化存储有用,也对深入COM学习有帮助,感兴趣的朋友们也可以发表下自己的心得(我不知道我能不能说得清楚,我的表达能力很差,大家有不清楚的可以说出来,或者我说错了的)。
我先说说发生上述的问题吧。
RootStorage :IStorage;
接口是引用指针的计数,因此在对象中当获得接口指针时,对象被引用的次数就增加了。
引用计数是用IUnknown._AddRef和IUnknown._Release来控制的。
对于IStorage也是一样,我虽然已经RootStorage :=nil 但是IStorage的引用数并没有减少,因此我并没有打开原来子存储的读取权限,说的清楚点就是:我打开A,B,C,D的模式都有
STGM_EXCLUSIVE,这个模式的意思是不允许其他用户以读或写的方式打开,我虽然已经把引用A,B,C,D的RootStorage := nil,但是,一旦拥有了一个对象接口的引用,该对象就不能被撤消。对于IStorage来说,这个根或子存储的读写模式已经存在,不能再打开了,要使它放弃模式,有效的增加或结束引用可以解决我的上述问题,就要用到_AddRef和_Release,虽然Delphi在合适的时候自动调用了_AddRef和_Release,但是有些情况下我们还是必须要自己调手动用这两个函数的。
在写COM程序时,做了一翻努力,却得到了一个自己本来认为不该为nil的接口,或是出现“试图使用一个不复存在的对象”错误时候,也许就要查看自己对接口的引用了,也许调用这两个函数能解决您的问题
 
正常情况下,是不需要调用_AddRed/_Release的。因为实际上如果所有的接口引用都为nil(自然只考虑在Delphi),那么接口就已经释放了。你根本不可能去调用 nil._Release。之所以你还能调用_Release,是因为你还有接口没有被释放。
出现“试图使用一个不复存在的对象”错误恰恰很可能是错误的调用了_Release
 
没有啊,我原来以为是不用调用_AddRef和_Release的,所以才出现问题,后来调用了,就没有问题了。
我现在又发现,就算这样:
P = ^TStorage
TStorage = record
Storage :IStorage;
end;
List :TList;
如果List中的Pointer是P的话,delphi内部也调用了这两个函数,随便屏蔽一个都不行
真是用得我头晕啊
 
现在发现新的问题,谁能给个好的决策啊
如果A在窗口1已经正在被使用的时候,在窗口2就不能打开A,
 
这个当然,因为你用了STGM_SHARE_EXCLUSIVE模式,是独占方式的。
我也正在用IStorage及相关,互相学习互相提高...
 
TO:johnsonleee
是这样啊,就是想有什么好的方法呢,用了_Release,那么窗口1打开A就会有“试图使用一个不复存在的对象”用_AddRef,就会无权存取,又不能重新打开结构化文件,因为已经打开了就被锁定了,怎么办?
 
这样做是不是有点自相矛盾?你既然在一个打开了,就不应在其他地方打开,因为是独占的。除非你把指针(IStorage对象变量)传给新打开的窗口,而不是重新打开。有没有做过Email客户端,顺便帮我看一下<a href="http://www.delphibbs.com/delphibbs/dispq.asp?lid=2611406">http://www.delphibbs.com/delphibbs/dispq.asp?lid=2611406关于Email解码的问题</a>
 
如果你只是需要禁止别的进程打开,那么只需要在打开 RootStorage的时候独占就可以了
_Release/_AddRef本身不需要直接调用.
如果你真的不想改变打开方式的话.可以利用List保存现有接口
 
OleCheck(stg.OpenStorage(StatStg.pwcsName, nil , STGM_READWRITE or STGM_SHARE_EXCLUSIVE, nil, 0, stgChild));
if stgChild.MoveElementTo(PWideChar(pwcsName), stg, 'KN', 0)=S_OK then
SHowMessage('OK');
为什么MoveElementTO返回不成功呢,还是存取权限的问题,stgChild只是刚刚打开啊,
谁给我答案我就给分了
 
后退
顶部