Word Addin中的IsolatedStorageException

时间:2014-06-02 14:13:30

标签: c# .net vsto openxml isolatedstorage

我使用功能区创建了一个Word加载项项目,当我想保存文档时,在使用OpenXml进行多次修改后,会引发异常。

Dim MainXMLDoc As New XmlDocument()
Using WordDoc As WordprocessingDocument = WordprocessingDocument.Open(DocPath, True)

Dim mainPart As MainDocumentPart = WordDoc.MainDocumentPart
If Not mainPart Is Nothing Then

    MainXMLDoc.Load(mainPart.GetStream())
    EXmlDocument.XMLDoc = Nothing
    EXmlDocument.XMLDoc = MainXMLDoc
    EXmlDocument.GetWordDocIds()
    ..............
end if

........
Dim stream As IO.Stream
stream = mainPart.GetStream(FileMode.Create, FileAccess.Write)

    MainXMLDoc.Save(stream) -----> exception

异常消息是:

  

Interception de System.IO.IsolatedStorage.IsolatedStorageException
  消息=无法确定域的标识。来源= mscorlib程序   堆栈跟踪:          在System.IO.IsolatedStorage.IsolatedStorage._GetAccountingInfo(证据)   证据,类型证据类型,IsolatedStorageScope fAssmDomApp,Object&   oNormalized)          在System.IO.IsolatedStorage.IsolatedStorage.GetAccountingInfo(证据)   证据,类型证据类型,IsolatedStorageScope fAssmDomApp,String&   typeName,String&实例名)          在System.IO.IsolatedStorage.IsolatedStorage._InitStore(IsolatedStorageScope)   范围,证据domainEv,类型domainEvidenceType,Evidence assemEv,   输入assemblyEvidenceType,Evidence appEv,Type appEvidenceType)          在System.IO.IsolatedStorage.IsolatedStorage.InitStore(IsolatedStorageScope)   scope,类型domainEvidenceType,类型assemblyEvidenceType)          在System.IO.IsolatedStorage.IsolatedStorageFile.GetStore(IsolatedStorageScope)   scope,类型domainEvidenceType,类型assemblyEvidenceType)          在MS.Internal.IO.Packaging.PackagingUtilities.ReliableIsolatedStorageFileFolder.GetCurrentStore()          在MS.Internal.IO.Packaging.PackagingUtilities.ReliableIsolatedStorageFileFolder..ctor()          在MS.Internal.IO.Packaging.PackagingUtilities.GetDefaultIsolatedStorageFile()          在MS.Internal.IO.Packaging.PackagingUtilities.CreateUserScopedIsolatedStorageFileStreamWithRandomName(Int32   retryCount,String&文件名)          在MS.Internal.IO.Packaging.SparseMemoryStream.SwitchModeIfNecessary()          在MS.Internal.IO.Packaging.SparseMemoryStream.Write(Byte []缓冲区,Int32偏移量,Int32计数)          在MS.Internal.IO.Packaging.CompressEmulationStream.Write(Byte []缓冲区,   Int32偏移量,Int32计数)          在MS.Internal.IO.Packaging.CompressStream.Write(Byte []缓冲区,Int32偏移量,Int32计数)          在MS.Internal.IO.Zip.ProgressiveCrcCalculatingStream.Write(Byte []   缓冲区,Int32偏移量,Int32计数)          在MS.Internal.IO.Zip.ZipIOModeEnforcingStream.Write(Byte []缓冲区,Int32偏移量,Int32计数)          在System.IO.StreamWriter.Flush(Boolean flushStream,Boolean flushEncoder)          在System.IO.StreamWriter.Write(Char值)          在System.Xml.XmlTextWriter.Indent(Boolean beforeEndElement)          在System.Xml.XmlTextWriter.AutoComplete(令牌令牌)          at System.Xml.XmlTextWriter.WriteStartElement(String prefix,String localName,String ns)          at System.Xml.XmlDOMTextWriter.WriteStartElement(String prefix,String localName,String ns)          在System.Xml.XmlElement.WriteStartElement(XmlWriter w)          在System.Xml.XmlElement.WriteElementTo(XmlWriter writer,XmlElement e)          在System.Xml.XmlElement.WriteTo(XmlWriter w)          在System.Xml.XmlDocument.WriteContentTo(XmlWriter xw)          在System.Xml.XmlDocument.WriteTo(XmlWriter w)          在System.Xml.XmlDocument.Save(Stream outStream)InnerException:

当文档大小超过1 MB时,会出现此问题。 经过多次搜索后,“保存”操作是通过隔离存储进行的,解决方案是:

  • 使用Clickonce安装
  • 创建新域
  • 修改注册表。

但对于这个项目,我不能使用ClickOnce,我无法修改注册表。

所以我对源代码进行了更改,以创建一个新域。

Imports DocumentFormat.OpenXml.Packaging
Imports System.IO

<Serializable()> Public Class ToIsolatedPackageSave
    Public Sub Save(ByRef mainPart As MainDocumentPart, ByRef xmlDocument As Xml.XmlDocument)
        Dim stream As IO.Stream
        stream = mainPart.GetStream(FileMode.Create, FileAccess.Write)
        xmlDocument.Save(stream) -----> same exception

    End Sub
End Class

并且

Dim stream As Stream
Dim isolatedPackageSave As ToIsolatedPackageSave
Dim isolatedAppDomain As AppDomain

Try
    Dim isolatedAppDomainSetup As AppDomainSetup = New AppDomainSetup()
    isolatedAppDomainSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory

    Dim isolatedEvidence As Evidence = New Evidence(AppDomain.CurrentDomain.Evidence)
    isolatedEvidence.AddAssembly(Reflection.Assembly.GetExecutingAssembly().FullName)
    isolatedEvidence.AddHost(New Zone(Security.SecurityZone.MyComputer))

    isolatedAppDomain = AppDomain.CreateDomain("TrustIsolatedDomain", isolatedEvidence, isolatedAppDomainSetup)
    isolatedPackageSave = isolatedAppDomain.CreateInstanceAndUnwrap(GetType(ToIsolatedPackageSave).Assembly.FullName, GetType(ToIsolatedPackageSave).FullName)
    '(IsolatedPackageSave)isolatedAppDomainSetup.CreateInstanceAndUnwrap(GetType(ToIsolatedPackageSave).Assembly.FullName, GetType(ToIsolatedPackageSave).FullName)
    isolatedPackageSave.Save(mainPart, MainXMLDoc)
Catch ex As Exception
Finally
    AppDomain.Unload(isolatedAppDomain)
End Try

但是这段代码并没有解决我的问题。

2 个答案:

答案 0 :(得分:7)

我跟随蒂姆刘易斯&#39;在这篇文章中建议注入所需的安全证据: http://rekiwi.blogspot.com/2008/12/unable-to-determine-identity-of-domain.html

public void VerifySecurityEvidenceForIsolatedStorage(Assembly assembly)
{
    var isEvidenceFound = true;
    var initialAppDomainEvidence = System.Threading.Thread.GetDomain().Evidence;
    try
    {
        // this will fail when the current AppDomain Evidence is instantiated via COM or in PowerShell
        using (var usfdAttempt1 = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForDomain())
        {
        }
    }
    catch (System.IO.IsolatedStorage.IsolatedStorageException e)
    {
        isEvidenceFound = false;
    }

    if (!isEvidenceFound)
    {
        initialAppDomainEvidence.AddHostEvidence(new Url(assembly.Location));
        initialAppDomainEvidence.AddHostEvidence(new Zone(SecurityZone.MyComputer));

        var currentAppDomain = Thread.GetDomain();
        var securityIdentityField = currentAppDomain.GetType().GetField("_SecurityIdentity", BindingFlags.Instance | BindingFlags.NonPublic);
        securityIdentityField.SetValue(currentAppDomain, initialAppDomainEvidence);

        var latestAppDomainEvidence = System.Threading.Thread.GetDomain().Evidence; // setting a breakpoint here will let you inspect the current app domain evidence
    }
}

然后在启动时调用以下代码:

VerifySecurityEvidenceForIsolatedStorage(this.GetType().Assembly);

答案 1 :(得分:0)

我认为,您无法在办公室插件中使用OpenXML。如果你想使用OpenXML,你必须离线(当文档没有打开时)。您只能使用来自插件内部的COM interops(office对象模型调用)。