Has anyone used Appium/WinAppDriver for automating desktop applications. - desktop

I am looking for automating a windows application,and researching on what tools to be used. I have come across Appium/WinAppDriver, but not sure if it has a good usage anywhere so far....Appreciate suggestions on this.

I'm currently using the WinAppDriver to automate a WPF program. It's very similar to Selenium, if you have any experience with that then I'd advise using the WinAppDriver over something like White. You also get to use the Selenium WebDriverWait which was a massive bonus.
There is also a tool known as 'Inspect' that comes with the Windows SDK that allows you to inspect a windows application similar to the web-browser dev tools.
You simply initiate a driver (similar to Selenium) however you also need to start the WinApp process.
C# example:
protected WindowsDriver<WindowsElement> GetWindowsDriver()
{
var appCapabilities = new DesiredCapabilities();
appCapabilities.SetCapability("app",
PathHelper.GetClientInstallPath() + "APPLICATION.exe");
appCapabilities.SetCapability("deviceName", "WindowsPC");
if (!IsWinAppDriverProcesssRunning())
{
StartWinAppProcessRunning();
}
var driver = new WindowsDriver<WindowsElement>(new Uri("http://127.0.0.1:4723"), appCapabilities);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
return driver;
}
private static bool IsWinAppDriverProcesssRunning()
{
const string processName = "WinAppDriver";
var existingProcesses = Process.GetProcessesByName(processName);
return existingProcesses.Any();
}
private static void StartWinAppProcessRunning()
{
const string winAppDirectory = #"C:\Program Files (x86)\Windows Application Driver";
var winAppProcess =
new Process
{
StartInfo =
{
FileName = Path.Combine(winAppDirectory, "WinAppDriver.exe"),
WindowStyle = ProcessWindowStyle.Hidden,
WorkingDirectory = winAppDirectory
}
};
winAppProcess.Start();
}

Related

How to create a child iteration using TFS API?

I have to create a child iteration in Team Foundation Server 2017 (on premise). In my current Visual Studio project I am using then NuGet packages "Microsoft.TeamFoundationServer.Client" and "Microsoft.VisualStudio.Services.Client". None of the APIs offer a method to create a child iteration. I also didn't find any documentation on how to achieve this task. Anyone out there who knows how to create a child iteration?
You could use below sample to create a child iteration using the TFS API:
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Server;
using System;
namespace _AddIteration
{
class Program
{
static void Main(string[] args)
{
string iterationName = "TestIteration";
string collection = #"http://server:8080/tfs/DefaultCollection";
var tfsServer = new Uri(collection);
var tpc = new TfsTeamProjectCollection(tfsServer);
tpc.Authenticate();
var css = tpc.GetService<ICommonStructureService>();
string rootNodePath = string.Format("\\{0}\\Iteration", "ProjectName");
var pathRoot = css.GetNodeFromPath(rootNodePath);
css.CreateNode(iterationName, pathRoot.Uri);
}
}
}

Call a python code from WCF

I need to make a python code available as WCF for another application to access it. The python code was build by the data science team and have no ability to change it. I tried running the program as a process shell but it gives 'System.InvalidOperationException' exception.
I created the same program as C# console application and it works fine. The question is
a. Is this the right way to go about making python code available to another application (REST API is not an option).
b. What is the issue with my code.
public string ClassifyText(string value)
{
string textoutput = "";
string exeFileName = HttpContext.Current.Server.MapPath("~/python.exe");
string argName = HttpContext.Current.Server.MapPath("~/predictionscript.py");
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = exeFileName;
start.Arguments = argName;
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
textoutput = result;
}
}
return textoutput;
}

How to simulate a CRM plugin sandbox isolation mode in unit tests?

Context
I would like to write some unit tests against classes what will be utilized by CRM 2016 CodeActivity and Plugin classes. The final assembly will be registered in sandbox isolation mode.
I want to be sure if a test case is green when running unit tests, it will not be more restricted in sandbox isolation security restrictions when registered and run in CRM.
Question
Is there any way to simulate the sandbox isolation when running unit tests?
That's a really good question. You can maybe simulate running the plugin assemblies and code activities in a sandbox based on this Sandbox example.
With that example you could run the codeactivity with a limited set of permissions.
Now, what are the exact limitations of CRM online? Found this article. There is a Sandbox Limitations sections with some of them. If you find another one please let me know. Cause I'd be keen on adding this feature to FakeXrmEasy
Cheers,
I found this today: https://github.com/carltoncolter/DynamicsPlugin/blob/master/DynamicsPlugin.Tests/PluginContainer.cs
Which I used to turn into this:
using System;
using System.Diagnostics;
using System.Globalization;
using System.Net;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
namespace Core.DLaB.Xrm.Tests.Sandbox
{
public static class SandboxWrapper
{
public static T Instantiate<T>(object[] constructorArguments = null)
{
return new SandboxWrapper<T>().Instantiate(constructorArguments);
}
public static T InstantiatePlugin<T>(string unsecureConfig = null, string secureConfig = null)
{
object[] args = null;
if (secureConfig == null)
{
if (unsecureConfig != null)
{
args = new object[] {unsecureConfig};
}
}
else
{
args = new object[]{unsecureConfig, secureConfig};
}
return new SandboxWrapper<T>().Instantiate(args);
}
}
public class SandboxWrapper<T> : MarshalByRefObject, IDisposable
{
private const string DomainSuffix = "Sandbox";
/// <summary>
/// The Sandbox AppDomain to execute the plugin
/// </summary>
public AppDomain SandboxedAppDomain { get; private set; }
public T Instantiate(object[] constructorArguments = null)
{
/*
* Sandboxed plug-ins and custom workflow activities can access the network through the HTTP and HTTPS protocols. This capability provides
support for accessing popular web resources like social sites, news feeds, web services, and more. The following web access restrictions
apply to this sandbox capability.
* Only the HTTP and HTTPS protocols are allowed.
* Access to localhost (loopback) is not permitted.
* IP addresses cannot be used. You must use a named web address that requires DNS name resolution.
* Anonymous authentication is supported and recommended. There is no provision for prompting the
on user for credentials or saving those credentials.
*/
constructorArguments = constructorArguments ?? new object[] { };
var type = typeof(T);
var source = type.Assembly.Location;
var sourceAssembly = Assembly.UnsafeLoadFrom(source);
var setup = new AppDomainSetup
{
ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
ApplicationName = $"{sourceAssembly.GetName().Name}{DomainSuffix}",
DisallowBindingRedirects = true,
DisallowCodeDownload = true,
DisallowPublisherPolicy = true
};
var ps = new PermissionSet(PermissionState.None);
ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.SerializationFormatter));
ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
ps.AddPermission(new FileIOPermission(PermissionState.None));
ps.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess));
//RegEx pattern taken from: https://msdn.microsoft.com/en-us/library/gg334752.aspx
ps.AddPermission(new WebPermission(NetworkAccess.Connect,
new Regex(
#"^http[s]?://(?!((localhost[:/])|(\[.*\])|([0-9]+[:/])|(0x[0-9a-f]+[:/])|(((([0-9]+)|(0x[0-9A-F]+))\.){3}(([0-9]+)|(0x[0-9A-F]+))[:/]))).+")));
// We don't need to add these, but it is important to note that there is no access to the following
ps.AddPermission(new NetworkInformationPermission(NetworkInformationAccess.None));
ps.AddPermission(new EnvironmentPermission(PermissionState.None));
ps.AddPermission(new RegistryPermission(PermissionState.None));
ps.AddPermission(new EventLogPermission(PermissionState.None));
SandboxedAppDomain = AppDomain.CreateDomain(DomainSuffix, null, setup, ps, null);
return Create(constructorArguments);
}
private T Create(object[] constructorArguments)
{
var type = typeof(T);
return (T)Activator.CreateInstanceFrom(
SandboxedAppDomain,
type.Assembly.ManifestModule.FullyQualifiedName,
// ReSharper disable once AssignNullToNotNullAttribute
type.FullName, false, BindingFlags.CreateInstance,
null, constructorArguments,
CultureInfo.CurrentCulture, null
).Unwrap();
}
#region IDisposable Support
//Implementing IDisposable Pattern: https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/dispose-pattern
private bool _disposed; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
if (SandboxedAppDomain != null)
{
AppDomain.Unload(SandboxedAppDomain);
SandboxedAppDomain = null;
}
}
_disposed = true;
}
// This code added to correctly implement the disposable pattern.
void IDisposable.Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
}
#endregion
}
}
Which can be used as such:
SandboxWrapper.InstantiatePlugin<YourPluginType>(unsecureString, secureString)
Not sure how much of it is valid or not, but it worked for handling my testing of xml and JSON serialization correctly.

Windows Phone 7 Consuming Webservice WSDL

Ok I have written some basic generic webservices before but I have never tried to consume a 3rd party one.
The one I am trying to consume is
http://opendap.co-ops.nos.noaa.gov/axis/webservices/predictions/wsdl/Predictions.wsdl
I am not getting any results back from this what so ever and cannot figure out why.
More odd is it is not even reaching PredictionsClient_getPredictionsAndMetadataCompleted when I put a break point in the code it doesn't even reach it.
Any suggestions would be greatly appreciated
public void Bouy(double meters)
{
PredictionService.Parameters PredictionParams = new PredictionService.Parameters();
PredictionService.PredictionsPortTypeClient PredictionsClient = new PredictionService.PredictionsPortTypeClient();
GeoCoordinateWatcher gc = new GeoCoordinateWatcher(GeoPositionAccuracy.Default);
//gc.Position.Location.Latitude, gc.Position.Location.Longitude
GeoCoordinate myLocation = new GeoCoordinate(27.931631,-82.802582);
foreach (var bl in BouyLocation.GetAll())
{
GeoCoordinate otherLocation = new GeoCoordinate(bl.Lat, bl.Lon);
PredictionParams.beginDate = DateTime.Now.ToString("yyyyMMdd");
PredictionParams.endDate = DateTime.Now.AddDays(1.0).ToString("yyyyMMdd");
PredictionParams.stationId = bl.LocationID;
PredictionParams.timeZone = 0;
PredictionParams.unit = 1;
PredictionParams.dataInterval = 6;
PredictionsClient.getPredictionsAndMetadataCompleted += new EventHandler<PredictionService.getPredictionsAndMetadataCompletedEventArgs>(PredictionsClient_getPredictionsAndMetadataCompleted);
PredictionsClient.getPredictionsAndMetadataAsync(PredictionParams);
double mymeters = myLocation.GetDistanceTo(otherLocation);
if (mymeters < meters)
{
TextBlock DynTextBlock = new TextBlock
{
Name = "Appearance" + bl.LocationID,
Text = bl.LocationName + PredictionResult,
TextWrapping = System.Windows.TextWrapping.Wrap,
Margin = new Thickness(12, -6, 12, 0),
Style = (Style)Resources["PhoneTextSubtleStyle"]
};
DynamicAppearance.Children.Add(DynTextBlock);
this.nearByLocations.Add(new BouyLocationModel() { LocationName = bl.LocationName, LocationID = bl.LocationID, Lat = bl.Lat, Lon = bl.Lon });
}
}
var test = nearByLocations;
}
void PredictionsClient_getPredictionsAndMetadataCompleted(object sender, PredictionService.getPredictionsAndMetadataCompletedEventArgs e)
{
string err = e.Error.ToString();
PredictionResult = e.Result.ToString();
}
Loooking at the code you have here I think that you have used the importing of a ServiceReference to auto build the classes for you?
Unfortunately I have found that this is rather temperamental on WP7 and the only way I actually got it to work was when I connected it to a Microsoft WCF service. Connecting to anything else just doesn't work.
If you do google searches there are various pages talking about the fact it doesn't work and ways around it (which I couldn't get to work).
However, there are ways around it but it isn't as simple as the auto-generated stuff. Basically you do things manually.
Although there are other ways to manually create the web service what I did was follow the information in the following which worked well: http://zetitle.wordpress.com/2010/10/14/using-reactive-extensions-with-webrequest/
You will need to parse the response yourself but XML to LINQ works really well for this.
Hope that helps, or maybe someone will have the solution as it is something I am interested in knowing how to get working too

Virtual Server IIS WMI Problem

I have been tasked with finding out what is causing an issue with this bit of code:
public static ArrayList GetEthernetMacAddresses()
{
ArrayList addresses = new ArrayList();
ManagementClass mc = new ManagementClass("Win32_NetworkAdapter");
// This causes GetInstances(options)
// to return all subclasses of Win32_NetworkAdapter
EnumerationOptions options = new EnumerationOptions();
options.EnumerateDeep = true;
foreach (ManagementObject mo in mc.GetInstances(options)) {
string macAddr = mo["MACAddress"] as string;
string adapterType = mo["AdapterType"] as string;
if (!StringUtil.IsBlank(macAddr) && !StringUtil.IsBlank(adapterType))
{
if (adapterType.StartsWith("Ethernet")) {
addresses.Add(macAddr);
}
}
}
return addresses;
}
On our (Win2003) virtual servers, this works when run as part of a console application but not from a web service running on IIS (on that same machine).
Alternatively, I can use this code in a web service on IIS (on the virtual server) and get the correct return values:
public static string GetMacAddresses()
{
ManagementClass mgmt = new ManagementClass(
"Win32_NetworkAdapterConfiguration"
);
ManagementObjectCollection objCol = mgmt.GetInstances();
foreach (ManagementObject obj in objCol)
{
if ((bool)obj["IPEnabled"])
{
if (sb.Length > 0)
{
sb.Append(";");
}
sb.Append(obj["MacAddress"].ToString());
}
obj.Dispose();
}
}
Why does the second one work and not the first one?
Why only when called through an IIS web service on a virtual machine?
Any help would be appreciated.
UPDATE: After much telephone time with all different levels of MS Support, the've come to the conclusion that this is "As Designed".
Since it is on a driver level for the virtual network adapter driver, the answer was that we should change our code "to work around the issue".
This means that you cannot reliable test code on virtual servers unless you with the same code that you use on physical servers, since we can't guarantee that the servers are exact replicas...
Okay, so I wrote this code to test the issue:
public void GetWin32_NetworkAdapter()
{
DataTable dt = new DataTable();
dt.Columns.Add("AdapterName", typeof(string));
dt.Columns.Add("ServiceName", typeof(string));
dt.Columns.Add("AdapterType", typeof(string));
dt.Columns.Add("IPEnabled", typeof(bool));
dt.Columns.Add("MacAddress", typeof(string));
//Try getting it by Win32_NetworkAdapterConfiguration
ManagementClass mgmt = new ManagementClass("Win32_NetworkAdapter");
EnumerationOptions options = new EnumerationOptions();
options.EnumerateDeep = true;
ManagementObjectCollection objCol = mgmt.GetInstances(options);
foreach (ManagementObject obj in objCol)
{
DataRow dr = dt.NewRow();
dr["AdapterName"] = obj["Caption"].ToString();
dr["ServiceName"] = obj["ServiceName"].ToString();
dr["AdapterType"] = obj["AdapterType"];
dr["IPEnabled"] = (bool)obj["IPEnabled"];
if (obj["MacAddress"] != null)
{
dr["MacAddress"] = obj["MacAddress"].ToString();
}
else
{
dr["MacAddress"] = "none";
}
dt.Rows.Add(dr);
}
gvConfig.DataSource = dt;
gvConfig.DataBind();
}
When it's run on a physical IIS box I get this:
Physical IIS server http://img14.imageshack.us/img14/8098/physicaloutput.gif
Same code on Virtual IIS server:
Virtual server http://img25.imageshack.us/img25/4391/virtualoutput.gif
See a difference? It's on the first line. The virtual server doesn't return the "AdapterType" string. Which is why the original code was failing.
This brings up an interesting thought. If Virtual Server is supposed to be an "virtual" representation of a real IIS server, why doesn't it return the same values?
Why are the two returning different results? It's possible that due to the different user accounts, you'll get different results running from the console and from a service.
Why does (1) fail and (2) work? Is it possible that a null result for adapterType return a null value? If so, would the code handle this condition?