Adding WpfBridge for automation of WPF and Silverlight

WpfBridge allows java to access .net 4 UI Automation libraries.  This
library enables Synthuse to access and automation WPF and Silverlight
apps.
This commit is contained in:
Edward Jakubowski
2014-04-03 22:29:36 -04:00
parent 2e1723f66e
commit d92f85e1b8
26 changed files with 1023 additions and 4 deletions

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<classpath> <classpath>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="native/WpfBridge/bin"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="lib" path="lib/jna-3.4.0.jar"/> <classpathentry kind="lib" path="lib/jna-3.4.0.jar"/>
<classpathentry kind="lib" path="lib/platform-3.4.0.jar"/> <classpathentry kind="lib" path="lib/platform-3.4.0.jar"/>

3
.gitignore vendored
View File

@@ -3,3 +3,6 @@ build/
lib/ lib/
dist/ dist/
synthuse.properties synthuse.properties
native/WpfBridge/x64
native/WpfBridge/release
!native/WpfBridge/bin

View File

@@ -39,7 +39,7 @@
<target name="compile" depends="init" description="compile the source including jars from lib directory" > <target name="compile" depends="init" description="compile the source including jars from lib directory" >
<!-- Compile the java code from ${src} into ${build} --> <!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}" includeantruntime="false"> <javac srcdir="${src}" destdir="${build}" includeantruntime="false" source="1.6" target="1.6">
<classpath> <classpath>
<pathelement path="${classpath}"/> <pathelement path="${classpath}"/>
<fileset dir="${lib}"> <fileset dir="${lib}">
@@ -58,6 +58,9 @@
<fileset dir="${src}"> <!-- includes images --> <fileset dir="${src}"> <!-- includes images -->
<include name="**/*.png" /> <include name="**/*.png" />
</fileset> </fileset>
<fileset dir="native/WpfBridge/bin"> <!-- includes native jni dlls -->
<include name="**/*.dll" />
</fileset>
<manifest> <manifest>
<attribute name="Main-Class" value="${main.class}"/> <attribute name="Main-Class" value="${main.class}"/>
<attribute name="Class-Path" value="${mf.classpath}"/> <attribute name="Class-Path" value="${mf.classpath}"/>

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski7@gmail.com
*/
#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("WpfBridge")];
[assembly:AssemblyDescriptionAttribute("")];
[assembly:AssemblyConfigurationAttribute("")];
[assembly:AssemblyCompanyAttribute("Synthuse")];
[assembly:AssemblyProductAttribute("WpfBridge")];
[assembly:AssemblyCopyrightAttribute("Copyright (c) Synthuse 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,10 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski7@gmail.com
*/
#include "StdAfx.h"
#include "Global.h"
#include "WpfAutomation.h"

20
native/WpfBridge/Global.h Normal file
View File

@@ -0,0 +1,20 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski7@gmail.com
*/
#pragma once
#include "WpfAutomation.h"
namespace Globals
{
using namespace System;
public ref class Global
{
public:
static WpfAutomation ^WPF_AUTO = gcnew WpfAutomation();
};
}

View File

@@ -0,0 +1,9 @@
========================================================================
DYNAMIC LINK LIBRARY : WpfBridge 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.

View File

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

View File

@@ -0,0 +1,7 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently
#pragma once

View File

@@ -0,0 +1,187 @@
/*
* 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;
}
void WpfAutomation::setFrameworkId(System::String ^propertyValue)
{
this->frameworkId = propertyValue;
}
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)
{
array<System::Int32> ^idArray = this->convertRuntimeIdString(runtimeIdValue);
Condition ^pcFramework = gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId);
Condition ^pcRunId = gcnew PropertyCondition(AutomationElement::RuntimeIdProperty, idArray);
Condition ^frameworkAndRuntimeId = gcnew AndCondition(pcFramework, 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)
{
System::Object ^currentVal = child->GetCurrentPropertyValue(AutomationElement::RuntimeIdProperty);
if (currentVal != nullptr)
{
array<System::Int32> ^idArray = (array<System::Int32> ^)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]);
}
++count;
}
return idStrArray;
}
//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, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId));
System::Int32 result = aec->Count;
//delete aec;
return result;
}
System::Int32 WpfAutomation::countDescendantWindows(System::String ^runtimeIdValue)
{
AutomationElement ^parent = findAutomationElementById(runtimeIdValue);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId));
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, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId));
System::Int32 result = aec->Count;
//delete aec;
return result;
}
System::Int32 WpfAutomation::countChildrenWindows(System::String ^runtimeIdValue)
{
AutomationElement ^parent = findAutomationElementById(runtimeIdValue);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Children, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId));
System::Int32 result = aec->Count;
//delete aec;
//delete frameworkAndRuntimeId;
return result;
}
array<System::String ^> ^ WpfAutomation::enumChildrenWindowIds(System::String ^runtimeIdValue)
{
AutomationElement ^parent = findAutomationElementById(runtimeIdValue);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Children, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId));
return getRuntimeIdsFromCollection(aec);
}
array<System::String ^> ^ WpfAutomation::enumDescendantWindowIds(System::String ^runtimeIdValue)
{
AutomationElement ^parent = findAutomationElementById(runtimeIdValue);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId));
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, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId));
return getRuntimeIdsFromCollection(aec);
}
array<System::String ^> ^ WpfAutomation::EnumDescendantWindowIdsFromHandle(System::IntPtr windowHandle)
{
//AutomationElement test = AutomationElement.FromHandle(new System.IntPtr(123123));
AutomationElement ^parent = AutomationElement::FromHandle(windowHandle);
AutomationElementCollection ^aec = parent->FindAll(TreeScope::Descendants, gcnew PropertyCondition(AutomationElement::FrameworkIdProperty, this->frameworkId));
return getRuntimeIdsFromCollection(aec);
}
System::String ^ WpfAutomation::getProperty(System::String ^propertyName, System::String ^runtimeIdValue)
{
AutomationElement ^parent = findAutomationElementById(runtimeIdValue);
//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);
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);
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

@@ -0,0 +1,39 @@
/*
* 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
//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);
array<System::String ^> ^ EnumDescendantWindowIdsFromHandle(System::IntPtr windowHandle);
//In all the above Enumerate methods will return a list of Runtime Ids for all related windows.
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);
array<System::String ^> ^ getRuntimeIdsFromCollection(System::Windows::Automation::AutomationElementCollection ^collection);
static System::String ^DEFAULT_FRAMEWORK = L"WPF";
System::String ^frameworkId;
};

View File

@@ -0,0 +1,181 @@
<?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>{3141812E-36D5-4E7C-A388-EFED9AE250A5}</ProjectGuid>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<Keyword>ManagedCProj</Keyword>
<RootNamespace>WpfBridge</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</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>
<IncludePath>$(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(IncludePath)</IncludePath>
</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>
<PostBuildEvent>
<Command>mkdir "$(ProjectDir)bin"
copy /Y "$(TargetPath)" "$(ProjectDir)bin\wpfbridge$(PlatformArchitecture)$(TargetExt)"
</Command>
</PostBuildEvent>
</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>
<PostBuildEvent>
<Command>mkdir "$(ProjectDir)bin"
copy /Y "$(TargetPath)" "$(ProjectDir)bin\wpfbridge$(PlatformArchitecture)$(TargetExt)"
</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="UIAutomationClient" />
<Reference Include="UIAutomationProvider" />
<Reference Include="UIAutomationTypes" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Global.h" />
<ClInclude Include="org_synthuse_WpfBridge.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="Stdafx.h" />
<ClInclude Include="WpfAutomation.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp" />
<ClCompile Include="Global.cpp" />
<ClCompile Include="org_synthuse_WpfBridge.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" />
</ItemGroup>
<ItemGroup>
<None Include="app.ico" />
<None Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="app.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,62 @@
<?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>
<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">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Global.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<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">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Global.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="ReadMe.txt" />
<None Include="app.ico">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="app.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</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>

BIN
native/WpfBridge/app.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
native/WpfBridge/app.rc Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,5 @@
%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 %*
pause

View File

@@ -0,0 +1,230 @@
/*
* 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: 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));
//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));
//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);
//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: EnumDescendantWindowIdsFromHandle
* Signature: (J)[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_org_synthuse_WpfBridge_EnumDescendantWindowIdsFromHandle(JNIEnv *env, jobject obj, jlong jwindowHandle)
{
array<System::String ^> ^mchildrenIds = Global::WPF_AUTO->EnumDescendantWindowIdsFromHandle(System::IntPtr(jwindowHandle));
//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: 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));
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));
//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));
//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

@@ -0,0 +1,115 @@
/*
* 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 <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: 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: EnumDescendantWindowIdsFromHandle
* Signature: (J)[Ljava/lang/String;
*/
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;
*/
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

View File

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

View File

@@ -2,7 +2,7 @@
* Copyright 2014, Synthuse.org * Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License. * Released under the Apache Version 2.0 License.
* *
* last modified by ejakubowski * last modified by ejakubowski7@gmail.com
*/ */
package org.synthuse; package org.synthuse;

View File

@@ -2,7 +2,7 @@
* Copyright 2014, Synthuse.org * Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License. * Released under the Apache Version 2.0 License.
* *
* last modified by ejakubowski * last modified by ejakubowski7@gmail.com
*/ */
package org.synthuse; package org.synthuse;

View File

@@ -0,0 +1,90 @@
/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski7@gmail.com
*/
package org.synthuse;
import java.io.*;
public class WpfBridge {
static
{
String archDataModel = System.getProperty("sun.arch.data.model");//32 or 64 bit
//System.loadLibrary("native/WpfBridge" + archDataModel); // WpfBridge32.dll (Windows) or WpfBridge32.so (Unixes)
loadNativeLibraryFromJar("/wpfbridge" + archDataModel + ".dll");
}
public static void loadNativeLibraryFromJar(String path) {
// Obtain filename from path
String[] parts = path.split("/");
String filename = (parts.length > 1) ? parts[parts.length - 1] : null;
// Split filename to prexif and suffix (extension)
String prefix = "";
String suffix = null;
if (filename != null) {
parts = filename.split("\\.", 2);
prefix = parts[0];
suffix = (parts.length > 1) ? "."+parts[parts.length - 1] : null;
}
File temp = null;
try {
// Prepare temporary file
temp = File.createTempFile(prefix, suffix);
temp.deleteOnExit();
} catch(Exception e) {
e.printStackTrace();
}
if (!temp.exists()) { //some reason the temp file wasn't create so abort
System.out.println("File " + temp.getAbsolutePath() + " does not exist.");
return;
}
// Prepare buffer for data copying
byte[] buffer = new byte[1024];
int readBytes;
// Open and check input stream
InputStream is = WpfBridge.class.getResourceAsStream(path);
if (is == null) { //check if valid
System.out.println("File " + path + " was not found inside JAR.");
return;
}
// Open output stream and copy data between source file in JAR and the temporary file
OutputStream os = null;
try {
os = new FileOutputStream(temp);
while ((readBytes = is.read(buffer)) != -1) {
os.write(buffer, 0, readBytes);
}
os.close();
is.close();
} catch(Exception e) {
e.printStackTrace();
}
// Finally, load the library
System.load(temp.getAbsolutePath());
}
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 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);
//In all the above Enumerate methods will return a list of Runtime Ids for all related windows.
native String GetProperty(String propertyName, String runtimeIdValue);
native String[] GetProperties(String runtimeIdValue);
native String[] GetPropertiesAndValues(String runtimeIdValue);
}

View File

@@ -1,5 +1,5 @@
# #
#Tue Mar 25 12:56:37 EDT 2014 #Thu Apr 03 22:00:23 EDT 2014
DEFAULT_PROP_FILENAME= DEFAULT_PROP_FILENAME=
urlList= urlList=
xpathList= xpathList=