WMI, Win32_Process - c#

I want to find which processes are using a particular dll using C# and WMI. Tried 3 approaches...
Getting CIM_DataFile object for the file and then get related processes.. It works for system dlls but not for My application dll.. It wont show any process associated with that even though process explorer shows the same.
Enumerating through all the processes and then enumerating through the process modules to find the DLL is being used or not.. Here also same issue.. working for system dlls but not for my application dlls.
Getting CIM_ProcessExecutables objects and getting DLLS/EXE and its linked processes... here also same thing is happening...
Is there anything im missing?
enter code here
using System;
using System.Management;
// Search the processes which have a certain file open
class App
{
public static void Main()
{
WhoHasThisFileOpen("c:\\\\users\\\\pawarnit\\\\source\\\\repos\\\\myprogram\\\\myprogram\\\\bin\\\\debug\\\\differentDllFile.dll");
Console.ReadLine();
}
static void WhoHasThisFileOpen(string objectQry)
{
SelectQuery query = new SelectQuery("select name from cim_datafile where name = '" + objectQry +"'" );
using (ManagementObjectSearcher searcher = new
ManagementObjectSearcher(query))
{
foreach (ManagementObject mo in searcher.Get())
{
Console.WriteLine("File Name: {0} \nIs currently opened by:",
mo.Properties["Name"].Value);
// Get processes having this File open
foreach (ManagementBaseObject b in mo.GetRelated("Win32_Process"))
{
ShowProcessProperties(b.ToString());
b.Dispose();
}
}
}
}
static void ShowProcessProperties(string objectClass)
{
using (ManagementObject process = new ManagementObject(objectClass))
{
process.Get();
PropertyDataCollection processProperties = process.Properties;
Console.WriteLine("ProcessID: {0,6} \tCommandLine: {1}",
processProperties["ProcessID"].Value,
processProperties["CommandLine"].Value);
}
}
}

Related

The best way get unique identification number from virtual machines, which will be the same on the main machine

I try to find a unique ID, which will be the same as the virtual machine and the main machine.
I tried using a monitor ID, bios number, but they can repeat for different end users.
using (ManagementObjectSearcher monitorSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DesktopMonitor"))
{
foreach (ManagementObject monitor in monitorSearcher.Get())
{
String MonitorName = monitor["Name"].ToString();
String MonitorId = monitor["DeviceId"].ToString();
Console.WriteLine("Monitor name: {0}", MonitorName);
Console.WriteLine("Monitor id: {0}", MonitorId);
}
}
ManagementClass managementClass = new ManagementClass("Win32_BIOS");
ManagementObjectCollection instances = managementClass.GetInstances();
foreach (ManagementBaseObject instance in instances)
{
string version = instance.Properties["SMBIOSBIOSVersion"].Value.ToString();
Console.WriteLine("The version is :" + version.ToString());
}
I read a lot and browsed various topics and forums, but nowhere can I find information or is it possible at all? Maybe there is at least one serial number which will be repeated on the main machine as well as on the virtual one?

Query User Sessions in Windows

There is a built-in tool: query.exe that allows you to view all active users and sessions in Windows.
It's output looks like:
PS C:\> query.exe user
USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME
>testusr console 1 Active none 12/16/2014 9:29 AM
Right now I have code that just parses the query.exe output, but some of us are concerned that future OS upgrades might change query's output so we're looking for an API call that can be used instead.
Is there anyway .Net way to gather the same information?
For alternatives, we don't necessary need all the fields, but we do need: Username, State, and Logon Time. We also need to run this code from the System context so any code or WMI classes that requires the user context won't work for us.
Well what I found and I think could be useful for you is Cassia project.
There is almost ready for you example in main page:
ITerminalServicesManager manager = new TerminalServicesManager();
using (ITerminalServer server = manager.GetLocalServer())
{
server.Open();
foreach (ITerminalServicesSession session in server.GetSessions())
{
Console.WriteLine("Hi there, " + session.UserAccount + " on session " + session.SessionId);
Console.WriteLine("It looks like you logged on at " + session.LoginTime +
" and are now " + session.ConnectionState);
}
}
As you can see when you get a TerminalServicesSession you will find UserName, LoginTime and ConnectionState.
Hope this will help you.
You can simply get the last logon time using WMI:
using System;
using System.Management;
using System.Windows.Forms;
namespace WMISample
{
public class MyWMIQuery
{
public static void Main()
{
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_LogonSession");
foreach (ManagementObject queryObj in searcher.Get())
{
Console.WriteLine("-----------------------------------");
Console.WriteLine("Win32_LogonSession instance");
Console.WriteLine("-----------------------------------");
Console.WriteLine("Last Logon: {0}", queryObj["StartTime"]);
}
}
catch (ManagementException e)
{
MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
}
}
}
}
Sounds like you want NetWkstaUserEnum. I couldn't find a native .NET version of this but it seems like a fairly light interop call.

Simple C# WMI Get & Put

I am trying to Read & Put values from and to WMI using C#.
The current example uses ccm namespace, for configmgr client.
The read functions works correctly, able to read ADV_RepeatRunBehavior value.
Though the Put(); doesn't work as expected, the values are not stored back and Invalid Class exception is thrown.
Some advice would be nice as I am new to this, many thanks.
static void Main(string[] args)
{
try
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher(
"root\\ccm\\Policy\\Machine",
"SELECT * FROM CCM_SoftwareDistribution WHERE PKG_PackageID='XXXXXXXX'");
foreach (ManagementObject queryObj in searcher.Get())
{
//Read works
//Console.WriteLine(queryObj["ADV_RepeatRunBehavior"].ToString());
//Console.ReadLine();
//Put doesn't
queryObj["ADV_RepeatRunBehavior"] = "RerunNever";
queryObj.Put();
}
}
catch (ManagementException z)
{
Console.WriteLine("An error occurred: " + z.Message);
Console.ReadLine();
}
}
Found the resolution for this.
You have to run Visual Studio as Administrator if testing on localhost
The connection to WMI has to be \\root\\ccm\\Policy\\Machine\\ActualConfig then its possible to Put() values.

C# List currently open files and programs

Is there a way I can get a list of all open applications and a list of all open files? For the files I only need the files that I opened (documents etc) not OS's open system files. The same for the applications (only browsers, document processors etc).
I already tried various functions from the Windows API like EnumWindows but I couldn't get what I wanted.
An example of what my ultimate goal would be, is to have lists like this:
Applications
Microsoft Word,
Notepad,
Mozilla Firefox
Files
foo.txt,
foo.mp3,
foo.doc
What I need is just the names, I don't need handles etc (even though I'm sure I'll have to use them to get what I want)
You can get a list of running processes with their information
public static string ListAllProcesses()
{
StringBuilder sb = new StringBuilder();
// list out all processes and write them into a stringbuilder
ManagementClass MgmtClass = new ManagementClass("Win32_Process");
foreach (ManagementObject mo in MgmtClass.GetInstances())
{
sb.Append("Name:\t" + mo["Name"] + Environment.NewLine);
sb.Append("ID:\t" + mo["ProcessId"] + Environment.NewLine);
sb.Append(Environment.NewLine);
}
return sb.ToString();
}
The only method (That I know) to see if the process is opened by user or system is to check it's owner. If it's system, then it's not run by user:
//You will need to reference System.Management.Dll and use System.Management namespace
public string GetProcessOwner(string processName)
{
string query = "Select * from Win32_Process Where Name = \"" + processName + "\"";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection processList = searcher.Get();
foreach (ManagementObject obj in processList)
{
string[] argList = new string[] { string.Empty, string.Empty };
int returnVal = Convert.ToInt32(obj.InvokeMethod("GetOwner", argList));
if (returnVal == 0)
{
// return DOMAIN\user
string owner = argList[1] + "\\" + argList[0];
return owner;
}
}
return "NO OWNER";
}
For the list of opened files, It is possible to do using Managed Code which is somehow hard. Here is an example on codeproject demonstrating the same matter
You can have a list of running processes with Process.GetProcesses(): http://msdn.microsoft.com/en-us/library/1f3ys1f9.aspx
But you can have the file they have open if they exposes some automation interface you know.

How do I retrieve the username that a Windows service is running under?

Given a service name, I would like to retrieve the username that it runs under (i.e. the username shown in the 'Log On' tab of a service's properties window).
There doesn't appear to be anything in the ServiceController class to retrieve this basic information. Nothing else in System.ServiceProcess looks like it exposes this information either.
Is there a managed solution to this, or am I going to have to drop down into something lower-level?
Using WMI, with the System.Management you can try the following code:
using System;
namespace WindowsServiceTest
{
class Program
{
static void Main(string[] args)
{
System.Management.SelectQuery sQuery = new System.Management.SelectQuery(string.Format("select name, startname from Win32_Service")); // where name = '{0}'", "MCShield.exe"));
using (System.Management.ManagementObjectSearcher mgmtSearcher = new System.Management.ManagementObjectSearcher(sQuery))
{
foreach (System.Management.ManagementObject service in mgmtSearcher.Get())
{
string servicelogondetails =
string.Format("Name: {0} , Logon : {1} ", service["Name"].ToString(), service["startname"]).ToString();
Console.WriteLine(servicelogondetails);
}
}
Console.ReadLine();
}
}
}
You can then later substitute the commented code with your service name, and it should only return the instances of your service process that is running.
WMI is your friend. Look at Win32_Service, specifically the StartName property. You can access WMI from C# via the System.Management.ManagementClass.
If you've not used WMI before, this article seems to be quite a good tutorial.
You can find this using the Windows Registry, reading the following string value, replacing [SERVICE_NAME] with the name of the Windows Service:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\[SERVICE_NAME]\ObjectName
Try this:
System.Security.Principal.WindowsIdentity.GetCurrent();
but the most obvious you will get LOCAL SYSTEM or NETWORK. The reason that you cannot show this user - that service can manage multiple users (shared by desktop, attached to current windows session, using shared resource ...)
System starts service, but any user can use it.
This solution works fine for me:
ManagementObject wmiService = new ManagementObject("Win32_Service.Name='" + this.ServiceName + "'");
wmiService.Get();
string user = wmiService["startname"].ToString();
public String getUsername() {
string username = null;
try {
ManagementScope ms = new ManagementScope("\\\\.\\root\\cimv2");
ms.Connect();
ObjectQuery query = new ObjectQuery
("SELECT * FROM Win32_ComputerSystem");
ManagementObjectSearcher searcher =
new ManagementObjectSearcher(ms, query);
foreach (ManagementObject mo in searcher.Get()) {
username = mo["UserName"].ToString();
}
string[] usernameParts = username.Split('\\');
username = usernameParts[usernameParts.Length - 1];
} catch (Exception) {
username = "SYSTEM";
}
return username;
}

Categories