How to keep app open after bash command started C# - c#

I have a problem with my code on linux. How do I keep app open after some bash commands are launched?
This code:
Process.Start("/bin/bash", " -c 'screen -S testScreen -d -m bash -c \"/home/test/Launcher.exe\"'");
Console.ReadKey();
What it does? it runs "Launcher.exe" in "testScreen", but for some reason, it closes program where that bit of code is there. I have there Console.ReadKey() in purpose and don't want to close it. Can someone explain me why does it close?

The Proces.Start method returns an object of type Process. After starting the bash command you can invoke WaitForExit on it.
var proc = Process.Start(...);
proc.WaitForExit();
Console.ReadKey();

Related

Start WSL Script from WPF C# Application

I would like to run a bash script using WSL from a WPF application. I have been using the Process.Start() method to try and run this script, passing some arguments along with it. I thought I had this function running perfectly before, however I am struggling to get the script to run on WSL.
Here is the code I have below, I can include the WSL script if needed.
I need to run the WSL script and pass some arguments to the script from the command line.
string path = "\"" + store.LPFolderPath + "\"";
Debug.WriteLine(path);
Process p = new Process();
ProcessStartInfo info = new ProcessStartInfo
{
FileName = "cmd.exe",
RedirectStandardInput = true,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
};
p.StartInfo = info;
p.Start();
if(p.StandardInput.BaseStream.CanWrite)
{
p.StandardInput.WriteLine(#"wsl");
p.StandardInput.WriteLine(#"cd path/To/Script");
//"./lpass == scriptFile "//
p.StandardInput.WriteLine(#"./lpass " + `ARG`);
p.StandardInput.WriteLine("exit");
p.StandardInput.Close();
};
p.WaitForExit();
From what I know this script does not run at all. Is there a mistake I am making utilizing Process or how would I go about debugging this C# call in order to find out my error?
This reminds me a bit of two questions I answered around using Python to launch WSL applications:
This one was using a subprocess.
And this one was using a SendKeys method.
In your case, you are attempting to use standard input, but I think the issue is similar. The first WriteLine launches WSL, but I believe it's now a separate process with its own standard input. The additional lines of standard input are probably going to the original process p, but are probably just waiting there until the WSL process terminates, which doesn't happen until your parent process terminates. Disclaimer - I haven't tried this myself; I'm just basing it on past experience with other languages.
The solution should be the same as I mention in the other answers -- Use arguments to the wsl command itself to call your script. E.g.:
p.StandardInput.WriteLine(#"wsl --cd path/To/Script -e bash -c lpass");
Or something similar. Try it from the command-line first:
wsl --cd path/To/Script -e bash -c lpass
The -e tells it to run the Bash shell, with the -c passing the ./lpass directly to Bash. The --cd is also a WSL argument which will set the initial starting directory, although it should be possible to move it into the Bash command as well:
wsl -e bash -c "cd path/To/Script; ./lpass"
If the lpass script has a shebang line, you can even bypass calling Bash:
wsl --cd path/to/Script -e ./lpass

bash shell doesn't show typed commands after interrupting C# Console Application

Take the following C# console app:
Console.Write("Your Name > ");
var input = Console.ReadLine();
Console.WriteLine("Hello " + input);
If I execute it in my bash shell using dotnet run and then interrupt it with Ctrl+C, I don't see any input in my bash shell anymore as also described in this question. Only with a reset I was able to restore it. Is there a way to ensure that this doesn't happen?

C# Screenshot winlogon as well as User Desktop

I am working with screen sharing project.But i was got into trouble to capture secure desktop.
I have already ask related question here and got Answer too
Pls go through above link
as suggested by dymanoid. I am using PsExec exe to capture secured desktop/winlogon desktop as below
The /x and /s switches run the process under the SYSTEM account and on the Winlogon desktop.
PsExec /i /h /x /d /s "path_\screencapture.exe"
Now screencapture exe is running as SYSTEM account on winlogon desktop, i able to see screencapture exe on user login screen but not on user desktop screen.
Now the things reverse i able to capture user login screen but not user desktop.
User desktop gives me Empty/black screen.
If i remove /x from command as below then i able to get userdesktop not secured desktop
PsExec /i /h /d /s "path_\screencapture.exe"
My question is if there any way to do this
I am unable to test my theory since I'm at work. + I do not have the rights to comment yet... So please bear with me, if this does not work.
Running as system could be related that it does not have a "desktop" directory.
So please create a these directories:
32-bit: %windir%\System32\config\systemprofile\desktop
64-bit: %windir%\SYSWOW64\config\systemprofile\desktop
Try again with the SYSTEM account:
PsExec -i -h -x -d -s "path_\screencapture.exe"
Sometimes the working directory is "read only" so by specifying that you could get it to work
PsExec -i -h -x -d -s -w c:\temp "path_\screencapture.exe"
If that does not work, try to attach it to a session, query the user-sessions available to see if a secure desktop are running its own sessioname, i command-prompt enter this:
query sessions
SESSIONNAME USERNAME ID STATE TYPE DEVICE
services 0 Disc
>console xxxx 2 Active
rdp-tcp 65536 Listen
My only session available here is services = 0 and mylogin = 2.
I would suggest to try
PsExec -i 0 -h -x -d -s -w c:\temp "path_\screencapture.exe"
or
PsExec -i 2 -h -x -d -s -w c:\temp "path_\screencapture.exe"
And see if there are any difference in the captures.
I have never worked with the secure desktop before, so it could be an extra layer. In a user situation the -i has always worked fine for me.
Good luck :)
Edit:
I have tested this out with luck, this is what I did:
Downloaded a capture tool with gui, I tried 7capture.com
Then I started 7capture.exe like this:
PsExec -i -s -x c:\7capture.exe
Now I showed the secure desktop with "run as admin" on something. When the popup comes, I pushed ALT+TAB and there was 7capture :)
Press the "Refresh" button to see a list of items. The "desktop" is called something like "$$$Secure UAP Background window" on my computer.
Voila, capture taken and visible
Now for the code on Screenshot secure desktop
I would change the desktop HWND call:
Win32Stuff.GetDesktopWindow();
To a Enum function and take a picture of every HWND you find in the secure desktop.
Untested, but I belive you can use this:
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
// Delegate to filter which windows to include
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
Give that a try and see if you can make it work for all scenarios.
Edit2:
Since these are 2 different user scopes, you need to run two copies of Screencapture.exe. One for secure desktop and one for the interactive session:
UAC:
PsExec -i -h -x -d -s "path_\screencapture.exe"
Without UAC:
PsExec -i -h -d "path_\screencapture.exe"

Launch a command shell from a console application run via Windows Task Scheduler

I have a Windows console application that is launched via a schedule setup in Task Scheduler. This console application, as part of its normal runtime, will launch a command prompt in order to run a java program. No, I have no control over the design of the Java program. It was supplied to me as is and I have no rights or access to make changes to it. I also cannot implement it in another language. I must use what was given to me.
At any rate, when my console application tries to run the command prompt it will work just fine if I'm launching the application manually. However, when I try it as an action within Task Scheduler, my console application will start and run as expected until it needs to launch the command prompt. At this point, the console application exits. No error message or code is provided.
How do I get the command prompt window to start as a new window from within my console application when no one is logged into the server?
Thanks for any hints or suggestions you can provide.
* UPDATE *
Here is the code snippet that launches the program from within my console application:
string parameter_save_path = #"C:\output\folder"
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo start_info = new System.Diagnostics.ProcessStartInfo();
start_info.WorkingDirectory = #"C:\mtselect-client";
start_info.FileName = "cmd.exe";
start_info.Arguments = "/C run.bat \"" + parameter_save_path + "\"";
process.StartInfo = start_info;
process.Start();
process.WaitForExit();
The run.bat is what launches the java program.
I think it's too late for this message, but...
Maybe in your batch file you are running your java application with something like: java -jar ApplicationName
First I would do should be comment out the "#echo off" from the batch file, next trace out the batch lines with one echo "x" (being x a natural number starting from 1 and increasing by 1 in each ocurrence). Next I will add a line with java -version, and so I will be sure java app is installed and accesible.
Maybe java needs be ran by an authenticated user and so have java_home defined. Maybe the application needs some JVM parameters like memory size, etc.
Have good luck, tell me and I will try to help

Passing parameters to bash when executing a script

I am trying to execute a bash shell script from Windows on a remote Linux machine.
I am using c# and the SSH.Net library.
The scripts live on the windows box and cannot be installed on the Linux machine. I read in the script using 'File.ReadAllText(...)' which loads in the script as string. Using SSH.Net I then execute the script on Linux:
SshCommand cmd;
using (var client = new SshClient(ConnectionInfo))
{
client.Connect();
cmd = client.CreateCommand(string.Format("sh -x -s < {0}", script));
cmd.Execute();
client.Disconnect();
}
return cmd.ExitStatus;
This works when the script doesn't have any parameters. But if I need to pass in some arguments the following executes the script but the params are missing:
cmd = client.CreateCommand(string.Format("sh -x -s p={0} < {1}", parameterString, script));
The sample script is:
#!/bin/bash
# check-user-is-not-root.sh
echo "Currently running $0 script"
echo "This Parameter Count is [$#]"
echo "All Parameters [$#]"
The output is:
Currently running bash script
This Parameter Count is [0]
All Parameters []
Update
For now I am using curl (like in the approved answer here:).
cmd = client.CreateCommand(string.Format("curl http://10.10.11.11/{0} | bash -s {1}", scriptName, args))
But I still think there must be a way to read in a bash script with arguments and run it across ssh on a remote Linux box.
Any help would be greatly appreciated.
Perhaps you are better off running ssh user#host 'command; another; more' or if you really have to use an explicit sh, something like ssh user#host "sh -c 'command; another; more'". That should also save you from putting the script in a temporary file.
I've done a little trouble-shooting, entirely off a linux box. I think that the
I think that your problem is 'p='.
I put your test script in /tmp/script, and ran the following:
$ ssh 192.168.2.3 sh -s foo bar baz < /tmp/script
Currently running sh script
This Parameter Count is [3]
All Parameters [foo bar baz]
I also tried
$ ssh 192.168.2.3 sh -s p=foo bar baz < /tmp/script
Currently running sh script
This Parameter Count is [3]
All Parameters [p=foo bar baz]
... so I'm not entirely sure why you're seeing a parameter count of 0, you should be seeing at least 'p=' as a parameter. It looks like you're trying to specify the argument list using 'p=' but that's not necessary. Give it a try without that, and see what happens.
To be clear, '/tmp/script' is stored on my local linux box, not on the remote machine. Anything sent to the standard input of the ssh command will be sent to the remote machine and processed as its standard input of the command being executed, so I could have just as easily used the command
$ cat /tmp/script | ssh 192.168.2.3 sh -s foo bar baz

Categories