GuOrg / Gu.Wpf.UiAutomation

MIT License
96 stars 17 forks source link

Unable to load Interop.UIAutomationClient.dll #47

Closed RobSmyth closed 6 years ago

RobSmyth commented 6 years ago

Hi,

I'm getting an exception when trying a very simple test to load a WPF app:

System.IO.FileNotFoundException : Could not load file or assembly 'Interop.UIAutomationClient, Version=4.5.0.0, Culture=neutral, PublicKeyToken=5b28cd3eabb9203e' or one of its dependencies. The system cannot find the file specified. at Gu.Wpf.UiAutomation.Application..ctor(ProcessReference process, Boolean isStoreApp) at Gu.Wpf.UiAutomation.Application.Launch(ProcessStartInfo processStartInfo, OnDispose onDispose) in C:\Git\Gu.Wpf.UiAutomation\Gu.Wpf.UiAutomation\Application.cs:line 314 at Gu.Wpf.UiAutomation.Application.Launch(String exeFileName, OnDispose onDispose) in C:\Git\Gu.Wpf.UiAutomation\Gu.Wpf.UiAutomation\Application.cs:line 289

I can see the DLL in the packages, so I recon it is a dependency problem.

My test code is:

[TestFixture] public sealed class MyTestFixture { [Test] public void Test() { using (var app = Application.Launch("TestWpfApp.exe")) { System.Threading.Thread.Sleep(5000); } } }

The test app appears and stays open. The exception occurs immediately (before the sleep).

Details:

This is my first go at using this framework ... have I missed something?

Thx

Rob

FoggyFinder commented 6 years ago

it sounds like a problem with .net 4.6.1. If you change project to .net 4.5 the exception will gone?

RobSmyth commented 6 years ago

Hi,

Changing the projects to .net 4.5 has no effect. Error remains as reported.

RobSmyth commented 6 years ago

Ah, now I look closer I have found that the problem is that the "Interop.UIAutomationClient" assembly is not copied to the output folder. If I manually copy it the problem is fixed.

The reference in my project file (added by the NuGet package) is:

`

..\packages\Gu.Wpf.UiAutomation.0.1.17.0\lib\net45\Interop.UIAutomationClient.dll
  <EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>

`

I'm not familiar with the 'EmbedInteropTypes' element here. I'm not able to configure the reference to have a local copy in VS2017.

How do I fix this?

Thanks

Rob

JohanLarsson commented 6 years ago

Sounds like we may have dumbed the packing somehow, I have only used it with Paket, maybe nuget does things differently? Ideally we should remove the interop dll, maybe we can use ILMerge or something. Thanks for reporting, we'll try to repro and fix.

JohanLarsson commented 6 years ago

@RobSmyth If you have time you can clone the repo and run the tests, if that works chances are the difference is nuget.exe.

JohanLarsson commented 6 years ago

Repro with nuget.exe was easy, question is how to fix it in a nice way. Copy local was set to true by default but that did not copy the dll. Surprisingly setting <EmbedInteropTypes>False</EmbedInteropTypes> made it copy on build, guess that is a hack solution but we should find something nicer.

JohanLarsson commented 6 years ago

I'm gonna have a go ad embedding the interop assembly in https://github.com/JohanLarsson/Gu.Wpf.UiAutomation/tree/embed

I don't know much about COM but it seems constants cannot be embedded. Strategy is to hardcode constants in Gu.Wpf.UiAutomation and throw tests at it.

RobSmyth commented 6 years ago

Hi,

I found that deleting Interop.UIAutomationClient.dll from my project fixed the problem. It appears I do not need it. So it looks like it was trying to load it as it was a reference in my project, although not used.

Do we need this assembly in the distribution?

Rob

JohanLarsson commented 6 years ago

We need to find a nicer solution for this, other libraries use a PS script in the tools folder of the package that changes on install. TBH I'm not sure we need the interop thing at all. Hopefully we can refactor away from it. The issue is great!

JohanLarsson commented 6 years ago

Refactored away from the interop thing. Cleaning up some more stuff before releasing, will be bumped major due to some breaking changes, hopefully the most used APIs will not be affected much.

JohanLarsson commented 6 years ago

I'm closing this, new version uses UIAutomationClient and UIAutomationTypes and no interop dll. This refactoring meant a couple of breaking changes but hopefully it did not touch the common APIs too much.

Roemer commented 6 years ago

Just as a warning: When you use the managed UIAutomationClient, you're back to UIA2 which lacks some features and bug fixes which are in the interop version and also you probably won't get future features in it as Microsoft pretty much abandoned the managed version.

Roemer commented 6 years ago

I just spent some time on this again. There definitely is a difference between using UIAutomationClient and using the interop version. See this example:

var auto = new UIAutomationClient.CUIAutomation();
var desktop = auto.GetRootElement();
Console.WriteLine(desktop.CurrentName);

var desktop2 = System.Windows.Automation.AutomationElement.RootElement;
Console.WriteLine(desktop2.Current.Name);

The first one using interop prints "Desktop", the second one prints an empty string. I tried with different .net versions but the result is always the same. This is only one difference, there are plenty of others as well.

JohanLarsson commented 6 years ago

Ah, thanks, maybe we will have to refactor back at some point.

RobSmyth commented 6 years ago

Sorry to be picky ... but it is not refactoring if it changes/drops/adds any functionality. :-)

JohanLarsson commented 6 years ago

@RobSmyth Have you seen gitter https://gitter.im/JohanLarsson/Gu.Wpf.UiAutomation