How can I run my application when windows session is disconnected? - c#

I have made a simple application in C# and WHITE, which click on a button to clear the logs.
I use to connect to my test machine using Remote Desktop Connection and execute that application. It works fine when my session is connected but whenever i disconnect my session, it stops working.
Is there any way to execute that application when windows session is disconnected?

You could write a Windows Service.

You could also use the task scheduler.
You may not need the C# wrapper, you can add yourself the required entry within the scheduler.

It works fine when my session is connected but whenever i disconnect my session, it stops working.
This is by design. When you disconnect your session, it is locked. When your session is locked, UI automation won't work.
You could hack around this by never locking the session, possibly via different remote desktop tools (VNC/PcAnywhere). But this is definitely a hack.
Instead I suggest a different approach. I recommend avoiding UI automation whenever possible. I have always found UI automation to be flaky and unreliable.
In the comments on your question you said your app is simply UI automation to click a button to clear a log. The logs are generated by the DebugView application.
I suggest you log to a file instead. This feature is mentioned on the web site for DebugView:
http://technet.microsoft.com/en-us/sysinternals/bb896647
You could also look into using remote monitoring.
If size is an issue, you can also look into the "Log file wrapping" and "log-file rollover" features.

Taken from
https://www.ranorex.com/help/latest/ranorex-remote/remote-faq#c13444
Create a batch file on your remote machine and insert the code below:
for /f "skip=1 tokens=3 usebackq" %%s in (
`query user %username%`
) do (
%windir%\System32\tscon.exe %%s /dest:console
)
Save this batch file on the desktop of your remote machine and name it: 'KeepSessionOpen.bat'.
If you need to disconnect the RDP session, you can now simply run this batch file using administrator privileges and your remote machine will remain unlocked.

Related

Difference between Process.Start() and Manual Start

I have a single form application which checks user states continuously via timer. I want to start the same .exe by using process.start("C:\inetpub\wwwroot\mywebapp\Checker\checker.exe") in Web Application. The exe appears in System processes list (not appear in application list in Windows Task Manager) after the code executed but it does nothing. It is not changing the user states nor sending Data to Database. But when I start same .exe manually on double clicking, it start working and it also appears in Windows Task Manager Application list and in Process Lists. The .exe is made with C#.Net and is executed file of C# windows application.
When launched by IIS the process will run under the account that started it, which will be the w3wp processes that is running your web application. Because this isn't your account it won't show up in task manager until you select the "show processes from all users" option. When you run it via a double click it is running under your account, so will be visible.
If the changes and database access rely on using your account to gain access then this wont work when it runs from within IIS. For example, if your database connection is done using "Windows Authentication" then it will try to log in as the IIS account, which is unlikely to work.
To fix this you can launch the processes by specifying a username/password in the ProcessStartInfo structure. However, this will require you to embed your password somewhere, which may not be desirable. Alternativly look at changing the database connection string so that you specify the logon credentials explicitly.

Counting all instances of a .exe running on a shared folder

I have a c# application that is on a shared folder in which I have 3 or 4 people who all run the same .exe file. I need to be able to count all instances of the running process.
So far I've tried mutex and:
Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length;
those work if I'm trying to compute the number of instances of the .exe file I have running on my machine, but this will be running on multiple machines all pointing back to the same shared executable.
I don't want to create a file that increments and decrements depending on if a user opens or closes it for that would be unreliable.
--------edit--------------
Does anybody know how Excel does it? If the 2nd person opens the file it says that it is in use and tells you who is using it
Thank you for your help!!!
There isn't any way other than to implement some form of a licensing service or if you have privileges to the running machines.
You can tell who has a share open:
open computer management (right click my computer and select manage)
then from the tree view on the left select:
system tools> shared folders> sessions
this lists who is accessing files through shares.
there is an SO answer about sdoing this programatically:
https://stackoverflow.com/a/2418657/359135
If you really wanted to take it further and you have the admin rights you could use this info to interrogate running processes on connected machines:
tasklist.exe /S SYSTEM /U USERNAME /P PASSWORD
http://www.watchingthenet.com/how-to-view-and-kill-processes-on-remote-windows-computers.html
I am not suggesting you do any of this.. more to highlight what would be required. I would run a server somewhere that received a open, close and ping notification from your app.
the ping notification would let you identify instances that had crashed, lost connectivity or for any other reason not sent a close notification to the server app.
I have seen this done just by having a table in a DB of open session that gets written to every minute or so. I don't know how this would work for millions of users but i have seen it working well for tens of users (up to about a hundred).
EDIT:
more on pinging..
if you have server side code you can actively look for missing pings, however I would be tempted to just use a DB table and add a where clause to your select when reading open sessions:
Select
*
FROM
Session
WHERE
LastPing > DATEADD(second,-60,Now())
and I would check for an old record on insert, so that you don't get lots of old rows hanging around.
EDIT: just to be clear if you used the crazy techniques listed at the start of this answer you would have no way of knowing that someone had copied the file to their machine locally and run it. If you make the program insist that it has a connection to a particular DB or server then you have much more control.
A process on one computer cannot detect processes running on a different computer unless you set up some kind of communication between them.
You could set up a shared file as you suggest, but yes it will be unreliable.
You could run a service on some central computer and each instance has to report back to the server, but of course that will have similar reliability issues. (If one instance dies without notifying the server, the server won't realize it's still running.)
When each instance runs, it could listen at a port, record its IP and port number in a central file, and when you need a count you try to connect to each of those ports to confirm that instance is still running.
There are lots of ways you can do it, but the work is up to you. No help from the OS like you get when they're all on the same machine.

Error When Connecting to Quickbooks in BlindMode Using QBXML Interface

I am experiencing an issue with an application that is attempting to access Quickbooks in blind mode (i.e. Quickbooks is not running). In short, I have a simple C# application that synchronizes information between a Quickbooks company file and SQL database on a web server to allow customers to make payments toward invoices online. The UI for the application only has one button and a few other settings so, I modified the code so that it can be run as a scheduled task in the middle of the night. Unfortunately, this has been much more trouble than I anticipated.
First, I could not get it to run through the task scheduler or an elevated command prompt. Then, I came across a post that stated that there is a bug in the SDK when attempting to access Quickbooks via the QBSDK if the host is a terminal server with multiple sessions. The temporary solution was to make sure that Quickbook is running on the session that the job is running on to prevent it from trying to attach to another session. So, I made sure that Quickbooks is loaded but, NOT logged in to a company file. While this solution works if I try to run my application from an elevated command prompt it still does not work when the job is launched from the windows task scheduler. I am not logged into the server remotely now but, the error message states something about not being able to open a session because there is a modal dialog box open. I will modify the post to include the specific error message as soon as I am able to connect to my client's server. Quickbooks is open on the session that is trying to run as a scheduled task and I am able to run the application from an elevated command prompt. Can someone please offer any suggestions or feedback about how I might go about solving this problem? Thanks in advance for your help!

invoke exe(with GUI) on remote machine

can we invoke exe of application(made in .net) on remote server using local machine.
we have full credentail on all machine to execute process.
how can we achive that ?its require to open GUI on remote machine.
we tried using WMI/.dat file invoke but all opens process on Task Manager & could not lunch GUI..
anyone have idea to accomplish same??
You can use psexec for this.
http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx
At one point in time, you could write a Windows Service, run it under the local system account, and allow it to interact with the desktop. However, this will only work on Windows XP. Vista (and I assume Windows 7) show the UAC prompt first, which is annoying and sometimes only shows up on the taskbar until it's clicked.
We got around this by writing a WinForms app that had no visibility on its own, but this app watches for a trigger. When the trigger occurs, the program then launches the appropriate exe.
For example, the trigger may specify to open up a web page on our intra net. The program uses the System.Diagnostics.Process.tart() to launch the web page in the default browser.
The trigger can be one of many things... The exe can poll a database, web service, etc. The exe can host a WCF host use remoting, or it could use a FileSystemWatcher.
The most complicated part of writing such an app is figuring out the appropriate trigger. Launching the app is trivial using the System.Diagnostics.Process.
For our situation, we set the program up to just launch when Windows starts, USG a registry setting.
Use PsExec tools
with -i switch
Like
psexec \\remotecomputer -u username -p password -i 2 "your exe loacation"

Screenshot of process under Windows Service

We have to run a process from a windows service and get a screenshot from it.
We tried the BitBlt and PrintWindow Win32 calls, but both give blank (black) bitmaps.
If we run our code from a normal user process, it works just fine.
Is this something that is even possible? Or could there be another method to try?
Things we tried:
Windows service running as Local System, runs process as Local System -> screenshot fails
Windows service running as Administrator, runs process as Administrator -> screenshot fails.
Windows application running as user XYZ, runs a process as XYZ -> screenshot works with both BitBlt or PrintWindow.
Tried checking "Allow service to interact with desktop" from Local System
We also noticed that PrintWindow works better for our case, it works if the window is behind another window.
For other requirements, both the parent and child processes must be under the same user. We can't really use impersonation from one process to another.
Currently i can't find the corresponding links, but the problem is, that a windows service runs in another session than a normal user application.
In XP this was not fully true. Here are all services started in Session 0 and the first user who logs into the system will also run in Session 0. So in that case, tricks like Allow service to interact with desktop work. But if you fast switch to another user he gets the Session 1 and has no chance to interact with the service directly. This is also true if you connect through RDP to a server version (like 2003 or 2008). These logins will also start in a session higher than 0.
Last but not least there is another drawback by using the interaction with the desktop:
If you enable this option and your service is running under the (default) SYSTEM account it won't be able to create a network connection anymore.
The correct way to get a custom GUI that works with a service is to separate them into two processes and do some kind of IPC (inter process communication). So the service will startup when the machine comes up and a GUI application will be started in the user session. In that case the GUI can create a screenshot, send it to the service and the service can do with it, whatever you like.
Have you tried to run as Local System with the "Allow service to interact with desktop" checked?
I don't think this is possible.
We had to change our scenario where our application wasn't started from a service, but was a standard windows program that has a NotifyIcon in the corner.
If someone still finds a real answer, let me know.
It works using Local System with the "Allow service to interact with desktop"
You can set it programatically using this sample code:
http://www.vbforums.com/showthread.php?t=367177 (it's vb.net but very simple)

Categories