Windows 8 taskmanager app history in C# - c#

I am trying to access application history from C#. I would like to present same information as in task manager, but I cannot find api/example. Of course I implement a desktop application.
To specify problem: I am not interested on CPU/RAM. The only thing I would like to get is Time.
UPDATE
To exactly show what I am talking about look at this screen:

There is no supported way to get this information. Sorry.

The description of the questions lacks details that you are talking about Metro Apps. The solution would be an equivalent of Process.TotalProcessorTime but for Metro Apps.
Unfortunately, you cannot get that information because as you stated the applications are running within another process (WWAHost.exe). The design of Metro is a bit more like the phone - you can't directly manipulate the system in the same way. There isn't a directly "Process" in the Windows Runtime (see here), which in turn means the Process class wouldn't make sense to port...

I assume by The only thing I would like to get is Time. you mean the start and end time of each process
The best way will be that you will have to build that history your self. If you need the history only when your application is running then you just implement the code bellow otherwise if you wish to build the history for a certain period even when your application is down then try to create a Windows service that does the job for you. Following are the steps you need to do assuming you know how to create a windows service project, compile and install it:
Getting running processes info :
using System;
using System.Diagnostics;
public static class ProcessStart
{
Process[] runningProcesses;
var processesStartTimes = new Dictionary<int, Datetime>();
var processesExitTimes = new Dictionary<int, Datetime>();
static ProcessStart()
{
// This will get current running processes
runningProcesses = Process.GetProcesses();
foreach (var p in processes)
{
p.Exited += new EventHandler(ProcessExited);
processesStartTimes.Add(p.Id, p.StartTime);
}
}
private void ProcessExited(object sender, System.EventArgs e)
{
var p = (Process)sender;
processesExitTimes.Add(p.Id, p.ExitTime);
}
}
Getting new started processes
You need to create a new Timer object and run it every second checking for new created processes. I copied the code above and extended it :
public static class ProcessStart
{
Process[] runningProcesses;
var processesStartTimes = new Dictionary<int, Datetime>();
var processesExitTimes = new Dictionary<int, Datetime>();
var updateTimer = new Timer(1000);
static ProcessStart()
{
// This will get current running processes
runningProcesses = Process.GetProcesses();
foreach (var p in processes)
{
p.Exited += new EventHandler(ProcessExited);
processesStartTimes.Add(p.Id, p.StartTime);
}
updateTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}
private void ProcessExited(object sender, System.EventArgs e)
{
var p = (Process)sender;
processesExitTimes.Add(p.Id, p.ExitTime);
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
runningProcesses = Process.GetProcesses();
foreach (var p in processes)
{
// This will only add the processes that are not added yet
if (!processesStartTimes.Keys.Contains(p.Id))
{
p.Exited += new EventHandler(ProcessExited);
processesStartTimes.Add(p.Id, p.StartTime);
}
}
}
}
Finally :
You just then need to play with the System.Diagnostics.Process class. That should be your best way for getting all information you need about windows processes. It will grant you access to a wide range of properties and methods. Here is the official MSDN lik for it:
Process Class
EDIT :
As I can see from your comment, you are interested in the time the CPU have spent running a specific process. The same System.Diagnostics.Process class contains that info as well. That can be found using the Process.PrivilegedProcessorTime property. The MSDN description for this property is :
A TimeSpan that indicates the amount of time that the process has spent running code inside the operating system core.
More information Here
EDIT 2:
The following 2 Properties could also give you probably what you need:
Process.UserProcessorTime : Here
A TimeSpan that indicates the amount of time that the associated process has spent running code inside the application portion of the process (not inside the operating system core).
Process.TotalProcessorTime : Here
A TimeSpan that indicates the amount of time that the associated process has spent utilizing the CPU. This value is the sum of the UserProcessorTime and the PrivilegedProcessorTime.

I've done some research on this, because I found it to be interesting how the metro apps integrate into the existing process structure.
As other people have pointed out here, it is not possible in a beautiful supported API way to get the info you want.
However, every app is launched as a different process and for processes there are known ways to get run time, cpu time etc.
If you find the correspondig process to your windows 8 app, you will be able to get the info you need.
Some apps are really easy to spot. They are just a executable like any other desktop application with a proper processname and description.
For example in this picture "Map", "Windows Reader" and "Microsoft Camera Application":
Some other apps are a bit harder to spot. They are hosted in a process that is launched by the wwahost.exe executabe. I could only spot the app name by looking at the module list.
This is the Bing app:
To enumerate the modules and mapped files from a process you can use the WinAPIs VirtualQueryEx and GetMappedFileName.
Then you want to look for files that are located at %programfiles%\WindowsApps. This is the folder where windows saves all the application files for it's apps.
Every app has a .pri file. This file contains binary metadata of the application. You could use it to find the name of the app from the process that is hosting it. In the same folder with the .pri file there is a AppxManifest.xml in which you could find all kinds of additional information about the app.
I will try to summarize my writing a bit:
enumerate processes with WinAPI and get all infos you need (run time, cpu time, etc).
enumerate mapped files of each process and look for ressources.pri. The directory where this file is located has the app name in it.
as bonus read the AppxManifest.xml file for additional info on the app. You might need Administrator privilege or additional privileges to read this file.

Related

Get process Id or process name after launching a Steam game via steam://rungameid/#

Is there a way to obtain the process name/id of a Steam game started via:
Process.Start("steam://rungameid/#");
As expected the above method returns Steam.exe.
Every game has a key in the registry under HKCU\SOFTWARE\Valve\Steam\Apps
You should be able to check for the Installed value of your game from there, then run the game using steam://rungameid/#, and then wait for the Running or Updating values to change to 1, and again for 0.
This makes it possible to track a game execution, however, you still can't directly have the process id of the game.
This is an old question but I just got done doing the same thing (for a project somewhat similar to what you're working on). You can use ManagementObjects from System.Management to find the ParentId of a process. If you are launching Steam, you will have the process Id of Steam, although the way you're currently launching games, you will need to look up the process Id of Steam.
One thing you will find is each game will generally spawn 2-3 different child processes. The steam overlay, the webclienthelper, and then the game itself (and possibly another for the game's launcher). They should all be children to the Steam process, though, and all should show up in the found processes list.
It would look something like this.
List<Process> procs = Process.GetProcesses();
Process steam = procs.Find(x => x.ProcessName == "Steam");
int steamId = steam.Id;
foreach (var proc in procs)
{
using (ManagementObject mo = new ManagementObject($"win32_process.handle='{proc.Id}'"))
{
if (mo != null)
{
try
{
mo.Get();
int parentPid = Convert.ToInt32(mo["ParentProcessId"]);
if (parentPid == steamId)
{
Console.WriteLine($"{proc.ProcessName} is running as a child to {mo["ParentProcessId"]}");
}
}
catch (Exception ex)
{
// the process ended between polling all of the procs and requesting the management object
}
}
}
}
In general, no.
Steam simply uses a custom URI prefix, which allows you to specify which application will service that request. But it doesn't create a new prefix for each game - instead, it's handled by steam.exe, which decides what application to actually run.
Steam itself of course does track the games it runs, but I assume it simply keeps track of their process IDs, perhaps with some influence from either Steam integration or the Steam overlay injection to track games that use a launcher. I don't think there's any simple way of keeping that information if you're not willing to mess around with other application's privates.
There may be some cases where you have other solutions; e.g. if you don't mind if there may be multiple Steam games running at the same time, you could try finding all processes that have the Steam overlay, but those are rather specific - they might work well for you, but fail for other users.
As the new process will not be started as a child process of steam, it will be impossible to derive its id. What you could try though is to derive the currently running game via the API - and then search through all running processes for their names. The API should expose the game's name via the gameextrainfo property, which should be identical to the process' name (untested, though).

C# monitor external process state

I am making a launcher app in C# on windows. However the process isn't directly started by my C# application but it uses a url to start it e.g "steam://rungameid/xxxxxxx"
I need it to monitor a process by name (say XYZ.exe) in the following fashion:
Receive an event when XYZ.exe starts
Receive an event when XYZ.exe exits
I just want to minimise and restore the my C# application's form when the application is running and not running respectively
thanks
Make a timer (with your preferred timer method) and poll every 'n' milliseconds (find what's best for you... I'd say for minimizing/restoring from a game, 500 milliseconds could be a good start, but experiment), then you can use something like:
bool processRunning = false;
void timerTickMethod()
{
var procIsRunning = Process.GetProcessesByName("xyz.exe").Any();
if(procIsRunning && !processRunning)
ProcessIsStartedEvent(); // or directly minimize your app
else if(!procIsRuning && processRunning)
ProcessIsEndedEvent(); // or directly restore your app
processRunning = procIsRunning;
}
If you want to make sure it's your xyz.exe that is running, you can pass in the full path to GetProcessesByName (so that if there's other xyz.exe in your system, it won't confuse your app)
Update
I was writing from memory, so maybe GetProcessesByName only work for friendly names (with no exe, or path).
If that's the case (I haven't tried), and you need the full path you could do it like:
var procIsRunning = Process.GetProcesses().Any(x => x.MainModule.Filename == #"c:\your\full\path.exe");

What is the fastest way to get a process name from a process id in C#

I have the Windows process ID (PID) of a bunch of running programs in C#, and I need to know the process name (e.g. chrome) for informational display.
I currently use this approach:
string processName;
using(var process = Process.GetProcessById(pid))
{
processName = process.ProcessName; // THIS is costly
}
It turns out it's one of the slowest function and most memory intensive in my diagnostics (according to Visual Studio Performance and Diagnostics). As an example, 70 calls requires 12.8 MB of memory. That's half of the total memory required by my app.
What are alternative (and faster) ways of getting a process name (OR a useful process description) from C#?
Note: The code should run without administrator privileges
This class is designed for that purpose so if you're not satisfied with what it offers, on the startup of your application you can generate a cache, simple map of running processes, to provide yourself a source of fast access. For the processes which has started or stopped later - monitor appropriate events and refresh the map accordingly, e.g. using WMI:
private IDictionary<int, string> _map;
private ManagementEventWatcher _watcher;
_watcher = new ManagementEventWatcher("SELECT ProcessID, ProcessName FROM Win32_ProcessStartTrace");
_watcher.EventArrived += ProcessStarted;
_watcher.Start();
private void ProcessStarted(object sender, EventArrivedEventArgs e)
{
// add proc to _map
}

Handle system folders event in windows

I am writing some C# code and I need to detect if a specific folder on my windows file system has been opened while the application is running. Is there any way to do it? WinAPI maybe?
There are three API things I think you should check out:
FindFirstChangeNotification() http://msdn.microsoft.com/en-us/library/aa364417%28VS.85%29.aspx
That gives you a handle you can wait on and use to find changes to a file in a particular file, directory, or tree of directories. It won't tell you when a directory is browsed, but it will tell you when a file is saved, renamed, and so on and so forth.
SetWindowsHookEx() http://msdn.microsoft.com/en-us/library/ms644990%28v=VS.85%29.aspx
You can set that up to give you a callback when any number of events occur - in fact I'm pretty positive that you CAN get this callback when a directory is opened, but it will probably be inordinately difficult because you'll be intercepting messages to explorer's window. So you'll be rebooting during debugging.
Windows Shells http://msdn.microsoft.com/en-us/library/bb776778%28v=VS.85%29.aspx
If that wasn't painful enough, you can try writing a shell program.
If you're trying to write a rootkit, I suppose you don't want me to spoil the details for you. If you're NOT trying to write a rootkit, I suggest you look it up - carefully. There are open source rootkits, and they all basically have to monitor file access this way to hide from the user / OS.
Go with the Windows Shell Extensions. You can use Shell Namespace Extensions to make a "virtual" folder that isn't there (or hides a real one), like the GAC (C:\Windows\assembly)
Here are several examples of Shell Extension coding in .Net 4.0.
A Column Handler would let you know when a folder is "Opened", and even let you provide extra data for each of the files (new details columns).
Check out the FileSystemWatcher class.
The closest thing that I can think of, that may be useful to you, is using the static Directory class. It provides methods to determine the last time a file or directory was accessed. You could setup a BackgroundWorker to monitor if the directory was accessed during a specified interval. Keep track of the start and end of the interval by using DateTime, and if the last access time falls between those, then you can use the BackgroundWorker's ProgressChanged event to notify the application.
BackgroundWorker folderWorker = new BackgroundWorker();
folderWorker.WorkerReportsProgress = true;
folderWorker.WorkerSupportsCancellation = true;
folderWorker.DoWork += FolderWorker_DoWork;
folderWorker.ProgressChanged += FolderWorker_ProgressChanged;
folderWorker.RunWorkerAsync();
void FolderWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = (BackgroundWorker)sender;
while(!worker.CancellationPending)
{
DateTime lastAccess = Directory.GetLastAccessTime(DIRECTORY_PATH);
//Check to see if lastAccess falls between the last time the loop started
//and came to end.
if(/*your check*/)
{
object state; //Modify this if you need to send back data.
worker.ReportProgress(0, state);
}
}
}
void FolderWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//Take action here from the worker.ReportProgress being invoked.
}
You could use the FileSystemInfo's LastAccessProperty. The problem though is that it can be cached.
FileSystemInfo: http://msdn.microsoft.com/en-us/library/975xhcs9.aspx
LastAccessTime Property: http://msdn.microsoft.com/en-us/library/system.io.filesysteminfo.lastaccesstimeutc.aspx
As noted that this can be pre-cached.
"The value of the LastAccessTimeUtc property is pre-cached if the current instance of the FileSystemInfo object was returned from any of the following DirectoryInfo methods:
GetDirectories
GetFiles
GetFileSystemInfos
EnumerateDirectories
EnumerateFiles
EnumerateFileSystemInfos
To get the latest value, call the Refresh method."
Therefore call the Refresh method but it still might not be up to date due to Windows caching the value. (This is according to msdn doc "FileSystemInfo.Refresh takes a snapshot of the file from the current file system. Refresh cannot correct the underlying file system even if the file system returns incorrect or outdated information. This can happen on platforms such as Windows 98." - link: http://msdn.microsoft.com/en-us/library/system.io.filesysteminfo.refresh.aspx
I think the only way you can reliably achieve this is by monitoring the currently running processes and watch closely for new Explorer.exe instances and/or new Explorer.exe spawned threads (the "Run every window on a separate process" setting gets in the way here).
I admit I don't have a clue about how to code this, but that's what I would look for.

How to programmatically detect when the OS (Windows) is waking up or going to sleep

Background
My son likes to use his laptop when he's not supposed to and I just thought it would be handy if I could write an application that would email me whenever he opened / closed his laptop.
(I'd even settle for something that notified me when there was network traffic on the machine)
Question
How do you programmatically detect when an OS is waking up or going to sleep? I found this link from this related post. But that covers OS X. I'm looking for the same thing for Windows 7.
(I'd like to do this in Java, if possible, but I'd settle for C#/C++)
Easiest way is not to write any code at all, even though this is stack overflow. Click Start, type Schedule and choose Scheduled Tasks. Set one up (click Create Task) and set a Trigger when the machine is unlocked. For the Action, have it send you an email.
Repeat for startup and when a user logs in, if you want. Done.
You're going to want to create a window and watch for the WM_POWERBROADCAST message (http://msdn.microsoft.com/en-us/library/aa373248%28v=vs.85%29.aspx) and check the wParam for your desired action. For example, your window should receive a WM_POWERBROADCAST with PBT_APMSUSPEND as the wParam when the system is about to enter a suspended state (i.e. closing a laptop). Resuming seems to have a few different wParam values: PBT_APMRESUMESUSPEND, PBT_APMRESUMECRITICAL and PBT_APMRESUMEAUTOMATIC
I search for a long time and found that this was the best way, the 'Sleep'-event was never working before:
private ManagementEventWatcher managementEventWatcher;
private readonly Dictionary<string, string> powerValues = new Dictionary<string, string>
{
{"4", "Entering Suspend"},
{"7", "Resume from Suspend"},
{"10", "Power Status Change"},
{"11", "OEM Event"},
{"18", "Resume Automatic"}
};
public void InitPowerEvents()
{
var q = new WqlEventQuery();
var scope = new ManagementScope("root\\CIMV2");
q.EventClassName = "Win32_PowerManagementEvent";
managementEventWatcher = new ManagementEventWatcher(scope, q);
managementEventWatcher.EventArrived += PowerEventArrive;
managementEventWatcher.Start();
}
private void PowerEventArrive(object sender, EventArrivedEventArgs e)
{
foreach (PropertyData pd in e.NewEvent.Properties)
{
if (pd == null || pd.Value == null) continue;
var name = powerValues.ContainsKey(pd.Value.ToString())
? powerValues[pd.Value.ToString()]
: pd.Value.ToString();
Console.WriteLine("PowerEvent:"+name);
}
}
public void Stop()
{
managementEventWatcher.Stop();
}
A very simple, perhaps crude, but effective way may be to have a program with a timer firing every minute. If the timer fires and it's been, say, 5 minutes of real time since its last execution then you can likely assume that the computer was sleeping since it's unlikely that your thread was unable to be scheduled for so long.
The other reason for the difference may be a clock adjustment, like DST or a manual change, but that kind of "noise" should be very low, in your scenario.
You could write a simple app and register it as a Windows service, to be started automatically at system startup. This app could then do whatever you want when it starts. And if it's a proper Windows app, it can register to get notification about impending system shutdown too (I don't remember the details but I implemented this in a C++ MFC app many years ago).
If you prefer Java, you could register your app as a service via a suitable service wrapper like Tanuki (it seems they have a free Community License option). Although this might be overkill. And it may be possible to get notification about the JVM shutting down when the system is closing (but I have no concrete experience with this).
http://www.pinvoke.net/default.aspx/powrprof.CallNtPowerInformation - Check out the link. It has almost all win32api for all windows function. You can call power management feature directly in your windows 7 laptop. For that create a Windows Service , that will use these specific api to notify the machine state.

Categories

Resources