c# interactiveProcessRunner - c#

Can someone tell me what the InteractiveProcessRunner is for? Is it identical to Process.Start?
Here is the class.
And here an example :
InteractiveProcessRunner runner =
new InteractiveProcessRunner(notepad.exe,hSessionToken);
THX

Whit this class you can run a process with the complete environment of the user active: if you call this code from a service, you should find the user mapped resources, the desktop and all the resources that are available when the user is loggen on interactively even if launched from a service ie not logged interactively.

The source code to which your link leads referes to this article: http://asprosys.blogspot.com/2009/03/perils-and-pitfalls-of-launching.html which explains the motivation behind it.
Summary: You can't really use Process.Start() when you want to start a new process as certain user from a windows service. The InteractiveProcessRunner lets you do this (supposedly, never used it so I can't verify it). So it's not the same as Process.Start() - it uses a different Windows API.

Related

Why can't a windows service created in C# detect that a screen saver is currently running?

As part of some work I need to get done for Windows 10, I have written a code in C# that essentially detects every minute whether a PC is in screen saver mode or not, and it writes to a table in MySQL the relevant status ("PC in use" if the screen saver is off, "available PC" if the screen saver is on).
I did this using (full link if required - https://www.codeproject.com/Articles/17067/Controlling-The-Screen-Saver-With-C):
// Returns TRUE if the screen saver is actually running
public static bool GetScreenSaverRunning( )
{
bool isRunning = false;
SystemParametersInfo( SPI_GETSCREENSAVERRUNNING, 0,
ref isRunning, 0 );
return isRunning;
}
The code works flawlessly in console application mode (I made a loop to test it out over a minute with a check up on screen save status every 10 seconds), this means in MySQL the status was set correctly every time, depending on the screen save status at the moment of the check up.
The problem occurs when I use this code for a windows service. The service is installed correctly, the log on tab is set on Local System (I also tried with the logged in user instead, same results) and I allow the service to interact with the desktop, just in case, but the difference here is that no matter if the PC enters screen save or not, it always returns false on GetScreenSaverRunning(), thus setting the status of the PC in MySQL as "PC in use", even if the screen saver is on at the moment of check up.
I get the sense that the problem isn't in the code itself, since it works without any issues as a console application, but perhaps something behind the scenes. I tried to search here and on many other websites, haven't found anything related to such a problem.
Does anyone have any idea at all what might be the issue? Any help and/or suggestions will be greatly appreciated!
Thank you in advance.
(I could post the code if required, but it is pretty much straight forward and the main part of it, controlling the screen save detection, is taken from the website mentioned above, afterwards it's a simple if (GetScreenSaverRunning() == true) )
Ever since Vista, Services are barred from a Interactive Session. Even if they run under the same rights, they do not get a interactive Session. I would guess that is getting in the way here.
While you can overwrite this behavior in the Service settings, this is not adviseable for new code. Consider making this a Background Task started by the Task Sheduler instead.
Because the windows service runs in different session then the windows logon. You can't interact with the desktop related services unless you run the windows service in win logon session. There used to be an option in Windows service manager where you can set the properties to "Interact with desktop session" but I don't think that ever worked.
There's a work around to run the windows service using the win logo session.
See this helper class that can get the current logged on user session and interact with the desktop services. https://github.com/murrayju/CreateProcessAsUser/blob/master/ProcessExtensions/ProcessExtensions.cs

Calling website through Windows Service

Looking at creating a windows service that will run on an IIS Server. Said service will access an url (mysite.com/mailflow.ashx) every 5 minutes. This is done to get the mailflow going, which is done by accessing the mailflow.ashx file.
Is: https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspx
what I'm looking for in my scenario or is there another class that will do the job?
Coming from a non-coding background but I want to do this on my own as a learning experience.
Small hints are more than enough.
Cheers!
Unless you really want to learn coding, I'd recommend simply creating a scheduled task in windows. Make it call the following js script (called wget in my case)
var WinHttpReq = new ActiveXObject("WinHttp.WinHttpRequest.5.1");
WinHttpReq.Open("GET", WScript.Arguments(0), /*async=*/false);
WinHttpReq.Send();
WScript.Echo(WinHttpReq.ResponseText);
and set the task to start the following program cscript with the following arguments /nologo C:\Path\To\wget.js http://my.url.com
There are plenty of ways to ping an remote url, so you may decide to use another option (perhaps simply launching then killing a browser) but coding a service really is overkill if this is the only task you need
Yes, the HttpWebRequest class is what you need.

How to run a non-admin process from admin c# application

I have a c# application that needs to do some things as an admin (some installation stuff) and then it needs to run another process as a non-admin. I haven't done anything with UAC before, but I assume there must be a way to do this, right?
This also needs to be automated, so assume that the c# app is started with admin credentials.
Basically the program will need to do something like this:
// MUST run this process as admin
Process adminInstall = new Process();
adminInstall.StartInfo.FileName = "install.bat";
adminInstall.Start();
adminInstall.WaitForExit();
// CANNOT run this process as admin
Process nonAdminProcess = new Process();
nonAdminProcess.StartInfo.FileName = "runner.cmd";
nonAdminProcess.StartInfo.UseShellExecute = false;
nonAdminProcess.StartInfo.RedirectStandardOutput = true;
nonAdminProcess.OutputDataReceived += new DataReceivedEventHandler(myHandler);
nonAdminProcess.Start();
nonAdminProcess.BeginOutputReadLine();
nonAdminProcess.WaitForExit();
You can embed a manifest in the executable using MT.exe (manifest tool) in the platform SDK after the binary is compiled, but before it is signed. You also have the option of using a custom manifest within your project properties. Open the project properties, then go to the application tab, then change the manifest option from default manifest, to custom manifest. Visual Studio will add a manifest to your project where you can specify "requireAdministrator" privleges. When your app runs, it will provide a UAC prompt, or ask for credentials if logged on as user. There is a good chance sub process will start as admin as well. Otherwise you will need to launch them with the "runas" verb which is undocumented.
Process.Start parameters has one for Username. See Process.Start reference:
http://msdn.microsoft.com/en-us/library/sxf2saat.aspx
There does not appear to be a nice way of doing this using the .Net classes. However, Process.Start with different credentials with UAC on explains a way of doing it using CreateProcessAsUserW after stealing a handle from another process.
If the aforementioned methods aren't viable, then you can try my method. But its ugly; you need to get a handle to a non admin process, then use DuplicateTokenEx (p/invoke) to copy its (non admin) privileges, then pass that into CreateProcessAsUser. You first need to identify a non admin process though, there may not be any. The newly created process will be spawned with whatever privileges the token you copied contained, not the token of the parent process.

Interactively log on another Windows user from c# code

I am trying to achive a situation:
I am logged as a user on my account.
I've created a two more accounts which I will try to log on in the
"background"
And now I want to execute my code to log on different user in the background,
so that if i can click ctrl+alt+del and go to the switch user screen
i can see that another account was logged on the system.
During investigation I've read that this was possbile with some undocumented winapi methods before Microsoft implemented Fast User Switch(FUS) which replaced GINA.
I don't want to Impersonate code as user. I want to start up the whole windows session for a user from code.
I've tried to do sth with CreateProcessWithLogonW() but this was unsuccessful.
Big virtual beer for anybody who can give me a hand with this! :)
Okay had to do a bit of digging to figure this out my self.
Essentially you would need to run a command in command prompt.
This should load explorer.exe as a second user.
runas /user:*computer name\*account name explorer.exe
Follow this to get an idea on running a command line command via c#:
How To: Execute command line in C#, get STD OUT results
Other sources:
http://www.computerhope.com/runas.htm
http://lifehacker.com/290435/switch-user-accounts-from-the-command-prompt

UAC gives me fits!

The code I am currently working on runs on Windows Server 2003, but needs to be able to write to EventLogs on multiple machines. I am coding in C#, using VS2008 Pro, and .NET Framework 3.5.
The code itself is relatively simple (thanks to the framework):
using (EventLog remoteEvtLog = new EventLog(LogName, HostName, EventSource))
{
remoteEvtLog.WriteEntry(Body);
}
"LogName" is a string containing the name of the log to write to - in most cases "Application".
"HostName" is a string containing the NetBIOS Name of the machine where the log entry should be written.
"EventSource" is a string containing the name of the event sender (this is a utility used by multiple apps, so usually it will have the name of the consuming application).
"Body" is a string containing the text to be written to the event log.
In most cases this works fine, but when the machine being written to uses UAC, any write which creates a new EventSource fails. This occurs even though the Security credentials used are members of the Administrators group - and I have not been able to find a way to specify the elevated priviledge level. Apparently, members of the Administrators goroup get two tokens - one limited, and one elevated, but as far as I can tell, the only way to specifiy the elevated token is through the UI - which is obviously a problem when remotely accessing the Logs.
Any ideas out there?
Your code is not supposed to create new event sources (the legacy auto-create behavior is unfortunate, but still wrong). If you need a separate event source for your application, then the installer for that application - which runs with elevated administrative privileges - should create it.

Categories

Resources