Retrieving Process Description Information - c#

I am trying to retrieve process information and I'm aware that I can use:
Process[] myProcesses = Process.GetProcesses();
but how do I retrieve the process description? Is it via some Win32 API call? I'm running Vista and when I click under the Processes tab in Task Manager, I see the description.

What you see in Task Manager is actually the Description field of the executable image.
You can use the GetFileVersionInfo() and VerQueryValue() WinAPI calls to access various version informations, e.g. CompanyName or FileDescription.
For .Net way, use the FileDescription member of FileVersionInfo, instantiated with the executable name got via Process.MainModule.FileName.
Another way would be through Assembly. Load the Assembly from the executable image, then query the AssemblyDescriptionAttribute custom attribute.

You just have to go a bit further down the properties.
Suppose you have an instance of notepad running.
Process[] proc = Process.GetProcessesByName("notepad");
Console.WriteLine("Process version- " + proc[0].MainModule.FileVersionInfo.FileVersion);
Console.WriteLine("Process description- " + proc[0].MainModule.FileVersionInfo.FileDescription);
There you go !

This is the only way I could see to do it. I tried Process and Win32_Process, but no go.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Diagnostics;
namespace Management
{
class Program
{
static void Main(string[] args)
{
var ps = Process.GetProcesses();
foreach (var p in ps)
{
try
{
var desc = FileVersionInfo.GetVersionInfo(p.MainModule.FileName);
Console.WriteLine(desc.FileDescription);
}
catch
{
Console.WriteLine("Access Denied");
}
}
Console.ReadLine();
}
}
}

Related

How to get user input data from a console program to a c# program?

How to get a user entered inputs in a console application (test app) to a c# program (monitor app)? I have successfully got a string value to my monitor app from the console that is hard corded in the test app. Now I want to allow the user to input a string from the console in test app and I want to capture that user entered string in test app from my monitored app.
Here are the test app and monitor app codes.
test app
using System;
namespace TestApp
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Test2");
Console.Write("Enter a string ");
string txtOne = Console.ReadLine();
Console.WriteLine(txtOne);
//Console.ReadLine();
}
}
}
monitor app code
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace GetStandardOutput
{
class Program
{
static void Main()
{
//
// Setup the process with the ProcessStartInfo class.
//
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = #"C:\Users\erandaka\Documents\Visual Studio 2015\Projects\TestApp\TestApp\bin\Debug\TestApp.exe"; // Specify exe name.
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
//
// Start the process.
//
using (Process process = Process.Start(start))
{
//
// Read in all the text from the process with the StreamReader.
//
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
Console.ReadLine();
}
}
}
}
}
Create a function to retrieve the desired value of the c program.
Use DLLImport, to call the function from your C# program:
https://msdn.microsoft.com/en-us/library/aa984739(v=vs.71).aspx

TestStack.White and CCleaner

I've very new to the TestStack (White) UI Automation library and I'm having a bit of an issue in terms of "hooking" the process. I'm trying to hook CCleaner, but I keep getting
An unhandled exception of type 'TestStack.White.AutomationException'
occurred in TestStack.White.dll
Additional information: Couldn't find window with title Piriform
CCleaner in process 1156, after waiting for 30 seconds:
My current code is:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using TestStack.White;
using TestStack.White.Factory;
using TestStack.White.UIItems.Finders;
using TestStack.White.InputDevices;
using TestStack.White.UIItems.WindowItems;
namespace NightWipe
{
class Program
{
private const string ExeSourceFile = #"C:\Program Files\CCleaner\CCleaner.exe";
private static TestStack.White.Application _application;
private static TestStack.White.UIItems.WindowItems.Window _mainWindow;
static void Main(string[] args)
{
clean();
}
public static string clean()
{
var psi = new ProcessStartInfo(ExeSourceFile);
_application = TestStack.White.Application.AttachOrLaunch(psi);
_mainWindow = _application.GetWindow("Piriform CCleaner");
_mainWindow.WaitWhileBusy();
return "";
}
}
}
I thought that maybe it was the name of the process since CCleaner starts another process (not CCleaner.exe) but CCleaner64.exe as seen here, which I can assume is for 64 bit operating systems maybe? Anyway I tried names including: "CCleaner", "CCleaner64"; but this threw the same exact exception.
I'm using Inspect by Microsoft and this is what it pulls for me (large image):
Inspect's information. Any idea what I'm doing wrong here?
The problem is that CCleaner is visible as WIN32 app. So GetWindow() doesn't work. You can try this code:
public void CCleanerSample()
{
var application = Application.AttachOrLaunch(new ProcessStartInfo(#"C:\Program Files\CCleaner\CCleaner.exe"));
AutomationElement ccleanerAutomationElement = null;
Console.Write("Waiting till WIN32 app is launching");
while (ccleanerAutomationElement == null)
{
ccleanerAutomationElement = AutomationElement.RootElement.FindFirst(TreeScope.Children,
new PropertyCondition(AutomationElement.NameProperty, "Piriform CCleaner"));
Thread.Sleep(1000);
Console.Write(".");
}
Console.WriteLine(" Done");
var mainWindow = new Win32Window(ccleanerAutomationElement, WindowFactory.Desktop, InitializeOption.NoCache,
new WindowSession(application.ApplicationSession, InitializeOption.NoCache));
}

Get Printer Names and number of trays

I was trying to display all available printer names on the server and number of trays associated to them. How to display number of trays associated to the printer?
I used the following code. It works but it doesn't display communicate with the all the information. Should I include messageBox? How to display all these information?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Printing;
using System.Drawing.Printing;
using System.Management;
namespace Find
{
class Program
{
static void Main(string[] args)
{
var printerQuery = new ManagementObjectSearcher("SELECT * from Win32_Printer");
foreach (var printer in printerQuery.Get())
{
var name = printer.GetPropertyValue("Name");
var status = printer.GetPropertyValue("Status");
var isDefault = printer.GetPropertyValue("Default");
var isNetworkPrinter = printer.GetPropertyValue("Network");
Console.WriteLine("{0} (Status: {1}, Default: {2}, Network: {3}",
name, status, isDefault, isNetworkPrinter);
}
}
}
}
Your code works fine for me. It's likely that your console window is displaying the information very quickly and then exiting. Try adding Console.ReadKey() at the end of your Main method, so that the Console session remains after displaying the information.
At the end of your Main method, add something like:
Console.Write("\nDone! Press any key to exit...");
Console.ReadKey();

Would you share your idea how to call python command from embedded Python.Net?

I've been played with Python.Net for a week, but I can't find any sample code to use Python.Net in embedded way although Python.Net source has several embeddeding tests. I've searched many threads from the previous emailing list (Python.Net), the results are not consistent and are clueless.
What I'm trying to do is to get result (PyObject po) from C# code after executing python command such as 'print 2+3' from python prompt via Python.Net because IronPython doesn't have compatibility with the module that I currently using.
When I executed it from nPython.exe, it prints out 5 as I expected. However, when I run this code from embedded way from C#. it returns 'null' always. Would you give me some thoughts how I can get the execution result?
Thank you,
Spark.
Enviroments:
1. Windows 2008 R2, .Net 4.0. Compiled Python.Net with Python27, UCS2 at VS2012
2. nPython.exe works fine to run 'print 2+3'
using NUnit.Framework;
using Python.Runtime;
namespace CommonTest
{
[TestFixture]
public class PythonTests
{
public PythonTests()
{
}
[Test]
public void CommonPythonTests()
{
PythonEngine.Initialize();
IntPtr gs = PythonEngine.AcquireLock();
PyObject po = PythonEngine.RunString("print 2+3");
PythonEngine.ReleaseLock(gs);
PythonEngine.Shutdown();
}
}
}
It seems like PythonEngine.RunString() doesn't work. Instead, PythonEngine.RunSimpleString() works fine.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Reflection;
using Python.Runtime;
namespace npythontest
{
public class Program
{
static void Main(string[] args)
{
string external_file = "c:\\\\temp\\\\a.py";
Console.WriteLine("Hello World!");
PythonEngine.Initialize();
IntPtr pythonLock = PythonEngine.AcquireLock();
var mod = Python.Runtime.PythonEngine.ImportModule("os.path");
var ret = mod.InvokeMethod("join", new Python.Runtime.PyString("my"), new Python.Runtime.PyString("path"));
Console.WriteLine(mod);
Console.WriteLine(ret);
PythonEngine.RunSimpleString("import os.path\n");
PythonEngine.RunSimpleString("p = os.path.join(\"other\",\"path\")\n");
PythonEngine.RunSimpleString("print p\n");
PythonEngine.RunSimpleString("print 3+2");
PythonEngine.RunSimpleString("execfile('" + external_file + "')");
PythonEngine.ReleaseLock(pythonLock);
PythonEngine.Shutdown();
}
}
}

Powershell Command in C#

I am trying to query the names all of the WMI classes within the root\CIMV2 namespace. Is there a way to use a powershell command to retrieve this information in C# ?
Along the lines of Keith's approach
using System;
using System.Management.Automation;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var script = #"
Get-WmiObject -list -namespace root\cimv2 | Foreach {$_.Name}
";
var powerShell = PowerShell.Create();
powerShell.AddScript(script);
foreach (var className in powerShell.Invoke())
{
Console.WriteLine(className);
}
}
}
}
I'm not sure why you mentioned PowerShell; you can do this in pure C# and WMI (the System.Management namespace, that is).
To get a list of all WMI classes, use the SELECT * FROM Meta_Class query:
using System.Management;
...
try
{
EnumerationOptions options = new EnumerationOptions();
options.ReturnImmediately = true;
options.Rewindable = false;
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\cimv2", "SELECT * FROM Meta_Class", options);
ManagementObjectCollection classes = searcher.Get();
foreach (ManagementClass cls in classes)
{
Console.WriteLine(cls.ClassPath.ClassName);
}
}
catch (ManagementException exception)
{
Console.WriteLine(exception.Message);
}
Personally I would go with Helen's approach and eliminate taking a dependency on PowerShell. That said, here's how you would code this in C# to use PowerShell to retrieve the desired info:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Management.Automation;
namespace RunspaceInvokeExp
{
class Program
{
static void Main()
{
using (var invoker = new RunspaceInvoke())
{
string command = #"Get-WmiObject -list -namespace root\cimv2" +
" | Foreach {$_.Name}";
Collection<PSObject> results = invoker.Invoke(command);
var classNames = results.Select(ps => (string)ps.BaseObject);
foreach (var name in classNames)
{
Console.WriteLine(name);
}
}
}
}
}
Just to note that there is a tool available that allows you to create, run, and save WMI scripts written in PowerShell, the PowerShell Scriptomatic tool, available for download from the Microsoft TechNet site.
Using this tool, you could explore all of the WMI classes within the root\CIMV2 or any other WMI namespace.
You'd probably want to just use the System.Management namespace like Helen answered, but you can also host powershell within your application. See http://www.codeproject.com/KB/cs/HowToRunPowerShell.aspx

Categories