Ouvrir une Form aussi bien à partir d'une appli Console que d'une Windows Form [Résolu]

eTill 16 Messages postés jeudi 11 janvier 2007Date d'inscription 4 août 2008 Dernière intervention - 25 juil. 2008 à 17:42 - Dernière réponse : cs_eldim 961 Messages postés lundi 30 mai 2005Date d'inscription 21 août 2014 Dernière intervention
- 4 août 2008 à 17:32
Bonjour,
j'ai besoin de créer une classe dans une Dll qui peut ouvrir une Windows Form. Cette classe peut aussi bien être appelée d'une application en mode console que d'une Windows Form. Pour les besoins de l'exemple, nous appellerons cette classe 'CalledForm'.
Pour l'instant, voici les options autour desquelles j'ai prospecté:

1/ la Form est ouverte avec Application.Run(CalledForm):
   a. mode Console: il faut que CalledForm soit fermée pour que ce qui est envoyé à la console soit lu.
   b. mode Form: plein de problèmes, soit des exceptions, soit CalledForm s'affiche à la place de l'autre Form, etc.

2/ la Form est ouvert avec CalledForm.Show()
   a. mode Console: CalledForm s'ouvre, mais ne se dessine pas, et le curseur se met en sablier (la Form se bloque)
   b. mode Form: tout va bien. Ca semble bien la méthode idoine.

après investigation sur le net, j'ai mis en place une solution tierce, qui consiste à 'threader' l'appel à Application.Run, dont voici les bases:
public partial class CalledForm: Form  , ----
{                 , ----
        private Thread m_localThread = new Thread(Run);  , ----
        private static void Run(Object frm)  , ----
        {  , ----
            Application.EnableVisualStyles();  , ----
            Application.Run((Form)frm);  , ----
        }  , ----
        public void ThreadedShow()  , ----
        {  , ----
            if (!m_localThread.IsAlive)  , ----
                m_localThread.Start(this);  , ----
        }  , ----
 }
 
3/ dans ce cas là, si la Form est ouverte avec CalledForm.ThreadedShow()
   a. mode Console. Tout va bien. C'est clairement la méthode recommandée.
   b. mode Form: ça marche, mais ce n'est pas optimale (CalledForm est clairement plus lente) et elle n'est pas fermée quand on quitte l'appli principale.

Ma question est donc, comment puis-je, par programmation, savoir dans quel mode je suis, pour pouvoir appeler la bonne méthode (Show() ouThreadedShow()) ?

A savoir:
 j'ai essayé Application.OpenForms, qui s'avère peu fiable, on peut se trouver dans des cas ou ça renvoie 0 alors que des formes sont en construction.
 j'ai égalemet essayé GetStdHandle et GetConsoleModemais ce n'est pas plus fiable non plus.
Afficher la suite 

33 réponses

Répondre au sujet
cs_eldim 961 Messages postés lundi 30 mai 2005Date d'inscription 21 août 2014 Dernière intervention - 4 août 2008 à 17:32
+3
Utile
Merci de l'indication j'aurai jamais trouvé...

-- Y a autant de bugs dans un programme que de malles-façons dans une maison. Tout dépend de la taille --
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de cs_eldim
cs_eldim 961 Messages postés lundi 30 mai 2005Date d'inscription 21 août 2014 Dernière intervention - 30 juil. 2008 à 12:24
0
Utile
Bonjour,

je ne vois pas bien la subtilité... sur mes applis, que l'appelle se fasse sous DOS ou Windows les form s'affichent pareil...
sans passer par un intermédiaire... suffit d'avoir winodws form en référence et de commencer ton programme par un static void main

-- Pourquoi faire simple quand on peut faire compliquer --
Commenter la réponse de cs_eldim
eTill 16 Messages postés jeudi 11 janvier 2007Date d'inscription 4 août 2008 Dernière intervention - 30 juil. 2008 à 18:57
0
Utile
Bonjour eldim.
De mon côté, les Forms ne réagissent pas pareilles, justement, c'est bien là le problème.
J'ai essayé de décrire les problèmes que je rencontre, et pour quelles raisons.

Attention, il ne s'agit pas d'un appelle d'une même Application à partir de la console (écrire le chemin de l'exe dans une fenêtre .cmd) vs son appel GUI (double click sur l'icône ou autre). Là, effectivement, c'est simple.

Le problème survient quand deux appli qui ont un mode d'exécution différents (CUI vs GUI) s'appuient sur une même DLL avec Form. Quelle méthode cette Dll doit offrir à l'application appellante pour que la fenêtre s'ouvre proprement Application.Run(CalledForm) ? CalledForm.Show() ? CalledForm.ThreadedShow() ?

C'est effectivement compliqué, et je m'en serais bien passé...
Commenter la réponse de eTill
cs_eldim 961 Messages postés lundi 30 mai 2005Date d'inscription 21 août 2014 Dernière intervention - 31 juil. 2008 à 07:56
0
Utile
je dois être mal réveillé car j'ai aussi une appli (par contre en vb.net mais c'est pareil)dont le corps est dans une dll et qui est appelée de plusieurs façon y compris en DOS et windows et en mettant le show directement dans la dll et non dans l'application et j'ai aucun souci
j'appel juste une procedure de la dll qui fait elle même le show

-- Pourquoi faire simple quand on peut faire compliquer --
Commenter la réponse de cs_eldim
eTill 16 Messages postés jeudi 11 janvier 2007Date d'inscription 4 août 2008 Dernière intervention - 31 juil. 2008 à 10:24
0
Utile
Ce dont je parle est assez facilement reproduisible:
Créer une nouvelle solution
Créer un premier projet de type ClassLibrairy avec juste une Form nommée 'CalledForm' dedans.
C'est plus flagrant si la Form a au moins un contrôle dedans (un simple Label suffit).
Créer un deuxième projet de type ConsoleApplication, avec ce code dedans:

class
Program
{

   static
void Main(
string[] args)
   {
   
CalledForm calledForm =
new
CalledForm();
   calledForm.Show();

   //System.Windows.Forms.Application.Run(calledForm);
   Console.WriteLine(
"Ouvert!");

   Console.ReadKey(
false);
   }
}
Commenter la réponse de eTill
cs_eldim 961 Messages postés lundi 30 mai 2005Date d'inscription 21 août 2014 Dernière intervention - 31 juil. 2008 à 11:00
0
Utile
ben désolé chez moi ça marche nickel
juste que ton show serait mieux avec un showdialog... (mais bon c'est le ba-ba)

-- Pourquoi faire simple quand on peut faire compliquer --
Commenter la réponse de cs_eldim
eTill 16 Messages postés jeudi 11 janvier 2007Date d'inscription 4 août 2008 Dernière intervention - 31 juil. 2008 à 11:22
0
Utile
C'est bien un Show() que je veux faire.
Un ShowDialog() rend la fenêtre modale, à savoir que la fenêtre doit être fermée pour que le programme principal continue de tourner, ce qui n'est pas ce dont j'ai besoin.
Effectivement, avec un ShowDialog (ou Application.Run(CalledForm)) la form s'ouvre. Mais fenêtre et console ne peuvent interagir.
Et c'est de façon certaine ce que je ne veux pas dans le cas où le module appelant est une Form.

Tu trouveras description de pb similaire dans le sujet de discussions Windows Form depuis application appli Console
http://www.csharpfr.com/infomsg_WINDOWS-FORM-DEPUIS-APPLICATION-APPLI-CONSOLE_1083719.aspx
Commenter la réponse de eTill
cs_eldim 961 Messages postés lundi 30 mai 2005Date d'inscription 21 août 2014 Dernière intervention - 31 juil. 2008 à 11:34
0
Utile
dans ce cas il te faut passer par un thread différent
et dans le load de ta form tu rajout un threading.thread.sleep(1)




-- Pourquoi faire simple quand on peut faire compliquer --
Commenter la réponse de cs_eldim
eTill 16 Messages postés jeudi 11 janvier 2007Date d'inscription 4 août 2008 Dernière intervention - 31 juil. 2008 à 11:46
0
Utile
Oui,
d'où la mise en place du 'ThreadShow'.
Mais l'utiliser systématiquement n'est pas efficace, en tout cas il dessert mes besoins dans le cas où le module appelant possède une Form.
Voilà où j'en suis arrivé et pourquoi je poste ce sujet.

Sinon, à quoi servirait le Sleep(1)?
Commenter la réponse de eTill
cs_eldim 961 Messages postés lundi 30 mai 2005Date d'inscription 21 août 2014 Dernière intervention - 31 juil. 2008 à 12:05
0
Utile
je connais pas le threadshow
c'est juste que je l'aurais fait comme ça:
Threading.Thread TH=new threading.thread( AdresseDeTaProcQui lance ta form)
TH.Start

et dans ta proc qui lance ta form ou dans le load de ta form
le sleep qui rend la main à ta procedure dos (ce qui fait que tu as deux procedures en parallèle)

-- Pourquoi faire simple quand on peut faire compliquer --
Commenter la réponse de cs_eldim
cs_eldim 961 Messages postés lundi 30 mai 2005Date d'inscription 21 août 2014 Dernière intervention - 31 juil. 2008 à 12:10
0
Utile
oups j'avais pas fait gaffe
c'est là que j'aurai pas fait comme toi..
mais j'ai pas les neurones connectés ce matin

-- Pourquoi faire simple quand on peut faire compliquer --
Commenter la réponse de cs_eldim
cs_eldim 961 Messages postés lundi 30 mai 2005Date d'inscription 21 août 2014 Dernière intervention - 31 juil. 2008 à 12:12
0
Utile
tu peux toujours tester si ton appli dispose d'un mainwindowhandle pour savoir quel type d'ouverture utiliser

-- Pourquoi faire simple quand on peut faire compliquer --
Commenter la réponse de cs_eldim
eTill 16 Messages postés jeudi 11 janvier 2007Date d'inscription 4 août 2008 Dernière intervention - 31 juil. 2008 à 12:21
0
Utile
Je n'ai pas essayé directement avec MainWindowHandle, mais avec Application.OpenForms(). Malheureusement, ce n'est pas un test fiable, entre autre au moment des differentes initialisations, où les fenêtres ne sont pas toutes forcément ouvertes. Je soupçonne que le pb risque d'être le même, mais je vais essayer.
Commenter la réponse de eTill
eTill 16 Messages postés jeudi 11 janvier 2007Date d'inscription 4 août 2008 Dernière intervention - 31 juil. 2008 à 12:37
0
Utile
Une appli console me retourne un MainWindowHandle non nul, malheureusement.

static
void Main(
string[] args)
{
System.Diagnostics.
Process cp = System.Diagnostics.
Process.GetCurrentProcess();

IntPtr wh = cp.MainWindowHandle;
Console
.WriteLine(
wh.ToString());

Console.ReadKey(
false);

}
Commenter la réponse de eTill
cs_eldim 961 Messages postés lundi 30 mai 2005Date d'inscription 21 août 2014 Dernière intervention - 31 juil. 2008 à 13:50
0
Utile
c'est du bricolage mais tu peux essayer de vérifier si une référence à windowsform est présente avec ça
system.Reflection.Assembly.GetCallingAssembly.GetReferencedAssemblies

-- Pourquoi faire simple quand on peut faire compliquer --
Commenter la réponse de cs_eldim
eTill 16 Messages postés jeudi 11 janvier 2007Date d'inscription 4 août 2008 Dernière intervention - 31 juil. 2008 à 14:21
0
Utile
Hmm, c'est très risqué, car cette info est très peu représentative de la réalité.
Je peux imaginer d'ores et déjà plein de cas de figure où une référence à une WindowsForm existe mais où je suis dans le cas d'un appel 'Console'.
Encore moins fiable que Application.OpenForms().
J'aimerais trouver un jeu de tests totalement fiables.
Merci tout de même.
Commenter la réponse de eTill
cs_eldim 961 Messages postés lundi 30 mai 2005Date d'inscription 21 août 2014 Dernière intervention - 31 juil. 2008 à 14:30
0
Utile
essai de regarder du coté des flux
lorsque l'appli est en mode console les flux de sortie sont redirigé par une api (je ne sais plus laquelle)
le tout c'est de trouver comment j'ai pas trop de temps cet aprem... mais je vai chercher

-- Pourquoi faire simple quand on peut faire compliquer --
Commenter la réponse de cs_eldim
cs_eldim 961 Messages postés lundi 30 mai 2005Date d'inscription 21 août 2014 Dernière intervention - 31 juil. 2008 à 16:06
0
Utile
essai ça
Process.GetCurrentProcess.StartInfo.RedirectStandardOutput

-- Pourquoi faire simple quand on peut faire compliquer --
Commenter la réponse de cs_eldim
eTill 16 Messages postés jeudi 11 janvier 2007Date d'inscription 4 août 2008 Dernière intervention - 31 juil. 2008 à 17:17
0
Utile
Il me retourne false dans tous les cas...
Commenter la réponse de eTill
cs_eldim 961 Messages postés lundi 30 mai 2005Date d'inscription 21 août 2014 Dernière intervention - 31 juil. 2008 à 17:33
0
Utile
tu peux faire un truc pas très propre en attendant de trouver mieux
si ça ça plante : Process.GetCurrentProcess.StandardOutput

c'est que c'est pas du dos

-- Pourquoi faire simple quand on peut faire compliquer --
Commenter la réponse de cs_eldim

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.

Ouvrir une Form aussi bien à partir d'une appli Console que d'une Windows Form - page 2