I am working on WMI(Windows Management Instrumentation) in C# and stuck at a point.
I have to create an application using WMI (C#) similar to File System Watcher.
I would like to get notified every time whenever within a particular folder a new file is created or deleted.
MY WQL query is :
SELECT * from _InstanceModificationEvent within 2 where TargetInstance ISA 'CIM_DataFile' and TargetInstance.Drive = 'C:' AND TargetInstance.Path='\\Test'
While running the query using wbemtest , it displays an Error message prompting Invalid Class.
Can someone please help me out regarding same?
In order to detect when a file is created , modified or deleted you must use the __InstanceOperationEvent WMI Class and the using the value of __Class property you can figure out out if the file was modified, deleted o created.
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)
{
// e.NewEvent
string wclass = ((ManagementBaseObject)e.NewEvent).SystemProperties["__Class"].Value.ToString();
string wop = string.Empty;
switch (wclass)
{
case "__InstanceModificationEvent":
wop = "Modified";
break;
case "__InstanceCreationEvent":
wop = "Created";
break;
case "__InstanceDeletionEvent":
wop = "Deleted";
break;
}
string wfilename = ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["FileName"].ToString();
if (!string.IsNullOrEmpty(((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["Extension"].ToString()))
{
wfilename += "." + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["Extension"].ToString();
}
Console.WriteLine(String.Format("The File {0} was {1}", wfilename, wop));
}
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();
//Check for changes in the path C:\Test
WmiQuery = #"Select * From __InstanceOperationEvent Within 1
Where TargetInstance ISA 'CIM_DataFile' and TargetInstance.Drive = 'C:' AND TargetInstance.Path='\\Test\\'";
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}", "__InstanceOperationEvent");
Console.WriteLine("Press Enter to exit");
EventWatcherAsync eventWatcher = new EventWatcherAsync();
Console.Read();
}
}
}
Related
There was such a problem: I ran the program many times and now it throws the following error FloodException: Flood prevention. Telegram now requires your program to do requests again only after 73611 seconds have passed (TimeToWait property). If you think the culprit of this problem may lie in TLSharp's implementation, open a Github issue please.
I attach the code below:
using System;
using System.Text;
using System.Windows.Forms;
using TeleSharp.TL;
using TeleSharp.TL.Messages;
using TLSharp.Core;
namespace tgBM
{
public partial class Form1: Form
{
string phone;
string code;
int n = 1;
StringBuilder sb = new StringBuilder ();
TelegramClient client = new TelegramClient (2646156, "08ec188e0bdee432e568120348f5f13a"); // create a client with parameters
public Form1 ()
{
InitializeComponent();
}
string str = "";
public async void authAsync()
{
var dialogs = (TLDialogs) await client.GetUserDialogsAsync();
foreach (var element in dialogs.Chats)
{
TLChat chat = element as TLChat;
if (element is TLChannel)
{
var offset = 0;
TLChannel channel = element as TLChannel;
if (channel.Title == "TOPLES")
{
TLChannel ch = element as TLChannel;
TLInputPeerChannel inputPeer = new TLInputPeerChannel() {ChannelId = ch.Id, AccessHash = (long) ch.AccessHash};
while (n! = 11)
{
try
{
TLChannelMessages res = await client.SendRequestAsync <TLChannelMessages>
(new TLRequestGetHistory() {Peer = inputPeer, Limit = 20, AddOffset = offset, OffsetId = 0});
var msgs = res.Messages;
if (res.Count> offset)
{
offset + = msgs.Count;
foreach (TLAbsMessage msg in msgs)
{
if (msg is TLMessage)
{
TLMessage message = msg as TLMessage;
str + = n.ToString () + "\ t" + message.Id + "\ t" + message.FromId + "\ t" + message.Message + Environment.NewLine;
}
if (msg is TLMessageService)
continue;
n ++;
}
}
else
break;
}
catch (Exception ex)
{
MessageBox.Show (ex.Message);
break;
}
}
}
}
textBox3.Text = str;
}
}
private async void button1_Click (object sender, EventArgs e)
{
phone = textBox1.Text;
await client.ConnectAsync (); // make a connection
var hash = await client.SendCodeRequestAsync(phone);
}
private async void button2_Click (object sender, EventArgs e)
{
code = textBox2.Text;
var user = await client.MakeAuthAsync(phone, await client.SendCodeRequestAsync(phone), code);
authAsync();
}
}
}
In a comment, you said are in a testing phase.
In this case, you should read https://core.telegram.org/api/auth#test-accounts
According to this page, there are 3 ways to perform tests while limiting the risk for FLOOD_WAIT errors:
Connect to the Test servers instead of the Production servers (seems not possible with TLSharp)
Use Test accounts with phone numbers 99966XYYYY (only available on Test servers)
Connect as a user with the phone number you use to create the API ID/Hash
I can do all that with WTelegramClient (TLSharp is no longer maintained and cannot connect to Telegram servers anymore)
I have a problem with Running the Windows Service. Service is connecting DB and through DataAdapter it creates local XML file. Then it transfer the file to the FTP server.
Get error 1064 when trying to start the service.
I checked and the error occurs when trying to create XML file from DB. I guese it's DB connection but don't know how to fix it.
When i run this code as Console app it works pretty well, no errors occures, but when i run it as windows service it is occuring :/ Maybe it is something with Connection string? or with Creating XML file throught DataAdapter? What's the difference here between Console App and windows service Connection to DB?
To check it, I commented out the part with connection to DB (CreateXML() method) and it works too, so FTP connection is not an issue.
I marked with comment the line of code which throw an error, it's located in the CreateXML() Method.
You have full code here
EDIT (solution):
If you have the same problem change Service to use your win account. Works without errors now.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.ServiceProcess;
using System.Timers;
namespace XMLShopService
{
public partial class XMLShopService : ServiceBase
{
Timer timer = new Timer();
//TIME MULTIPLIERS
private static int seconds = 1000; //miliseconds to SECONDS multiplier -- DON'T TOUCH --
private static int minutes = 60000; //miliseconds to MINUTES multiplier -- DON'T TOUCH --
private static int hours = 3600000; //miliseconds to HOURS multiplier -- DON'T TOUCH --
//TIME INTERVAL SETTINGS
private int timeInterval = 3; //SET HERE - time interval in (SECONDS or MINUTES or HOURS), then pick timeMultiplier below
private int timeMultiplier = minutes; //SET HERE - time format you would like to use in timer as interval (SECONDS or MINUTES or HOURS) pick one from above and implement after "="
public XMLShopService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Debugger.Launch();
WriteToFile("START : " + DateTime.Now);
CreateXML();
FtpFileUpload();
//TIMER
timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
timer.Interval = timeInterval * timeMultiplier; // -- DON'T TOUCH -- Represent time interval in MILISECONDS
timer.Enabled = true;
}
protected override void OnStop()
{
WriteToFile("STOP : " + DateTime.Now);
}
//FUNCTIONS USED
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
WriteToFile("ReStart script at : " + DateTime.Now);
CreateXML();
FtpFileUpload();
WriteToFile("Script finished at : " + DateTime.Now);
}
private void CreateXML()
{
//XML file settings
string fileName = "file.xml"; //SET HERE - XML local file name
string localFilePath = #"path" + fileName; //SET HERE - XML local file path (full)
double priceMultiplier = 3; //SET HERE - price multiplier
//SQL Query - products codes & prices * multiplier
string queryString = "SELECT ItemCode, Price * " + priceMultiplier + " FROM database WHERE PriceList = 1 AND Price > 0";
//SQL connection string
SqlConnection conn = new SqlConnection();
conn.ConnectionString = #"Server=server;" + //SET HERE - SQL Server
"Initial Catalog=database;" + //SET HERE - Server database
"Integrated Security=true";
//Creating XML file in the specific location, overwriting old file
try
{
using (SqlCommand sqlComm = new SqlCommand(queryString, conn) { CommandType = CommandType.Text })
{
WriteToFile("SQL 1: " + DateTime.Now);
SqlDataAdapter da = new SqlDataAdapter(sqlComm);
WriteToFile("SQL 2: " + DateTime.Now);
DataSet ds = new DataSet();
da.Fill(ds); //!!!---THIS IS WHERE ERROR OCCURS---!!!
WriteToFile("SQL 3: " + DateTime.Now);
ds.Tables[0].WriteXml(localFilePath);
WriteToFile("SQL 4: " + DateTime.Now);
}
WriteToFile("DB connection ok: " + DateTime.Now);
}
catch (Exception)
{
WriteToFile("ERROR - create file: " + DateTime.Now);
throw;
}
}
private void FtpFileUpload()
{
string ftpUsername = "userName"; //SET HERE - FTP username
string ftpPassword = "pass"; //SET HERE - FTP Password
string ftpFolderPath = #"ftpServerPath/test/"; //SET HERE - FTP folder dir -- TODO: TEST FOLDER PATH TO CHANGE --
string fileName = "file.xml"; //SET HERE - XML local file name
string localFilePath = #"path" + fileName; //SET HERE - XML local file dir (full)
//DELETE old file
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpFolderPath + fileName);
request.Method = WebRequestMethods.Ftp.DeleteFile;
request.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
WriteToFile(response.StatusDescription + " " + DateTime.Now);
}
}
//Throw on errors
catch (Exception)
{
WriteToFile("ERROR - delete old file: " + DateTime.Now);
throw;
}
//UPLOAD UpToDate file
try
{
//Set request
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpFolderPath + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
request.UsePassive = true;
request.UseBinary = true;
request.KeepAlive = true;
//Load file
FileStream stream = File.OpenRead(localFilePath);
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, buffer.Length);
stream.Close();
//Upload file
Stream reqStream = request.GetRequestStream();
reqStream.Write(buffer, 0, buffer.Length);
reqStream.Close();
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
WriteToFile(response.StatusDescription + " " + DateTime.Now);
}
request = null;
}
//Throw on errors
catch (Exception)
{
WriteToFile("ERROR - upload UpToDate file: " + DateTime.Now);
throw;
}
}
//SCRIPT LOGS
public void WriteToFile(string Message)
{
string path = AppDomain.CurrentDomain.BaseDirectory + "\\Logs";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string filepath = AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\ServiceLog.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);
}
}
}
}
}
Sorry if someone just posts a link to the answer, but I was really struggling to google this.
I can't figure out how to detect mobile phones when they're plugged in and then access their storage. The former is just something I don't know where to start looking and the second befuddles me a little because I'm used to accessing storage with a drive letter. The phones I've used (iPhone 4S and a few different Samsung galaxy's and notes) don't have a drive letter. So where would I start?
I use C# but I'm comfortable with the dllimports etc.
I've now done this code from the thread I linked in a comment above, nice and easy to throw into a program.
using System;
using System.Management;
using System.Threading;
namespace USBDeviceTester
{
class Program
{
static void Main(string[] args)
{
Thread myThread = new Thread(new ThreadStart(ThreadWorker));
myThread.Start();
}
public static void ThreadWorker()
{
WqlEventQuery insertQuery = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher insertWatcher = new ManagementEventWatcher(insertQuery);
insertWatcher.EventArrived += new EventArrivedEventHandler(DeviceInsertedEvent);
insertWatcher.Start();
WqlEventQuery removeQuery = new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'");
ManagementEventWatcher removeWatcher = new ManagementEventWatcher(removeQuery);
removeWatcher.EventArrived += new EventArrivedEventHandler(DeviceRemovedEvent);
removeWatcher.Start();
// Do something while waiting for events
System.Threading.Thread.Sleep(20000000);
}
private static void DeviceInsertedEvent(object sender, EventArrivedEventArgs e)
{
Console.WriteLine("");
Console.WriteLine(" --- DEVICE INSERTED ---");
Console.WriteLine("");
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
foreach (var property in instance.Properties)
{
Console.WriteLine(property.Name + " = " + property.Value);
}
Console.WriteLine("");
}
static void DeviceRemovedEvent(object sender, EventArrivedEventArgs e)
{
Console.WriteLine("");
Console.WriteLine(" --- DEVICE REMOVED ---");
Console.WriteLine("");
//ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
//foreach (var property in instance.Properties)
//{
// Console.WriteLine(property.Name + " = " + property.Value);
//}
}
}
}
Which returns information as so:
--- DEVICE REMOVED ---
--- DEVICE INSERTED ---
Availability =
Caption = Apple Mobile Device USB Driver
ClassCode =
ConfigManagerErrorCode = 0
ConfigManagerUserConfig = False
CreationClassName = Win32_USBHub
CurrentAlternateSettings =
CurrentConfigValue =
Description = Apple Mobile Device USB Driver
DeviceID = USB\VID_05AC&PID_12A0\3ABFD2ED02E3982B5F4455FD684716A6D4958A74
ErrorCleared =
ErrorDescription =
GangSwitched =
InstallDate =
LastErrorCode =
Name = Apple Mobile Device USB Driver
NumberOfConfigs =
NumberOfPorts =
PNPDeviceID = USB\VID_05AC&PID_12A0\3ABFD2ED02E3982B5F4455FD684716A6D4958A74
PowerManagementCapabilities =
PowerManagementSupported =
ProtocolCode =
Status = OK
StatusInfo =
SubclassCode =
SystemCreationClassName = Win32_ComputerSystem
SystemName = MyComputerName
USBVersion =
I have two network adapters in my machine. E.g. adapter A and adapter B. The A keeps connected
I want to monitor the connection status of adapter B. I mean, connected or disconnected status.
I tried the System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged
But it doesn't work, since the adapter A connected.
Maybe WMI is helpful, but I don't have any experience about it, also didn't find much useful article.
Could any one help to show me
how to subscribe WMI event of the adapter A connection status in C#
You can use the Win32_NetworkAdapter WMI class and the NetConnectionStatus property with the __InstanceModificationEvent event.
The WQL sentence will look like so
Select * From __InstanceModificationEvent Within 1 Where TargetInstance ISA 'Win32_NetworkAdapter' AND TargetInstance.Name='Network adapter name'
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"]);
//2 (0x2) Connected
//7 (0x7) Media disconnected
Console.WriteLine("TargetInstance.NetConnectionStatus : " + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["NetConnectionStatus"]);
}
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_NetworkAdapter' AND TargetInstance.Name='Tarjeta Mini de media altura WLAN Wireless-N DW1501' ";
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();
}
}
}
the goal is like i said in the Topic. I know there are a lot of articles on that specific Problem and i tried all most all of them.
But since non of them worked out for me, I'm now trying to find out why this one just works sometimes and sometimes nothing is happening although many things are printed.
So this is my code which right now should wait for a job to be printed and just tell me about it. Nothing more.
private void StartMonitor()
{
try
{
var opt = new ConnectionOptions { EnablePrivileges = true };
var scope = new ManagementScope("root\\CIMV2", opt);
scope.Connect();
var query = new WqlEventQuery("SELECT * FROM __InstanceOperationEvent WITHIN 60 WHERE TargetInstance ISA \"Win32_PrintJob\"");
var watcher = new ManagementEventWatcher(query);
Console.WriteLine("Ready to receive Printer Job events...");
var pjEvent = watcher.WaitForNextEvent();
if (pjEvent != null) Console.WriteLine("Event occured: " + pjEvent.Properties["PagesPrinted"]);
}
catch (ManagementException e)
{
Console.WriteLine(e.StackTrace);
Console.WriteLine(e.ErrorCode);
Console.WriteLine(e.ErrorInformation);
_Error = e.Message;
throw;
}
}
To get the progress of the printed pages for a particular job, try using a smaller polling interval and use the EventArrivedEventHandler delegate attached to the WMI event for handling the incoming data in a asynchronous way.
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.Caption : " + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["Caption"]);
Console.WriteLine("TargetInstance.JobStatus : " + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["JobStatus"]);
Console.WriteLine("TargetInstance.PagesPrinted : " + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["PagesPrinted"]);
Console.WriteLine("TargetInstance.Status : " + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["Status"]);
}
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 __InstanceOperationEvent Within 1 "+
"Where TargetInstance ISA 'Win32_PrintJob' ";
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}", "__InstanceOperationEvent");
Console.WriteLine("Press Enter to exit");
EventWatcherAsync eventWatcher = new EventWatcherAsync();
Console.Read();
}
}
}
To get the total pages printed by a job I would try monitoring __InstanceDeletionEvents, I believe that at that time Win32_PrintJob.TotalPages should show the printed pages accurately (can't test this right now, sorry). There is also a nice alternative here:
Monitoring a Printer Queue from VB.NET
If you look at the article comments, the author also advises to monitor JOB_WRITTEN events to get the total number of pages printed.
If you are trying to monitor the progress of large print jobs, try monitoring __InstanceModificationEvents once the job is created, something like this:
Select * From __InstanceModificationEvent Within 1
Where TargetInstance Isa "Win32_PrintJob"
And TargetInstance.PagesPrinted > PreviousInstance.PagesPrinted