Skip to content

Commit

Permalink
Exceptions thrown by UIA server in UI thread in WPF should be caught …
Browse files Browse the repository at this point in the history
…and redirected to automating thread in order to report error correctly. Otherwise automated app just crashes as with usual uncaught exception in dispatcher. On UIA client side added UiaCallFailedException because otherwise it is TargetInvocationException without any details, which is very common.
  • Loading branch information
ivan-danilov committed Nov 21, 2014
1 parent 37039b7 commit 33c1d17
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 10 deletions.
50 changes: 40 additions & 10 deletions ManagedUiaCustomizationCore/AutomationPeerAugmentationHelper.cs
Expand Up @@ -159,6 +159,42 @@ public object WrapObjectReplacer(AutomationPeer peer, object iface)
}
}

private static void GuardUiaServerInvocation(Action invocation, Dispatcher dispatcher)
{
if (dispatcher == null)
throw new ElementNotAvailableException();
Exception remoteException = null;
bool completed = false;
dispatcher.Invoke(DispatcherPriority.Send, TimeSpan.FromMinutes(3.0), (Action)(() =>
{
try
{
invocation();
}
catch (Exception e)
{
remoteException = e;
}
catch
{
remoteException = null;
}
finally
{
completed = true;
}
}));
if (completed)
{
if (remoteException != null)
throw remoteException;
}
else if (dispatcher.HasShutdownStarted)
throw new InvalidOperationException("AutomationDispatcherShutdown");
else
throw new TimeoutException("AutomationTimeout");
}

private class StandalonePropertyGetter
{
private readonly AutomationProperty _property;
Expand All @@ -172,7 +208,9 @@ public object Getter(AutomationPeer peer)
{
var propertyProvider = peer as IStandalonePropertyProvider;
if (propertyProvider == null) return null;
return propertyProvider.GetPropertyValue(_property);
object result = null;
GuardUiaServerInvocation(() => result = propertyProvider.GetPropertyValue(_property), peer.Dispatcher);
return result;
}
}

Expand All @@ -187,15 +225,7 @@ public SendingToUIThreadInterceptor(AutomationPeer peer)

public void Intercept(IInvocation invocation)
{
if (_dispatcher.CheckAccess())
{
invocation.Proceed();
}
else
{
Action a = invocation.Proceed;
_dispatcher.Invoke(a);
}
GuardUiaServerInvocation(invocation.Proceed, _dispatcher);
}
}
}
Expand Down
Expand Up @@ -81,6 +81,7 @@
<Compile Include="Schema\UiaPatternInfoHelper.cs" />
<Compile Include="Schema\UiaPropertyInfoHelper.cs" />
<Compile Include="AttributeDrivenPatternHelpers\UiaTypesHelper.cs" />
<Compile Include="UiaCallFailedException.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
Expand Down
8 changes: 8 additions & 0 deletions ManagedUiaCustomizationCore/NativeMethods.cs
Expand Up @@ -33,6 +33,14 @@ public static void WrapUiaComCall(Action call)
throw newEx;
throw;
}
catch (Exception e)
{
throw new UiaCallFailedException("Automation call failure", e);
}
catch
{
throw new UiaCallFailedException("Automation call failure");
}
}

#region Taken from UIAComWrapper - exception wrapping
Expand Down
27 changes: 27 additions & 0 deletions ManagedUiaCustomizationCore/UiaCallFailedException.cs
@@ -0,0 +1,27 @@
using System;
using System.Runtime.Serialization;

namespace ManagedUiaCustomizationCore
{
[Serializable]
public class UiaCallFailedException : Exception
{
public UiaCallFailedException()
{
}

public UiaCallFailedException(string message) : base(message)
{
}

public UiaCallFailedException(string message, Exception inner) : base(message, inner)
{
}

protected UiaCallFailedException(
SerializationInfo info,
StreamingContext context) : base(info, context)
{
}
}
}

0 comments on commit 33c1d17

Please sign in to comment.