Colleagues, I have need to run a script/program on certain basic OS level events. In particular when a file in Windows is opened. The open may be read-only or to edit, and may be initiated by a number of means, either from windows explorer (open or ), be selected from a viewing or editing application from the native file chooser, or drag-n-drop into an editing or viewing application.
Further, i need the trigger to "hold" the event from completing the action until the runtime on the program has completed. The event handler program may return a pass state, or fail state. If fail state has been returned, then the event must disallow the initially requested action.
Lastly, I need to add to the file in question a property or attribute that will contain metadata that will be used by the above event trigger handler program to make a determination as to the pass/fail condition that will ultimately determine if the user is permitted to open the file.
Please note that this is NOT a windows event log situation, but one at the OS level file open event.
thanks very much for your help.
Edit
What I had hoped that someone was aware of was an OS level trigger, similar to how you can enable a trigger on an event-log writer occurance in Windows (ie: send an email, run a script when an event hits the event logger).
The application environment I work in, a PLM system, allows for event handling. So, when a user initiates an action, say a checkout of a file from an object, there are 3 available handlers or triggers that can be programmed. The "check" or "pre-action" trigger is a process that fires when the user starts initiates the event, but before the system permits it to be processed. So, one can block or otherwise alter the response of the system programmatically based on some condition, like user context.
I have also enabled startup/shutdown script firing via group policy, so i can delay a server shutdown until a database has closed properly. This was done in Windows server 2003. So, with that hook, i could manage shutdown or startup.
Hence, I had hoped someone might be aware of an OS trigger that would do the same for a file-open operation. This would be deployed on all workstations and desktops.
Again, if there are any ideas, it would be greatly appreciated.
Thanks again.
regards,
j
A couple strategies come to mind. One is to run the app with your own DLL to intercept API calls like WriteFile. Another would be to run the app under the debugger interface.
Related
First off, I know some proper ways of making a truly interactive Windows Service.
The situation is, I do have a tool that does not interact with the user as such. However, it does display non-blocking notifications both via popup windows and via the Windows Notification Area (aka System Tray). It also writes a logfile of the notifications it displays.
This tool is normally spawned by a main user application and as long as the main application is a normal application, these notifications do work as intended.
When this tool is spawned by a Windows Service, no notifications are displayed, naturally. (The Desktop Session for the service isn't visible.) But this would be OK, we have the logfile and these notifications are just - notifications, nothing the user absolutely must see under all circumstances.
The question now becomes: Is a process running in the context of a Service (the Service itself or any process it starts) "allowed" to make Windows API calls that display a visible GUI?
Will most Windows API calls (e.g. creating and showing a window, using Shell_NotifyIcon, etc.) behave the same in the invisible session of the service?
Or would I have to make sure throughout the source code, that no GUI displaying/modifying stuff is called in the context of the service?
And yes, calling ::MessageBox is a bad idea because it will block. But I can handle these calls.
And yes, this could be designed better, but it's what I have at the moment and it would be nice if I hadn't to rip the whole tool apart to make sure no GUI related code is run in the service.
GUI elements from a Windows Service are shown on Session 0. On Windows XP & 2003, users were allowed to log in to Session 0 and interact normally with the windows created by a service, but Microsoft put a knife in the heart of interactive services in Vista (and beyond) by isolating Session 0.
So, to answer your specific questions:
Is a process running in the context of a Service (the Service itself
or any process it starts) "allowed" to make Windows API calls that
display a visible GUI?
Will most Windows API calls (e.g. creating and showing a window, using Shell_NotifyIcon, etc.) behave the same in the invisible session
of the service?
Yes, GUI calls are allowed and should succeed as normal. The only notable exceptions that I know of are those related to tray icons because the process providing the task bar (explorer.exe) is not running in the isolated Session 0.
Or would I have to make sure throughout the source code, that no GUI displaying/modifying stuff is called in the context of the service?
That should not be necessary, though you should proceed cautiously with any GUI interaction from your service. Test thoroughly!
I would like to provide some info wrt. Raymonds Chen's comment to the other answer
You should avoid presenting UI in a service because you may trigger
the UI Detection Service which will switch the user to your service UI
temporarily. – Raymond Chen
I find these good articles:
What is Interactive Services Detection and Why is it Blinking at Me?
Inside Session 0 Isolation and the UI Detection Service, Part1, Part2
Where one can find explanation on what the UI detection service (UI0Detect) is and does and how it's supposed to work.
Interactive Services Detection (the blinking button on the taskbar) is
a mitigation for legacy applications that detects if a service is
trying to interact with the desktop. This is handled by the
Interactive Services Detection (UI0Detect) service.
However, one must note that this only can work if the service that is trying to view a GUI has the flag "Allow service to interact with desktop" set, because only then the service process will be running on WinSta0of Session0 even allowing it to show anything at all.
Alex Ionescu mentions this:
If UI0Detect.exe ...
the SCM has started it at the request of the Window Hook DLL. The
service will proceed ...
The service first does some
validation to make sure it’s running on the correct WinSta0\Default
windowstation and desktop and then notifies the SCM of success or
failure.
So, to come back to Raymond's comment: As far as I can see, as long as a service doesn't tick the type= interact option (see sc.exe), and normally you don't tick this, the UI0Detect service doesn't do anything and there shouldn't be any "danger" of triggering it.
Note: The information above is based on my limited research and tests on only a single Windows 7 PC.
I have an executable that can run normally or as service. At the startup it may show an error message if there is an error (using MessageBox api). This can cause failure if the application is running as service but not allowed to interact with desktop.The process may appear to be hanging. Is there a programmatic way to detect if the application can interact with desktop ? I can then use some other error notification mechanism (log file etc)
You could specify MB_SERVICE_NOTIFICATION when calling MessageBox(), which will display the message in the currently active session.
But, displaying a message box from within a service is not what you really want.
Services are supposed to run in the background and not interact with users directly. One of their characteristics is that they can (and often do) run even when no user is logged on. In Windows Vista they even run in a totally different session than all other users'. Displaying a MessageBox could result in your services being blocked, because the message was invoked in your service's own session without the user knowing about it.
Writing to some sort of a log file or using windows' EventLog is the prefered method.
From MSDN:
To determine whether a service is running as an interactive service,
call the GetProcessWindowStation function to retrieve a handle to the
window station, and the GetUserObjectInformation function to test
whether the window station has the WSF_VISIBLE attribute.
In .NET you can use Environment.UserInteractive
The UserInteractive property reports false for a Windows process or a
service like IIS that runs without a user interface. If this property
is false, do not display modal dialogs or message boxes because there
is no graphical user interface for the user to interact with.
From http://msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx:
To determine whether a service is running as an interactive service, call the GetProcessWindowStation function to retrieve a handle to the window station, and the GetUserObjectInformation function to test whether the window station has the WSF_VISIBLE attribute.
Short Version:
Are the event sources "Application" and "Application Error" always included in the Application Event Log? Are they available on new installations of Windows XP, Vista and Windows 7? Would it be really bad to use them instead of creating my own source (an impossibility for me)?
Long Version:
I have a ClickOnce application that is used by users without administrative privileges on their machines.
When I try to write to the Appliction Event Log, I get a security exception. (The Windows event logging infrastructure is trying to create me a new event source, and gets a security violation.)
So I would like to try reusing an existing event source. I have found a only two"generic-sounding" sources in the Application Event Log. Are these always part of a Windows installation, and would make a reasonable choice?
Application
Application Error
I am sure this is frowned upon, as I should distinguish my application using its own event source. But this is for infrequent fatal errors, which should be getting logged elsewhere by my code. I just want a really easy place to find them on a client machine in case it all goes wrong...
When I try to write to the Appliction Event Log, I get a security exception. (The Windows event logging infrastructure is trying to create me a new event source, and gets a security violation.)
I have just answered this here: Using EventLog in ClickOnce application
So I would like to try reusing an existing event source. I have found a only two"generic-sounding" sources in the Application Event Log. Are these always part of a Windows installation, and would make a reasonable choice?
It's really not wise to do this. Existing event sources will be used by either Windows applications, or by third party applications. If any of those are removed, or changed by something like a service pack or patch, your program will crash unless you have implemented exception handling to handle the exception gracefully, but then you wont have any event logging.
Also consider the work you may have to do to port your app to the next version of Windows. I suggest you will be making a rod for your own back.
In the answer I linked to, I suggested the best way to handle the problem, is to install your application using admin privs with the installer creating the source, or by creating a simple app that effectively does the same using the admin role.
The only thing else I can suggest is to always run your application in admin mode.
I need to track to a log when a service or application in Windows is started, stopped, and whether it exits successfully or with an error code.
I understand that many services do not log their own start and stop times, or if they exit correctly, so it seems the way to go would have to be inserting a hook into the API that will catch when services/applications request a process space and relinquish it.
My question is what function do I need to hook in order to accomplish this, and is it even possible? I need it to work on Windows XP and 7, both 64-bit.
I think your best bet is to use a device driver. See PsSetCreateProcessNotifyRoutine.
Windows Vista has NotifyServiceStatusChange(), but only for single services. On earlier versions, it's not possible other than polling for changes or watching the event log.
If you're looking for a user-space solution, EnumProcesses() will return a current list. But it won't signal you with changes, you'd have to continually poll it and act on the differences.
If you're watching for a specific application or set of applications, consider assigning them to Job Objects, which are all about allowing you to place limits on processes and manage them externally. I think you could even associate Explorer with a job object, then all tasks launched by the user would be associated with your job object automatically. Something to look into, perhaps.
Why not use the Windows scheduler?
I have several applications that have to run at certain times according to business rules not the typical every weekday at 1pm.
I also need a way for the applications to provide feedback of their progress so that I can have rules that notify me when the applications are running slow or aren't even running anymore.
What Windows API should I be looking into? (like, a time version of the FileWatcher apis)
What's the best way to have the application notify the scheduler of its progress (files, sockets, windows messages, ???)?
For Vista/Win2k8, there's the nice Task Scheduler 2.0 API: http://msdn.microsoft.com/en-us/library/aa384138(VS.85).aspx. Previous version have the Task Scheduler 1.0 API, but I've never used it.
AppControls has a CronJob component that you can use to create scheduled events. This saves your program from having to wake up every minute and check the schedule itself. Instead, just schedule the job and indicate a callback method.
I have used this component for scheduling jobs myself and have been very happy with the way that it works.
I think what you really want is a common framework for your applications that report to something (you or the system messages or tracing or perfmon, event log, whatever) and also to receive via some inter process protocol a way to receive messages and respond.
based on the reporting you can change the scheduling or make changes, etc.
So, there is some monitor app, and then each of your other apps does common reporting.
events I can think of:
- started
- stopped
- error
- normal log messages
- and of course specific things your apps do.
I think there are probably existing classes/framework that do this - you'll have to check around.
If it were me, I would make a service that could talk to all the other apps and perhaps was even an http server. It would be able to route messages to particular apps and start stop those processes and query them.
There are lots of ways to do what you want though. those were just off the top of my head.
Alternatively you might just be able to get these to be services and they handle messages sent to them. Their normal processing does nothing until they are "woken up" with some task command.
You have more questions in one. Normally you should split them. But let's overlook this and try to answer.
To schedule certain events (including running an application): Use TJvScheduledEvents from JVCL. IMHO JVCL is the best Delphi open source library around with extensive number of components, developers & support. TJvScheduledEvents is quite neat, uses threads for event scheduling and also you have in JVCL a detailed editor for your events (it needs a small hack to use it though).
To provide 'feedback' from your applications to a (remote) central point: A very very very good solution (if your requirements permit) is to log the progress of your applications in a table (let's call it LOG) on a Firebird server. In LOG you can have the following fields: COMPUTER, USERNAME, APPNAME, MSG, LOGDATE (etc. etc.). In the After Insert trigger of the LOG table you can fire an event (let's call it NEW_LOG). In your console app you can register the interest for this event and so, your application will be automatically updated with everything which happens in any of your applications, so you can do log analysis, graphs etc. Of course you can do it with IB, but IB costs.
...going on Windows API route you need headers (which probably aren't translated), you'll encounter our dearest Pointers/PChars etc. etc. Of course, building from scratch everything isn't worthwhile but when this is already done in a Delphi way, why don't use it?
Use service with a timer that is fired regulary (for example each minute). It reads the schedule and looks if some are due before the next iteration. If so, you can execute them.
You can add an interface that shows all running apps. For the feedback and query that using a desktop application.