How to track application usage? (2) - c#

I asked this question yesterday and got a great response/code example. The only problem is that I forgot to mention that I am forced to work with the .Net Framework 2.0 and can't use the List.Select ( I assume the linq namespace). Does anyone have a good work around for List.Select seen below:
class Program
{
struct ProcessStartTimePair
{
public Process Process { get; set; }
public DateTime StartTime { get; set; }
public DateTime ExitTime
{
get
{
return DateTime.Now; // approximate value
}
}
public ProcessStartTimePair(Process p) : this()
{
Process = p;
try
{
StartTime = p.StartTime;
}
catch (System.ComponentModel.Win32Exception)
{
StartTime = DateTime.Now; // approximate value
}
}
}
static void Main(string[] args)
{
SqlConnection cnn = new SqlConnection(#"Data Source=XXXXXX;Initial Catalog=XXXXXX;User ID=XXXX;Password=XXXX");
List<ProcessStartTimePair> knownProcesses = new List<ProcessStartTimePair>();
while (true)
{
foreach (Process p in Process.GetProcesses())
{
if (!knownProcesses.Select(x => x.Process.Id).Contains(p.Id))
{
knownProcesses.Add(new ProcessStartTimePair(p));
//Console.WriteLine("Detected new process: " + p.ProcessName);
}
}
for (int i = 0; i < knownProcesses.Count; i++)
{
ProcessStartTimePair pair = knownProcesses[i];
try
{
if (pair.Process.HasExited)
{
Console.WriteLine(pair.Process.ProcessName + " has exited (alive from {0} to {1}).", pair.StartTime.ToString(), pair.ExitTime.ToString());
knownProcesses.Remove(pair);
i--; // List was modified, 1 item less
// TODO: Store in the info in the database
String sql = "insert into procs (machine,login,process,start_time,end_time) ";
sql += "values ('" + Environment.MachineName + "','" + System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString().Split('\\')[1] + "','" + pair.Process.ProcessName + "','" + pair.StartTime.ToString() + "','" + pair.ExitTime.ToString() + "');";
SqlCommand cmd = new SqlCommand(sql, cnn);
try
{
cnn.Open();
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
//Console.WriteLine(ex.Message);
}
finally
{
cnn.Close();
}
}
}
catch (System.ComponentModel.Win32Exception)
{
// Would have to check whether the process still exists in Process.GetProcesses().
// The process probably is a system process.
}
}
//Console.WriteLine();
System.Threading.Thread.Sleep(5000);
}
}
}

I'm not sure the datatype of Id. I'll assume an int, you get the idea:
List<int> idList = new List<int>();
foreach(ProcessStartTimePair proc in knownProcesses)
{
idList.Add(proc.Process.Id);
}
if(idList.Contains(p.Id))
{
// ...
}
You just have to do the work of getting the list of IDs yourself.
Also, it's generally a better idea to edit your original question, and leave comments on the answers of others.

Try this:
if(!knownProcesses.Exists(x => x.Process.Id == p.Id))
Or, if you are using Visual Studio 2005 (not 2008),
if(!knownProcesses.Exists(delegate(ProcessStartTimePair x) { return x.Process.Id == p.Id; }))

Related

C# SQL records from table to list

I'm trying to get all records from table and print them out in console.
My Userlist.cs
public List<Userlist> CreateList()
{
using (SqlConnection conn = new SqlConnection(Sqlstring))
{
using (SqlCommand cmd = new SqlCommand(ListCreateQuery, conn))
{
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
List<Userlist> Users = new List<Userlist>();
while (reader.Read())
{
Userlist U = new Userlist();
U.fornavn = (string)reader["Fornavn"];
U.efternavn = (string)reader["Efternavn"];
U.mail = (string)reader["Mail"];
U.tlfnr = (string)reader["TlfNr"];
Users.Add(U);
}
return Users;
}
}
}
}
And I try to print it out from my main (Or a method is fine)
if (UserAnswer == "1")
{
Console.Clear();
Userlist UL = new Userlist();
foreach (Userlist user in UL.CreateList())
{
Console.WriteLine(user);
}
Console.ReadKey();
}
When I run it, it only prints mynamespace.userlist 3 times over (my number of records)
Passing a class object into Console.WriteLine will invoke it's .ToString() method if the object is not null. If you want the property values to be displayed when calling .ToString() you can override the method in your class:
public class Userlist
{
.....
public override string ToString()
{
return "fornavn: " + fornavn + " efternavn: " + efternavn + " mail: " + mail
+ " tlfnr: " + tlfnr;
}
}
You are using toString on the object so it prints the objects name
You need to use it on each property and write:
foreach(Userlist user in UL.CreateList())
{
Console.WriteLine(user.fornavn);
Console.WriteLine(user.efternavn );
Console.WriteLine(user.mail);
Console.WriteLine(user.tlfnr);
}

WMI Query Library C#

I am having hard time understanding why there's not a single WMI query library
in here or google pointed out. Simply interface to query WMI for information. All I can find is "write a new query like this..."-style of topics all over web which makes no sense to me while there's few hundred queries I am working with.
So, here's my current effort building one:
using System;
using System.Management;
namespace hardware
{
public class Info
{
public static Tuple<string[], int, int> Query(string Select, string From, string Where = null, string Answer = null, string Root = "root\\CIMV2")
{
int Count = 0;
string[] Values = Select.Split(',');
if (Where != null && Answer != null)
{
ManagementObjectSearcher s = new ManagementObjectSearcher(Root, "SELECT " + Select + " FROM " + From + " WHERE " + Where + " = '" + Answer + "'");
string[] res = new string[Values.Length];
foreach (ManagementObject wQuery in s.Get())
{
foreach (string value in Values)
{
res[Count] = Convert.ToString(wQuery[value]);
Count++;
}
}
var result = new Tuple<string[], int, int> (res, Values.Length, Count);
return result;
}
else
{
ManagementObjectSearcher s = new ManagementObjectSearcher(Root, "SELECT " + Select + " FROM " + From);
string[] res = new string[Values.Length];
foreach (ManagementObject wQuery in s.Get())
{
foreach (string value in Values)
{
res[Count] = Convert.ToString(wQuery[value]);
Count++;
}
}
var result = new Tuple<string[], int, int>(res, Values.Length, Count);
return result;
}
}
}
}
I've been trying to get above in working order now for a weeks. Coming from basic string multi-dimensional array (return string[,] or string[][]) just started testing, if returning tuple (which I used few years ago successfully) would be better choice.
So, anyone know, if there is library already written?
if not, then best way to do above query from reference DLL library?
I know this question is old. But you can use ORMi library. I think it will just fit on your needs.
For example:
1) Define your class:
[WMIClass("Win32_Processor")]
public class Processor
{
public string Name { get; set; }
[WMIProperty("NumberOfCores")]
public int Cores { get; set; }
public string Description { get; set; }
}
2) Query:
WMIHelper helper = new WMIHelper("root\\CimV2");
List<Processor> processors = helper.Query<Processor>().ToList();
3) Or lazy coding option:
var processors = helper.Query("SELECT * FROM Win32_Processor");
You can find more information in here:
https://github.com/nicoriff/ORMi
https://medium.com/#luque.nicolas/compare-ormi-and-traditional-net-wmi-implementation-f00db26d10a3

Passing values between Windows form and a database

I faced a problem while trying to build a Windows form solution for a college assignment, and hope somebody can point out my mistake.
The solution is about a mobile shop. I have two classes, Apple and Android forms. I need to read the data in the database table, categorize the entries to either Android or Apple phones, and then display all phones in a list when the form loads.
I can successfully categorize phones, but when trying to read the entries, I always end up with the same entry twice in my list on the form, while the second entry doesn't appear at all.
I know I made a big stupid mistake while doing the connection but I can't find it!.
Here is my code:
public abstract class MobilePhone {
private Int32 phoneID;
private string operatingSystem;
private string make;
private string model;
public enum Condition { Poor, Fair, Good, Mint };
private Condition condition;
private decimal originalPrice;
private DateTime datePurchase;
private string description;
private clsDataConnection dbConnection;
//constructor
public MobilePhone(string make, string model, decimal originalPrice, DateTime datePurchase, Condition condition, string description) {
this.make = make;
this.model = model;
this.originalPrice = originalPrice;
this.datePurchase = datePurchase;
this.condition = condition;
this.description = description;
}
Not complete, but that's what is relevant:
public class ApplePhone : MobilePhone {
decimal ApproxValue;
public ApplePhone(string make, string model, decimal originalPrice, DateTime datePurchase, Condition condition, string description)
: base(make, model, originalPrice, datePurchase, condition, description) {
}
The Android class is the same but with different other functions.
class Shop {
clsDataConnection dbConnection;
const int NotAdded = -1; // invalid primary key
private string name;
private decimal ApproxValue;
private Int32 phoneID;
private string operatingSystem;
private string make;
private string model;
private MobilePhone.Condition condition;
private decimal originalPrice;
private DateTime datePurchase;
private string description;
Int32 Index;
private List<MobilePhone> phonesForSale;
//constructor
public Shop(string name) {
this.name = name;
}
MobilePhone phone;
public void SelectAll() {
dbConnection = new clsDataConnection();
dbConnection.Execute("SellectAllPhones");
}
public void FilterByOperatingSystem(string operatingSystem) {
dbConnection = new clsDataConnection();
dbConnection.AddParameter("#OperatingSystem", operatingSystem);
dbConnection.Execute("FilterByOperatingSystem");
}
public Int32 Count {
get {
//return the count of records
return dbConnection.Count;
}
}
public string DescribeCurrentPhone(int Index) {
Int32 phoneID;
string make;
string model;
MobilePhone.Condition condition;
decimal originalPrice;
DateTime datePurchase;
string description;
phoneID = Convert.ToInt32(phonesForSale[Index].PhoneID);
make = Convert.ToString(phonesForSale[Index].Make);
model = Convert.ToString(phonesForSale[Index].Model);
condition = phonesForSale[Index].GetCondition;
originalPrice = Convert.ToDecimal(phonesForSale[Index].OriginalPrice);
datePurchase = Convert.ToDateTime(phonesForSale[Index].DatePurchased);
description = Convert.ToString(phonesForSale[Index].Description);
//set up a new object of class list item
string listItemText = make + " " + "|" + " " + model + " " + "|" + " " + condition + " " + "|" + " " + "£" + Math.Round(originalPrice, 2) + " " + "|" + " " + datePurchase.ToShortDateString() + " " + "|" + " " + description;
return listItemText;
}
public List<MobilePhone> Allphones {
get {
phonesForSale = new List<MobilePhone>();
int count = Count;
Index = 0;
while (Index < count) {
phoneID = Convert.ToInt32(dbConnection.DataTable.Rows[Index]["PhoneId"]);
operatingSystem = Convert.ToString(dbConnection.DataTable.Rows[Index]["OperatingSystem"]);
make = Convert.ToString(dbConnection.DataTable.Rows[Index]["Make"]);
model = Convert.ToString(dbConnection.DataTable.Rows[Index]["Model"]);
string conditionString = Convert.ToString(dbConnection.DataTable.Rows[Index]["Condition"]);
originalPrice = Convert.ToInt32(dbConnection.DataTable.Rows[Index]["OriginalPrice"]);
datePurchase = Convert.ToDateTime(dbConnection.DataTable.Rows[Index]["DatePurchased"]);
description = Convert.ToString(dbConnection.DataTable.Rows[Index]["Description"]);
// Set Condition
if (conditionString == "Poor") {
condition = MobilePhone.Condition.Poor;
} else if (conditionString == "Fair") {
condition = MobilePhone.Condition.Fair;
} else if (conditionString == "Good") {
condition = MobilePhone.Condition.Good;
} else if (conditionString == "Mint") {
condition = MobilePhone.Condition.Mint;
}
//check Operating System
if (operatingSystem == "IOS") {
phone = new ApplePhone(make, model, originalPrice, datePurchase, condition, description);
//ApproxValue = ApplePhone.CalculateApproximateValue();
} else if (operatingSystem == "Android") {
phone = new AndroidPhone(make, model, originalPrice, datePurchase, condition, description);
//ApproxValue = AndroidPhone.CalculateApproximateValue();
}
Index++;
phonesForSale.Add(phone);
}
return phonesForSale;
}
}
And the form code is:
public partial class FormMain : Form {
public FormMain() {
InitializeComponent();
Shop shop = new Shop("");
}
private void FormMain_Load(object sender, EventArgs e) {
DisplayItems("");
}
protected int DisplayItems(string operatingSystem) {
Shop MyShop = new Shop("");
Int32 RecordCount;
Int32 Index = 0;
Int32 PID;
if (operatingSystem != "") {
MyShop.FilterByOperatingSystem(operatingSystem);
} else {
MyShop.SelectAll();
}
RecordCount = MyShop.Count;
ArrayList MyPhones = new ArrayList();
while (Index < RecordCount) {
// I Suspect this line is the problem but don't know how to fix it
PID = MyShop.Allphones[Index].PhoneID
string listItemText = MyShop.DescribeCurrentPhone(PID);
//add the new item to the list
MyPhones.Add(listItemText);
//increment the index
Index++;
}
listBox1.DataSource = MyPhones;
return RecordCount;
}
I am not used to connecting to databases, so any advice will be of help!
An example of an alternative to the DB connection you have made is below
List<MyPhone> myIPhoneList = new List<Myphone>();
List<MyPhone> myAndroidList = new List<Myphone>();
SqlConnection myDBConnection = new SqlConnection("MyConnectionString"); //DB Connection
SqlCommand dbCommand = new SqlCommand("SelectAllPhones"); //Stored Procedure
SqlDataReader recordReader = dbCommand.ExecuteReader(); //Execute
//Read records return in to phone objects
while (recordReader.Read()) {
var phoneField1 = recordReader["PhoneField1FromDatabase"];
var phoneField2 = recordReader["PhoneField2FromDatabase"];
//etc...
var myPhone = new MyPhone();
myPhone.Name = phoneField1;
//etc...
if (myPhone.OS == "iPhone")
myIPhoneList.Add(myPhone);
if (myPhone.OS = "Android")
myAndroidList.Add(myPhone);
}
Just a twist to Wheels answer really,
I'd personally put a filter on the stored-proc.
SqlCommand dbCommand = new SqlCommand("SelectAllPhones"); //Stored Procedure
becomes something like:
using (SqlConnection conn = new SqlConnection())
{
using (SqlCommand cmd = new SqlCommand("SelectAllPhones", conn))
{
cmd.Parameters.Add(new SqlParameter() { ParameterName = "#OS", SqlDbType = SqlDbType.VarChar, Direction = ParameterDirection.Input, Value = phoneOS });
cmd.CommandType = CommandType.StoredProcedure;
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
// load your data...
}
}
}
Only because there is very little point dragging both sets of phone data (android/iphone) for each class. You may as well only pull back the data you require.
Of course the Stored-Proc will need an update to cater for the parameter.
something like:
AND PhoneOS = #OS
needs appending to your SQL condition.
clsDataConnection dbConnection; is unknown to me - is this a third party library or a class you've wrote and not included?
public Int32 Count
{
get
{
//return the count of records
return dbConnection.Count;
}
}
dbConnection.Count seems very non-standard. Doesn't read as if you're trying to get the number of rows, more the number of connections - which is invalid here.
dbConnection.DataTables[0].Rows.Count; would be a better way of determining the rows using your existing code, as currently it reads as if your counting the number of database connections which isn't what your after - and would be redundant if using either mine or Wheels as you wont need to know beforehand how many rows your about to process.

Displaying the Incorrect Cost

My goal is to display the cost for a One-Day Conference on a web page, which is $50.00. However, I keep getting $0.00 in return. I tested my SELECT statement in SQL and it is retrieving the correct data. Now I have narrowed down the problem to be in my if...else if statements in the PayBackCC method but I am not certain. It should get the cost from variable cOneDCost. Any help is appreciated.
Code behind
protected void PayBackInfo()
{
try
{
con.Open();
SqlCommand PBCredit = new SqlCommand("SELECT * FROM PaymentInfo, ConferenceReg WHERE PaymentInfoID=PaymentInfoIDNum AND PaymentInfoID=#payID AND ConferenceReg.Deleted='N' AND ConferenceIDNum=#confID", con);
PBCredit.Parameters.AddWithValue("#confID", confID);
PBCredit.Parameters.AddWithValue("#payID", Request.QueryString["payID"]);
SqlDataReader readerPB = PBCredit.ExecuteReader();
while (readerPB.Read())
{
piID = readerPB["PaymentInfoID"].ToString();
cID = readerPB["ConferenceIDNum"].ToString();
poID = readerPB["PurchaseOrder"].ToString();
partnersNum = readerPB["PartnersIDNum"].ToString();
cFullCost = Convert.ToDecimal(readerPB["ConferenceFullFee"]).ToString("#,##0.00");
cOneDCost = Convert.ToDecimal(readerPB["ConferenceOneDayFee"]).ToString("#,##0.00");
partnersCost = Convert.ToDecimal(readerPB["PartnersFee"]).ToString("#,##0.00");
PayBackCC();
}
readerPB.Close();
}
finally
{
con.Close();
}
}
private void PayBackCC()
{
if (!partnersNum.Equals("null") || !partnersNum.Equals("0"))
{
msgLbl.Text = "$" + partnersCost;
}
else if (!cFullCost.Equals("0"))
{
msgLbl.Text = "$" + cFullCost;
}
else if (!cOneDCost.Equals("0"))
{
msgLbl.Text = "$" + cOneDCost;
}
}
Please change
if (!partnersNum.Equals("null") || !partnersNum.Equals("0"))
to
if (!String.IsNullOrEmpty(partnersNum) || !partnersNum.Equals("0"))
unless you are expecting "null" string from your query

How to prevent resources from being consumed by long-running queries?

I hava access DB, one of my function(C#.net) need to Exec a SQL more than 4000 times with transaction.
It seems that after execution the DB file stay opened exclusively. because there is a *.ldb file, and that file stay there for a long time.
Is that caused by dispose resources incorrectly???
private int AmendUniqueData(Trans trn)
{
int reslt = 0;
foreach (DataRow dr in _dt.Rows)
{
OleDbParameter[] _params = {
new OleDbParameter("#templateId",dr["Id"].ToString()),
new OleDbParameter("#templateNumber",dr["templateNumber"].ToString())
};
string sqlUpdateUnique = "UPDATE " + dr["proformaNo"].ToString().Substring(0,2) + "_unique SET templateId = #templateId WHERE templateNumber=#templateNumber";
reslt = OleDBHelper.ExecSqlWithTran(sqlUpdateUnique, trn, _params);
if (reslt < 0)
{
throw new Exception(dr["id"].ToString());
}
}
return reslt;
}
the transaction:
using (Trans trn = new Trans())
{
try
{
int reslt=AmendUniqueData(trn);
trn.Commit();
return reslt;
}
catch
{
trn.RollBack();
throw;
}
finally
{
trn.Colse();
}
}
forget closing the database connection.

Categories

Resources