[C#] Form show't te laat.

Pagina: 1
Acties:

  • Equator
  • Registratie: April 2001
  • Laatst online: 10:00

Equator

Crew Council

🦺#Rodekruis #whisky #barista

Topicstarter
Ik start een executable (gemaakt in C#) welke een textfile uitleest.
De regels in die textfile zijn ofwel commando's in een bepaalde format, ofwel zogenoemde headers.

Een header wordt gestripped van zijn header chars en zou weggeschreven moeten worden in een textveld. (textbox1, multiline, vertical scrollbar)
Een commando wordt als een argument gebruikt voor een new System.Diagnostics.Process.
Dit process start een vbs bestand af, en wacht totdat hij klaar is.

Het probleem zit hem in het feit dat het form pas weer wordt gegeven als alle commando's zijn gestart. Op dat moment staan alle headers wel keurig in het textveld..

Het zou iets moeten worden dat bepaalde inlogtaken kan doen. Het is puur spielerij verder.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
private void StartLogon()
        {
            string TextFile = @"C:\\test.txt";
            // Open file
            try // Check if File exists
            {
                if (File.Exists(TextFile))
                {
                    try // Try to open the file
                    {
                        using (StreamReader sr = new StreamReader(TextFile.ToString()))
                        {
                            string line;
                            while ((line = sr.ReadLine()) != null)
                            {
                                if (line.StartsWith("[")) //Line is a header.
                                {
                                    trim(line);
                                    if(trimmedline == "END")
                                    {
                                        this.Close();
                                    }
                                    else
                                    {
                                        this.textBox1.AppendText(trimmedline + "\r\n");
                                    }
                                }
                                else
                                { // line is not a header, but a command.
                                    System.Diagnostics.Process proc = new System.Diagnostics.Process();
                                    proc.EnableRaisingEvents = false;
                                    proc.StartInfo.FileName="c:\\logon.vbs";
                                    proc.StartInfo.Arguments=line;
                                    proc.Start();
                                    proc.WaitForExit();
                                }

                            }
                        }
                    }
                    catch(IOException ioe)
                    {
                        MessageBox.Show(ioe.Message);
                    }
                    catch(Exception e)
                    {
                        MessageBox.Show(e.Message);
                    }
                    // File sluiten hoeft niet door using..
                } //close for if statement
                else
                {
                    MessageBox.Show("File does not exist");
                }
            }
            catch(IOException ioe)
            {
                MessageBox.Show(ioe.Message);
            }
        }

void trim verwijderd de blokhaken om de header regel.. (Ik wil nog een keer met regex gaan spelen..)

Overigens moet de inputtextfile en de naam/locatie van het script straks als argument aan het programma worden meegegeven.

Weet iemand een mogelijke oplossing voor het probleem dat het form zich pas laat zien als alle commando's zijn afgelopen :?

Ik heb de proc.WaitForExit(); al enkele waardes gegeven (in miliseconden) maar zelfs bij 3 seconden laat hij niet het form zien eerdat hij alle commando's heeft door lopen. Hij wacht wel keurig 3 seconden tussen elk commando.

Is er misschien een handigere manier van shell commando's aftrappen :?

[ Voor 3% gewijzigd door Equator op 22-02-2005 14:16 ]


  • sig69
  • Registratie: Mei 2002
  • Nu online
Waar wordt "StartLogon" aangeroepen?

Roomba E5 te koop


  • whoami
  • Registratie: December 2000
  • Laatst online: 10:24
Ik zou m'n form tonen, de commando's uitvoeren op een aparte thread, en die de dingen laten loggen naar mijn form.

https://fgheysels.github.io/


  • stp_4
  • Registratie: Maart 2003
  • Laatst online: 30-04 19:47
wanneer/waar roep je StartLogon() aan dan?

[ Voor 8% gewijzigd door stp_4 op 22-02-2005 14:21 ]

stp - PSN ID: stp_4


  • Equator
  • Registratie: April 2001
  • Laatst online: 10:00

Equator

Crew Council

🦺#Rodekruis #whisky #barista

Topicstarter
StartLogon() wordt aangeroepen in public frmLogon() Direct na InitializeComponent();

  • whoami
  • Registratie: December 2000
  • Laatst online: 10:24
CyberJ schreef op dinsdag 22 februari 2005 @ 14:25:
StartLogon() wordt aangeroepen in public frmLogon() Direct na InitializeComponent();
Tja, je applicatie gaat dus eerst die StartLogon method gaan aanroepen, en pas als die method gedaan heeft, kan hij verder gaan met het tonen van je form.
Je StartLogon neemt de volledige applicatie in beslag; daarom dus dat ik die processen in een andere thread zou opstarten, en de voortgang van die thread zou laten loggen op m'n form.

Zoiets:

code:
1
2
3
4
5
6
7
8
9
frmLogon()
{
   // bla...

   // Start hier de taak...
   MyTask c = new MyTask();
    c.OnLogInformation += new EventHandler (...);
   c.Start();
}


MyTask is hier dus een class die hetgeen jij in die startlogon method hebt staan, uitvoert, maar dan op een andere thread.
OnLogInformation is een event dat je declareert in die class, en die je triggert iedere keer dat je informatie moet gaan loggen.

Zie ook hier:
[rml]whoami in "[ C#] button.Show() vanuit anderen Thread"[/rml]

[ Voor 5% gewijzigd door whoami op 22-02-2005 14:36 ]

https://fgheysels.github.io/


  • Equator
  • Registratie: April 2001
  • Laatst online: 10:00

Equator

Crew Council

🦺#Rodekruis #whisky #barista

Topicstarter
Hmm, okay.. Ik begrijp wel enigzins waar je heen wilt, maar ik snap niet helemaal hoe dat met die EventHandlers loopt.
Ik heb een public EventHandler LogInfo in de Class gestoken. Maar geef ik daarmee info terug naar het mainform, of moet de handler het tetveld zelf aanpassen.. :?

Even MSDN nalopen.

  • sig69
  • Registratie: Mei 2002
  • Nu online
Kijk hier eens bijvoorbeeld

Roomba E5 te koop


  • whoami
  • Registratie: December 2000
  • Laatst online: 10:24
CyberJ schreef op dinsdag 22 februari 2005 @ 15:14:
Hmm, okay.. Ik begrijp wel enigzins waar je heen wilt, maar ik snap niet helemaal hoe dat met die EventHandlers loopt.
Ik heb een public EventHandler LogInfo in de Class gestoken. Maar geef ik daarmee info terug naar het mainform, of moet de handler het tetveld zelf aanpassen.. :?

Even MSDN nalopen.
Je hebt dus een event gemaakt waar je je een event-handler kunt aanhangen.
In je MainForm (dus, waar je je 'task' start), hang je een event-handler aan dat event:
code:
1
myTask.LogInfo += new EventHandler (OnLogInformation);

In je MainForm zal je dus een method moeten hebben die OnLogInformation heet, en die voldoet aan de signature die bepaalt wordt door 'eventhandler'.

In je 'Task' class, kan je nu die LogInfo event gaan triggeren als dat nodig is, bv, iedere keer dat een proces beindigd is. Iedere keer je die event triggered, wordt 'OnLogInformation' op je mainform uitgevoerd. In die OnLogInfomration method kan je dus code stoppen die de voortgang van je applicatie weergeeft.


Note: eigenlijk zou het netter zijn als je niet 'EventHandler' gebruikt, maar een eigen, custom delegate. Op die manier kan je zelf specifieren welke argumenten jouw method moet hebben.

Bv:
code:
1
delegate void LogInformationEventHandler( object sender, LogInfoEventArgs e );

Waarbij LogInfoEventArgs dan een custom class is, met als member bv een string met informatie die moet gelogd worden.

In je 'Task' class heb je dan bv deze code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Task
{
    public LogInformationEventHandler LogInfo;

    public void Start()
    {
         Thread t = new Thread (new ThreadStart ( PerformTasks ));
         t.Start();
    }

    private void PerformTasks()
    {
        for( int i = 0; i < 100; i++ )
        {
            OnLogInfo(this, new LogInfoEventArgs( "item " + i.ToString());
            Sleep(1000);
        }
    }
   
    private void OnLogInfo(object sender, LogInfoEventArgs e )
    {
          // Trigger hier de event op een thread - safe manier (zie de link naar m'n eerder topic).
    }
}


In je main form moet je dus nu nog een method koppelen aan die event:
code:
1
2
3
MyTask t = new MyTask();
t.LogInfo += new LogInfoEventHandler(OnBliep);
t.Start();

code:
1
2
3
4
private void OnBliep( object sender, LogInfoEventArgs e )
{
     listBox1.Items.Add (e.Information);
}


De code is niet compleet, gewoon uit de losse hand getyped, dus er zullen zeker wel foutjes in zitten, maar ik hoop dat je een beetje snapt wat ik bedoel. :P

https://fgheysels.github.io/


  • Equator
  • Registratie: April 2001
  • Laatst online: 10:00

Equator

Crew Council

🦺#Rodekruis #whisky #barista

Topicstarter
* Equator voelt zich dom..
Ik snap er de ballen van. Sorry whoami, dat ligt niet aan jou.

Ik probeer het zo makkelijk mogelijk te houden, dus laat die delegate maar even zitten.

Ik heb in mijn MainForm nu dit staan:
C#:
1
2
3
StartProc sp = new StartProc();
sp.LogInfo += new EventHandler(OnLogInformation(sMessage));
sp.StartProcedure();

HIerin is StartProc() dus de class.
LogInfo is de EventHandler in deze class
OnLogInformation is een void/method in het MainForm die een string als input verwacht en deze Append aan de text van het textveld.

Ik loop echter even spaak in de class.
C#:
1
2
3
4
public event EventHandler LogInfo
{
            
}

Ik kan even niet bedenken wat er hier nou in zou moeten staan 8)7
En nu zal er ergens verder op in de class (in de StartProcedure() dus dit event moeten worden aagesproken.

  • whoami
  • Registratie: December 2000
  • Laatst online: 10:24
In je eerste code snippit zie ik een fout op regel 2; je mag enkel een method naam meegeven als arugment aan die 'EventHandler':
code:
1
sp.LogInfo += new EventHandler(OnLogInformation);

Aangezien jouw LogInfo van het type EventHandler is (EventHandler is een delegate die reeds voorgedefinieerd is in .NET), moet die OnLogInformation method in je main form er zo uit zien:
code:
1
2
3
void OnLogInformation(object sender, EventArgs e )
{
}

[sub]Als je kijkt in de MSDN naar 'EventHandler' zal je zien dat deze zo gedefinieerd is:
code:
1
2
3
4
public delegate void EventHandler(
   object sender,
   EventArgs e
);

Deze delegate bepaalt dus hoe de signature van je method er moet uitzien.

Verder, om even op je vraag te antwoorden:
je class StartProc zou er zo moeten uitzien ongeveer:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class StartProc
{
     // Dit is je custom event.
     public event EventHandler LogInfo;

     // Dit is de method waarmee je je taak start
     public void Start()
     {
           // Start hier een nieuwe thread ...
     }
 
     // Dit is de method die de uiteindelijke stappen uitvoert, en die dus op de
     // andere thread draait.
     private void PerformTasks()
     {
          // In deze method 'invoke' je uw custom event (LogInfo), als dat nodig is
          // (bv, iedere keer je een process uitgevoerd hebt)
          // Dit doe je door onderstaande method aan te roepen
          OnLogInfo();
     }

      private void OnLogInfo()
       {
            // Voer hier de event-handler die je aan LogInfo gekoppeld hebt (als je dat gedaan hebt)
            // daarom eerst checken of LogInfo null is of niet.
            if( LogInfo != null )
            {
                // Je hebt dus een event-handler voor dit event.
                // Kijk nu of die op een Windows control wordt uitgevoerd, zoja, 
                // dan moet je hem mbhv 'Invoke' uitvoeren.
                System.Windows.Forms.Control  c = LogInfo.Target as System....Control;
                
                if( c == null )
                 {
                       LogInfo(this, EventArgs.Empty);
                 }
                 else
                 {
                         c.Invoke (LogInfo, ... .);
                 }
            }
       }
}


Echter, aangezien je nu 'EventHandler' gebruikt, heb je eigenlijk geen mogelijkheid om een parameter mee te geven aan je method die je aan LogInfo gekoppeld hebt waarin staat wat je precies moet loggen.
Dit kan je echter opvangen door in je StartProc class een variable te zetten met daarin de informatie die je wilt weergeven:
code:
1
2
3
4
5
6
7
private void PerformTasks()
{
      // Set information that must be shown in the log.
      LogInformation = "Bliep";
      // Invoke the log.
      OnLogInformation();
}


Nu kan je alsnog aan die informatie door, in de method die je in je MainForm hebt, en die je aan je custom event gekoppeld hebt dit te doen:
code:
1
2
3
4
5
6
7
8
9
private void OnLogInformation(object sender, EventArgs e)
{
      // Cast sender to an instance of StartProc.
      // Dit moet lukken, aangezien je in je StartProc class 'this' hebt meegegeven 
      // toen je jouw custom event triggerde.
     StartProc s = sender as StartProc;

     listBox1.Items.Add (s.LogInformation);
}

[ Voor 19% gewijzigd door whoami op 22-02-2005 16:31 ]

https://fgheysels.github.io/

Pagina: 1