static Boolean IsWaitingForUserInput(String processName)
{
???
}
|
|
|
ich frage lieber nicht was du damit anstellen willst... :)
– MiW 10.09.2009
|
||
|
Ich verstehe nicht was Du meinst. Egal, es ist so: wir haben automatisierte Abläufe die z.B. Excel involvieren. Manchmal meint Excel beim Schließen, dass sich was geändert hat und frägt nach. Diese Fälle sollte detektiert werden damit wir da benachrichtigt werden und zeitnah eingreifen können. Wir können niemand gerade bezahlen, der sich den ganzen Tag das Bildschirm anguckt ;-)
– jdehaan 10.09.2009
|
||
|
Ist es legitim, Fragen sowohl hier als auch bei stackoverflow.com zu posten, ohne eine Antwort abzuwarten? Beide Male wurde die Frage am 10. September gestellt.
– knivil 22.09.2009
|
||
|
Warum nicht ? Man kann doch fragen wann und wo man will. Glaube kaum daß dafür jemandem der Kopf abgerissen wird.
– MiW 20.10.2009
|
|
|
| 2 |
Ein globaler System-Hook ist meiner Meinung nach die beste Lösung. Damit erschlägt er all seine Anforderungen.
BTW. Was über die WIN32-API funktioniert geht auch mit C#. – klaus_b 10.09.2009
|
|
|
gut zu wissen.
habe total den Anschluss bei C# verloren und hänge immer noch gedanklich bei c++ fest. Sollte mich wirklich mal eingehend damit beschäftigen. – MiW 10.09.2009
|
||
|
Auf jedem Fall hiflreich! Die Einzige Anforderung die mir nicht gefällt ist, dass ständig diese Hooks aktiv sein müssen. Falls ich nichts besseres finde werde ich es so machen.
– jdehaan 10.09.2009
|
||
|
Wenn die autmatisierten Abläufe, die Du angesprochen hast zeitgesteuert sind, kannst du ja vorher den Hook initialisieren und dann irgendwann wieder beenden.
– MiW 11.09.2009
|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
using System.Diagnostics;
namespace Util
{
public class ModalChecker
{
public static Boolean IsWaitingForUserInput(String processName)
{
Process[] processes = Process.GetProcessesByName(processName);
if (processes.Length == 0)
throw new Exception("No process found matching the search criteria");
if (processes.Length > 1)
throw new Exception("More than one process found matching the search criteria");
// for thread safety
ModalChecker checker = new ModalChecker(processes[0]);
return checker.WaitingForUserInput;
}
#region Native Windows Stuff
private const int WS_EX_DLGMODALFRAME = 0x00000001;
private const int GWL_EXSTYLE = (-20);
private delegate int EnumWindowsProc(IntPtr hWnd, int lParam);
[DllImport("user32")]
private extern static int EnumWindows(EnumWindowsProc lpEnumFunc, int lParam);
[DllImport("user32", CharSet = CharSet.Auto)]
private extern static uint GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32")]
private extern static uint GetWindowThreadProcessId(IntPtr hWnd, out IntPtr lpdwProcessId);
#endregion
// The process we want the info from
private Process _process;
private Boolean _waiting;
private ModalChecker(Process process)
{
_process = process;
_waiting = false; //default
}
private Boolean WaitingForUserInput
{
get
{
EnumWindows(new EnumWindowsProc(this.WindowEnum), 0);
return _waiting;
}
}
private int WindowEnum(IntPtr hWnd, int lParam)
{
IntPtr processId;
GetWindowThreadProcessId(hWnd, out processId);
if (processId.ToInt32() != _process.Id)
return 1;
// belongs to our process, check it!
uint style = GetWindowLong(hWnd, GWL_EXSTYLE);
if ((style & WS_EX_DLGMODALFRAME) != 0)
{
_waiting = true;
return 0; // stop searching further
}
return 1;
}
}
}
|
|
| 1 | ||
|
Vermutlich weil ein Programm solange es aktiv ist immer auf die eingabe eines Users wartet, wenn es im idle zustand ist, also nicht aktiv arbeitet.
Müßtest das noch mit ner abfrage machen ob das programm versucht sich zu schließen. – Jesman 10.09.2009
|
||
|
gfoidl, Du hast Recht. Es liefert sehr oft true zurück auch im Falle normaler User-interaktion. Ich glaube die Lösung muss noch aufgebohrt werden.
– jdehaan 10.09.2009
|
||
|
Ich glaub des ist deshalb da die Anwendung in der Nachrichtenschleife die meiste Zeit wartet.
– gfoidl 10.09.2009
|
|
|
public partial class Form1 : Form
{
public Form1()
{
Application.EnterThreadModal += new EventHandler(OnEnterModal);
Application.LeaveThreadModal += new EventHandler(OnLeaveModal);
InitializeComponent();
}
public void OnEnterModal(object sender, EventArgs e)
{
textBox1.Text += "start Modal..." + Environment.NewLine;
}
public void OnLeaveModal(object sender, EventArgs e)
{
textBox1.Text += "stop Modal..." + Environment.NewLine;
}
private void button1_Click(object sender, EventArgs e)
{
DialogResult dlgres = MessageBox.Show("You must enter a name.", "Name Entry Error",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
|
|
| 1 |
Das bezieht aber nur auf die eigene Anwendung und nicht auf eine ANDERE - oder gilt das global?
– gfoidl 10.09.2009
|
|
|
@gfoidl: sorry keine Ahnung, habs nicht probiert. Aber ich denke wenn die Anwendung aus deiner Anwendung heraus aufgerufen wird, dann gilt dies auch dafür ;-)
– Scout 10.09.2009
|
||
|
Ich will die andere Prozesse quasi nebenbei überwachen nicht starten und es gilt definitiv nicht global, denn nicht alle Apps sind "managed" (leider ;-) )
– jdehaan 10.09.2009
|
||
|
aber global ist doch nicht verkehrt, prüfste halt vorher ob der Prozeß einer ist, der gemanaged werden soll. (Anhand des Prozeßnamens)
– MiW 10.09.2009
|
||
|
danke für den Minuspunkt, nur weil ich davon ausgegangen bin, dass er die Applicationen aus seinem Programm aufruft... naja egal. Seine Lösung ist doch super.
– Scout 10.09.2009
|
||
|
ich hab ihn dir nicht gegeben. Hab für diese Frage gar keine Bewertungen abgegeben.
– MiW 10.09.2009
|
|
|
public class ModalChecker
{
#region Native Windows Stuff
private const int WS_EX_DLGMODALFRAME = 0x00000001;
private const int GWL_EXSTYLE = (-20);
private delegate int EnumWindowsProc(IntPtr hWnd, int lParam);
[DllImport("user32")]
private extern static int EnumWindows(EnumWindowsProc lpEnumFunc, int lParam);
[DllImport("user32", CharSet = CharSet.Auto)]
private extern static uint GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32")]
private extern static uint GetWindowThreadProcessId(IntPtr hWnd, out IntPtr lpdwProcessId);
#endregion
public delegate void ProcessModalDelegate(ModalChecker sender, Process p, IntPtr handleOfModalWindow);
public event ProcessModalDelegate ProcessModal;
// The process we want the info from
private Thread _checker;
private Process _current;
private bool _waiting;
private List<string> _ignoreList = new List<string>();
public ModalChecker()
{
_checker = new Thread(new ThreadStart(CheckerThread));
_checker.Start();
}
public void Stop()
{
_checker.Abort();
}
public void AddToIgnoreList(Process p)
{
lock (_ignoreList)
_ignoreList.Add(p.ProcessName.ToLower());
}
private void CheckerThread()
{
while (true)
{
Process[] par = Process.GetProcesses();
foreach (Process p in par)
{
lock( _ignoreList )
if (_ignoreList.Contains(p.ProcessName.ToLower()))
continue;
_current = p;
EnumWindows(new EnumWindowsProc(this.WindowEnum), 0);
}
}
}
private bool WaitingForUserInput(Process p)
{
EnumWindows(new EnumWindowsProc(this.WindowEnum), 0);
return _waiting;
}
private int WindowEnum(IntPtr hWnd, int lParam)
{
IntPtr processId;
GetWindowThreadProcessId(hWnd, out processId);
if (processId.ToInt32() != _current.Id)
return 1;
// belongs to our process, check it!
uint style = GetWindowLong(hWnd, GWL_EXSTYLE);
if ((style & WS_EX_DLGMODALFRAME) != 0)
{
if (ProcessModal != null)
ProcessModal(this, _current, hWnd);
return 0; // stop searching further
}
return 1;
}
}
static void mc_ProcessModal(ModalChecker sender, Process p, IntPtr handleOfModalWindow)
{
if (p.ProcessName == "PrivacyIconClient")
{
Console.WriteLine(p.ProcessName + " added to ignore list");
sender.AddToIgnoreList(p);
}
else
Console.WriteLine(p.ProcessName + " reported as modal. Handle it or it will be reported again.");
}
[MTAThread]
static void Main()
{
ModalChecker mc = new ModalChecker();
mc.ProcessModal += new ModalChecker.ProcessModalDelegate(mc_ProcessModal);
while (true)
{
Thread.Sleep(1000);
}
}
|
|
|
|