I'm trying to create a screen that would pop up that would stop the user from doing anything on the screen, I want it so the user can only type in the box provided and they can't press any other key to exit the screen (like win R, alt f4, ....), any Ideas on what I can do here? thank you.
There isn't much you can do to prevent all the ways of killing a task. If you were creating a Kiosk style application, you can replace explorer.exe and use a custom shell that you write. Exiting your application then immediately logs off, but you still need to handle things like task manager. But in your case, you want to share the desktop with other users. I think the easiest way is to lock the workstation programmatically
using System.Runtime.InteropServices;
[DllImport("user32.dll")]
public static extern bool LockWorkStation();
Then call LockWorkStation(); when you have occasion to do so. Let the OS handle the blocking of the user operations.
Related
I'm currently writing a C# program which basically functions as a watchdog for a 3rd party program: If the traffic falls below a certain value, the process is killed and then restarted [using a simple taskkill /im].
This is working perfectly fine, with one exception - if the program is minimized to the system tray, it will not respond to taskkill /im and you have to force-terminate it with taskkill /f /im.
As one can guess, this is by far not the best way to end a program. So I'm currently searching for a way to access the Windows system tray and basically perform a click on the program/call a method to maximize it back to normal.
I had thought about literally simulating a click on the tray, but found this method to be way to inaccurate and unpredictable.
Is there another way to accomplish this [by using a system api, for example]?
Thanks!
You can try using the user32.dll to maximize the processes window.
// Pinvoke declaration for ShowWindow
private const int SW_SHOWMAXIMIZED = 3;
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
// Sample usage
ShowWindow(proc.MainWindowHandle, SW_SHOWMAXIMIZED);
Taken from this SO answer.
For a complete list of window states visit this MSDN Page
You can get the WindowHandle by doing something like this
var processes = Process.GetProcessesByName("nameOfYourProcess");
foreach(var process in processes)
{
var windowHandle = process.getMainWindowHandle;
}
Though this will only work if the process still has a Window.
The only way you can iteract with the tray icon of another application in windows is by simulation the mouse click. This has the mayor flaw that if the user is interacting with the mouse at the same time you "steel" hes cursor and he cannot work.
If you know you will not end up with a memory leek (if its a managed app you've won) and the application you are killing isn't doing some important stuff when it's exiting a process kill is the better option.
In my application I'd like to accomplish 2 things when a user wants to take a break and clicks a log out button.
Lock the machine
Launch a custom screen saver that would show the time the user is logged out.
I managed to do the lock easily by:
[DllImport("user32.dll")]
private static extern void LockWorkStation();
I found a tutorial on how to make a custom screen saver. I downloaded the sample code and it worked fine. But when I added the LockWorkStation(); line it killed the screen saver.
Can you help me with this or suggest a workaround?
EDIT
This screen saver from tutorial is just w WinForm. Should I somehow install it to the system? Is it possible form my application level?
The solution most likely is the following:
Lock the workstation
Show the screensaver
For the second step, the following is important:
You application is simply a program showing a window. As such any windows it tries to show are not shown to the user when the workstation is locked.
Your window will only be shown when you register your program as a real screensaver, set it as the current screensaver and than start it, for example using the SC_SCREENSAVE message.
I've got a command line application that starts up and does some work. During that time, it listens to keystrokes (s => show status). It's not the typical command prompt where you press 's' and <ENTER> - it's the type which reacts as soon as the key is pressed the status is shown.
Now I'm trying to "control" that command line application from a fancy GUI application by sending keystrokes. I've tried the more conventional approach of writing to the Process' StandardInput but that doesn't seem to have an effect at all. Also, because the actual process doesn't have a window (it's started with CreateNoWindow=true) I can't try the Win32 API for sending keystrokes to a window.
Is there any other way of doing it?
Fancy console applications are problematic.
They have a tendency to directly read the keyboard input, instead of going through stdin. They also have a tendency to directly control their console, instead of going through stdout.
AFAIK, there is no way to programmatically control these apps. If you really, really need to, I would explore something like AutoHotKey controlling the app on a private desktop (AHK uses a virtual keyboard/mouse driver). I'm not sure how you would read the results off the console, though; it may be possible to create an intermediate console app that's started by your program (in the private desktop) and starts the target app. The intermediate app would then share its console with the target app and use low-level I/O to detect changes.
Or you could use Detours to bend the target app to your will.
Well, I seem to have found an answer to my own question.
It's a real "kludged together" solution, but it works - and for all the intents and purposes of the application I'm building, it doesn't matter.
So, what I did was use two WinAPI functions called
static extern bool ShowWindow(IntPtr WindowHandle, int nCmdShow);
static extern bool SetForegroundWindow(IntPtr WindowHandle);
The first one can be used to Show/Hide a window by changing nCmdShow to 1 and 0 respectively. The other one puts the window (determined by WindowHandle) to the front. Combining these two together, I was able to programmaticly bring the console window up front, do a simple SendKeys.Send(); operation and then hide it again.
// Use a WIN API command to bring the command line to front
SetForegroundWindow(workerProcess.MainWindowHandle);
// Send a keystore to re-display the STATUS of the worker
SendKeys.Send("s");
// Hide the window again.
ShowWindow(workerProcess.MainWindowHandle, 0);
Now, it's a real kludge job, but it gets the job done. One potential pitfall would be if a user is using the computer for something else, and would nail that 1 in a 10000000 moment when the window is active with a 'q' - it would quit the worker program. But the application is intended to be used on dedicated machines that most likely won't even have monitors, keyboards or mice attached to them so it wouldn't be an issue.
Thanks to all who answered, since you did - in one way or another, steer me towards the right solution.
I found an even better way to accomplish the functionality without the theoretical risk of causing problems with simultaneous user input and window-switching.
The trick is to use the WinAPI functions called PostMessage to send up KeyDown (or KeyUp) message to the process which does the same thing. No need to bring the process window to the front and hide it immediately afterwards!
I'm sending the key-down command with key 'S' as the argument:
// 0x0100 - VM_KEYDOWN
// 0x0101 - VM_KEYUP
// 0x53 - S-key
PostMessage(workerProcess.MainWindowHandle, 0x0100, 0x53, 0);
PostMessage(workerProcess.MainWindowHandle, 0x0101, 0x53, 0);
I have an application that I would like to write an automated test for. The automated test will mimic an Operator's usage of the application. I cannot change the source code of the application as it is "frozen" for review.
The application will display a pop-up (message) window informing the operator to click on a button after measurements are finished. The button is enabled some time after the message window is closed.
I need to know how to detect when the application enables this button. My research so far indicates that the application should broadcast a custom message to help the automated testing; but I cannot modify the source code.
Also, the application will enable radio buttons after the "Measurements Finished" button has been clicked, asking if the measurements were valid. I need to detect this also.
Summary:
How do I detect when a button
(control) is enabled in another
application?
How do I get the handle of the other
application?
I am using C# with MS Visual Express 2010 on Windows NT, Vista & 7. If you suggest tools, I need them to be free as the company has a very tight budget.
I think you could do the job using FindWindow API, passing title and receiving the handle.
Then, enumerating children components, you could find the button (if you catch its name, next time you can use it to be quicker) and get the enabled state.
I think you could use AutoIT software (script) or its logic.
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr FindWindow(string strClassName, int nptWindowName);
EDITED:
Check this link to find a simple way to do what you need.
I hope this helps you.
I'm currently working on an access control program in C# and I've come across the problem of blocking windows. The original idea I've come up with is rendering a plain black form over the position given by the IntPtr window handle of the process. The problem within that is updating the form's position smoothly and z-index of the position (being I don't want it topmost). I've also noticed a ridiculously high resource use with my solution as I was using a loop to constantly check position.
Thus why I ask: What would be the best solution for this without eating major resources? The entry point is merely the name of the running process.
Presently the idea is only blocking off browsers (IE: a school application to prevent distraction when a lecture is active).
More Information:
I'm not looking to close a window in
my own application, I'm trying to
obscure windows from other processes.
My application is not a
virus/annoying program, it's
essentially meant to prevent uses of
potentially distracting applications
in a school environment. It's made
for lectures in a school computer
lab.
I'm presently pulling the main window
from the process caught by the
process name of browsers.
I can't completely disable the computers either.
I really hate hate hate any application trying to mess around with other application's windows. Sorry, this comes from very deep.
The only thing I can think of that is somewhat sensible is to lock the current user session, and swith the computer to another desktop belonging to another account with no rights to do anything except what's required under the circumstances.
Or if it is acceptable to disable the use of the computers entirely, you could put all the monitors on a single power switch on the teacher's desk.
If you are looking to hide your application window, I can suggest 3 things. First thing, try setting your form's visible property true and calling the hide() method. Second thing is to set your form's transparency to 100%, which will hide it. The third is, maybe consider your application should be a windows service instead of a windows form application.
If you are looking to hide other windows so that your application is always on top, set the TopMost property to true in your form: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.topmost(VS.71).aspx
This might help too: http://www.codeproject.com/KB/cs/windowhider.aspx
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
static void MinimizeProcess(string procName)
{
foreach (Process p in Process.GetProcesses())
{
if (p.ProcessName == procName)
{
ShowWindow(p.MainWindowHandle,11);
}
}
}
If you have an array of process names you'd obviously want to refactor this to take in an array so that you're not looping through every process for everything you want to minimize, but you get the idea.
You could use the windows api to hide the offending window. user32.showwindow
Not exactly what you've asked for, but might be simpler.
You can do:
this.Hide()
this.Visible = false;
Or if this is the main for you dont want to show, simply dont run the forum when you start the app.