I used reflection a couple of time to get values from the screen element, call methods etc. But now I am working on an application called Avaya, as this is not a really famous application I cannot find any help. My goal is to get some fields from this application, using automation UI library is not possible as the fields are not visible with any UI inspector like Spy++ and etc..
The only way to solve my issue is to develop a small code that interrogate the application and the result will be what is available for me, each method, each value, etc..
Then I have to start from the interface, I went to regedit and I got a list of 20 interfaces, then I start my code looping at these interfaces to get all classes and after that loop to each methods and proprieties, is that correct? Then I start my code getting a type and creating and instance..:
try {
foreach (string ThisInterface in ArrayInterfaces)
{
ThisInterfacee = ThisInterface;
//Call this interface
Type AvayaWorkspaceType = Type.GetTypeFromProgID(ThisInterface, true);
//Create Instance of this
object workspace = Activator.CreateInstance(AvayaWorkspaceType);
Any ideas of how to continues??
Thanks a lot any suggestion is welcome :)
I use reflection and C#
Solution: Reason why I am not able is because Reflection will only work with .NET base application, for other applications you should use IUIautomation or user32.dll
Related
Having spent the last few days reading everything I can find about C# reflection on COM objects, trying many experiments in code, and analyzing sample code to try and improve my understanding, I am now forced to admit that I just don't know enough, so I am requesting help from the Community.
I need to be able to access and update the properties of a late bound COM object that is wrapped as System._COM Object.
I tried all the standard refection stuff without success and I looked through using IDispatch, but I'm not comfortable with using the pointers involved, so I'm hoping I have missed something pretty simple in the normal interface. I found papers on MSDN that DO show how to do what I need, but all the examples are in C++ and it is over my head.
It would be really helpful if someone could explain why the following simple C# code just doesn't work as expected:
try
{
// late binding:
// localCB is a COM object (System._COMObject) created by Activator.CreateInstance() from
// the ProgID of a registered COM .DLL.
//
// The original .DLL has a string PROPERTY called
// "TESTEXTERNAL1". localCB has an IDispatch Interface. The original COM .DLL has a separate Typelib,
// and, although I did not register the typelib separately, I can see from OLEView on the COM object
// that the GUID for the typelib is included in it.
// Here's the code that is puzzling me...
var vv = localCB.GetType().InvokeMember("TESTEXTERNAL1", BindingFlags.GetProperty,
null, localCB, null);
string rt = vv.ToString();
// works exactly as expected and returns the value of TESTEXTERNAL1 - OK.
// now try and update the SAME PROPERTY, on the SAME COM object...
Parameters = new Object[1];
Parameters[0] = "Hello, World!";
localCB.GetType().InvokeMember("TESTEXTERNAL1", BindingFlags.SetProperty,
null, localCB, Parameters);
// throws an (inner) exception: HRESULT 0x8002003 DISP_E_MEMBERNOTFOUND !!!
}
catch (Exception xa)
{
string xam = xa.Message;
}
Is it unreasonable to expect an object that has already found and provided a property, to be able to update the same property? Is there some "alternative update" strategy that I am not aware of?
Many thanks for any help,
Pete.
UPDATE:
in response to Jon's request, here are snippets of the OleView:
(I had to use images because Oleview would not let me cut & paste, sorry...)
OleView of the COM .DLL
OLEView typelib view
Jon, I think you have correctly identified that the problem is with a setter method. The DLL is written in Fujitsu COBOL and provides an "under the covers" GET and SET for fields identified as PROPERTY. Accessing the COM component from C# or COBOL, it works fine, but, as you can see, it doesn't work when I try and access it for SET with reflection. Because I am unfamiliar with using reflection I was doubtful whether I had the syntax right, so I tried to make the SET as close as possible to the GET. I think I will need to generate my own SET methods (for each PROPERTY) into the COBOL and then change my "BindingFlags.SetProperty" to be "BindingFlags.InvokeMember". (I did the homework on BindingFlags and found that if you specify "SetProperty" it automatically implies the other 2 flags you mentioned.)
I think the key to it all is in recognizing that the problem is with the Fujitsu *COM Class SET, and it took your experienced eye to see that. Many thanks. If you have any other comments after seeing the OLEView, or can suggest any alternative approach in order to get the properties set, I'd be very interested. (I'm not looking forward to having to generate SETter methods for every property; it smacks of brute force... :-))
Thanks again,
Pete.
Hans was correct. The problem was with the setter method. I have written code to generate a setter for each of the properties, back in the original COBOL COM component. It wasn't as tedious or ugly as I thought it would be (about 7 lines of COBOL for each PROPERTY) and it is all working very well now. Many thanks to the community and particularly Hans Passant for support.
I'm currently tinkering around with Workflow Foundation. I have an activity which contains the argument:
System.Activities.InArgument<double> Temperature
However, I want to get the value of this argument in my activity in order to do some validation with it (and also set properties in my activity based on this argument). I understand there is a Get method which takes an ActivityContext, so the actual value would be known at runtime. My question is, how can I get the ActivityContext, or is there a better way?
Note: I'm hosting the WorkflowDesigner in my app which I drop my activities on. So Activity1 contains a property "Temperature", and this is passed into Activity2 as an InArgument. I then validate Activity2, but so far can't get the ActivityContext. I don't need it at execution time, but at design time.
Thanks in advance.
It sounds like you are wanting to use dependency properties like they had in WF3 to tie the output of activity1 to the input of activity2 at design time. Is that correct?
In the WF4 re-write they ripped out all of the dependency property stuff that allowed this.
Speaking specifically to getting access to the ActivityContext item at design time: I don't believe that is going to be possible. The AC object is created at the time of activity execution. It is what allows one instance of an activity to be executed multiple times (each iteration of a loop has a separate AC object associated with it because the AC object is created during runtime).
Here is a good Microsoft blog article describing the difference between WF3 and WF4 activity run-time execution. I think it might help clarify what you are wanting to do and how to approach the problem.
Can you pass the ActivityContext to Activity2 as an argument?
What about using Custom Activity Designers?
I come from a PHP background and have used Wordpress quite a lot, I love how their plugin architecture works and the ability to hook events to event names. One of the best parts I like about it is being able to *add_filter()* to any database value just before it gets shown to the end user. My question is multi-part on how to replicate the whole plugin architecture in a C#.NET environment?
Part 1:
To create plug-ins I have researched the MEF framework would probably be the best (Managed Extensibility Framework -http://mef.codeplex.com/). This is designed specifically to take the grunt work out by giving you the ability to monitor directories for new plug-ins, tracking dependencies and other normal things. MEF ships with .NET 3.5+
Part 2
Hooking events? I can't seem to find much information about replicating a global channel based event system. From what I have upto yet I need a publish/subscribe pattern (which isn't that hard to make as you just create some concrete objects and give them events). The hard part is giving each event a 'channel' name and for all the events in the whole system to be part of a global collection (Mediator pattern).
To replicate: (http://codex.wordpress.org/Function_Reference/add_filter)
Example 1
// Add's my button to the end of the content
add_filter('the_content', 'my_plugin_button');
function my_plugin_button( $content ) {
// Add's my button to the end of the content
return $content . "<a href='#'>My button</a>";
}
OR
Example 2
// Add a new admin menu item by hooking in
add_action('admin_menu', 'my_plugin_menu');
function my_plugin_menu() {
add_options_page('My Plugin Options', 'My Plugin', 'manage_options', 'my-unique-identifier', 'my_plugin_options');
}
I hope your all with me upto yet? I have managed to replicate the functionality I need in Javascript and even jQuery has their .on() event function... same thing but channel or list based...
My 2 examples:
http://jsfiddle.net/AaronLayton/U3ucS/53/
http://jsfiddle.net/AaronLayton/eyNre/33/
Can anyone point me in the correct direction or is this the totaly wrong approach for c#?
I think NServiceBus can help you a lot with these issues. Udi Dahan which is the author of NServiceBus has also written a lot of articles about Domain Event pattern, which is a publish/subscribe mechanism.
Know it's been a long time since you posted this and you probably built something already. However I have been thinking about something like this myself. There are 2 options - really forget WordPress and try and build something much cleaner - it's a mess at the bottom of WordPress' code :D
Or this:
function the_content()
{
var result = get_the_content();
// do other stuff...if you want to.
execute_filters(ref result);
execute_actions(ref result);
return result;
}
function execute_filters(ref string result, string action_name)
{
var filters = get_pre_filters(action_name);
filters.ForEach(filter =>
{
/// somehow call the method name in filter. PHP is generally global. C# namespaced,
/// so you would need to think about that.
}
}
function execute_actions(ref string result, string action_name)
{
/// and so on....
}
When building something to mimic WordPress, you need to remember many of the issues of WordPress' plugin architecture (in my personal opinion)... It seems to want to run every plugin near enough on every page even if that page has nothing to do with that plugin. I onced installed a plugin that added 60 database queries to each page call, and it wasn't used.
Try and think smart about it when you are building it. Try and add a way to only have the plugins that are going to get used on the page/post of your new setup to be run e.g. in your database have a "Plugins" field on the post/page object with a list of plugins allowed to run on that page. That way you won't need to check all the plugins each time to see if it wants to run.
Anyways. Hope you got something working.
I have a dll file, and I took an object from it and called the functions inside this dll by the object, like this:
Command testClass = (Command)assembly.CreateInstance(creatObject);
testClass.Execute();
I used reflection for some reason. So I need to use invoke function & set values for variables, then calling the basic function Execute.
Previously I wrote the following:
object returnValue = objectType.GetMethod("setValues").Invoke(classObject, arguments);
testClass.Execute();
but it wasn't useful for me.
I used the following:
object returnValue = objectType.GetMethod("setValues").Invoke(classObject, arguments);
object returnValue1 = objectType.GetMethod("Execute").Invoke(classObject, null);
I just want to ask if this is right, to calling the execute in this way, and by the way it works!
Calling methods using Reflection the way you use it is "okay" as long as you know what you're doing. There are quite a few things to consider when using Reflection:
It is unsafe - you can very easily make a mistake - if you change the method name, you won't be notified by the compiler and you'll discover that at runtime
It is slow - Reflection is simply inefficient - calling a method is slower by orders of magnitude.
If you need to do this only rarely, then it may be fine. However, your initial approach using a shared base class Command appears to be a much better idea to me. Could you clarify why you decided to use Reflection, so that we can (perhaps) suggest a better way?
If you need dynamic invocation, you could also consider using C# 4.0 dynamic, which does all this stuff behind the scene for you and is more efficient than simple Reflection. However, you should still have a very good reason for doing this.
It's not right, why do you use Reflection, provide a common interface and call the method directly. If you don't know why you use reflection then it's wrong :)
If you are implementing a extensible system, perhaps MEF would be better?
Thanks for your answers, sure i know why i used Reflection.
Because i need to set the values for a function setValues(i, j..etc) in run time, and these parameters and their names are different from dll to another.
then i have to invoke this function with its current values, & finally run another function named Execute() with the same current values, which could be changed from execute to another for the program!
so when i just used:
object returnValue = objectType.GetMethod("setValues").Invoke(classObject, arguments);
testClass.Execute();
the execute didnt work with the run time values which been entered.
But by this :
object returnValue = objectType.GetMethod("setValues").Invoke(classObject, arguments);
object returnValue1 = objectType.GetMethod("Execute").Invoke(classObject, null);
it works.
So i just want to be sure, that my work is right and not only suitable for my case!
I have a windows form with a listview control. I have a selectedIndex changed event where i am performing some action. Through reflection I am trying to set the value of the list view.
But the event is not getting fired. Any help will be helpfull.
Edit
The event looks like
private void LV1_SelectedIndexChanged(object sender, EventArgs e)
{
if (LV1.SelectedItems.Count>0)
{
if (LV1.SelectedItems[0].Text.ToString() == "testing")
{
// Do some work.
}
}
}
I am using relection in another project and changing the selected item as follows
Assembly a = Assembly.LoadFrom(exePath);
Type formType = a.GetType(formName);
testForm = (Form)a.CreateInstance(formType.FullName);
if (testForm != null)
{
Type t1 = testForm.GetType();
FieldInfo fi = t1.GetField(controlName, flags);
object ctrl = fi.GetValue(testForm);
ListView l1 = (ListView)ctrl;
l1.Items[0].Selected = true;
}
Automating another application is fun howver not a trivial task. There's a few options but I guess most of them is out of scope for you. One would be to programatically take over the mouse and keyboard and trough those channels manage the program. Another way would be to manipulate memory, As I said neither are trivial to implement and very easily broken if the aplpication is updated.
I would suggest instead of trying to automate the application to look for infliction points. Are there any service endpoints you could automate and achieve the same result? any API or dll's used by the application you could use instead?
If you really have to automate the application there do exist several frameworks for doing that (usually build for testing purposes). The only one I can think off right now is made by Assima as is ment for training purposes.
I think your problem is here:
testForm = (Form)a.CreateInstance(formType.FullName);
You are creating a new instance of the form. I'm assuming your main project is an exe that runs an shows the form. Your second project is then another exe that runs and wants to change the selected item. By creating a new instance of the form you will be changing the selected item on the new form, not the old one.
What you need to do is somehow pass the form object over to the secondary project. possibly some static method that gets a singleton instance of the form maybe.
I'm still not entirely sure why you are using reflection, you could just give the second project a reference to the first.
The first question I'd ask is: why are you using reflection here? Just set the value through the public API. If you are messing underneath the public API, then yes: it is entirely possible that some events won't get fired.
Perhaps if you could show us exactly how you are doing this?