Is there a way to detect a configuration changes in printers using C#?
I have thread in c# which usually sleeps and I want it to be notified when there is any change in configuration (like someone adds/removes/updates the printer or someone changes the default printer). Once it is notified, it will display simple message.
Is this possible using C#.NET or Using WMI? I have already gone through the solution available but none of them seems to be suitable for the requirement I have.
You can monitor the printer configuration changes using the __InstanceModificationEvent event and the Win32_Printer WMI class
Try this sample.
using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
namespace GetWMI_Info
{
public class EventWatcherAsync
{
private void WmiEventHandler(object sender, EventArrivedEventArgs e)
{
Console.WriteLine("TargetInstance.Name : " + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["Name"]);
}
public EventWatcherAsync()
{
try
{
string ComputerName = "localhost";
string WmiQuery;
ManagementEventWatcher Watcher;
ManagementScope Scope;
if (!ComputerName.Equals("localhost", StringComparison.OrdinalIgnoreCase))
{
ConnectionOptions Conn = new ConnectionOptions();
Conn.Username = "";
Conn.Password = "";
Conn.Authority = "ntlmdomain:DOMAIN";
Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), Conn);
}
else
Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), null);
Scope.Connect();
WmiQuery = "Select * From __InstanceModificationEvent Within 1 " +
"Where TargetInstance ISA 'Win32_Printer' ";
Watcher = new ManagementEventWatcher(Scope, new EventQuery(WmiQuery));
Watcher.EventArrived += new EventArrivedEventHandler(this.WmiEventHandler);
Watcher.Start();
Console.Read();
Watcher.Stop();
}
catch (Exception e)
{
Console.WriteLine("Exception {0} Trace {1}", e.Message, e.StackTrace);
}
}
public static void Main(string[] args)
{
Console.WriteLine("Listening {0}", "__InstanceModificationEvent");
Console.WriteLine("Press Enter to exit");
EventWatcherAsync eventWatcher = new EventWatcherAsync();
Console.Read();
}
}
}
Related
I am doing a project in which i have to send the variable data from my console application project to windows form application( i have to write that data into textbox). I am trying to pass a variable val to my form and below code is what i tried to do but passed value(num variable in windows form) is zero instead of 1 (serial.Val in console application which is passed as argument and then i am calling the form).
Can anyone please help me with that ?
This is my windows forms code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WindowsFormsApplication2;
namespace WindowsFormsApplication2
{
public partial class Serial_comm_1 : Form
{
//private static int temp;
private DateTime Datetime;
string indata;
static SerialPort COMport;
// private static int num;
public Serial_comm_1(int num)
{
InitializeComponent();
string Port_Name = "COM3"; // Store the selected COM port name to "Port_Name" varaiable
int Baud_Rate = 9600; // Convert the string "9600" to int32 9600
COMport = new SerialPort(Port_Name, Baud_Rate);
COMport.Parity = Parity.None;
COMport.StopBits = StopBits.One;
COMport.DataBits = 8;
COMport.Handshake = Handshake.None;
COMport.RtsEnable = true;
COMport.DtrEnable = true;
TextBox_Transmit_Data.Text = num.ToString();
//try to open the port
#region
try
{
COMport.Open();
textBox_System_Log.Text = "";
}
catch (UnauthorizedAccessException SerialException) //exception that is thrown when the operating system denies access
{
MessageBox.Show(SerialException.ToString());
textBox_System_Log.Text = Port_Name + Environment.NewLine + Baud_Rate;
textBox_System_Log.Text = textBox_System_Log.Text + Environment.NewLine + SerialException.ToString();
COMport.Close();
}
catch (System.IO.IOException SerialException) // An attempt to set the state of the underlying port failed
{
MessageBox.Show(SerialException.ToString());
textBox_System_Log.Text = Port_Name + Environment.NewLine + Baud_Rate;
textBox_System_Log.Text = textBox_System_Log.Text + Environment.NewLine + SerialException.ToString();
COMport.Close();
}
catch (InvalidOperationException SerialException) // The specified port on the current instance of the SerialPort is already open
{
MessageBox.Show(SerialException.ToString());
textBox_System_Log.Text = Port_Name + Environment.NewLine + Baud_Rate;
textBox_System_Log.Text = textBox_System_Log.Text + Environment.NewLine + SerialException.ToString();
COMport.Close();
}
catch //Any other ERROR
{
MessageBox.Show("ERROR in Opening Serial PORT -- UnKnown ERROR");
COMport.Close();
}
#endregion
}
private void Button_Transmit_Data_Click(object sender, EventArgs e)
{
//Local Variables
string Port_Name = "COM3"; // Store the selected COM port name to "Port_Name" variable
int Baud_Rate = 9600; // Convert the string "9600" to int32 9600
string Data = TextBox_Transmit_Data.Text; //Store the string in Textbox to variable "Data"
COMport.ReadTimeout = 3500; //Setting ReadTimeout =3500 ms or 3.5 seconds
Console.WriteLine(COMport.IsOpen);
COMport.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
//Program1 prog = new Program1();
//If we are able to open the port
if (COMport.IsOpen == true)
{
COMport.WriteLine(Data); // Send Data
textBox_System_Log.Text = Port_Name + Environment.NewLine + Baud_Rate;
textBox_System_Log.Text = textBox_System_Log.Text + Environment.NewLine + Data + " Written to Port" + Environment.NewLine;
}
else
{
TextBox_Received_Data.Enabled = true; // Enable the Receive Groupbox
MessageBox.Show("Unable to Write to COM port ");
COMport.Close();
}
}
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
indata = sp.ReadLine();
this.Invoke(new EventHandler(display_data_event));
}
private void display_data_event(object sender, EventArgs e)
{
Datetime = DateTime.Now;
String time = Datetime.Hour + ":" + Datetime.Minute + ":" + Datetime.Second;
textBox_System_Log.AppendText(time + "\t\t\t" + indata + Environment.NewLine);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void label1_Click(object sender, EventArgs e)
{
}
private void textBox_Received_Data_TextChanged(object sender, EventArgs e)
{
}
private void TextBox_Transmit_Data_TextChanged(object sender, EventArgs e)
{
}
}
}
This is my trail of console application:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WindowsFormsApplication2;
using System.Windows.Forms;
namespace ConsoleApplication1
{
class Program1
{
private int val;
public int Val
{
get { return val; }
set { val = value; }
}
static void Main(string[] args)
{
Program1 serial = new Program1();
serial.Val = 1;
System.Windows.Forms.Application.Run(new Serial_comm_1(serial.Val));
//Serial_comm_1 serial_form1 = new Serial_comm_1(serial.Val);
}
}
}
From your app you want to start the other app:
// Create a new Process
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo = new System.Diagnostics.ProcessStartInfo();
process.StartInfo.FileName = #"C:\Projects\Temp912\bin\Debug\Temp912.exe";
process.StartInfo.Arguments = "Test Argument";
process.StartInfo.UseShellExecute = false;
process.Start();
Now from your Windows Form App, modify the Main method:
using System;
using System.Windows.Forms;
namespace Temp912
{
static class Program
{
[STAThread]
static void Main(string[] args)
{
string arg1 = "";
if ((args != null) && (args.Length > 0))
{
arg1 = args[0];
MessageBox.Show("Arg1: " + arg1, "Arg App Started With Parameter");
}
else
{
MessageBox.Show("Arg1: N/A", "Arg App Started Without Parameter");
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
If you need to pass the parameter value(s) to your Main Form, expose a property or properties on your form, and set the value(s) before you launch the form.
Edit Per Question:
Form Code
public string MyProperty { get; set; } // change the data type to int or whatever
Than in Program.cs, instead of:
Application.Run(new Form1());
Do this:
// create an instance of your form
Form1 form1 = new Form1();
// set the property or properties
form1.MyProperty = arg1;
Then call:
// this is should work, I didn't test this like the other code
Application.Run(form1);
I have managed to get the Service working, along with the FileSystemEventHandler inserting into a text file, but this now needs to be changed to insert into a database and a text file.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
namespace WindowsServiceTest
{
public partial class Service1 : ServiceBase
{
Timer timer = new Timer(); // name space(using System.Timers;)
public static string path = ConfigurationManager.AppSettings["findpath"];
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
WriteToFile("Service is started at " + DateTime.Now);
timer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
timer.Interval = 10000; //number in milisecinds
timer.Enabled = true;
FileSystemWatcher watcher = new FileSystemWatcher
{
Path = path,
NotifyFilter = NotifyFilters.LastWrite,
};
watcher.Created += new FileSystemEventHandler(FileSystemWatcher_Changed);
watcher.Renamed += new RenamedEventHandler(FileSystemWatcher_Renamed);
watcher.Changed += new FileSystemEventHandler(FileSystemWatcher_Changed);
watcher.EnableRaisingEvents = true;
}
public static void FileSystemWatcher_Changed(object source, FileSystemEventArgs e)
{
using (SqlConnection con = new SqlConnection("Data Source=localhost\\SQLEXPRESS;Database=ServiceTest;Integrated Security=True;"))
{
try
{
con.Open();
var command = new SqlCommand("Insert into test(URL, Location) values(#URL, #agendaname);", con);
command.Parameters.Add("#URL", System.Data.SqlDbType.VarChar, 100).Value = e.Name;
command.Parameters.Add("#agendaname", System.Data.SqlDbType.VarChar, 100).Value = "Case History";
command.ExecuteNonQuery();
}
catch
{
WriteToFile($"Failed to insert: {e.Name} into the database");
}
}
}
public static void FileSystemWatcher_Renamed(object source, RenamedEventArgs e)
{
WriteToFile($"File Renamed: {e.OldFullPath} renamed to {e.FullPath}");
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
WriteToFile("Service is recalled at " + DateTime.Now);
}
protected override void OnStop()
{
WriteToFile("Service is stopped at " + DateTime.Now);
}
public static void WriteToFile(string Message)
{
string path = AppDomain.CurrentDomain.BaseDirectory + "\\Logs";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string filepath = AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\ServiceLog_" + DateTime.Now.Date.ToShortDateString().Replace('/', '_') + ".txt";
if (!File.Exists(filepath))
{
// Create a file to write to.
using (StreamWriter sw = File.CreateText(filepath))
{
sw.WriteLine(Message);
}
}
else
{
using (StreamWriter sw = File.AppendText(filepath))
{
sw.WriteLine(Message);
}
}
}
}
}
I think that I've done the database insert wrong because the catch block is being inserted into the text file. However, I've run the code by itself in a separate project and was inserting into the database in a Console Application.
Any help is appreciated, kind regards.
Windows services run under a different security context than console apps. As the comments have disclosed, the exception is related to your connection string.
If we analyze the connectiong string we can see that you are authenticating with IntegratedSecurity="True". Because your windows service is running under
a service account authentication is failing. I've specified 2 options for resolving this.
Option 1: Have Service run as windows account (Not recommended but will work for testing)
Open run box (Win Flag + R)
Type Services.MSC
Locate your service and right click properties
Choose the logon tab
Enter your windows auth username and password for service to run as
Option 2: Create SQL Server account
Create username and password in SQL for database
Update connection string to specify new username and password created
I created a windows service that will connect to remote MQ and get the message as MQSTR format but after getting the message I didn't closed connection to remote MQ . My windows service will continuously check if data is available in remote MQ or not but after getting one message I need to restart my service to get the another message from remote MQ . Can anyone tell me what I need to do to get message constantly from remote MQ . Any clue or any link will do fine . Please Help
My C# windows service code is like this :
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace MQ_listner
{
static class Program
{
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
}
Service1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MQ_listner
{
public partial class Service1 : ServiceBase
{
private MQReader MQReader;
private string _serviceName = "MQ_Listener";
private DateTime _TimeStart;
private bool _run = true;
private Thread _thread;
int WaitWhenStop = 0;
private DateTime _TimeEnd;
private TimeSpan _TimeDifference;
private TimeSpan _TimeElasped = new TimeSpan(0);
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
EventLog.WriteEntry(_serviceName + "was started at" + _TimeStart.ToString());
_run = true;
_thread = new Thread(new ThreadStart(StartMQListenerService));
_thread.IsBackground = true;
_thread.Start();
}
catch (Exception ex)
{
EventLog.WriteEntry(_serviceName + "was not started . Error Message : " + ex.ToString());
}
}
protected override void OnStop()
{
_run = false;
_thread.Join(WaitWhenStop);
_TimeEnd = DateTime.Now;
_TimeDifference = _TimeEnd.Subtract(_TimeStart);
_TimeElasped = _TimeElasped.Add(_TimeDifference);
EventLog.WriteEntry(_serviceName + "was stopped at " + _TimeEnd.ToString() + "\r\n ran for total time :" + _TimeElasped.ToString());
}
// MQ connection service
public void StartMQListenerService()
{
try
{
if (_run)
{
if (MQReader == null)
{
MQReader = new MQReader();
MQReader.InitializeConnections();
EventLog.WriteEntry(_serviceName + "MQ connection is established");
}
}
}
catch (Exception ex)
{
System.Diagnostics.EventLog.WriteEntry(_serviceName, ex.ToString());
System.Diagnostics.ProcessStartInfo startinfo = new System.Diagnostics.ProcessStartInfo();
startinfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startinfo.FileName = "NET";
startinfo.Arguments = "stop" + this.ServiceName;
Process.Start(startinfo);
}
}
}
}
****MQReader.cs****
using System;
using IBM.WMQ;
using System.Diagnostics;
using System.IO;
using System.Xml;
using System.Linq;
using System.Xml.Linq;
using System.Configuration;
namespace MQ_listner
{
internal class MQReader
{
public MQReader()
{
}
public void InitializeConnections()
{
MQQueueManager queueManager;
MQMessage queueMessage;
MQGetMessageOptions queueGetMessageOptions;
MQQueue queue;
string QueueName;
string QueueManagerName;
string ChannelInfo;
string channelName;
string PortNumber;
string transportType;
string connectionName;
QueueManagerName = ConfigurationManager.AppSettings["QueueManager"];
QueueName = ConfigurationManager.AppSettings["Queuename"];
ChannelInfo = ConfigurationManager.AppSettings["ChannelInformation"];
PortNumber = ConfigurationManager.AppSettings["Port"];
char[] separator = { '/' };
string[] ChannelParams;
ChannelParams = ChannelInfo.Split(separator);
channelName = ConfigurationManager.AppSettings["Channel"];
transportType = ConfigurationManager.AppSettings["TransportType"];
connectionName = ConfigurationManager.AppSettings["ConnectionName"];
String strReturn = "";
try
{
queueManager = new MQQueueManager(QueueManagerName,
channelName, connectionName);
strReturn = "Connected Successfully";
queue = queueManager.AccessQueue(QueueName,
MQC.MQOO_INPUT_AS_Q_DEF + MQC.MQOO_FAIL_IF_QUIESCING);
queueMessage = new MQMessage();
queueMessage.Format = MQC.MQFMT_STRING;
queueGetMessageOptions = new MQGetMessageOptions();
queue.Get(queueMessage, queueGetMessageOptions);
strReturn = queueMessage.ReadString(queueMessage.MessageLength);
}
catch (MQException exp)
{
strReturn = "Exception: " + exp.Message;
}
string path1 = #"C:\documents\Example.txt";
System.IO.File.WriteAllText(path1, strReturn);
}
}
}
Can anyone tell me what is wrong in my code? Do I need anything to add here to get message constantly from remote MQ . Please Help . Any link or clue will do fine .
EDIT
after certain amount of time I need to restart my service to fetch data from remote mq . Can you tell me why windows service needs to restart to fetch data . Any clue? any idea ?
Where is your queue close and queue manager disconnect? If you connect and/or open something, you must make sure you close and disconnect from it. I would strongly suggest you take an MQ programming course. Or go to the MQ Technical Conference which has sessions on programming MQ.
I posted a fully functioning C# MQ program that retrieves all of the messages on a queue at MQQueueManager message pooling
Here is an updated version of your MQReader class that should give you the right idea. Note: I did not test it. I leave that for you. :)
Also, you should be putting your connection information in a Hashtable and pass the Hashtable to the MQQueueManager class.
using System;
using IBM.WMQ;
using System.Diagnostics;
using System.IO;
using System.Xml;
using System.Linq;
using System.Xml.Linq;
using System.Configuration;
namespace MQ_listner
{
internal class MQReader
{
private MQQueueManager qManager = null;
private MQMessage inQ = null;
private bool running = true;
public MQReader()
{
}
public bool InitQMgrAndQueue()
{
bool flag = true;
Hashtable qMgrProp = new Hashtable();
qMgrProp.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
qMgrProp.Add(MQC.HOST_NAME_PROPERTY, ConfigurationManager.AppSettings["ConnectionName"]);
qMgrProp.Add(MQC.CHANNEL_PROPERTY, ConfigurationManager.AppSettings["Channel"]);
try
{
if (ConfigurationManager.AppSettings["Port"] != null)
qMgrProp.Add(MQC.PORT_PROPERTY, System.Int32.Parse(ConfigurationManager.AppSettings["Port"]));
else
qMgrProp.Add(MQC.PORT_PROPERTY, 1414);
}
catch (System.FormatException e)
{
qMgrProp.Add(MQC.PORT_PROPERTY, 1414);
}
if (ConfigurationManager.AppSettings["UserID"] != null)
qMgrProp.Add(MQC.USER_ID_PROPERTY, ConfigurationManager.AppSettings["UserID"]);
if (ConfigurationManager.AppSettings["Password"] != null)
qMgrProp.Add(MQC.PASSWORD_PROPERTY, ConfigurationManager.AppSettings["Password"]);
try
{
qManager = new MQQueueManager(ConfigurationManager.AppSettings["QueueManager"],
qMgrProp);
System.Console.Out.WriteLine("Connected Successfully");
inQ = qManager.AccessQueue(ConfigurationManager.AppSettings["Queuename"],
MQC.MQOO_INPUT_AS_Q_DEF + MQC.MQOO_FAIL_IF_QUIESCING);
System.Console.Out.WriteLine("Open queue Successfully");
}
catch (MQException exp)
{
System.Console.Out.WriteLine("MQException CC=" + mqex.CompletionCode + " : RC=" + mqex.ReasonCode);
flag = false;
}
return flag;
}
public void LoopThruMessages()
{
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.Options |= MQC.MQGMO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING;
gmo.WaitInterval = 2500; // 2.5 seconds wait time or use MQC.MQEI_UNLIMITED to wait forever
MQMessage msg = null;
while (running)
{
try
{
msg = new MQMessage();
inQ.Get(msg, gmo);
System.Console.Out.WriteLine("Message Data: " + msg.ReadString(msg.MessageLength));
}
catch (MQException mqex)
{
if (mqex.Reason == MQC.MQRC_NO_MSG_AVAILABLE)
{
// no meesage - life is good - loop again
}
else
{
running = false; // severe error - time to exit
System.Console.Out.WriteLine("MQException CC=" + mqex.CompletionCode + " : RC=" + mqex.ReasonCode);
}
}
catch (System.IO.IOException ioex)
{
System.Console.Out.WriteLine("ioex=" + ioex);
}
}
try
{
if (inQ != null)
{
inQ.Close();
System.Console.Out.WriteLine("Closed queue");
}
}
catch (MQException mqex)
{
System.Console.Out.WriteLine("MQException CC=" + mqex.CompletionCode + " : RC=" + mqex.ReasonCode);
}
try
{
if (qMgr != null)
{
qMgr.Disconnect();
System.Console.Out.WriteLine("disconnected from queue manager");
}
}
catch (MQException mqex)
{
System.Console.Out.WriteLine("MQException CC=" + mqex.CompletionCode + " : RC=" + mqex.ReasonCode);
}
}
public void StopIt()
{
running = false;
}
}
}
Whenever you stop the service, make sure it calls the StopIt method in MQReader.
I have a console app that monitors a database using SqlDependency. The app is to monitor the database table and send an email once a new record is added in the table.
Everything works fine, just that each time a new record is added the whole query is executed again and all the records in the table are returned. What I actually want is to return only the newly added record in the table.
Here is my code below:
SQLWatcher class:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TestApp
{
public enum SqlWatcherNotificationType
{
Blocking,
Threaded // Launch in another thread so SqlWatcher can immediately start monitoring again.
}
public class SqlWatcher : IDisposable
{
private string ConnectionString;
private SqlConnection Connection;
private SqlCommand Command;
private SqlDataAdapter Adapter;
private DataSet Result;
private SqlWatcherNotificationType NotificationType;
public SqlWatcher(string ConnectionString, SqlCommand Command, SqlWatcherNotificationType NotificationType)
{
this.NotificationType = NotificationType;
this.ConnectionString = ConnectionString;
SqlDependency.Start(this.ConnectionString);
this.Connection = new SqlConnection(this.ConnectionString);
this.Connection.Open();
this.Command = Command;
this.Command.Connection = this.Connection;
Adapter = new SqlDataAdapter(this.Command);
}
public void Start()
{
RegisterForChanges();
}
public void Stop()
{
SqlDependency.Stop(this.ConnectionString);
}
public delegate void SqlWatcherEventHandler(DataSet Result);
public event SqlWatcherEventHandler OnChange;
public DataSet DataSet
{
get { return Result; }
}
private void RegisterForChanges()
{
// Remove old dependency object
this.Command.Notification = null;
// Create new dependency object
SqlDependency dep = new SqlDependency(this.Command);
dep.OnChange += new OnChangeEventHandler(Handle_OnChange);
// Save data
Result = new DataSet();
Adapter.Fill(Result);
// Notify client of change to DataSet
switch (NotificationType)
{
case SqlWatcherNotificationType.Blocking:
OnChange(Result);
break;
case SqlWatcherNotificationType.Threaded:
ThreadPool.QueueUserWorkItem(ChangeEventWrapper, Result);
break;
}
}
public void ChangeEventWrapper(object state)
{
DataSet Result = (DataSet)state;
OnChange(Result);
}
private void Handle_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type != SqlNotificationType.Change)
throw new ApplicationException("Failed to create queue notification subscription!");
//Clean up the old notification
SqlDependency dep = (SqlDependency)sender;
dep.OnChange -= Handle_OnChange;
//Register for the new notification
RegisterForChanges();
}
public void Dispose()
{
Stop();
}
}
}
Implementation:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Linq;
using System.Data.SqlClient;
using System.Linq;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
namespace TestApp
{
class Program
{
private static SqlWatcher SqlQueueWatcher;
// string pin = string.Empty;
string siteURL = "http://docapp/sites/nlpc";
public string benefitCheck()
{
DataContext db = new DataContext("Data Source=;Initial Catalog=ServiceTest;User ID=;password = ;Integrated Security=true");
BenefitDocModel RSAName = new BenefitDocModel();
CustomerCareContextDataContext LandingDb = new CustomerCareContextDataContext(siteURL);
IEnumerable<BenefitDocModel> r = db.GetTable<BenefitDocModel>().ToList<BenefitDocModel>();
var query = r.ToList();
var rsa = from rr in query
select ( new { rr.PIN , rr.Document_Name, rr.Firstname, rr.Surname, rr.URL});
foreach (var rsapin in rsa)
{
Console.WriteLine(rsapin);
// sendEmail(rsapin.PIN);
}
/*pin = RSAName.PIN;
RSAsLibraryDocument test = new RSAsLibraryDocument();
BenefitDocModel RSAName1 = db.GetTable<BenefitDocModel>().FirstOrDefault(x => x.PIN == pin);
if (pin == RSAName1.PIN)
{
test.PIN = RSAName.PIN;
test.UserID = RSAName.UserID;
test.Firstname = RSAName.Firstname;
test.Surname = RSAName.Surname;
test.Document_Name = RSAName.Document_Name;
test.Document_URL = RSAName.URL;
test.UserType = RSAName.UserType;
test.Name = RSAName.PIN + RSAName.Document_Name;
}*/
return "success";
}//
public void SQLServiceStartForLog()
{
//BenefitDocModel rsapin = db.GetTable<BenefitDocModel>().FirstOrDefault(x => x.PIN == pin);
//cmd.Notification = null;
string connS = "Data Source=;Initial Catalog=ServiceTest;User ID=;password = ;Integrated Security=true";
SqlCommand cmd = new SqlCommand();
//cmd.Notification = null;
cmd = new SqlCommand("SELECT UserID, Surname, Firstname, PIN, URL, Document_Name FROM dbo.BenefitDoc");
cmd.CommandType = CommandType.Text;
SqlQueueWatcher = new SqlWatcher(connS, cmd, SqlWatcherNotificationType.Blocking);
SqlQueueWatcher.OnChange += new SqlWatcher.SqlWatcherEventHandler(QueueSQLWatcher_OnChangeForLog);
cmd.Notification = null;
SqlQueueWatcher.Start();
}
private void QueueSQLWatcher_OnChangeForLog(DataSet Result)
{
try
{
Console.WriteLine("Database monitoring is starting....");
benefitCheck();
Console.WriteLine("Database monitoring completed.");
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public void sendEmail(string pin)
{
MailMessage mail = new MailMessage("", "");
SmtpClient client = new SmtpClient();
client.Port = 25;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Host = "smtp.gmail.com";
client.EnableSsl = true;
client.Credentials = new System.Net.NetworkCredential("", "");
mail.Subject = "New Record added for RSA with " + pin;
mail.Body = "The benefit application for user has been created.";
client.Send(mail);
}
public static void Stop()
{
SqlQueueWatcher.Dispose();
}
static void Main(string[] args)
{
Program n = new Program();
n.SQLServiceStartForLog();
Console.ReadLine();
}
}
}
That is not how SqlDependency works. Basically the way it works is you give it a query and if the query results change, it triggers a notification. But when you execute the datareader, it will not only return the changes. It returns data as if it was a regular query.
If you want to get only the changes, then you need to have a column in your table with something like LastModifiedDateTime and then query those records where LastModifiedDateTime is bigger than when you retrieved records the last time.
Alternatively, there is this NuGet package that will do this sort of thing for you if you are interested in using it.
Is there any way to register for an event that fires when an executable of a particular filename starts? I know it's easy enough to get an event when a process exits, by getting the process handle and registering for the exited event. But how can you be notified when a process, that isn't already running, starts...without polling all the running processes?
You could use the following:
private ManagementEventWatcher WatchForProcessStart(string processName)
{
string queryString =
"SELECT TargetInstance" +
" FROM __InstanceCreationEvent " +
"WITHIN 10 " +
" WHERE TargetInstance ISA 'Win32_Process' " +
" AND TargetInstance.Name = '" + processName + "'";
// The dot in the scope means use the current machine
string scope = #"\\.\root\CIMV2";
// Create a watcher and listen for events
ManagementEventWatcher watcher = new ManagementEventWatcher(scope, queryString);
watcher.EventArrived += ProcessStarted;
watcher.Start();
return watcher;
}
private ManagementEventWatcher WatchForProcessEnd(string processName)
{
string queryString =
"SELECT TargetInstance" +
" FROM __InstanceDeletionEvent " +
"WITHIN 10 " +
" WHERE TargetInstance ISA 'Win32_Process' " +
" AND TargetInstance.Name = '" + processName + "'";
// The dot in the scope means use the current machine
string scope = #"\\.\root\CIMV2";
// Create a watcher and listen for events
ManagementEventWatcher watcher = new ManagementEventWatcher(scope, queryString);
watcher.EventArrived += ProcessEnded;
watcher.Start();
return watcher;
}
private void ProcessEnded(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject targetInstance = (ManagementBaseObject) e.NewEvent.Properties["TargetInstance"].Value;
string processName = targetInstance.Properties["Name"].Value.ToString();
Console.WriteLine(String.Format("{0} process ended", processName));
}
private void ProcessStarted(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject targetInstance = (ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value;
string processName = targetInstance.Properties["Name"].Value.ToString();
Console.WriteLine(String.Format("{0} process started", processName));
}
You would then call either WatchForProcessStart and/or WatchForProcessEnd passing in your process name (eg "notepad.exe").
The ManagementEventWatcher object is returned from the two Watch* methods as it implements IDisposable and so you should call Dispose on these objects when you have finished with them to prevent issues.
You could also change the polling value in the queries if you need the event to be raised more quickly after the process has started. To do this change the line "WITHIN 10" to be WITHIN something less than 10.
WMI can create events when processes are created. You could then filter these events.
Here is code.
Notice that you have to start Visual Studio like Administrator in order to execute this code.
using System;
using System.Management;
namespace AppLaunchDetector
{
class Program
{
static void Main(string[] args)
{
ManagementEventWatcher w = null;
WqlEventQuery q;
try
{
q = new WqlEventQuery();
q.EventClassName = "Win32_ProcessStartTrace";
w = new ManagementEventWatcher(q);
w.EventArrived += new EventArrivedEventHandler(ProcessStartEventArrived);
w.Start();
Console.ReadLine(); // block main thread for test purposes
}
catch (Exception ex)
{
}
finally
{
w.Stop();
}
}
static void ProcessStartEventArrived(object sender, EventArrivedEventArgs e)
{
foreach (PropertyData pd in e.NewEvent.Properties)
{
Console.WriteLine("\n============================= =========");
Console.WriteLine("{0},{1},{2}", pd.Name, pd.Type, pd.Value);
}
}
}
}