diff --git a/.gitignore b/.gitignore index dc6b6da..8df1a62 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ dist/ synthuse.properties native/WpfBridge/x64 native/WpfBridge/release -!native/WpfBridge/bin \ No newline at end of file +native/WpfBridge/Debug +!native/WpfBridge/bin diff --git a/native/WpfBridge/WpfAutomation.cpp b/native/WpfBridge/WpfAutomation.cpp index fa4cd59..31a9ee2 100644 --- a/native/WpfBridge/WpfAutomation.cpp +++ b/native/WpfBridge/WpfAutomation.cpp @@ -34,6 +34,8 @@ array ^ WpfAutomation::convertRuntimeIdString(System::String ^run AutomationElement ^ WpfAutomation::findAutomationElementById(System::String ^runtimeIdValue) { + if (runtimeIdValue == nullptr || runtimeIdValue->Equals(L"")) + return AutomationElement::RootElement; array ^idArray = this->convertRuntimeIdString(runtimeIdValue); Condition ^pcFramework = gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId); Condition ^pcRunId = gcnew PropertyCondition(AutomationElement::RuntimeIdProperty, idArray); @@ -47,22 +49,28 @@ array ^ WpfAutomation::getRuntimeIdsFromCollection(System::Win System::Int32 count = 0; for each(AutomationElement ^child in collection) { - System::Object ^currentVal = child->GetCurrentPropertyValue(AutomationElement::RuntimeIdProperty); - if (currentVal != nullptr) - { - array ^idArray = (array ^)currentVal; - for each(System::Int32 val in idArray) - { - idStrArray[count] += System::Convert::ToString(val) + L"-"; - //System::String->Concat(idStrArray[count], System::String->Concat(val->ToString(), L"-")); - } - idStrArray[count] = idStrArray[count]->TrimEnd('-'); - //System::Console::WriteLine("id: {0}", idStrArray[count]); - } + 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 ^idArray = (array ^)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() @@ -135,6 +143,84 @@ array ^ WpfAutomation::EnumDescendantWindowIdsFromHandle(Syste return getRuntimeIdsFromCollection(aec); } +array ^ WpfAutomation::EnumDescendantWindowInfo(System::String ^runtimeIdValue, System::String ^properties) +{ + AutomationElement ^parent = findAutomationElementById(runtimeIdValue); + AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId)); + + //create array for keeping order of properties + System::String ^delim = L","; + array ^propSpltArray = properties->Split(delim->ToCharArray()); + TreeWalker ^tw = TreeWalker::ControlViewWalker; + + array ^winInfoList = gcnew array(aec->Count); + System::Int32 count = 0; + for each(AutomationElement ^child in aec) //loop through all descendants + { + array ^aps = child->GetSupportedProperties(); + array ^propValues = gcnew array(propSpltArray->Length);//keep order + 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)) + { + //System::Console::WriteLine("shortPropName: {0}", shortPropName); + System::Object ^currentVal = child->GetCurrentPropertyValue(ap); + if (currentVal == nullptr) + continue; + if (ap->ProgrammaticName->Equals(L"AutomationElementIdentifiers.RuntimeIdProperty")) + { + array ^idArray = (array ^)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(); + } + } + if (currentPropertyStr->Equals(L"")) //if there isn't a value skip + 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","; + ++count; + } + return winInfoList; +} + +System::String ^ WpfAutomation::getParentRuntimeId(System::String ^runtimeIdValue) +{ + AutomationElement ^target = findAutomationElementById(runtimeIdValue); + 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); diff --git a/native/WpfBridge/WpfAutomation.h b/native/WpfBridge/WpfAutomation.h index e1ce513..ea9308e 100644 --- a/native/WpfBridge/WpfAutomation.h +++ b/native/WpfBridge/WpfAutomation.h @@ -24,13 +24,17 @@ public: array ^ enumDescendantWindowIds(System::Int32 processId); array ^ EnumDescendantWindowIdsFromHandle(System::IntPtr windowHandle); //In all the above Enumerate methods will return a list of Runtime Ids for all related windows. + array ^ EnumDescendantWindowInfo(System::String ^runtimeIdValue, System::String ^properties); - System::String ^getProperty(System::String ^propertyName, System::String ^runtimeIdValue); + + System::String ^ getParentRuntimeId(System::String ^runtimeIdValue); + System::String ^ getProperty(System::String ^propertyName, System::String ^runtimeIdValue); array ^ getProperties(System::String ^runtimeIdValue); array ^ getPropertiesAndValues(System::String ^runtimeIdValue); private: array ^ convertRuntimeIdString(System::String ^runtimeIdValue); System::Windows::Automation::AutomationElement ^ findAutomationElementById(System::String ^runtimeIdValue); + System::String ^ getRuntimeIdFromElement(System::Windows::Automation::AutomationElement ^element); array ^ getRuntimeIdsFromCollection(System::Windows::Automation::AutomationElementCollection ^collection); static System::String ^DEFAULT_FRAMEWORK = L"WPF"; diff --git a/native/WpfBridge/bin/wpfbridge32.dll b/native/WpfBridge/bin/wpfbridge32.dll index 7fd0949..b275d90 100644 Binary files a/native/WpfBridge/bin/wpfbridge32.dll and b/native/WpfBridge/bin/wpfbridge32.dll differ diff --git a/native/WpfBridge/bin/wpfbridge64.dll b/native/WpfBridge/bin/wpfbridge64.dll index ab73fbd..d063b13 100644 Binary files a/native/WpfBridge/bin/wpfbridge64.dll and b/native/WpfBridge/bin/wpfbridge64.dll differ diff --git a/native/WpfBridge/build.bat b/native/WpfBridge/build.bat index 6c0af5f..626076c 100644 --- a/native/WpfBridge/build.bat +++ b/native/WpfBridge/build.bat @@ -1,3 +1,4 @@ +REM set path=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin;%path% %WinDir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe /p:configuration=release /p:platform=x64 %* %WinDir%\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe /p:configuration=release /p:platform=win32 %* diff --git a/native/WpfBridge/org_synthuse_WpfBridge.cpp b/native/WpfBridge/org_synthuse_WpfBridge.cpp index 449666a..a23de4c 100644 --- a/native/WpfBridge/org_synthuse_WpfBridge.cpp +++ b/native/WpfBridge/org_synthuse_WpfBridge.cpp @@ -15,7 +15,7 @@ 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) +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(propertyValue)); @@ -27,7 +27,7 @@ JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_SetFrameworkId(JNIEnv *env, j * Method: CountDescendantWindows * Signature: ()I */ -JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountDescendantWindows__(JNIEnv *env, jobject obj) +JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countDescendantWindows__(JNIEnv *env, jobject obj) { return Global::WPF_AUTO->countDescendantWindows(); } @@ -37,7 +37,7 @@ JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountDescendantWindows__(JNIE * 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) +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(runtimeIdValue)); @@ -51,7 +51,7 @@ JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountDescendantWindows__Ljava * Method: CountChildrenWindows * Signature: ()I */ -JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountChildrenWindows__(JNIEnv *env, jobject obj) +JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countChildrenWindows__(JNIEnv *env, jobject obj) { return Global::WPF_AUTO->countChildrenWindows(); } @@ -62,7 +62,7 @@ JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountChildrenWindows__(JNIEnv * 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) +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(runtimeIdValue)); @@ -76,7 +76,7 @@ JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountChildrenWindows__Ljava_l * Method: EnumChildrenWindowIds * Signature: (Ljava/lang/String;)[Ljava/lang/String; */ -JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumChildrenWindowIds(JNIEnv *env, jobject obj, jstring jruntimeIdValue) +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumChildrenWindowIds(JNIEnv *env, jobject obj, jstring jruntimeIdValue) { const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string array ^mchildrenIds = Global::WPF_AUTO->enumChildrenWindowIds(marshal_as(runtimeIdValue)); @@ -103,7 +103,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumChildrenWindowIds * 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) +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 ^mchildrenIds = Global::WPF_AUTO->enumDescendantWindowIds(marshal_as(runtimeIdValue)); @@ -130,7 +130,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowI * Method: EnumDescendantWindowIds * Signature: (J)[Ljava/lang/String; */ -JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowIds__J(JNIEnv *env, jobject obj, jlong jprocessId) +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIds__J(JNIEnv *env, jobject obj, jlong jprocessId) { array ^mchildrenIds = Global::WPF_AUTO->enumDescendantWindowIds((System::Int32)jprocessId); @@ -151,7 +151,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowI * Method: EnumDescendantWindowIdsFromHandle * Signature: (J)[Ljava/lang/String; */ -JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowIdsFromHandle(JNIEnv *env, jobject obj, jlong jwindowHandle) +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIdsFromHandle(JNIEnv *env, jobject obj, jlong jwindowHandle) { array ^mchildrenIds = Global::WPF_AUTO->EnumDescendantWindowIdsFromHandle(System::IntPtr(jwindowHandle)); @@ -166,12 +166,51 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowI return results; } +/* + * 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 ^mwinInfo = Global::WPF_AUTO->EnumDescendantWindowInfo(marshal_as(runtimeIdValue), marshal_as(properties)); + //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(mwinInfo[i]))); + } + env->ReleaseStringUTFChars(jproperties, properties); //release string + env->ReleaseStringUTFChars(jruntimeIdValue, runtimeIdValue); //release string + return results; +} + + +/* + * 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(runtimeIdValue)); + marshal_context context; //lets you marshal managed classes to unmanaged types + jstring result = env->NewStringUTF(context.marshal_as(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) +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 @@ -189,7 +228,7 @@ JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_GetProperty(JNIEnv *env, j * Method: GetProperties * Signature: (Ljava/lang/String;)[Ljava/lang/String; */ -JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_GetProperties(JNIEnv *env, jobject obj, jstring jruntimeIdValue) +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_getProperties(JNIEnv *env, jobject obj, jstring jruntimeIdValue) { const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string array ^mprops = Global::WPF_AUTO->getProperties(marshal_as(runtimeIdValue)); @@ -212,7 +251,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_GetProperties(JNIEnv * Method: GetPropertiesAndValues * Signature: (Ljava/lang/String;)[Ljava/lang/String; */ -JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_GetPropertiesAndValues(JNIEnv *env, jobject obj, jstring jruntimeIdValue) +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_getPropertiesAndValues(JNIEnv *env, jobject obj, jstring jruntimeIdValue) { const char *runtimeIdValue = env->GetStringUTFChars(jruntimeIdValue, 0);//convert string array ^mprops = Global::WPF_AUTO->getPropertiesAndValues(marshal_as(runtimeIdValue)); diff --git a/native/WpfBridge/org_synthuse_WpfBridge.h b/native/WpfBridge/org_synthuse_WpfBridge.h index e6d8f07..8ecb288 100644 --- a/native/WpfBridge/org_synthuse_WpfBridge.h +++ b/native/WpfBridge/org_synthuse_WpfBridge.h @@ -1,9 +1,3 @@ -/* - * Copyright 2014, Synthuse.org - * Released under the Apache Version 2.0 License. - * - * last modified by ejakubowski7@gmail.com -*/ /* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class org_synthuse_WpfBridge */ @@ -15,98 +9,114 @@ extern "C" { #endif /* * Class: org_synthuse_WpfBridge - * Method: SetFrameworkId + * Method: setFrameworkId * Signature: (Ljava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_SetFrameworkId +JNIEXPORT void JNICALL Java_org_synthuse_WpfBridge_setFrameworkId (JNIEnv *, jobject, jstring); /* * Class: org_synthuse_WpfBridge - * Method: CountDescendantWindows + * Method: countDescendantWindows * Signature: ()I */ -JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountDescendantWindows__ +JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countDescendantWindows__ (JNIEnv *, jobject); /* * Class: org_synthuse_WpfBridge - * Method: CountDescendantWindows + * Method: countDescendantWindows * Signature: (Ljava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountDescendantWindows__Ljava_lang_String_2 +JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countDescendantWindows__Ljava_lang_String_2 (JNIEnv *, jobject, jstring); /* * Class: org_synthuse_WpfBridge - * Method: CountChildrenWindows + * Method: countChildrenWindows * Signature: ()I */ -JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountChildrenWindows__ +JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countChildrenWindows__ (JNIEnv *, jobject); /* * Class: org_synthuse_WpfBridge - * Method: CountChildrenWindows + * Method: countChildrenWindows * Signature: (Ljava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_CountChildrenWindows__Ljava_lang_String_2 +JNIEXPORT jint JNICALL Java_org_synthuse_WpfBridge_countChildrenWindows__Ljava_lang_String_2 (JNIEnv *, jobject, jstring); /* * Class: org_synthuse_WpfBridge - * Method: EnumChildrenWindowIds + * Method: enumChildrenWindowIds * Signature: (Ljava/lang/String;)[Ljava/lang/String; */ -JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumChildrenWindowIds +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumChildrenWindowIds (JNIEnv *, jobject, jstring); /* * Class: org_synthuse_WpfBridge - * Method: EnumDescendantWindowIds + * Method: enumDescendantWindowIds * Signature: (Ljava/lang/String;)[Ljava/lang/String; */ -JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowIds__Ljava_lang_String_2 +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIds__Ljava_lang_String_2 (JNIEnv *, jobject, jstring); /* * Class: org_synthuse_WpfBridge - * Method: EnumDescendantWindowIds + * Method: enumDescendantWindowIds * Signature: (J)[Ljava/lang/String; */ -JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowIds__J +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIds__J (JNIEnv *, jobject, jlong); /* * Class: org_synthuse_WpfBridge - * Method: EnumDescendantWindowIdsFromHandle + * Method: enumDescendantWindowIdsFromHandle * Signature: (J)[Ljava/lang/String; */ -JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowIdsFromHandle +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowIdsFromHandle (JNIEnv *, jobject, jlong); /* * Class: org_synthuse_WpfBridge - * Method: GetProperty - * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; + * Method: enumDescendantWindowInfo + * Signature: (Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_GetProperty +JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_enumDescendantWindowInfo (JNIEnv *, jobject, jstring, jstring); /* * Class: org_synthuse_WpfBridge - * Method: GetProperties - * Signature: (Ljava/lang/String;)[Ljava/lang/String; + * Method: getParentRuntimeId + * Signature: (Ljava/lang/String;)Ljava/lang/String; */ -JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_GetProperties +JNIEXPORT jstring JNICALL Java_org_synthuse_WpfBridge_getParentRuntimeId (JNIEnv *, jobject, jstring); /* * Class: org_synthuse_WpfBridge - * Method: GetPropertiesAndValues + * 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_GetPropertiesAndValues +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 diff --git a/src/org/synthuse/Config.java b/src/org/synthuse/Config.java index 35dc2fc..d5afe05 100644 --- a/src/org/synthuse/Config.java +++ b/src/org/synthuse/Config.java @@ -11,6 +11,7 @@ public class Config extends PropertiesSerializer { public static String DEFAULT_PROP_FILENAME = "synthuse.properties"; + public String disableWpf = "false"; public String urlList = ""; public String xpathList = ""; public String xpathHightlight = ".*process=\"([^\"]*)\".*"; diff --git a/src/org/synthuse/SynthuseDlg.java b/src/org/synthuse/SynthuseDlg.java index 2070c74..5249d47 100644 --- a/src/org/synthuse/SynthuseDlg.java +++ b/src/org/synthuse/SynthuseDlg.java @@ -162,9 +162,9 @@ public class SynthuseDlg extends JFrame { btnRefresh.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { //lblStatus.setText("Loading Windows Enumerated Xml..."); + //WindowsEnumeratedXml wex = new WindowsEnumeratedXml(textPane, lblStatus); + //wex.run(); WindowsEnumeratedXml.getXmlThreaded(textPane, lblStatus); - //appendToPane(WindowsEnumeratedXml.getXml()); - //lblStatus.setText("Windows Enumerated Xml loaded"); } }); btnRefresh.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_REFRESH_IMG))); diff --git a/src/org/synthuse/WindowInfo.java b/src/org/synthuse/WindowInfo.java index e36f989..a2b5e2f 100644 --- a/src/org/synthuse/WindowInfo.java +++ b/src/org/synthuse/WindowInfo.java @@ -17,6 +17,8 @@ import com.sun.jna.ptr.PointerByReference; public class WindowInfo { + public static String WPF_PROPERTY_LIST = "RuntimeIdProperty,ParentRuntimeIdProperty,ProcessIdProperty,FrameworkIdProperty,ClassNameProperty,NameProperty"; + public HWND hwnd; public String hwndStr = ""; public HWND parent = null; @@ -28,8 +30,12 @@ public class WindowInfo { public String processName = ""; public long pid = 0; public Object xmlObj = null; + public String framework = "win32";//default as win32 + public String runtimeId = ""; + //Default Win32 support public WindowInfo(HWND hWnd, boolean isChild) { + this.framework = "win32"; byte[] buffer = new byte[1024]; User32.instance.GetWindowTextA(hWnd, buffer, buffer.length); text = Native.toString(buffer); @@ -61,7 +67,39 @@ public class WindowInfo { } this.hwnd = hWnd; hwndStr = Api.GetHandleAsString(hWnd); - + } + + //support for WPF and Silverlight + public WindowInfo(String enumProperties, boolean isChild) { + //WPF_PROPERTY_LIST = "RuntimeIdProperty,ParentRuntimeIdProperty,ProcessIdProperty,FrameworkIdProperty,ClassNameProperty,NameProperty"; + String[] spltProperties = enumProperties.split(","); + if (spltProperties.length > 0) + this.runtimeId = spltProperties[0]; + this.hwndStr = this.runtimeId; + if (spltProperties.length > 1 && isChild) + this.parentStr = spltProperties[1]; + this.isChild = isChild; + if (spltProperties.length > 2) + this.pid = Long.parseLong(spltProperties[2]); + if (spltProperties.length > 3) + this.framework = spltProperties[3]; + if (spltProperties.length > 4) + this.className = spltProperties[4]; + if (spltProperties.length > 5) + this.text = spltProperties[5]; + /* + this.rect = new RECT(); + try { + String rectStr = wb.getProperty("BoundingRectangleProperty", runtimeId); + String[] rectSplt = rectStr.split(","); + this.rect.right = Integer.parseInt(rectSplt[0]); + this.rect.bottom = Integer.parseInt(rectSplt[1]); + this.rect.left = Integer.parseInt(rectSplt[2]); + this.rect.top = Integer.parseInt(rectSplt[3]); + } catch (Exception e) { + e.printStackTrace(); + } + */ } public String toString() { diff --git a/src/org/synthuse/WindowsEnumeratedXml.java b/src/org/synthuse/WindowsEnumeratedXml.java index 30f02c0..4973a91 100644 --- a/src/org/synthuse/WindowsEnumeratedXml.java +++ b/src/org/synthuse/WindowsEnumeratedXml.java @@ -12,6 +12,7 @@ import java.io.StringWriter; import java.sql.Timestamp; import java.text.DecimalFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; @@ -91,6 +92,10 @@ public class WindowsEnumeratedXml implements Runnable{ } } Api.User32.instance.EnumWindows(new ParentWindowCallback(), 0); + + //Enumerate WPF windows and add to list + if (!SynthuseDlg.config.disableWpf.equals("true")) + infoList.putAll(EnumerateWindowsWithWpfBridge("WPF")); // convert window info list to xml dom try { @@ -108,22 +113,30 @@ public class WindowsEnumeratedXml implements Runnable{ WindowInfo w = infoList.get(handle); //System.out.println(w); // create new win xml element - Element win = doc.createElement("win"); + Element win = null; + if (w.framework.equals("win32")) + win = doc.createElement("win"); + else + win = doc.createElement("wpf"); win.setAttribute("hwnd", w.hwndStr); win.setAttribute("text", w.text); - win.setAttribute("TEXT", w.text.toUpperCase()); + if (w.text != null) + win.setAttribute("TEXT", w.text.toUpperCase()); win.setAttribute("class", w.className); - win.setAttribute("CLASS", w.className.toUpperCase()); + if (w.className != null) + win.setAttribute("CLASS", w.className.toUpperCase()); if (!w.isChild) { parentCount++; if (w.processName != null && !w.processName.isEmpty()) { if (!processList.containsKey(w.pid+"")) processList.put(w.pid+"", w.hwndStr); win.setAttribute("process", w.processName); - win.setAttribute("PROCESS", w.processName.toUpperCase()); - win.setAttribute("pid", w.pid+""); + if (w.processName != null) + win.setAttribute("PROCESS", w.processName.toUpperCase()); } } + if (w.pid != 0) + win.setAttribute("pid", w.pid+""); //else //win.setAttribute("parent", w.parent + ""); // not really needed since child node is append to parent node @@ -159,6 +172,28 @@ public class WindowsEnumeratedXml implements Runnable{ return ""; } + public static Map EnumerateWindowsWithWpfBridge(String frameworkType) { + final Map infoList = new LinkedHashMap(); + WpfBridge wb = new WpfBridge(); + wb.setFrameworkId(frameworkType); + List parentIds = new ArrayList(Arrays.asList(wb.enumChildrenWindowIds(""))); + //System.out.println("enumChildrenWindowIds"); + String[] allIds = wb.enumDescendantWindowInfo("", WindowInfo.WPF_PROPERTY_LIST); + //System.out.println("enumDescendantWindowIds " + allIds.length); + for(String runtimeIdAndInfo : allIds) { + //System.out.println("getting window info for: " + runtimeIdAndInfo); + String onlyRuntimeId = runtimeIdAndInfo; + if (runtimeIdAndInfo.contains(",")) + onlyRuntimeId = runtimeIdAndInfo.substring(0, runtimeIdAndInfo.indexOf(",")); + //System.out.println("is parent? " + onlyRuntimeId); + if (parentIds.contains(onlyRuntimeId)) //is Parent? + infoList.put(onlyRuntimeId, new WindowInfo(runtimeIdAndInfo, false)); + else// must be child + infoList.put(onlyRuntimeId, new WindowInfo(runtimeIdAndInfo, true)); + } + return infoList; + } + public static String escapeXmlAttributeValue(String unescapedStr) { String result = ""; try { diff --git a/src/org/synthuse/WpfBridge.java b/src/org/synthuse/WpfBridge.java index 75c65ee..769e236 100644 --- a/src/org/synthuse/WpfBridge.java +++ b/src/org/synthuse/WpfBridge.java @@ -69,22 +69,24 @@ public class WpfBridge { System.load(temp.getAbsolutePath()); } - native void SetFrameworkId(String propertyValue); //default is WPF, but also accepts Silverlight, Win32 + native void setFrameworkId(String propertyValue); //default is WPF, but also accepts Silverlight, Win32 //Descendants will walk the full tree of windows, NOT just one level of children - native int CountDescendantWindows(); - native int CountDescendantWindows(String runtimeIdValue); + native int countDescendantWindows(); + native int countDescendantWindows(String runtimeIdValue); - native int CountChildrenWindows(); - native int CountChildrenWindows(String runtimeIdValue); + native int countChildrenWindows(); + native int countChildrenWindows(String runtimeIdValue); - native String[] EnumChildrenWindowIds(String runtimeIdValue); //if runtimeIdValue is null will start at desktop - native String[] EnumDescendantWindowIds(String runtimeIdValue); //if runtimeIdValue is null will start at desktop - native String[] EnumDescendantWindowIds(long processId); - native String[] EnumDescendantWindowIdsFromHandle(long windowHandle); + native String[] enumChildrenWindowIds(String runtimeIdValue); //if runtimeIdValue is null will start at desktop + native String[] enumDescendantWindowIds(String runtimeIdValue); //if runtimeIdValue is null will start at desktop + native String[] enumDescendantWindowIds(long processId); + native String[] enumDescendantWindowIdsFromHandle(long windowHandle); //In all the above Enumerate methods will return a list of Runtime Ids for all related windows. + native String[] enumDescendantWindowInfo(String runtimeIdValue, String properties); //returns properties comma separated - native String GetProperty(String propertyName, String runtimeIdValue); - native String[] GetProperties(String runtimeIdValue); - native String[] GetPropertiesAndValues(String runtimeIdValue); + native String getParentRuntimeId(String runtimeIdValue); + native String getProperty(String propertyName, String runtimeIdValue); + native String[] getProperties(String runtimeIdValue); + native String[] getPropertiesAndValues(String runtimeIdValue); } diff --git a/synthuse.properties b/synthuse.properties index 9fea982..6bbd54a 100644 --- a/synthuse.properties +++ b/synthuse.properties @@ -1,6 +1,7 @@ # -#Thu Apr 03 22:00:23 EDT 2014 +#Sat Apr 05 17:18:52 EDT 2014 DEFAULT_PROP_FILENAME= urlList= xpathList= xpathHightlight=.*process\="([^"]*)".* +disableWpf=false