2010-11-12 30 views
1

J'ai une application héritée écrite en .Net. Aucune source disponible. Il utilise les scripts vb pour étendre sa logique interne via la gestion des événements. C'est donc un mélange de com et .net. J'ai utilisé l'application SpyUI et observé que l'interface utilisateur est écrite avec Windows Forms. Les contrôles sont intitulés dans le style .Net & il ressemble à Windows forme un (vC++ et vb UI semble complètement différent).WinForms: Form.FromHandle renvoie null pour le formulaire principal de processus pour le code chargé dans l'exécutable .net

Je souhaite étendre l'interface utilisateur de l'application en obtenant l'instance System.Windows.Forms.Form pour le formulaire principal et modifier l'arborescence des contrôles.

donc j'écrire le code dans le script vb qui crée mon objet com, quelque chose comme:

Set obj = CreateObject("MyUiExtender") 
obj.InjectIntoUi() 

J'essaie d'obtenir la poignée principale forme de l'objet de processus a été chargé et ce code fonctionne:

Process.GetCurrentProcess().MainWindowHandle; // a meaningfull value 
Process.GetCurrentProcess().MainWindowTitle; // the title of the application 

jusqu'à présent, si bon, mais ce qui suit ne fonctionne pas -> il retourne null

var mainForm = Control.FromHandle(Process.GetCurrentProcess().MainWindowHandle) 

Mon obje ct a été chargé dans l'exécutable et j'essaie d'obtenir une instance de formulaire pour le même processus. Je suppose que c'est une sorte de problème de limites d'applications. Mon code travail parfait si mon objet com est chargé dans l'application .net via

t = Type.GetTypeFromProgID("MyUiExtender") 
dynamic c = Activator.CreateInstance(t) 
c.InjectIntoUi(); 

Je suppose que l'utilisation des limites d'application des ruines VBS en quelque sorte ...

Est-il encore possible d'obtenir principale instance de formulaire de demande en tant instance de classe Windows.Forms.Form?

Répondre

1

Le problème est que Control.FromHandle ne fonctionne que pour le processus en cours. Si vous voulez obtenir la forme principale d'un autre processus .Net, vous devez injecter votre code dans un autre processus.

Il existe peu d'approches pour cela. Le plus commun consiste à utiliser CreateRemoteThread pour charger une DLL non managée dans un autre espace d'adressage de processus, puis charger l'assembly .NET. Pour le rendre possible, vous devez utiliser C++ géré.

Si vous êtes le débutant, je recommande d'utiliser la bibliothèque existante. Jetez un oeil au projet Hawkeye à CodePlex: http://hawkeye.codeplex.com/ Vous pouvez trouver une bibliothèque prête là.

Vous pouvez également jeter un oeil à http://smuxplugins.codeplex.com/ Ceci est encore un autre exemple de l'injection de code.