2014-06-13 2 views
0

J'ai récemment commencé à coder en C# (en mai de cette année) et je trouve qu'il est préférable d'apprendre en travaillant avec du code. cette demande http://www.c-sharpcorner.com/UploadFile/satisharveti/ActiveApplicationWatcher01252007024921AM/ActiveApplicationWatcher.aspx. J'essaye de le recréer cependant le mien sauvera l'information dans une base de données de sql (nouveau à ceci aussi bien). J'ai cependant quelques problèmes de codage car il ne fait pas ce que je m'attends à faire. C'est le code principal que j'utilise.J'essaye de créer un observateur d'application de fenêtres?

private void GetTotalTimer() 
    { 
     //This gets the window that a user has open 
     SqlConnection RConn = new SqlConnection(@"server=ANDILE-PC;Initial Catalog=Log Records;Integrated Security=SSPI;"); 
     string Connstring = RConn.ToString(); 
     DateTime now = DateTime.Now; 
     IntPtr hwnd = APIFunc.getforegroundWindow(); 
     Int32 pid = APIFunc.GetWindowProcessID(hwnd); 
     Process p = Process.GetProcessById(pid); 
     appName = p.ProcessName; 
     string time = now.ToString(); 
     const int nChars = 256; 
     int handle = 0; 
     StringBuilder Buff = new StringBuilder(nChars); 
     handle = GetForegroundWindow(); 

     appltitle = APIFunc.ActiveApplTitle().Trim().Replace("\0", ""); 
     string queryString = "Select Top 1[Window Title] FROM [TimerLogs]"; 
     using (RConn) 
     { 
      using (SqlCommand command = RConn.CreateCommand()) 
      { 
       command.CommandText = queryString; 
       RConn.Open(); 
       using (SqlDataReader reader = command.ExecuteReader()) 
       { 
        while (reader.Read()) 
        { 
         string windowtitle = reader["Window Title"].ToString(); 
         if (appltitle != windowtitle) 
         { 

          endTime = DateTime.Now; 
          appduration = endTime.Subtract(startTime); 

          cmd = new SqlCommand("insert into [TimerLogs] values (@time,@appName,@appltitle,@Elapsed_Time,@userName)", RConn); 
          cmd.Parameters.AddWithValue("@time", time); 
          cmd.Parameters.AddWithValue("@appName", appName); 
          cmd.Parameters.AddWithValue("@appltitle", appltitle); 
          cmd.Parameters.AddWithValue("@Elapsed_Time", appduration.ToString()); 
          cmd.Parameters.AddWithValue("@userName", userName); 

          cmd.ExecuteNonQuery(); 
          RConn.Close(); 

         } 

        } 
        reader.Close(); 
       } 

       RConn.Close(); 
      } 

     } 
    } 

Malheureusement, ceci est le résultat. enter image description here il ne sauvegarde pas les données comme je le souhaite. Qu'est-ce que je fais de mal Je pensais qu'avec le lecteur sql, il vérifiait d'abord une valeur et ne sauvegardait que s'il ne correspondait pas, mais il enregistre s'il y a correspondance ou non.

mon lecteur retourne « {} System.Data.SqlClient.SqlDataReader » au lieu des données du tableau

+1

Vous devez apprendre à utiliser les fonctionnalités de débogage de votre IDE. Définir un point d'arrêt, puis parcourir le code ligne par ligne et voir ce qu'il fait. – mason

+1

votre if (appltitle! = Lecteur.ToString()) condition toujours vrai vérifier correctement –

+2

Je suis nouveau à la fois C# et sql donc au lieu de simplement voter vers le bas de l'utilisation de certaines critiques constructives parce que vos votes aident à rien, je vouloir comprendre cette langue encore en essayant de tout ce que je reçois sont des votes en bas. Comment est-ce utile si j'ai fait une erreur le signaler aveuglément vers le bas-vote ne aide personne –

Répondre

4

Ok, nous avons eu trois problèmes en cours ici. Concentrons-nous d'abord sur votre bug:

Vous utilisez reader.ToString() mais cette méthode ne vous convient pas.

Regardez ici ->http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.aspx (vous pouvez atteindre cette page et des pages similaires en plaçant votre curseur dans un nom de type et en appuyant sur 'F1'). Ainsi, à la place de votre 'ToString()', vous devez accéder au champ que vous voulez comparer de manière sécurisée en utilisant reader.GetString(0).

Deuxième problème: À l'intérieur du bloc else if, vous fermez SqlDataReader deux fois. Cela jetterait une exception.

Maintenant, au large du troisième problème:

Utilisez toujours un objet de connexion par requête SQL. Les connexions SQL sont mises en cache dans .NET afin que vous n'ayez pas à vous soucier de timeloss et que vous ne soyez pas obligé de vérifier constamment l'état de votre connexion.

Pour faciliter les choses, laissez-moi vous montrer la magie des déclarations en utilisant:

using (SqlConnection myConn = new SqlConnection(connstring)) 
{ 
    myConn.Open(); 
    // execute first statement 
} 


using (SqlConnection myConn2 = new SqlConnection(connstring)) 
{ 
    myConn2.Open(); 
    // execute second statement 
} 

partie d'une déclaration à l'aide est la déclaration de l'objet que vous souhaitez utiliser.L'objet doit être de type 'IDisposable'. Dans une instruction using, l'objet est traité comme un objet 'normal', pour la plupart au moins. Vous ne pouvez pas changer sa référence (ce qui signifie que vous ne pouvez pas assigner une nouvelle SqlConnection à myConn2) mais c'est à peu près tout.

Les choses deviennent plus intéressantes lorsque vous quittez une instruction using. Indépendamment de la façon dont vous le laissez (une instruction return à l'intérieur, une exception non gérée est survenue, ou le programme continue juste après avoir tout exécuté à l'intérieur de l'instruction using) l'objet sera éliminé. Et dans le cas d'une SqlConnection ou d'une SqlDataReader, sa méthode Close() sera également appelée dans le cadre de l'implémentation Dispose().

+0

Ok, mais je veux obtenir la dernière valeur dans la colonne titre de la fenêtre, je pensais que vous utilisez sqldatareader pour obtenir cette information est-ce que je le fais mal? –

+0

euh? Nous parlons de colonnes ici, pas de rangées. Votre instruction renvoie uniquement une ligne et un champ. Pour accéder à la première ligne, vous devez déjà faire tout ce qui est nécessaire (en appelant 'Read()' une fois). Vous devez maintenant accéder à la première colonne de cet enregistrement. –

+0

bien la dernière rangée dans le titre de la fenêtre serait une valeur que j'essaie d'utiliser lire mais après avoir utilisé les points de rupture, j'ai trouvé qu'il ne retournait pas les valeurs comme je le pensais –

0

Problème: Vous comparez le appltitle (je pense variable de chaîne) avec l'objet SqlDataReader. ce qui vous donnera toujours pas égal et comme vous inversez votre résultat, il sera toujours vrai d'où il stocke les données dans des données quelle que soit la situation.

Solution: Vous devez vérifier la variable appltitle avec la colonne appropriée de l'instruction SELECT.

reader[0] vous donne la window title de la base de données (spécifié dans l'instruction SELECT)

Remplacer cette:

if (appltitle != reader.ToString()) 

avec ceci:

if (appltitle != reader[0].ToString()) 
+0

En quoi cela diffère-t-il de la [0] Je vais essayer juste vouloir comprendre –

+0

@Broken_Code: lecteur [0] vous donne la première valeur de paramètre de l'instruction SELECT qui est 'window title', vérifier ma réponse éditée. –

+0

J'ai essayé d'utiliser le lecteur [0]. Cependant, les résultats n'ont pas changé. J'ai également utilisé des points de rupture et il dit toujours System.Data.SqlClient.SqlDataReader pour ma valeur au lieu de la valeur de ligne de titre de la dernière fenêtre –

Questions connexes