2012-06-24 2 views
2

Что контролирует данные текущего домена приложения?У AppDomain Evidence нет зоны?

var evidence = Thread.GetDomain().Evidence; 

Что контролирует, если оно является нулевым или ненулевым, и что определяет его содержание?

Когда мое приложение запрашивает эти хоста доказательства объектов из области доказательства

var z = evidence.GetHostEvidence<Zone> 
var p = evidence.GetHostEvidence<Publisher> 
var s = evidence.GetHostEvidence<Site> 
var n = evidence.GetHostEvidence<StrongName> 
var u = evidence.GetHostEvidence<Url> 

он появляется, как если бы они иногда все нуль при выполнении некоторых условий. Причина, по которой я считаю, что это исключение, вызванное внутри IsolatedStorage._GetAccountingInfo(...), где, просматривая код в рефлекторе, ясно, что это исключение будет выдаваться только в том случае, если доказательство домена содержит null для всех вышеупомянутых объектов доказательства объекта. Это приведет к невозможности инициализации изолированного хранилища.

К сожалению, я не могу воспроизвести его в своей собственной системе. Значение зоны, например, всегда будет правильным значением, говорящим «Мой компьютер», поэтому я изо всех сил пытаюсь решить эту проблему.

Что контролирует содержимое этих значений в домене приложения по умолчанию для настольного приложения Windows Forms?

+0

Он инициализируется хостом CLR, когда он создает основной домен. Тяжелые изменения в .NET 4 с внедрением EvidenceBase, поэтому я бы поискал необычные сценарии хостинга, которые по-прежнему используют устаревшие доказательства. Включение ClickOnce и одновременная активация COM-by-side COM. –

+0

Спасибо, Ханс. Это приложение .NET 4 winforms, развернутое через обычный MSI. Таким образом, проблемы возникают при нормальном выполнении на обычных машинах с .NET4. В чем разница между доказательствами домена и собранием? В моих собраниях я ожидаю, что большинство доказательств будет отсутствовать, поскольку оно не является сильным. –

ответ

0

Оказалось, что виновник действительно был «необычным сценарием развертывания», как предложил Ганс в комментарии к моему вопросу. Мы используем шифрование (обертывание) для нескольких сборок и, по-видимому, это затухает с доказательствами, требуемыми изолированным хранилищем.

2

Аналогичная ситуация возникает, когда код COM object accessed by a native Win32 application (по умолчанию AppDomain «s Evidence пуста), или когда он будет загружен и run inside of the command line version of PowerShell.exe. Я столкнулся с этой проблемой при использовании сборки OpenXML (в частности, EPPlus), которая использует IsolStorage, когда офисный документ превышает определенный размер файла.

Вместо того, чтобы разворачивать еще один AppDomain внутри по умолчанию и имея дело с дополнительным уровнем Marshaling/Remoting, я предпочитаю использовать отражение для гашения с текущим доказательством AppDomain.

Вот доказательство концепции в C#:

using System; 

namespace AppDomainEvidence 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var initialAppDomainEvidence = System.Threading.Thread.GetDomain().Evidence; // Setting a breakpoint here will let you inspect the current AppDomain's evidence 
      try 
      { 
       var usfdAttempt1 = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForDomain(); // This will fail when the current AppDomain Evidence is instantiated via COM or in PowerShell 
      } 
      catch (Exception e) 
      { 
       // Set breakpoint here to inspect Exception "e" 
      } 

      // Create a new Evidence that include the MyComputer zone 
      var replacementEvidence = new System.Security.Policy.Evidence(); 
      replacementEvidence.AddHostEvidence(new System.Security.Policy.Zone(System.Security.SecurityZone.MyComputer)); 

      // Replace the current AppDomain's evidence using reflection 
      var currentAppDomain = System.Threading.Thread.GetDomain(); 
      var securityIdentityField = currentAppDomain.GetType().GetField("_SecurityIdentity", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); 
      securityIdentityField.SetValue(currentAppDomain,replacementEvidence); 

      var latestAppDomainEvidence = System.Threading.Thread.GetDomain().Evidence; // Setting a breakpoint here will let you inspect the current AppDomain's evidence 

      var usfdAttempt2 = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForDomain(); // This should work 
     } 
    } 
} 

И вот обходной путь я реализовал в PowerShell:

# This one will fail 
$usfd = [System.IO.IsolatedStorage.IsolatedStorageFile]::GetUserStoreForDomain() 

# Inspect the current AppDomain's Evidence 
[threading.thread]::GetDomain().Evidence 


# Modify the current AppDomain's Evidence 
$evidence = new-object System.Security.Policy.Evidence 
$zone = new-object System.Security.Policy.Zone('MyComputer') 
$evidence.AddHost($zone) 
$currentAppDomain = [threading.thread]::GetDomain() 
$securityIdentityField=$currentAppDomain.GetType().GetField('_SecurityIdentity','Instance,NonPublic') 
$securityIdentityField.SetValue($currentAppDomain, $evidence) 

# Inspect the current AppDomain's Evidence 
[threading.thread]::GetDomain().Evidence 

# This one will succeed 
$usfd = [System.IO.IsolatedStorage.IsolatedStorageFile]::GetUserStoreForDomain() 
+1

Спасибо, ваше сообщение было очень полезно. Я столкнулся с тем же вопросом (который SpreadsheetLight, который также использует OpenXML). Сначала я попробовал «поворот еще одного подхода AppDomain», который быстро исчерпал память при попытке передать большие DataTables поверх границы удаленного доступа AppDomain посредством сериализации. Ваше решение отлично работает! – Heinzi

+1

Спасибо, это потрясающе! У меня была аналогичная проблема, пытаясь отладить мой Office Addin, который использует OpenXML. Я продолжал получать ошибку IsolStorageFile Не удалось определить личность домена. Этот код зафиксировал мой AppDomain и позволил моему коду работать без ошибок! – snoopen

Смежные вопросы