Мне удалось изменить пример проекта Github> googlecast / CastHelloText-chrome для отображения веб-страницы.
receiver.html
я заменил DIV
на IFRAME
и установил его для 100% ширины и высоты. displayText()
я изменил innerHTML
на src
. chromehellotext.html
, было заменить YOUR_APPLICATION_ID
идентификатором приложения, созданным путем регистрации получателя. Обратите внимание , что некоторые сайты, такие как Google и Yahoo, не будут отображаться внутри iframe. Если вам действительно нужно это сделать, вы можете пропустить iframe и просто установить window.location.href
на URL. Это, конечно, перезапишет код получателя, поэтому единственный способ изменить URL-адреса - это сначала вручную отключиться и перезагрузить. Вместо этого я попытался использовать window.open
, но это не сработало.
Следуя моему предыдущему ответу, мне удалось создать базовый искатель исключений. Он использует класс ILReader
, основанный на отражении, доступный здесь в блоге Хайбо Луо MSDN. (Просто добавьте ссылку на проект.)
Обновления:
Вот полный код. Вы просто хотите использовать метод GetAllExceptions (MethodBase)
либо как расширение, либо как статический метод.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using ClrTest.Reflection;
public static class ExceptionAnalyser
{
public static ReadOnlyCollection<Type> GetAllExceptions(this MethodBase method)
{
var exceptionTypes = new HashSet<Type>();
var visitedMethods = new HashSet<MethodBase>();
var localVars = new Type[ushort.MaxValue];
var stack = new Stack<Type>();
GetAllExceptions(method, exceptionTypes, visitedMethods, localVars, stack, 0);
return exceptionTypes.ToList().AsReadOnly();
}
public static void GetAllExceptions(MethodBase method, HashSet<Type> exceptionTypes,
HashSet<MethodBase> visitedMethods, Type[] localVars, Stack<Type> stack, int depth)
{
var ilReader = new ILReader(method);
var allInstructions = ilReader.ToArray();
ILInstruction instruction;
for (int i = 0; i < allInstructions.Length; i++)
{
instruction = allInstructions[i];
if (instruction is InlineMethodInstruction)
{
var methodInstruction = (InlineMethodInstruction)instruction;
if (!visitedMethods.Contains(methodInstruction.Method))
{
visitedMethods.Add(methodInstruction.Method);
GetAllExceptions(methodInstruction.Method, exceptionTypes, visitedMethods,
localVars, stack, depth + 1);
}
var curMethod = methodInstruction.Method;
if (curMethod is ConstructorInfo)
stack.Push(((ConstructorInfo)curMethod).DeclaringType);
else if (method is MethodInfo)
stack.Push(((MethodInfo)curMethod).ReturnParameter.ParameterType);
}
else if (instruction is InlineFieldInstruction)
{
var fieldInstruction = (InlineFieldInstruction)instruction;
stack.Push(fieldInstruction.Field.FieldType);
}
else if (instruction is ShortInlineBrTargetInstruction)
{
}
else if (instruction is InlineBrTargetInstruction)
{
}
else
{
switch (instruction.OpCode.Value)
{
// ld*
case 0x06:
stack.Push(localVars[0]);
break;
case 0x07:
stack.Push(localVars[1]);
break;
case 0x08:
stack.Push(localVars[2]);
break;
case 0x09:
stack.Push(localVars[3]);
break;
case 0x11:
{
var index = (ushort)allInstructions[i + 1].OpCode.Value;
stack.Push(localVars[index]);
break;
}
// st*
case 0x0A:
localVars[0] = stack.Pop();
break;
case 0x0B:
localVars[1] = stack.Pop();
break;
case 0x0C:
localVars[2] = stack.Pop();
break;
case 0x0D:
localVars[3] = stack.Pop();
break;
case 0x13:
{
var index = (ushort)allInstructions[i + 1].OpCode.Value;
localVars[index] = stack.Pop();
break;
}
// throw
case 0x7A:
if (stack.Peek() == null)
break;
if (!typeof(Exception).IsAssignableFrom(stack.Peek()))
{
//var ops = allInstructions.Select(f => f.OpCode).ToArray();
//break;
}
exceptionTypes.Add(stack.Pop());
break;
default:
switch (instruction.OpCode.StackBehaviourPop)
{
case StackBehaviour.Pop0:
break;
case StackBehaviour.Pop1:
case StackBehaviour.Popi:
case StackBehaviour.Popref:
case StackBehaviour.Varpop:
stack.Pop();
break;
case StackBehaviour.Pop1_pop1:
case StackBehaviour.Popi_pop1:
case StackBehaviour.Popi_popi:
case StackBehaviour.Popi_popi8:
case StackBehaviour.Popi_popr4:
case StackBehaviour.Popi_popr8:
case StackBehaviour.Popref_pop1:
case StackBehaviour.Popref_popi:
stack.Pop();
stack.Pop();
break;
case StackBehaviour.Popref_popi_pop1:
case StackBehaviour.Popref_popi_popi:
case StackBehaviour.Popref_popi_popi8:
case StackBehaviour.Popref_popi_popr4:
case StackBehaviour.Popref_popi_popr8:
case StackBehaviour.Popref_popi_popref:
stack.Pop();
stack.Pop();
stack.Pop();
break;
}
switch (instruction.OpCode.StackBehaviourPush)
{
case StackBehaviour.Push0:
break;
case StackBehaviour.Push1:
case StackBehaviour.Pushi:
case StackBehaviour.Pushi8:
case StackBehaviour.Pushr4:
case StackBehaviour.Pushr8:
case StackBehaviour.Pushref:
case StackBehaviour.Varpush:
stack.Push(null);
break;
case StackBehaviour.Push1_push1:
stack.Push(null);
stack.Push(null);
break;
}
break;
}
}
}
}
}
Подводя итог, этот алгоритм рекурсивно перечисляет (сначала в глубину) любые методы, вызываемые в указанном, путем чтения инструкции CIL (а также отслеживание уже посещенных методов). Он поддерживает единый список коллекций, которые могут быть созданы с помощью объекта HashSet
, который возвращается в конце. Кроме того, он поддерживает массив локальных переменных и стек, чтобы отслеживать исключения, которые не генерируются сразу после их создания.
Конечно, этот код в нем не является безошибочным » s текущее состояние. Есть несколько улучшений, которые мне нужно сделать, чтобы он был надежным, а именно:
rethrow
. Кроме того, я считаю, что код разумно полный. Может потребоваться немного больше исследований, прежде чем я точно выясню, как выполнять обнаружение управления потоком (хотя я считаю, что теперь могу увидеть, как это работает на уровне IL).
Моя методология для этого типа ситуаций - обрабатывать все исключения, которые я хочу, а затем переопределять событие UnhandledException приложения для регистрации любых других, о которых я не знаю. Затем, если я столкнусь с чем-то, что, как мне кажется, я могу решить, я просто обновлю его соответствующим образом.
Надеюсь, что это поможет!
This answer was posted in the other question you reference and I know I have recommended it before in another similar question. You should give Exception Hunter a try. It lists out every single exception that can possibly be thrown. When I ran it for the first time on my code I was quite surprised by the size of this list for even simple functions. There is a 30 day trial for free so there is no reason not to give it a try.
Это не должно быть очень сложно. Вы можете получить список исключений, созданных следующим способом:
IEnumerable<TypeReference> GetCreatedExceptions(MethodDefinition method)
{
return method.GetInstructions()
.Where(i => i.OpCode == OpCodes.Newobj)
.Select(i => ((MemberReference) i.Operand).DeclaringType)
.Where(tr => tr.Name.EndsWith("Exception"))
.Distinct();
}
Фрагменты используют Lokad.Quality.dll из Open Source Lokad Shared Libraries (которые используют Mono.Cecil для выполнения тяжелой работы вокруг кода отражение). На самом деле я поместил этот код в один из тестовых примеров в магистрали .
Скажем, у нас есть такой класс:
class ExceptionClass
{
public void Run()
{
InnerCall();
throw new NotSupportedException();
}
void InnerCall()
{
throw new NotImplementedException();
}
}
затем, чтобы получить все исключения только из метода Run:
var codebase = new Codebase("Lokad.Quality.Test.dll");
var type = codebase.Find<ExceptionClass>();
var method = type.GetMethods().First(md => md.Name == "Run");
var exceptions = GetCreatedExceptions(method)
.ToArray();
Assert.AreEqual(1, exceptions.Length);
Assert.AreEqual("NotSupportedException", exceptions[0].Name);
Теперь все, что осталось, - это пройти вниз по стеку вызовов методов до определенной глубины. Вы можете получить список методов, на которые ссылается такой метод:
var references = method.GetReferencedMethods();
Теперь, прежде чем мы сможем вызвать GetCreatedExceptions для любого метода в стеке, нам просто нужно фактически заглянуть в кодовую базу и разрешить все экземпляры MethodReference экземплярам MethodDefinition, фактически содержащим байтовый код (с некоторым кешированием для избегайте сканирования существующих веток). Это наиболее трудоемкая часть кода (поскольку объект Codebase не реализует поиск методов поверх Cecil), но это должно быть выполнимо.
I'm very doubtful there is any (at least straightforward) way to do this in C#. Saying that, I do have an idea that may work, so read on please...
Firstly, it's worth noting that doing a brute-force search using a huge number of permutations of arguments clearly is not feasible. Even having prior knowledge of parameter types (which I don't believe is desirable in your situation), the task essentially reduces to the halting problem in the general case, since you don't know the function will terminate given certian parameters. Ideally, exceptions should stop this, but it isn't always the case of course.
Now, perhaps the most reliable method is to analyse the source code (or more realistically CIL code) itself to see which exceptions might be thrown. This I believe may actually be workable. A simple algorithm might go something like:
This would even allow you to get detailed information about the exceptions, such as whether they are thrown directly by the called method, or deeper in the call stack, or even the exception messages themselves. Anyway, I'll consider giving an implementation of this a try later this afternoon, so I'll let you know how feasible the idea is then.
Unlike java C# does not have the concept of checked exceptions.
On a macro level you should catch everything and log or inform the user of the error. When you know about the specific exceptions a method may raise then definetly handle that appropriately but be sure to let any other exceptions bubble up (preferably) or log them, otherwise you will have bugs that you will not be able to find and generally make life miserable for anyone hired to help reduce the bug list - have been there, not fun! :)
John Robbins had a series of articles on creating FxCop rules including an MSDN article that would indicate which exceptions were thrown. This was to warn about missing XML documentation for the exceptions but the idea would be the same.
Я написал надстройку для Reflector под названием ExceptionFinder, которая этим занимается. Вы можете получить его по адресу:
http://exfinderreflector.codeplex.com/
С уважением, Джейсон