Update native bridge to UI Automation for speed and reliability

Native UI Automation bridge redesigned for speed and reliability.  The
bridge library has been renamed to UiaBridge.  Native components use VS
2010 C++ and .Net 4.
This commit is contained in:
Edward Jakubowski
2014-04-29 23:33:10 -04:00
parent 7a267a6d9a
commit acf215fe00
48 changed files with 1453 additions and 1105 deletions

View File

@@ -1,351 +0,0 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski7@gmail.com
*/
#include "StdAfx.h"
#include "WpfAutomation.h"
using namespace System;
using namespace System::Windows::Automation;
WpfAutomation::WpfAutomation(void)
{
this->frameworkId = WpfAutomation::DEFAULT_FRAMEWORK;
this->touchableOnly = true;
}
void WpfAutomation::setFrameworkId(System::String ^propertyValue)
{
this->frameworkId = propertyValue;
}
void WpfAutomation::setTouchableOnly(System::Boolean val)
{
this->touchableOnly = val;
}
System::Windows::Automation::Condition ^ WpfAutomation::getSearchConditions()
{
array<System::Windows::Automation::Condition ^> ^cons = nullptr;
if (this->touchableOnly)
{
cons = gcnew array<System::Windows::Automation::Condition ^>(3);
cons[0] = gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId);//is WPF framework
cons[1] = gcnew PropertyCondition(AutomationElement::IsEnabledProperty, true);//is enabled
cons[2] = gcnew PropertyCondition(AutomationElement::IsOffscreenProperty, false);// is off screen
}
else
{
cons = gcnew array<System::Windows::Automation::Condition ^>(1);
cons[0] = gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId);//is WPF framework
}
System::Windows::Automation::Condition ^result = gcnew System::Windows::Automation::AndCondition(cons);
return result;
}
array<System::Int32> ^ WpfAutomation::convertRuntimeIdString(System::String ^runtimeIdValue)
{
System::String ^delim = L"-";
array<System::String ^> ^idStrArray = runtimeIdValue->Split(delim->ToCharArray());
array<System::Int32> ^idArray = gcnew array<System::Int32>(idStrArray->Length);
for(System::Int32 i = 0 ; i < idStrArray->Length ; i++)
{
idArray[i] = System::Int32::Parse(idStrArray[i]);
}
return idArray;
}
AutomationElement ^ WpfAutomation::findAutomationElementById(System::String ^runtimeIdValue, System::Boolean unfiltered)
{
if (runtimeIdValue == nullptr || runtimeIdValue->Equals(L""))
return AutomationElement::RootElement;
array<System::Int32> ^idArray = this->convertRuntimeIdString(runtimeIdValue);
if (unfiltered)
return AutomationElement::RootElement->FindFirst(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::RuntimeIdProperty, idArray));
//Condition ^pcFramework = gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId);
Condition ^pcRunId = gcnew PropertyCondition(AutomationElement::RuntimeIdProperty, idArray);
Condition ^frameworkAndRuntimeId = gcnew AndCondition(getSearchConditions(), pcRunId);
return AutomationElement::RootElement->FindFirst(TreeScope::Descendants, frameworkAndRuntimeId);
}
array<System::String ^> ^ WpfAutomation::getRuntimeIdsFromCollection(System::Windows::Automation::AutomationElementCollection ^collection)
{
array<System::String ^> ^idStrArray = gcnew array<System::String ^>(collection->Count);
System::Int32 count = 0;
for each(AutomationElement ^child in collection)
{
idStrArray[count] = getRuntimeIdFromElement(child);
++count;
}
return idStrArray;
}
System::String ^ WpfAutomation::getRuntimeIdFromElement(System::Windows::Automation::AutomationElement ^element)
{
System::String ^result = L"";
System::Object ^currentVal = element->GetCurrentPropertyValue(AutomationElement::RuntimeIdProperty);
if (currentVal != nullptr)
{
array<System::Int32> ^idArray = (array<System::Int32> ^)currentVal;
for each(System::Int32 val in idArray)
{
result += System::Convert::ToString(val) + L"-";
}
result = result->TrimEnd('-');
//System::Console::WriteLine("id: {0}", result);
}
return result;
}
//Descendants will walk the full tree of windows, NOT just one level of children
System::Int32 WpfAutomation::countDescendantWindows()
{
//AutomationElementCollection ^aec = rootElem->FindAll(TreeScope::Children, Condition::TrueCondition);
AutomationElementCollection ^aec = AutomationElement::RootElement->FindAll(TreeScope::Descendants, getSearchConditions());
if (aec == nullptr)
return 0;
System::Int32 result = aec->Count;
//delete aec;
return result;
}
System::Int32 WpfAutomation::countDescendantWindows(System::String ^runtimeIdValue)
{
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, getSearchConditions());
if (aec == nullptr)
return 0;
System::Int32 result = aec->Count;
//delete aec;
//delete frameworkAndRuntimeId;
return result;
}
System::Int32 WpfAutomation::countChildrenWindows()
{
//AutomationElementCollection ^aec = rootElem->FindAll(TreeScope::Children, Condition::TrueCondition);
AutomationElementCollection ^aec = AutomationElement::RootElement->FindAll(TreeScope::Children, getSearchConditions());
if (aec == nullptr)
return 0;
System::Int32 result = aec->Count;
//delete aec;
return result;
}
System::Int32 WpfAutomation::countChildrenWindows(System::String ^runtimeIdValue)
{
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Children, getSearchConditions());
if (aec == nullptr)
return 0;
System::Int32 result = aec->Count;
//delete aec;
//delete frameworkAndRuntimeId;
return result;
}
array<System::String ^> ^ WpfAutomation::enumChildrenWindowIds(System::String ^runtimeIdValue)
{
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Children, getSearchConditions());
if (aec == nullptr)
return nullptr;
return getRuntimeIdsFromCollection(aec);
}
array<System::String ^> ^ WpfAutomation::enumDescendantWindowIds(System::String ^runtimeIdValue)
{
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, getSearchConditions());
if (aec == nullptr)
return nullptr;
return getRuntimeIdsFromCollection(aec);
}
array<System::String ^> ^ WpfAutomation::enumDescendantWindowIds(System::Int32 processId)
{
Condition ^frameworkAndProcessId = gcnew AndCondition(
gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId),
gcnew PropertyCondition(AutomationElement::ProcessIdProperty, processId));
AutomationElement ^parent = AutomationElement::RootElement->FindFirst(TreeScope::Descendants, frameworkAndProcessId);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, getSearchConditions());
if (aec == nullptr)
return nullptr;
return getRuntimeIdsFromCollection(aec);
}
System::String ^ WpfAutomation::getRuntimeIdFromHandle(System::IntPtr windowHandle)
{
//AutomationElement test = AutomationElement.FromHandle(new System.IntPtr(123123));
AutomationElement ^target = AutomationElement::FromHandle(windowHandle);
if (target == nullptr)
return nullptr;
return getRuntimeIdFromElement(target);
}
array<System::String ^> ^ WpfAutomation::enumDescendantWindowInfo(System::String ^runtimeIdValue, System::String ^properties)
{
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
if (parent == nullptr)
return nullptr;
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, getSearchConditions());
//when wildcard is enabled it will pull all property names & values
System::Boolean wildcardEnabled = false;
if (properties->Equals(L"*"))
wildcardEnabled = true;
//create array for keeping order of properties
System::String ^delim = L",";
array<System::String ^> ^propSpltArray = properties->Split(delim->ToCharArray());
TreeWalker ^tw = TreeWalker::ControlViewWalker;
array<System::String ^> ^winInfoList = gcnew array<System::String ^>(aec->Count);
System::Int32 count = 0;
for each(AutomationElement ^child in aec) //loop through all descendants
{
array<AutomationProperty^> ^aps = child->GetSupportedProperties();
array<System::String ^> ^propValues = gcnew array<System::String ^>(propSpltArray->Length);//keep order
System::String ^wildcardProperties = L"";
if (wildcardEnabled) {
wildcardProperties += "ParentRuntimeIdProperty:" + getRuntimeIdFromElement(tw->GetParent(child)) + ",";
//propValues = gcnew array<System::String ^>(aps->Length +1 );//add one for parent property since it doesn't exist
}
for(int i=0 ; i < propValues->Length ; i++)
{
propValues[i] = L"";
if (propSpltArray[i]->Equals("ParentRuntimeIdProperty"))//custom property for getting parent
{
propValues[i] = getRuntimeIdFromElement(tw->GetParent(child));
}
}
for each(AutomationProperty ^ap in aps) //loop through all supported Properties for a child
{
System::String ^currentPropertyStr = L""; //current property values
//System::Console::WriteLine("property: {0}", ap->ProgrammaticName);
System::String ^shortPropName = L" null ";
if (ap->ProgrammaticName->Contains(L"."))
shortPropName = ap->ProgrammaticName->Substring(ap->ProgrammaticName->IndexOf(L".") + 1);
if (properties->Contains(shortPropName) || properties->Contains(ap->ProgrammaticName) || ap->ProgrammaticName->Equals(properties) || wildcardEnabled)
{
//System::Console::WriteLine("shortPropName: {0}", shortPropName);
System::Object ^currentVal = child->GetCurrentPropertyValue(ap);
if (currentVal == nullptr)
continue;
if (ap->ProgrammaticName->Equals(L"AutomationElementIdentifiers.RuntimeIdProperty"))
{
array<System::Int32> ^idArray = (array<System::Int32> ^)currentVal;
for each(System::Int32 val in idArray)
{
currentPropertyStr += System::Convert::ToString(val) + L"-";
}
currentPropertyStr = currentPropertyStr->TrimEnd('-');
//System::Console::WriteLine("id: {0}", result);
}
else//not runtimeId which is an Int32[]
{
currentPropertyStr = currentVal->ToString();
currentPropertyStr = currentPropertyStr->Replace(",","&#44;");
}
}
if (currentPropertyStr->Equals(L"")) //if there isn't a value skip
continue;
if (wildcardEnabled) {
wildcardProperties += shortPropName + ":" +currentPropertyStr + ",";
continue;
}
//System::Console::WriteLine("currentPropertyStr: {0}", currentPropertyStr);
//find the correct order to return this property
for(int i=0 ; i < propSpltArray->Length ; i++)
{
if (propSpltArray[i]->Equals(shortPropName) || propSpltArray[i]->Equals(ap->ProgrammaticName))
propValues[i] = currentPropertyStr;
}
}
//output properties in the correct order
for(int i=0 ; i < propSpltArray->Length ; i++)
winInfoList[count] += propValues[i] + L",";
if (wildcardEnabled)
winInfoList[count] += wildcardProperties;
++count;
}
return winInfoList;
}
System::String ^ WpfAutomation::getRuntimeIdFromPoint(System::Int32 x, System::Int32 y)
{
AutomationElement ^target = AutomationElement::FromPoint(System::Windows::Point(x,y));
if (target == nullptr)
return nullptr;
return getRuntimeIdFromElement(target);
}
System::String ^ WpfAutomation::getParentRuntimeId(System::String ^runtimeIdValue)
{
AutomationElement ^target = findAutomationElementById(runtimeIdValue, true);
if (target == nullptr)
return nullptr;
TreeWalker ^tw = TreeWalker::ControlViewWalker;
AutomationElement ^parent = tw->GetParent(target);
return getRuntimeIdFromElement(parent);
}
System::String ^ WpfAutomation::getProperty(System::String ^propertyName, System::String ^runtimeIdValue)
{
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
if (parent == nullptr)
return nullptr;
//System::Object ^currentVal = parent->GetCurrentPropertyValue(AutomationElement::RuntimeIdProperty);
array<AutomationProperty^> ^aps = parent->GetSupportedProperties();
for each(AutomationProperty ^ap in aps)
{
//System::Console::WriteLine("property: {0}", ap->ProgrammaticName);
if (ap->ProgrammaticName->Contains(L"." + propertyName) || ap->ProgrammaticName->Equals(propertyName))
{
System::Object ^currentVal = parent->GetCurrentPropertyValue(ap);
return currentVal->ToString();
}
}
return nullptr;
}
array<System::String ^> ^ WpfAutomation::getProperties(System::String ^runtimeIdValue)
{
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
if (parent == nullptr)
return nullptr;
array<AutomationProperty^> ^aps = parent->GetSupportedProperties();
array<System::String ^> ^propStrArray = gcnew array<System::String ^>(aps->Length);
System::Int32 count = 0;
for each(AutomationProperty ^ap in aps)
{
System::Object ^currentVal = parent->GetCurrentPropertyValue(ap);
if (currentVal == nullptr)
continue;
propStrArray[count] = ap->ProgrammaticName;
++count;
}
return propStrArray;
}
array<System::String ^> ^ WpfAutomation::getPropertiesAndValues(System::String ^runtimeIdValue)
{
AutomationElement ^parent = findAutomationElementById(runtimeIdValue, true);
if (parent == nullptr)
return nullptr;
array<AutomationProperty^> ^aps = parent->GetSupportedProperties();
array<System::String ^> ^propStrArray = gcnew array<System::String ^>(aps->Length);
System::Int32 count = 0;
for each(AutomationProperty ^ap in aps)
{
System::Object ^currentVal = parent->GetCurrentPropertyValue(ap);
if (currentVal == nullptr)
continue;
propStrArray[count] = ap->ProgrammaticName + ":" + currentVal->ToString();
++count;
}
return propStrArray;
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski7@gmail.com
*/
#pragma once
public ref class WpfAutomation
{
public:
WpfAutomation(void);
void setFrameworkId(System::String ^propertyValue); //default is WPF, but also accepts Silverlight, Win32
void setTouchableOnly(System::Boolean val); //default is true
//Descendants will walk the full tree of windows, NOT just one level of children
System::Int32 countDescendantWindows();
System::Int32 countDescendantWindows(System::String ^runtimeIdValue);
System::Int32 countChildrenWindows();
System::Int32 countChildrenWindows(System::String ^runtimeIdValue);
array<System::String ^> ^ enumChildrenWindowIds(System::String ^runtimeIdValue); //if runtimeIdValue is null will start at desktop
array<System::String ^> ^ enumDescendantWindowIds(System::String ^runtimeIdValue); //if runtimeIdValue is null will start at desktop
array<System::String ^> ^ enumDescendantWindowIds(System::Int32 processId);
//In all the above Enumerate methods will return a list of Runtime Ids for all related windows.
array<System::String ^> ^ enumDescendantWindowInfo(System::String ^runtimeIdValue, System::String ^properties);
System::String ^ getRuntimeIdFromHandle(System::IntPtr windowHandle);
System::String ^ getRuntimeIdFromPoint(System::Int32 x, System::Int32 y);
System::String ^ getParentRuntimeId(System::String ^runtimeIdValue);
System::String ^ getProperty(System::String ^propertyName, System::String ^runtimeIdValue);
array<System::String ^> ^ getProperties(System::String ^runtimeIdValue);
array<System::String ^> ^ getPropertiesAndValues(System::String ^runtimeIdValue);
private:
array<System::Int32> ^ convertRuntimeIdString(System::String ^runtimeIdValue);
System::Windows::Automation::AutomationElement ^ findAutomationElementById(System::String ^runtimeIdValue, System::Boolean unfiltered);
System::String ^ getRuntimeIdFromElement(System::Windows::Automation::AutomationElement ^element);
array<System::String ^> ^ getRuntimeIdsFromCollection(System::Windows::Automation::AutomationElementCollection ^collection);
System::Windows::Automation::Condition ^ getSearchConditions();
static System::String ^DEFAULT_FRAMEWORK = L"WPF";
static System::Boolean ^DEFAULT_TOUCHABLE = true;
System::String ^frameworkId;
System::Boolean ^touchableOnly;
};

Binary file not shown.

Binary file not shown.

View File

@@ -1,300 +0,0 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski7@gmail.com
*/
#include "StdAfx.h"
#include "org_synthuse_WpfBridge.h"
#include "WpfAutomation.h"
#include "Global.h"
#include <msclr/marshal.h> //using namespace msclr::interop;
using namespace System;
using namespace System::Windows::Automation;
using namespace msclr::interop;
using namespace Globals;
JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_setFrameworkId(JNIEnv *env, jobject obj, jstring jpropertyValue)
{
const char *propertyValue = env->GetStringUTFChars(jpropertyValue, 0);//convert string
Global::WPF_AUTO->setFrameworkId(marshal_as<String ^>(propertyValue));
env->ReleaseStringUTFChars(jpropertyValue, propertyValue); //release string
}
/*
* Class: org_synthuse_WpfBridge
* Method: setTouchableOnly
* Signature: (Z)V
*/
JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_setTouchableOnly(JNIEnv *env, jobject obj, jboolean jval)
{
Global::WPF_AUTO->setTouchableOnly((bool)(jval == JNI_TRUE));
}
/*
* Class: org_synthuse_WpfBridge
* Method: CountDescendantWindows
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countDescendantWindows__(JNIEnv *env, jobject obj)
{
return Global::WPF_AUTO->countDescendantWindows();
}
/*
* Class: org_synthuse_WpfBridge
* Method: CountDescendantWindows
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countDescendantWindows__Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring jruntimeIdValue)
{
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
jint result = Global::WPF_AUTO->countDescendantWindows(marshal_as<String ^>(runtimeIdValue));
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
return result;
}
/*
* Class: org_synthuse_WpfBridge
* Method: CountChildrenWindows
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countChildrenWindows__(JNIEnv *env, jobject obj)
{
return Global::WPF_AUTO->countChildrenWindows();
}
/*
* Class: org_synthuse_WpfBridge
* Method: CountChildrenWindows
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countChildrenWindows__Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring jruntimeIdValue)
{
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
jint result = Global::WPF_AUTO->countChildrenWindows(marshal_as<String ^>(runtimeIdValue));
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
return result;
}
/*
* Class: org_synthuse_WpfBridge
* Method: EnumChildrenWindowIds
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumChildrenWindowIds(JNIEnv *env, jobject obj, jstring jruntimeIdValue)
{
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
array<System::String ^> ^mchildrenIds = Global::WPF_AUTO->enumChildrenWindowIds(marshal_as<String ^>(runtimeIdValue));
if (mchildrenIds == nullptr)
return NULL;
//create result object array to the same size as the managed children Ids string array
jclass stringClass = env->FindClass("java/lang/String");
jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0);
marshal_context context; //lets you marshal managed classes to unmanaged types
//char **childrenIds = new char *[mchildrenIds->Length];
for(int i = 0 ; i < mchildrenIds->Length ; i++)
{
//childrenIds[i] = (char *)context.marshal_as<const char *>(mchildrenIds[i]);
//env->SetObjectArrayElement(results, i, env->GetStringUTFChars(childrenIds[i], 0)
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mchildrenIds[i])));
}
//delete[] childrenIds;
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
return results;
}
/*
* Class: org_synthuse_WpfBridge
* Method: EnumDescendantWindowIds
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIds__Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring jruntimeIdValue)
{
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
array<System::String ^> ^mchildrenIds = Global::WPF_AUTO->enumDescendantWindowIds(marshal_as<String ^>(runtimeIdValue));
if (mchildrenIds == nullptr)
return NULL;
//create result object array to the same size as the managed children Ids string array
jclass stringClass = env->FindClass("java/lang/String");
jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0);
marshal_context context; //lets you marshal managed classes to unmanaged types
//char **childrenIds = new char *[mchildrenIds->Length];
for(int i = 0 ; i < mchildrenIds->Length ; i++)
{
//childrenIds[i] = (char *)context.marshal_as<const char *>(mchildrenIds[i]);
//env->SetObjectArrayElement(results, i, env->GetStringUTFChars(childrenIds[i], 0)
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mchildrenIds[i])));
}
//delete[] childrenIds;
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
return results;
}
/*
* Class: org_synthuse_WpfBridge
* Method: EnumDescendantWindowIds
* Signature: (J)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIds__J(JNIEnv *env, jobject obj, jlong jprocessId)
{
array<System::String ^> ^mchildrenIds = Global::WPF_AUTO->enumDescendantWindowIds((System::Int32)jprocessId);
if (mchildrenIds == nullptr)
return NULL;
//create result object array to the same size as the managed children Ids string array
jclass stringClass = env->FindClass("java/lang/String");
jobjectArray results = env->NewObjectArray(mchildrenIds->Length, stringClass, 0);
marshal_context context; //lets you marshal managed classes to unmanaged types
for(int i = 0 ; i < mchildrenIds->Length ; i++)
{
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mchildrenIds[i])));
}
return results;
}
/*
* Class: org_synthuse_WpfBridge
* Method: getRuntimeIdFromHandle
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getRuntimeIdFromHandle(JNIEnv *env, jobject obj, jlong jwindowHandle)
{
System::String ^mrunId = Global::WPF_AUTO->getRuntimeIdFromHandle(System::IntPtr(jwindowHandle));
if (mrunId == nullptr)
return NULL;
marshal_context context; //lets you marshal managed classes to unmanaged types
jstring result = env->NewStringUTF(context.marshal_as<const char *>(mrunId));
return result;
}
/*
* Class: org_synthuse_WpfBridge
* Method: enumDescendantWindowInfo
* Signature: (Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowInfo(JNIEnv *env, jobject obj, jstring jruntimeIdValue, jstring jproperties)
{
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
const char *properties = env->GetStringUTFChars(jproperties, 0);//convert string
array<System::String ^> ^mwinInfo = Global::WPF_AUTO->enumDescendantWindowInfo(marshal_as<String ^>(runtimeIdValue), marshal_as<String ^>(properties));
if (mwinInfo == nullptr)
return NULL;
//create result object array to the same size as the managed window info string array
jclass stringClass = env->FindClass("java/lang/String");
jobjectArray results = env->NewObjectArray(mwinInfo->Length, stringClass, 0);
marshal_context context; //lets you marshal managed classes to unmanaged types
for(int i = 0 ; i < mwinInfo->Length ; i++)
{
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mwinInfo[i])));
}
env->ReleaseStringUTFChars(jproperties, properties); //release string
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
return results;
}
/*
* Class: org_synthuse_WpfBridge
* Method: getRuntimeIdFromPoint
* Signature: (II)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getRuntimeIdFromPoint(JNIEnv *env, jobject obj, jint x, jint y)
{
System::String ^mresult = Global::WPF_AUTO->getRuntimeIdFromPoint(x, y);
if (mresult == nullptr)
return NULL;
marshal_context context; //lets you marshal managed classes to unmanaged types
jstring result = env->NewStringUTF(context.marshal_as<const char *>(mresult));
return result;
}
/*
* Class: org_synthuse_WpfBridge
* Method: getParentRuntimeId
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getParentRuntimeId(JNIEnv *env, jobject obj, jstring jruntimeIdValue)
{
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
System::String ^mresult = Global::WPF_AUTO->getParentRuntimeId(marshal_as<String ^>(runtimeIdValue));
if (mresult == nullptr)
return NULL;
marshal_context context; //lets you marshal managed classes to unmanaged types
jstring result = env->NewStringUTF(context.marshal_as<const char *>(mresult));
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
return result;
}
/*
* Class: org_synthuse_WpfBridge
* Method: GetProperty
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getProperty(JNIEnv *env, jobject obj, jstring jpropertyName, jstring jruntimeIdValue)
{
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
const char *propertyName = env->GetStringUTFChars(jpropertyName, 0);//convert string
System::String ^mresult = Global::WPF_AUTO->getProperty(marshal_as<String ^>(propertyName), marshal_as<String ^>(runtimeIdValue));
if (mresult == nullptr)
return NULL;
marshal_context context; //lets you marshal managed classes to unmanaged types
jstring result = env->NewStringUTF(context.marshal_as<const char *>(mresult));
env->ReleaseStringUTFChars(jpropertyName, propertyName); //release string
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
return result;
}
/*
* Class: org_synthuse_WpfBridge
* Method: GetProperties
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_getProperties(JNIEnv *env, jobject obj, jstring jruntimeIdValue)
{
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
array<System::String ^> ^mprops = Global::WPF_AUTO->getProperties(marshal_as<String ^>(runtimeIdValue));
if (mprops == nullptr)
return NULL;
//create result object array to the same size as the managed children Ids string array
jclass stringClass = env->FindClass("java/lang/String");
jobjectArray results = env->NewObjectArray(mprops->Length, stringClass, 0);
marshal_context context; //lets you marshal managed classes to unmanaged types
for(int i = 0 ; i < mprops->Length ; i++)
{
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mprops[i])));
}
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
return results;
}
/*
* Class: org_synthuse_WpfBridge
* Method: GetPropertiesAndValues
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_getPropertiesAndValues(JNIEnv *env, jobject obj, jstring jruntimeIdValue)
{
const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string
array<System::String ^> ^mprops = Global::WPF_AUTO->getPropertiesAndValues(marshal_as<String ^>(runtimeIdValue));
if (mprops == nullptr)
return NULL;
//create result object array to the same size as the managed children Ids string array
jclass stringClass = env->FindClass("java/lang/String");
jobjectArray results = env->NewObjectArray(mprops->Length, stringClass, 0);
marshal_context context; //lets you marshal managed classes to unmanaged types
for(int i = 0 ; i < mprops->Length ; i++)
{
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mprops[i])));
}
env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string
return results;
}

View File

@@ -1,141 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_synthuse_WpfBridge */
#ifndef _Included_org_synthuse_WpfBridge
#define _Included_org_synthuse_WpfBridge
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_synthuse_WpfBridge
* Method: setFrameworkId
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_setFrameworkId
(JNIEnv *, jobject, jstring);
/*
* Class: org_synthuse_WpfBridge
* Method: setTouchableOnly
* Signature: (Z)V
*/
JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_setTouchableOnly
(JNIEnv *, jobject, jboolean);
/*
* Class: org_synthuse_WpfBridge
* Method: countDescendantWindows
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countDescendantWindows__
(JNIEnv *, jobject);
/*
* Class: org_synthuse_WpfBridge
* Method: countDescendantWindows
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countDescendantWindows__Ljava_lang_String_2
(JNIEnv *, jobject, jstring);
/*
* Class: org_synthuse_WpfBridge
* Method: countChildrenWindows
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countChildrenWindows__
(JNIEnv *, jobject);
/*
* Class: org_synthuse_WpfBridge
* Method: countChildrenWindows
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countChildrenWindows__Ljava_lang_String_2
(JNIEnv *, jobject, jstring);
/*
* Class: org_synthuse_WpfBridge
* Method: enumChildrenWindowIds
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumChildrenWindowIds
(JNIEnv *, jobject, jstring);
/*
* Class: org_synthuse_WpfBridge
* Method: enumDescendantWindowIds
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIds__Ljava_lang_String_2
(JNIEnv *, jobject, jstring);
/*
* Class: org_synthuse_WpfBridge
* Method: enumDescendantWindowIds
* Signature: (J)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIds__J
(JNIEnv *, jobject, jlong);
/*
* Class: org_synthuse_WpfBridge
* Method: enumDescendantWindowInfo
* Signature: (Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowInfo
(JNIEnv *, jobject, jstring, jstring);
/*
* Class: org_synthuse_WpfBridge
* Method: getRuntimeIdFromHandle
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getRuntimeIdFromHandle
(JNIEnv *, jobject, jlong);
/*
* Class: org_synthuse_WpfBridge
* Method: getRuntimeIdFromPoint
* Signature: (II)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getRuntimeIdFromPoint
(JNIEnv *, jobject, jint, jint);
/*
* Class: org_synthuse_WpfBridge
* Method: getParentRuntimeId
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getParentRuntimeId
(JNIEnv *, jobject, jstring);
/*
* Class: org_synthuse_WpfBridge
* Method: getProperty
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getProperty
(JNIEnv *, jobject, jstring, jstring);
/*
* Class: org_synthuse_WpfBridge
* Method: getProperties
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_getProperties
(JNIEnv *, jobject, jstring);
/*
* Class: org_synthuse_WpfBridge
* Method: getPropertiesAndValues
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_getPropertiesAndValues
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif

36
native/uiabridge.sln Normal file
View File

@@ -0,0 +1,36 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uiabridge", "uiabridge\uiabridge.vcxproj", "{BAC1B079-7B87-4396-B17F-91A86DF1AE29}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "uiabtest", "uiabtest\uiabtest.vcxproj", "{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Debug|Win32.ActiveCfg = Debug|Win32
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Debug|Win32.Build.0 = Debug|Win32
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Debug|x64.ActiveCfg = Debug|x64
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Debug|x64.Build.0 = Debug|x64
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Release|Win32.ActiveCfg = Release|Win32
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Release|Win32.Build.0 = Release|Win32
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Release|x64.ActiveCfg = Release|x64
{BAC1B079-7B87-4396-B17F-91A86DF1AE29}.Release|x64.Build.0 = Release|x64
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Debug|Win32.ActiveCfg = Debug|Win32
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Debug|Win32.Build.0 = Debug|Win32
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Debug|x64.ActiveCfg = Debug|x64
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Debug|x64.Build.0 = Debug|x64
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Release|Win32.ActiveCfg = Release|Win32
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Release|Win32.Build.0 = Release|Win32
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Release|x64.ActiveCfg = Release|x64
{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

BIN
native/uiabridge.suo Normal file

Binary file not shown.

View File

@@ -1,9 +1,3 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski7@gmail.com
*/
#include "stdafx.h"
using namespace System;
@@ -17,12 +11,12 @@ using namespace System::Security::Permissions;
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly:AssemblyTitleAttribute("WpfBridge")];
[assembly:AssemblyTitleAttribute("uiabridge")];
[assembly:AssemblyDescriptionAttribute("")];
[assembly:AssemblyConfigurationAttribute("")];
[assembly:AssemblyCompanyAttribute("Synthuse")];
[assembly:AssemblyProductAttribute("WpfBridge")];
[assembly:AssemblyCopyrightAttribute("Copyright (c) Synthuse 2014")];
[assembly:AssemblyCompanyAttribute("na")];
[assembly:AssemblyProductAttribute("uiabridge")];
[assembly:AssemblyCopyrightAttribute("Copyright (c) na 2014")];
[assembly:AssemblyTrademarkAttribute("")];
[assembly:AssemblyCultureAttribute("")];
@@ -37,7 +31,7 @@ using namespace System::Security::Permissions;
// You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly:AssemblyVersionAttribute("1.1.*")];
[assembly:AssemblyVersionAttribute("1.0.*")];
[assembly:ComVisible(false)];

View File

@@ -4,7 +4,7 @@
*
* last modified by ejakubowski7@gmail.com
*/
#include "StdAfx.h"
#include "stdafx.h"
#include "Global.h"
#include "WpfAutomation.h"
#include "uiabridge.h"
using namespace uiabridge;

View File

@@ -5,7 +5,8 @@
* last modified by ejakubowski7@gmail.com
*/
#pragma once
#include "WpfAutomation.h"
#include "uiabridge.h"
using namespace uiabridge;
namespace Globals
{
using namespace System;
@@ -13,7 +14,7 @@ namespace Globals
public ref class Global
{
public:
static WpfAutomation ^WPF_AUTO = gcnew WpfAutomation();
static AutomationBridge ^AUTO_BRIDGE = nullptr;
};
}

View File

@@ -1,9 +1,8 @@
========================================================================
DYNAMIC LINK LIBRARY : WpfBridge Project Overview
DYNAMIC LINK LIBRARY : uiabridge Project Overview
========================================================================
Created By Edward Jakubowski ejakubowski7@gmail.com
Description:
This is a bridge for java to access .net 4 UI Automation libraries. This
library enables Synthuse to access and automation WPF and Silverlight apps.
library enables Synthuse to access and automate WinForms, WPF and Silverlight apps.

View File

@@ -0,0 +1,6 @@
// stdafx.cpp : source file that includes just the standard includes
// uiabridge.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
#include <msclr/marshal.h>

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,157 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski7@gmail.com
*/
#include "stdafx.h"
#include <msclr/marshal.h> //using namespace msclr::interop;
#include "org_synthuse_UiaBridge.h"
#include "uiabridge.h"
#include "Global.h"
using namespace System;
using namespace System::Windows::Automation;
using namespace msclr::interop;
using namespace Globals;
using namespace uiabridge;
/*
* Class: org_synthuse_UiaBridge
* Method: initialize
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_synthuse_UiaBridge_initialize(JNIEnv *env, jobject obj, jstring jproperties)
{
Global::AUTO_BRIDGE = gcnew AutomationBridge();
}
/*
* Class: org_synthuse_UiaBridge
* Method: shutdown
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_synthuse_UiaBridge_shutdown(JNIEnv *env, jobject obj)
{
}
/*
* Class: org_synthuse_UiaBridge
* Method: addEnumFilter
* Signature: (Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_org_synthuse_UiaBridge_addEnumFilter(JNIEnv *env, jobject obj, jstring jpropertyName, jstring jpropertyValue)
{
const char *propertyName = env->GetStringUTFChars(jpropertyValue, 0);//convert string
const char *propertyValue = env->GetStringUTFChars(jpropertyValue, 0);//convert string
return (jint)Global::AUTO_BRIDGE->addEnumFilter(marshal_as<String ^>(propertyName), marshal_as<String ^>(propertyValue));
}
/*
* Class: org_synthuse_UiaBridge
* Method: clearEnumFilters
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_synthuse_UiaBridge_clearEnumFilters(JNIEnv *env, jobject obj)
{
Global::AUTO_BRIDGE->clearEnumFilters();
}
/*
* Class: org_synthuse_UiaBridge
* Method: enumWindowInfo
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_UiaBridge_enumWindowInfo__Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring jproperties)
{
const char *properties = env->GetStringUTFChars(jproperties, 0);//convert string
array<System::String ^> ^mwinInfo = Global::AUTO_BRIDGE->enumWindowInfo(marshal_as<String ^>(properties));
if (mwinInfo == nullptr)
return NULL;
//create result object array to the same size as the managed children Ids string array
jclass stringClass = env->FindClass("java/lang/String");
jobjectArray results = env->NewObjectArray(mwinInfo->Length, stringClass, 0);
marshal_context context; //lets you marshal managed classes to unmanaged types
//char **childrenIds = new char *[mchildrenIds->Length];
for(int i = 0 ; i < mwinInfo->Length ; i++)
{
//childrenIds[i] = (char *)context.marshal_as<const char *>(mchildrenIds[i]);
//env->SetObjectArrayElement(results, i, env->GetStringUTFChars(childrenIds[i], 0)
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mwinInfo[i])));
}
//delete[] childrenIds;
env->ReleaseStringUTFChars(jproperties, properties); //release string
return results;
}
/*
* Class: org_synthuse_UiaBridge
* Method: enumWindowInfo
* Signature: (ILjava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_UiaBridge_enumWindowInfo__ILjava_lang_String_2(JNIEnv *env, jobject obj, jint jwindowHandle, jstring jproperties)
{
const char *properties = env->GetStringUTFChars(jproperties, 0);//convert string
array<System::String ^> ^mwinInfo = Global::AUTO_BRIDGE->enumWindowInfo(System::IntPtr(jwindowHandle), marshal_as<String ^>(properties));
if (mwinInfo == nullptr)
return NULL;
//create result object array to the same size as the managed children Ids string array
jclass stringClass = env->FindClass("java/lang/String");
jobjectArray results = env->NewObjectArray(mwinInfo->Length, stringClass, 0);
marshal_context context; //lets you marshal managed classes to unmanaged types
//char **childrenIds = new char *[mchildrenIds->Length];
for(int i = 0 ; i < mwinInfo->Length ; i++)
{
//childrenIds[i] = (char *)context.marshal_as<const char *>(mchildrenIds[i]);
//env->SetObjectArrayElement(results, i, env->GetStringUTFChars(childrenIds[i], 0)
env->SetObjectArrayElement(results, i, env->NewStringUTF(context.marshal_as<const char *>(mwinInfo[i])));
}
//delete[] childrenIds;
env->ReleaseStringUTFChars(jproperties, properties); //release string
return results;
}
/*
* Class: org_synthuse_UiaBridge
* Method: getWindowInfo
* Signature: (IILjava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_synthuse_UiaBridge_getWindowInfo__IILjava_lang_String_2(JNIEnv *env, jobject obj, jint jx, jint jy, jstring jproperties)
{
const char *properties = env->GetStringUTFChars(jproperties, 0);//convert string
System::String ^mwinInfo = Global::AUTO_BRIDGE->getWindowInfo(jx, jy, marshal_as<String ^>(properties));
env->ReleaseStringUTFChars(jproperties, properties); //release string
marshal_context context;
return env->NewStringUTF(context.marshal_as<const char *>(mwinInfo));
}
/*
* Class: org_synthuse_UiaBridge
* Method: getWindowInfo
* Signature: (ILjava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_synthuse_UiaBridge_getWindowInfo__ILjava_lang_String_2(JNIEnv *env, jobject obj, jint jwindowHandle, jstring jproperties)
{
const char *properties = env->GetStringUTFChars(jproperties, 0);//convert string
System::String ^mwinInfo = Global::AUTO_BRIDGE->getWindowInfo(System::IntPtr(jwindowHandle), marshal_as<String ^>(properties));
env->ReleaseStringUTFChars(jproperties, properties); //release string
marshal_context context;
return env->NewStringUTF(context.marshal_as<const char *>(mwinInfo));
}
/*
* Class: org_synthuse_UiaBridge
* Method: getWindowInfo
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_synthuse_UiaBridge_getWindowInfo__Ljava_lang_String_2Ljava_lang_String_2(JNIEnv *env, jobject obj, jstring jruntimeIdStr, jstring jproperties)
{
const char *properties = env->GetStringUTFChars(jproperties, 0);//convert string
const char *runtimeIdStr = env->GetStringUTFChars(jruntimeIdStr, 0);//convert string
System::String ^mwinInfo = Global::AUTO_BRIDGE->getWindowInfo(marshal_as<String ^>(runtimeIdStr), marshal_as<String ^>(properties));
env->ReleaseStringUTFChars(jruntimeIdStr, runtimeIdStr); //release string
env->ReleaseStringUTFChars(jproperties, properties); //release string
marshal_context context;
return env->NewStringUTF(context.marshal_as<const char *>(mwinInfo));
}

View File

@@ -0,0 +1,85 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_synthuse_UiaBridge */
#ifndef _Included_org_synthuse_UiaBridge
#define _Included_org_synthuse_UiaBridge
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_synthuse_UiaBridge
* Method: initialize
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_synthuse_UiaBridge_initialize
(JNIEnv *, jobject, jstring);
/*
* Class: org_synthuse_UiaBridge
* Method: shutdown
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_synthuse_UiaBridge_shutdown
(JNIEnv *, jobject);
/*
* Class: org_synthuse_UiaBridge
* Method: addEnumFilter
* Signature: (Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_org_synthuse_UiaBridge_addEnumFilter
(JNIEnv *, jobject, jstring, jstring);
/*
* Class: org_synthuse_UiaBridge
* Method: clearEnumFilters
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_org_synthuse_UiaBridge_clearEnumFilters
(JNIEnv *, jobject);
/*
* Class: org_synthuse_UiaBridge
* Method: enumWindowInfo
* Signature: (Ljava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_UiaBridge_enumWindowInfo__Ljava_lang_String_2
(JNIEnv *, jobject, jstring);
/*
* Class: org_synthuse_UiaBridge
* Method: enumWindowInfo
* Signature: (ILjava/lang/String;)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_UiaBridge_enumWindowInfo__ILjava_lang_String_2
(JNIEnv *, jobject, jint, jstring);
/*
* Class: org_synthuse_UiaBridge
* Method: getWindowInfo
* Signature: (IILjava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_synthuse_UiaBridge_getWindowInfo__IILjava_lang_String_2
(JNIEnv *, jobject, jint, jint, jstring);
/*
* Class: org_synthuse_UiaBridge
* Method: getWindowInfo
* Signature: (ILjava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_synthuse_UiaBridge_getWindowInfo__ILjava_lang_String_2
(JNIEnv *, jobject, jint, jstring);
/*
* Class: org_synthuse_UiaBridge
* Method: getWindowInfo
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_synthuse_UiaBridge_getWindowInfo__Ljava_lang_String_2Ljava_lang_String_2
(JNIEnv *, jobject, jstring, jstring);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,422 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski7@gmail.com
*/
// This is the main DLL file.
#include "stdafx.h"
#include "uiabridge.h"
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Windows::Automation;
using namespace uiabridge;
AutomationBridge::AutomationBridge()
{
enumFilters = gcnew Dictionary<System::String ^, System::String ^>();
cacheRequest = nullptr;
initializeCache();
}
AutomationBridge::~AutomationBridge()
{
enumFilters->Clear();
if (cacheRequest != nullptr)
cacheRequest->Pop(); //disable UI Automation Cache
//Console::WriteLine("disposing of AutomationBridge");
}
void AutomationBridge::initializeCache()
{
cacheRequest = gcnew CacheRequest();
//cacheRequest->AutomationElementMode = AutomationElementMode::Full;
cacheRequest->TreeFilter = Automation::RawViewCondition;
cacheRequest->TreeScope = TreeScope::Element;// | TreeScope::Children;
/*
cacheRequest->Add(AutomationElement::RuntimeIdProperty);
cacheRequest->Add(AutomationElement::ProcessIdProperty);
cacheRequest->Add(AutomationElement::FrameworkIdProperty);
cacheRequest->Add(AutomationElement::LocalizedControlTypeProperty);
cacheRequest->Add(AutomationElement::ControlTypeProperty);
cacheRequest->Add(AutomationElement::ClassNameProperty);
cacheRequest->Add(AutomationElement::NameProperty);
cacheRequest->Add(AutomationElement::BoundingRectangleProperty);
*/
System::String ^cachedPropStr = L"RuntimeIdProperty,ParentRuntimeIdProperty,NativeWindowHandleProperty,ProcessIdProperty,FrameworkIdProperty,LocalizedControlTypeProperty,ControlTypeProperty,ClassNameProperty,NameProperty,BoundingRectangleProperty";
array<AutomationProperty^> ^rootProperties = AutomationElement::RootElement->GetSupportedProperties();
List<AutomationProperty^> ^cacheList = gcnew List<AutomationProperty^>();
if (cachedPropStr->Contains(L"NativeWindowHandleProperty")) //special property not in the root property list
{
cacheList->Add(AutomationElement::NativeWindowHandleProperty);
cacheRequest->Add(AutomationElement::NativeWindowHandleProperty);
}
for each(AutomationProperty ^ap in rootProperties) //loop through all supported Properties for a child
{
System::String ^currentPropertyStr = L""; //current property values
System::String ^shortPropName = L" null ";
if (ap->ProgrammaticName->Contains(L".")) //get short Property name
shortPropName = ap->ProgrammaticName->Substring(ap->ProgrammaticName->IndexOf(L".") + 1);
if (cachedPropStr->Contains(shortPropName) || cachedPropStr->Contains(ap->ProgrammaticName))
{
cacheList->Add(ap);// add property to cachedRootProperties
cacheRequest->Add(ap); // add property to cacheRequest
//Console::WriteLine("caching property {0}", ap->ProgrammaticName);
}
}
cachedRootProperties = cacheList->ToArray();
cacheRequest->Push(); //enable UI Automation Cache
//cachedRootProperties = AutomationElement::RootElement->GetSupportedProperties();
}
int AutomationBridge::addEnumFilter(System::String ^propertyName, System::String ^propertyValue)
{
enumFilters->Add(propertyName, propertyValue);
return enumFilters->Count;
}
void AutomationBridge::clearEnumFilters()
{
enumFilters->Clear();
}
Boolean AutomationBridge::isElementFiltered(System::Windows::Automation::AutomationElement ^element)
{
return isElementFiltered(element, nullptr);
}
Boolean AutomationBridge::isElementFiltered(System::Windows::Automation::AutomationElement ^element, List<System::String ^> ^filterModifierList)
{
Boolean result = false;
int filterMatchCount = 0;
if (enumFilters->Count == 0)
return result;
array<AutomationProperty^> ^aps = cachedRootProperties;//element->GetSupportedProperties();
for each(AutomationProperty ^ap in aps) //loop through all supported Properties for a child
{
System::String ^currentPropertyStr = L""; //current property values
System::String ^shortPropName = L" null ";
if (ap->ProgrammaticName->Contains(L".")) //get short Property name
shortPropName = ap->ProgrammaticName->Substring(ap->ProgrammaticName->IndexOf(L".") + 1);
//System::Console::WriteLine("property: {0}", shortPropName);
for each(System::String ^key in enumFilters->Keys)
{
if (filterModifierList != nullptr)
if (filterModifierList->Contains(key) && key->StartsWith(PARENT_MODIFIER+ "/") ) // modifier has been applied and filters should be ignored
{
++filterMatchCount;
//System::Console::WriteLine("PARENT_MODIFIER {0}", key);
continue;
}
else if(filterModifierList->Contains(key) && key->StartsWith(FIRST_MODIFIER+ "/")) //first already found stop!
{
//System::Console::WriteLine("FIRST_MODIFIER {0}", key);
return true;
}
System::String ^filterProp = key;
System::String ^modifier = L"";
int pos = key->IndexOf(L"/");
if (pos != -1)//tree modifier
{
modifier = filterProp->Substring(0, pos);
filterProp = filterProp->Substring(pos+1);
//System::Console::WriteLine("modifier: {0}, {1}, {2}", modifier, filterProp, key);
}
if (shortPropName->Equals(filterProp) || ap->ProgrammaticName->Equals(filterProp))
{//this element has a matching filter property
//System::Console::WriteLine("matched property: {0}", filterProp);
System::String ^valStr = L"";
if (ap->ProgrammaticName->Equals(L"AutomationElementIdentifiers.RuntimeIdProperty"))
{//runtimeId are int array so need to test it differently
array<System::Int32> ^idArray = (array<System::Int32> ^)element->GetCurrentPropertyValue(ap);
for each(System::Int32 val in idArray)
{
valStr += System::Convert::ToString(val) + L"-";
}
valStr = valStr->TrimEnd('-');
//System::Console::WriteLine("runtimeId: {0}", valStr);
}
else //all other property types that are strings
{
valStr = element->GetCachedPropertyValue(ap)->ToString();
//valStr = element->GetCurrentPropertyValue(ap)->ToString();
}
//System::Console::WriteLine("test property vals: {0} , {1}", valStr, enumFilters[key]);
if (valStr->Equals(enumFilters[key])) // value matches filter value
{
//System::Console::WriteLine("matched property vals: {0} , {1}", valStr, enumFilters[key]);
//result = false;
++filterMatchCount;
if (filterModifierList != nullptr)
if (modifier->Equals(PARENT_MODIFIER)) //if modifier is parent then add to modifier list
{
//System::Console::WriteLine("modifier added1 {0}", key);
filterModifierList->Add(key);
}
else if(modifier->Equals(FIRST_MODIFIER)) {
//System::Console::WriteLine("first modifier added1 {0} {1}", key, filterModifierList->Count);
//for each (System::String ^mod in filterModifierList)
// System::Console::WriteLine("mod {0}", mod);
filterModifierList->Add(key);
return false;
}
}
else// not matched
if (filterModifierList != nullptr)
if (modifier->Equals(ALL_MODIFIER)) //doesn't matter if ALL modifier doesn't match, need to keep searching
{
//System::Console::WriteLine("modifier added2 {0}", key);
filterModifierList->Add(key);
}
else if(modifier->Equals(FIRST_MODIFIER))
filterModifierList->Add(ALL_MODIFIER + "/" + filterProp);
}
}
}
//System::Console::WriteLine("filterMatchCount: {0}", filterMatchCount);
if (filterMatchCount > 0)
return false;
else
return true;
//return result;
}
void AutomationBridge::processFilterModifier(Boolean filtered, Boolean modifierChanged, List<System::String ^> ^filterModifierList)
{
if (!filtered) //not filtered so return element
{
//winInfoList->Add(getWindowInfo(currentElement, properties));
//winInfoList->AddRange(enumWindowInfo(currentElement, properties, filterModifierList));
if (modifierChanged && filterModifierList[filterModifierList->Count - 1]->StartsWith(FIRST_MODIFIER) == false) //modifier was added and needs to be removed
{// don't remove First modifier
//System::Console::WriteLine("modifier removed1 {0}", filterModifierList[filterModifierList->Count - 1]);
filterModifierList->RemoveAt(filterModifierList->Count - 1);
}
}
else //filtered, but if modifier used keep searching children
{
if (modifierChanged) //modifier was added and needs to be removed (ALL)
{
//winInfoList->AddRange(enumWindowInfo(currentElement, properties, filterModifierList));
if (filterModifierList[filterModifierList->Count - 1]->StartsWith(FIRST_MODIFIER) == false)// don't remove First modifier
{
//System::Console::WriteLine("modifier removed2 {0}", filterModifierList[filterModifierList->Count - 1]);
filterModifierList->RemoveAt(filterModifierList->Count - 1);
}
}
}
}
System::String ^ AutomationBridge::getRuntimeIdFromElement(System::Windows::Automation::AutomationElement ^element)
{
System::String ^result = L"";
System::Object ^currentVal = element->GetCurrentPropertyValue(AutomationElement::RuntimeIdProperty);
if (currentVal != nullptr)
{
array<System::Int32> ^idArray = (array<System::Int32> ^)currentVal;
for each(System::Int32 val in idArray)
{
result += System::Convert::ToString(val) + L"-";
}
result = result->TrimEnd('-');
//System::Console::WriteLine("id: {0}", result);
}
return result;
}
array<System::String ^> ^ AutomationBridge::enumWindowInfo(System::String ^properties)
{
return enumWindowInfo(AutomationElement::RootElement, properties);
}
array<System::String ^> ^ AutomationBridge::enumWindowInfo(System::IntPtr windowHandle, System::String ^properties)
{
AutomationElement ^element = AutomationElement::FromHandle(windowHandle);
List<System::String ^> ^winInfoList = gcnew List<System::String ^>();
if (!isElementFiltered(element)) //test parent should be filtered
winInfoList->Add(getWindowInfo(element, properties));
winInfoList->AddRange(enumWindowInfo(element, properties));
return winInfoList->ToArray();
}
array<System::String ^> ^ AutomationBridge::enumWindowInfo(AutomationElement ^element, System::String ^properties)
{
List<System::String ^> ^filterModifierList = gcnew List<System::String ^>(); //can change descendants filters based on parent's filters
return enumWindowInfo(element, properties, filterModifierList);
}
array<System::String ^> ^ AutomationBridge::enumWindowInfo(AutomationElement ^element, System::String ^properties, List<System::String ^> ^filterModifierList)
{
List<System::String ^> ^winInfoList = gcnew List<System::String ^>();
if (element == nullptr)
return winInfoList->ToArray();
TreeWalker ^tw = TreeWalker::RawViewWalker;
//System::Console::WriteLine("get info: {0}", getWindowInfo(element, properties));
//AutomationElement ^currentElement = tw->GetFirstChild(element, cacheRequest);
AutomationElement ^currentElement = nullptr;
/*if (element->CachedChildren != nullptr)
{
System::Console::WriteLine("using cached child");
currentElement = element->CachedChildren[0];
}
else*/
{
//System::Console::WriteLine("not cached child");
currentElement = tw->GetFirstChild(element, cacheRequest);
}
if (currentElement == nullptr)
{
//System::Console::WriteLine("no children {0}", element->CachedChildren->Count);
//System::Console::WriteLine("no children");
return winInfoList->ToArray();
}
//else
// System::Console::WriteLine("yes children");
while (currentElement != nullptr)
{
try
{
int fmlOriginalSize = filterModifierList->Count;
Boolean filtered = isElementFiltered(currentElement, filterModifierList);
Boolean modifierChanged = fmlOriginalSize != filterModifierList->Count;
if (!filtered) //not filtered so return element
{
winInfoList->Add(getWindowInfo(currentElement, properties));
winInfoList->AddRange(enumWindowInfo(currentElement, properties, filterModifierList));
}
else //filtered, but if modifier used keep searching children
{
if (modifierChanged) //modifier was added search children
winInfoList->AddRange(enumWindowInfo(currentElement, properties, filterModifierList));
}
processFilterModifier(filtered, modifierChanged, filterModifierList); //cleans filterModifierList
//System::Console::WriteLine("element: {0}", currentElement);
//currentElement->
currentElement = tw->GetNextSibling(currentElement, cacheRequest);
} catch (Exception ^ex)
{
System::Console::WriteLine("Exception: {0} {1}", ex->Message, ex->StackTrace);
}
}
return winInfoList->ToArray();
}
System::String ^ AutomationBridge::getWindowInfo(AutomationElement ^element, System::String ^properties)
{
System::String ^resultProperties = L"";
System::String ^propertyNameErrorCheck = L"";
try
{
//when wildcard is enabled it will pull all property names & values
System::Boolean wildcardEnabled = false;
if (properties->Equals(L"*"))
wildcardEnabled = true;
//create array for keeping order of properties
System::String ^delim = L",";
array<System::String ^> ^propSpltArray = properties->Split(delim->ToCharArray());
TreeWalker ^tw = TreeWalker::ControlViewWalker;
System::Int32 count = 0;
array<AutomationProperty^> ^aps = cachedRootProperties;//element->GetSupportedProperties();
array<System::String ^> ^propValues = gcnew array<System::String ^>(propSpltArray->Length);//keep order
System::String ^wildcardProperties = L"";
if (wildcardEnabled) {
wildcardProperties += "ParentRuntimeIdProperty:" + getRuntimeIdFromElement(tw->GetParent(element, cacheRequest)) + ",";
//propValues = gcnew array<System::String ^>(aps->Length +1 );//add one for parent property since it doesn't exist
}
for(int i=0 ; i < propValues->Length ; i++)
{
propValues[i] = L"";
if (propSpltArray[i]->Equals("ParentRuntimeIdProperty"))//custom property for getting parent
{
propValues[i] = getRuntimeIdFromElement(tw->GetParent(element, cacheRequest));
}
}
for each(AutomationProperty ^ap in aps) //loop through all supported Properties for a child
{
propertyNameErrorCheck = ap->ProgrammaticName;//debug purposes
System::String ^currentPropertyStr = L""; //current property values
//System::Console::WriteLine("property: {0}", ap->ProgrammaticName);
System::String ^shortPropName = L" null ";
if (ap->ProgrammaticName->Contains(L"."))
shortPropName = ap->ProgrammaticName->Substring(ap->ProgrammaticName->IndexOf(L".") + 1);
if (properties->Contains(shortPropName) || properties->Contains(ap->ProgrammaticName) || ap->ProgrammaticName->Equals(properties) || wildcardEnabled)
{
//System::Console::WriteLine("shortPropName: {0}", shortPropName);
//System::Object ^currentVal = element->GetCurrentPropertyValue(ap);
System::Object ^currentVal = element->GetCachedPropertyValue(ap);
if (currentVal == nullptr)
continue;
if (ap->ProgrammaticName->Equals(L"AutomationElementIdentifiers.RuntimeIdProperty"))
{
array<System::Int32> ^idArray = (array<System::Int32> ^)currentVal;
for each(System::Int32 val in idArray)
{
currentPropertyStr += System::Convert::ToString(val) + L"-";
}
currentPropertyStr = currentPropertyStr->TrimEnd('-');
//System::Console::WriteLine("id: {0}", result);
}
else//not runtimeId which is an Int32[]
{
currentPropertyStr = currentVal->ToString();
currentPropertyStr = currentPropertyStr->Replace(",","&#44;");
}
}
if (currentPropertyStr->Equals(L"")) //if there isn't a value skip
continue;
if (wildcardEnabled) {
wildcardProperties += shortPropName + ":" +currentPropertyStr + ",";
continue;
}
//System::Console::WriteLine("currentPropertyStr: {0}", currentPropertyStr);
//find the correct order to return this property
for(int i=0 ; i < propSpltArray->Length ; i++)
{
if (propSpltArray[i]->Equals(shortPropName) || propSpltArray[i]->Equals(ap->ProgrammaticName))
propValues[i] = currentPropertyStr;
}
}
//output properties in the correct order
for(int i=0 ; i < propSpltArray->Length ; i++)
resultProperties += propValues[i] + L",";
if (wildcardEnabled)
resultProperties += wildcardProperties;
} catch (Exception ^ex) //when some elements close during enumeration it might cause valid exceptions
{
System::Console::WriteLine("Exception ({2}): {0} {1}", ex->Message, ex->StackTrace, propertyNameErrorCheck);
}
return resultProperties;
}
System::String ^ AutomationBridge::getWindowInfo(System::Int32 x, System::Int32 y, System::String ^properties)
{
AutomationElement ^element = AutomationElement::FromPoint(System::Windows::Point(x, y));
return getWindowInfo(element, properties);
}
System::String ^ AutomationBridge::getWindowInfo(System::IntPtr windowHandle, System::String ^properties)
{
AutomationElement ^element = AutomationElement::FromHandle(windowHandle);
return getWindowInfo(element, properties);
}
System::String ^ AutomationBridge::getWindowInfo(System::String ^runtimeIdStr, System::String ^properties)
{
System::String ^filter = L"First/RuntimeIdProperty"; //get first matching runtimeIdProperty
enumFilters->Add(filter, runtimeIdStr);
array<System::String ^> ^props = enumWindowInfo(properties);
enumFilters->Remove(filter);
if (props->Length > 0) //if result array has a match return first result
return props[0];
else
return "";
//return getWindowInfo(element, properties);
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski7@gmail.com
*/
// uiabridge.h
#pragma once
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Windows::Automation;
namespace uiabridge {
public ref class AutomationBridge
{
public:
AutomationBridge(void);
~AutomationBridge();
int addEnumFilter(System::String ^propertyName, System::String ^propertyValue);
void clearEnumFilters();
Boolean isElementFiltered(System::Windows::Automation::AutomationElement ^element);
Boolean isElementFiltered(System::Windows::Automation::AutomationElement ^element, List<System::String ^> ^filterModifierList);
System::String ^ getRuntimeIdFromElement(System::Windows::Automation::AutomationElement ^element);
array<System::String ^> ^ enumWindowInfo(System::String ^properties);
array<System::String ^> ^ enumWindowInfo(System::IntPtr windowHandle, System::String ^properties);
array<System::String ^> ^ enumWindowInfo(AutomationElement ^element, System::String ^properties);
array<System::String ^> ^ enumWindowInfo(AutomationElement ^element, System::String ^properties, List<System::String ^> ^filterModifierList);
System::String ^ getWindowInfo(AutomationElement ^element, System::String ^properties);
System::String ^ getWindowInfo(System::Int32 x, System::Int32 y, System::String ^properties);
System::String ^ getWindowInfo(System::IntPtr windowHandle, System::String ^properties);
System::String ^ getWindowInfo(System::String ^runtimeIdStr, System::String ^properties);
static System::String ^ALL_MODIFIER = L"All";// find all matching elements of this filter
static System::String ^PARENT_MODIFIER = L"Parent";//find all children of this matching parent filter
static System::String ^FIRST_MODIFIER = L"First"; //find first element matching this filter then stop
private:
void initializeCache();
Dictionary<System::String ^, System::String ^> ^enumFilters;
void AutomationBridge::processFilterModifier(Boolean filtered, Boolean modifierChanged, List<System::String ^> ^filterModifierList);
CacheRequest ^cacheRequest;
array<AutomationProperty^> ^cachedRootProperties;
};
}

View File

@@ -19,10 +19,10 @@
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{3141812E-36D5-4E7C-A388-EFED9AE250A5}</ProjectGuid>
<ProjectGuid>{BAC1B079-7B87-4396-B17F-91A86DF1AE29}</ProjectGuid>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<Keyword>ManagedCProj</Keyword>
<RootNamespace>WpfBridge</RootNamespace>
<RootNamespace>uiabridge</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -120,8 +120,7 @@
</Link>
<PostBuildEvent>
<Command>mkdir "$(ProjectDir)bin"
copy /Y "$(TargetPath)" "$(ProjectDir)bin\wpfbridge$(PlatformArchitecture)$(TargetExt)"
</Command>
copy /Y "$(TargetPath)" "$(ProjectDir)bin\uiabridge$(PlatformArchitecture)$(TargetExt)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -137,8 +136,7 @@ copy /Y "$(TargetPath)" "$(ProjectDir)bin\wpfbridge$(PlatformArchitecture)$(Targ
</Link>
<PostBuildEvent>
<Command>mkdir "$(ProjectDir)bin"
copy /Y "$(TargetPath)" "$(ProjectDir)bin\wpfbridge$(PlatformArchitecture)$(TargetExt)"
</Command>
copy /Y "$(TargetPath)" "$(ProjectDir)bin\uiabridge$(PlatformArchitecture)$(TargetExt)"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
@@ -146,28 +144,29 @@ copy /Y "$(TargetPath)" "$(ProjectDir)bin\wpfbridge$(PlatformArchitecture)$(Targ
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="UIAutomationClient" />
<Reference Include="UIAutomationClientsideProviders" />
<Reference Include="UIAutomationProvider" />
<Reference Include="UIAutomationTypes" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Global.h" />
<ClInclude Include="org_synthuse_WpfBridge.h" />
<ClInclude Include="org_synthuse_UiaBridge.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="Stdafx.h" />
<ClInclude Include="WpfAutomation.h" />
<ClInclude Include="uiabridge.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp" />
<ClCompile Include="Global.cpp" />
<ClCompile Include="org_synthuse_WpfBridge.cpp" />
<ClCompile Include="org_synthuse_UiaBridge.cpp" />
<ClCompile Include="Stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="WpfAutomation.cpp" />
<ClCompile Include="uiabridge.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="app.ico" />

View File

@@ -15,16 +15,16 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="uiabridge.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="org_synthuse_WpfBridge.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="WpfAutomation.h">
<ClInclude Include="org_synthuse_UiaBridge.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Global.h">
@@ -32,16 +32,16 @@
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="uiabridge.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="AssemblyInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="WpfAutomation.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="org_synthuse_WpfBridge.cpp">
<ClCompile Include="org_synthuse_UiaBridge.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Global.cpp">

View File

@@ -0,0 +1,40 @@
#include "stdafx.h"
using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly:AssemblyTitleAttribute("uiabtest")];
[assembly:AssemblyDescriptionAttribute("")];
[assembly:AssemblyConfigurationAttribute("")];
[assembly:AssemblyCompanyAttribute("na")];
[assembly:AssemblyProductAttribute("uiabtest")];
[assembly:AssemblyCopyrightAttribute("Copyright (c) na 2014")];
[assembly:AssemblyTrademarkAttribute("")];
[assembly:AssemblyCultureAttribute("")];
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly:AssemblyVersionAttribute("1.0.*")];
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];

View File

@@ -0,0 +1,35 @@
========================================================================
APPLICATION : uiabtest Project Overview
========================================================================
AppWizard has created this uiabtest Application for you.
This file contains a summary of what you will find in each of the files that
make up your uiabtest application.
uiabtest.vcxproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.
uiabtest.vcxproj.filters
This is the filters file for VC++ projects generated using an Application Wizard.
It contains information about the association between the files in your project
and the filters. This association is used in the IDE to show grouping of files with
similar extensions under a specific node (for e.g. ".cpp" files are associated with the
"Source Files" filter).
uiabtest.cpp
This is the main application source file.
AssemblyInfo.cpp
Contains custom attributes for modifying assembly metadata.
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" to indicate parts of the source code you
should add to or customize.
/////////////////////////////////////////////////////////////////////////////

BIN
native/uiabtest/app.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
native/uiabtest/app.rc Normal file

Binary file not shown.

View File

@@ -0,0 +1,3 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by app.rc

View File

@@ -1,5 +1,7 @@
// stdafx.cpp : source file that includes just the standard includes
// WpfBridge.pch will be the pre-compiled header
// uiabtest.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"

11
native/uiabtest/stdafx.h Normal file
View File

@@ -0,0 +1,11 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
// TODO: reference additional headers your program requires here
#include <stdio.h>
#include <conio.h>
#include <tchar.h>

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski7@gmail.com
*/
// uiabtest.cpp : main project file.
#include "stdafx.h"
using namespace System;
using namespace System::Windows::Automation;
using namespace uiabridge;
void outputResults(array<System::String ^> ^winInfo)
{
System::IO::StreamWriter ^file = gcnew System::IO::StreamWriter("c:\\temp.txt");
for each(System::String ^prop in winInfo)
{
Console::WriteLine(prop);
file->WriteLine(prop);
}
file->Flush();
file->Close();
}
int main(array<System::String ^> ^args)
{
Console::WriteLine(L"UI Automation Bridge Test");
AutomationBridge ^ab = gcnew AutomationBridge();
System::String ^propList = L"RuntimeIdProperty,ParentRuntimeIdProperty,NativeWindowHandleProperty,ProcessIdProperty,FrameworkIdProperty,LocalizedControlTypeProperty,ClassNameProperty,NameProperty";
//System::String ^propList = L"RuntimeIdProperty,BoundingRectangleProperty";
Console::WriteLine(propList);
//System::String ^winInfo1 = ab->getWindowInfo(System::IntPtr(3409618), propList);
System::DateTime start = System::DateTime::Now;
//ab->addEnumFilter("Parent/ClassNameProperty", "Notepad");
//ab->addEnumFilter("First/RuntimeIdProperty", "42-4784952");
//ab->addEnumFilter("ClassNameProperty", "Notepad");
//ab->addEnumFilter("All/ClassNameProperty", "Edit");
//ab->addEnumFilter("All/LocalizedControlTypeProperty", "menu item");
ab->addEnumFilter("Parent/FrameworkIdProperty", "WinForm");
//ab->addEnumFilter("Parent/FrameworkIdProperty", "WPF");
//ab->addEnumFilter("Parent/ClassNameProperty", "WindowsForms10.Window.8.app.0.2bf8098_r13_ad1");
array<System::String ^> ^winInfo = ab->enumWindowInfo(propList); //L"*"
//ab->clearEnumFilters();
//ab->addEnumFilter("Parent/FrameworkIdProperty", "WinForm");
//array<System::String ^> ^winInfo = ab->enumWindowInfo(System::IntPtr(3409618), propList); //L"*"
//array<System::String ^> ^winInfo = ab->enumWindowInfo(System::IntPtr(12977932), propList); //L"*"
//Console::WriteLine("enumWindowInfo x,y: {0}", ab->getWindowInfo(100,100, propList); //L"*"
outputResults(winInfo);
//Globals::Global::AUTO_BRIDGE->clearEnumFilters();
//winInfo = nullptr;
//winInfo = Globals::Global::AUTO_BRIDGE->enumWindowInfo(System::IntPtr(7603636), propList);
//Console::WriteLine("winInfo length: {0}", winInfo->Length);
//winInfo = Globals::Global::AUTO_BRIDGE->enumWindowInfo(System::IntPtr(7603636), propList);
//Console::WriteLine("winInfo length: {0}", winInfo->Length);
//Console::WriteLine("getWindowInfo RuntimeIdProperty: {0}", ab->getWindowInfo("42-4784952", propList));
//System::Threading::Thread::Sleep(10000); //10 seconds sleep
//array<System::String ^> ^winInfo2 = ab->enumWindowInfo(propList); //L"*"
//outputResults(winInfo2);
System::Double seconds = System::Math::Round(System::DateTime::Now.Subtract(start).TotalSeconds, 4);
Console::WriteLine(L"Total Elements: {0} in {1} seconds", winInfo->Length, seconds);
getch();//wait for user input
return 0;
}

View File

@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{7958D1B7-F169-40FA-A7A0-10E8E0F90CDA}</ProjectGuid>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<Keyword>ManagedCProj</Keyword>
<RootNamespace>uiabtest</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>
</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>
</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>
</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>
</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="UIAutomationClient" />
<Reference Include="UIAutomationClientsideProviders" />
<Reference Include="UIAutomationProvider" />
<Reference Include="UIAutomationTypes" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<None Include="app.ico" />
<None Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="resource.h" />
<ClInclude Include="stdafx.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="app.rc" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="uiabtest.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\uiabridge\uiabridge.vcxproj">
<Project>{bac1b079-7b87-4396-b17f-91a86df1ae29}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="ReadMe.txt" />
<None Include="app.ico">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="app.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ClCompile Include="uiabtest.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="AssemblyInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>