Force Windows service to use RDP session - c#

I have a very specific issue I fail to fix with my application.
I am building up a remote software validation tool (in C#) for a secure software located inside a VDI-type infrastructure built up on Windows Server 2016.
The idea is to USB plug in a smart card with valid a certificate inside a distant computer (using classic Windows 10), access the VDI by connecting via RDP (using Windows Remote Desktop) and use the validation tool to gain access to the secured application.
Everything works smoothly as long as I am using the application from an executable launched via Visual Studio debug or built up as .exe and launched inside the remote session.
However, I have an obligation to embed the executables as Windows Services, and in such it renders the validation tools unusable. I have found out that it is because in such case the validation software uses the VDI smart card service and not, as I expected, the smart card service from the computer I access the VDI with.
As such, the validation tools seeks for cards on the VDI and not on my access computer.
So, my question is, is there such a way to "hijack" the VDI smart card reader service with the one from my own computer, or is there any way the App can detect the service from my RDP session ?
Thanks
Edit: a simplified C# method code we use to gather the data from the service:
protected void ExtractRawSC()
{
//----------------------- TEST SYSCAL
var proc1 = new ProcessStartInfo();
string Command = "certutil -scinfo > C:\\Users\\Administrateur\\Documents\\output.txt";
proc1.UseShellExecute = true;
proc1.WorkingDirectory = #"C:\Windows\System32";
proc1.FileName = #"C:\Windows\System32\cmd.exe";
proc1.Verb = "runas";
proc1.Arguments = "/c " + Command;
//proc1.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(proc1);
//------------------------
}

Related

Process.Start() working but no window is popping up

I have a web API project that has a call that allows the user to basically start a separate application on the server.
Basically my web API is a gateway to remotely call this application from an MVC project.
Problem:
The problem I am facing is that the Process.Start() method is working perfectly (as in I can see the process starting on the server's task manager) but no window is popping up? I can run the application directly and see it start in its own window.
Web API Code:
public void ReconnectEPLAN()
{
if (CheckEplanConnection() == false)
{
Process process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.FileName = #"C:\Program Files\EPLAN\Pro Panel\2.8.3\Bin\W3u.exe"; //works but no ui poopup
process.StartInfo.CreateNoWindow = false;
process.Start();
}
}
What can I do to force the started process's app window to appear as well?
On your server, IIS runs as a service (unlike IIS Express, which runs in the user space).
Since Windows Vista, services can no longer interact with the user's desktop directly.
See:
How to run console application from Windows Service?
https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/f8f91e8f-5954-43a7-8bc4-80ed2ff1e3b1/quotallow-service-to-interact-with-desktopquot-does-not-work-on-vista?forum=windowssdk
https://www.codeproject.com/Questions/1239551/Why-does-process-start-goes-to-background-when-sta
Services cannot interact directly with the user at all: this is because services can run on a machine that doesn't have a user logged in at all, so there is no way to interact with them.

C# System.Diagnostics.Process doesn't work properly

I am using System.Diagnostics.Process in a Windows service application. The application that I call uses DropBox API and Google Drive API. When I login on Google Drive or DropBox it is supposed to open the Web browser and allow access to Drop or Drive, but it doesn't open it. Other functions works properly (create folder on local computer, read files, write logfiles etc).
When I open this application manually with double click, the login process works properly, the web browser is shown and I can allow access.
Something similar happens with other application using Saraff Twain. If I open it manually it works properly, I can scan and save files (on this process some alerts or message box are shown, like a "scanning", "no paper", "no scanner" messages) but when the windows service call it no messages are shown, it scans and save files but without messages.
If I call this application from another windows form or console application the applications works properly.
I don't know what is the problem with the Windows service.
Thanks for your help.
Here is the code that I used in the Windows service app (here it fails), and Windows forms app (here it works fine). I have tried calling CMD.exe and application path as argument, and directly the path on file name.
p.StartInfo.UseShellExecute = false;
p.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/C" + " \"" + execName+"\" " + argument;
//p.StartInfo.Verb = "runas";
// writeLogLine(argument + " " + execName);
p.Start();
output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
writeLogLine("out" + output);
A Windows Service is not meant for user interaction as it should be capable of running without any users logged in.
Windows Services are isolated from the users' desktops as a security measure this is why any interaction with a desktop is bound to fail.
Either replace the Windows Service with a regular desktop application or change the Windows Service in such a way that it doesn't need desktop access.

Start Node.js server from a C# Application

A requirement has arisen that I need to start a Node.js server from a C# application, this is as simple as running a server.js script within the Node.js console. However, I'm not entirely certain how exactly to achieve that.
Here's what I've looked into so far:
In the Node.js installation, there's a file called C:\Program Files (x86)\nodejs\nodevars.bat, this is the command prompt window for Node.js. To start the server, I could possibly be using the following steps:
Execute the nodevars.bat file.
SendKeys to the new process console window to start the server.
This approach feels a bit fragile. There's no guarantee that the target user will have their Node.js installation in the same place, also sending keys to a process may not be an ideal solution.
Another method could be:
Write a batch file that executes nodevars.bat.
Execute the batch file from the C# application.
This seems like a better approach. However, the only problem here is that the nodevars.bat opens in a new console window.
So to the question(s), is there a way I can start a node.js server script using functionality built into the node.js installation? Perhaps sending arguments to the node.exe?
If it is to serve multiple users, i.e. as a server, then you can use the os-service package, and install a Windows service. You can then start and stop the service using the standard API.
If you are to start the server as a "single purpose" server, i.e. to serve only the current user, then os-service is the wrong approach. (Typically when using this approach you will specify a unique port for the service to use, which will only be used by your application).
To start a batch file or other Console application, from C#, without showing a console window, use the standard method, but be sure to specify:
ProcessStartInfo psi = new ProcessStartInfo();
psi.UseShellExecute = false; // This is important
psi.CreateNoWindow = true; // This is what hides the command window.
psi.FileName = #"c:\Path\to\your\batchfile.cmd";
psi.Arguments = #"-any -arguments -go Here"; // Probably you will pass the port number here
using(var process = Process.Start(psi)){
// Do something with process if you want.
}
There are a few different ones but I recommend the os-service package.

Automating IISRESET via remote desktop connection after a TFS build

I want to automate a process, which is invoked after a successful build on TFS. The process will RDP to a test server, then call a C# application on that server, and reset IIS on that server. Each step will return the result so whether or not to call next step is based on the previous step.
There are a few obstacles in implementing it. Below is what I want to know if it is possible, and how to code it.
1) Invoking the process via a build on TFS
There is an option in Build definition to invoke automated test. I assume that the process can be invoked by implementing it as a test.
2) RDP to remote server
I found the links below, which might be a solution
Process rdcProcess = new Process();
rdcProcess.StartInfo.FileName = Environment.ExpandEnvironmentVariables(#"%SystemRoot%\system32\cmdkey.exe");
rdcProcess.StartInfo.Arguments = "/generic:TERMSRV/192.168.0.217 /user:" + "username" + " /pass:" + "password";
rdcProcess.Start();
rdcProcess.StartInfo.FileName = Environment.ExpandEnvironmentVariables(#"%SystemRoot%\system32\mstsc.exe");
rdcProcess.StartInfo.Arguments = "/v " + "192.168.0.217"; // ip or name of computer to connect
rdcProcess.Start();
Run mstsc.exe with specified username and password
Automating remote desktop connection
3) IISReset
I think it should be simply invoke "IISRESET" after RDP, but the problem is that, HOW to captrue the result of running IISRESET.
The tools that might be suitable are:
1) Powershell - I don't know much about Powershell but am willing to learn if required
2) C#
My question is that how to implement it, any code example, and idea would be very much appreciated.
Check my answer here which is somewhat related: Answer
If the user which runs the TFSBuild Service on the build server have enough rights on the test server then you can use psexec or powershell to run your commands remotely. Read the below links:
PSEXEC
PowerShell Remote commands
There is no inbuilt activity/process which can help you run scripts on remote machines in TFS build workflow.
Step 1 for you is to identify how you are going to run scripts on the remote machine, as mentioned above you can either use PSEXEC or Powershell (though running PowerShell on remote computers may be a little more complicated to set up).
Step2, write the actual scripts to do the work, stop services, install MSI etc.
Step3, Edit your current build defintion - create a new custom activity or make use of InvokeProcess activity from within your build definition to invoke the script that you have created in Step 2. InvokeProcess Activity
in most cases you do not need to run iisreset
if you want to upgrade an asp.net application, try to put app_offline.htm in the application folder, it will stop an application and application files will be unlocked
after upgrading an application, it will restart automatically, or you can "touch" web.config to force restart
You might be better using the Lab Build to run the scripts as part of an environment ob the target computer. It can run any powershell against that machine as well as deploy and execute applications....
Question: HOW to capture the result of running IISRESET
I believe the old fashioned way, Hope this is what you are looking for
c:> IISRESET >> C:\temp.log
You can use the above either from CMD or powershell
In the past I have used Psexec to run commands against a remote server and where ever we need to control flow on the result of that command, we simply piped the console out to a shared folder and checked for our success flag.
I am not sure if TFS can run commands in this manner but we implemented it on hudson/jenkins.
This won't answer your question directly but it may offer a better way forward
An Example:
psexec.exe \remoteserver "iisreset > h:\iisreset.log"
Then run a grep or similar against the iisreset.log with your success flag as a condition to run the next step.

Can I run another Command Prompt/GUI process in a Windows Service?

I am writing a windows service that occasionaly has to renew IP address of the system and It would call ipconfig /renew to do it.
The code is going to look like this
Process ipconfigProcess = new Process();
ipconfigProcess.StartInfo.FileName = "ipconfig";
ipconfigProcess.StartInfo.Arguments = " /renew";
ipconfigProcess.StartInfo.UseShellExecute = false;
ipconfigProcess.StartInfo.RedirectStandardOutput = true;
ipconfigProcess.Start();
strOutput = compiler.StandardOutput.ReadToEnd();
ipconfigProcess.WaitForExit();
I suppose a windows service is not allowed to show windows/dialogs. So my question is whether renewing ip as above would be a problem in windows service because it may or may not show a console to run ipconfig ?
I think the only issue you're going to face is that of permissions - you should have no problem running a process like this (as long as you don't want to interact with any kind of UI), but your windows service needs to run as an account that will be able to spawn a process and execute ipconfig.
This does not require an instance of cmd.exe. Many command line applications are used in this manner.
A service can use GUI functions and/or create a console. Windows creates a dummy display surface to draw on as necessary. (Obviously, this dummy surface can't interact with the user.)

Categories

Resources