Execute SSH command line with sudo and enter password afterward [duplicate] - vb.net

I am trying to use Renci SSH.NET to connect to a remote Linux server from a C# web application and execute shell scripts. I want to run the scripts one after another. But not getting how to run the scripts and read the output and store it in a label.
I have tried the below code, but not able to pass multiple commands one line after another.
SshClient sshclient = new SshClient("host", UserName, Password);
sshclient.Connect();
ShellStream stream = sshclient.CreateShellStream("commands", 80, 24, 800, 600, 1024);
public StringBuilder sendCommand(string customCMD)
{
StringBuilder answer;
var reader = new StreamReader(stream);
var writer = new StreamWriter(stream);
writer.AutoFlush = true;
WriteStream(customCMD, writer, stream);
answer = ReadStream(reader);
return answer;
}
private void WriteStream(string cmd, StreamWriter writer, ShellStream stream)
{
writer.WriteLine(cmd);
while (stream.Length == 0)
{
Thread.Sleep(500);
}
}
private StringBuilder ReadStream(StreamReader reader)
{
StringBuilder result = new StringBuilder();
string line;
while ((line = reader.ReadLine()) != null)
{
result.AppendLine(line);
}
return result;
}
I am trying to run the below commands
sudo su - wwabc11
whoami
cd /wwabc11/batch/bin/
pwd
How to run the commands one after another and read the output information? Thanks.

Just write the "commands" to the StreamWriter.
writer.WriteLine("sudo su - wwabc11");
writer.WriteLine("whoami");
// etc
See also C# send Ctrl+Y over SSH.NET.
Though note that using CreateShellStream ("shell" channel) is not the correct way to automate a commands execution. You should use CreateCommand/RunCommand ("exec" channel). Though SSH.NET limited API to the "exec" channel does not support providing an input to commands executed this way. And whoami and the others are actually inputs to sudo/su command.
A solution would be to provide the commands to su on its command-line, like:
sudo su - wwabc11 -c "whoami ; cd /wwabc11/batch/bin/ ; pwd"
For an example of code that uses CreateCommand to execute a command and reads its output, see see SSH.NET real-time command output monitoring.

Related

How does Lettuce dynamic command interface work with Redis modules?

Trying to send RedisTimeSeries commands thru Lettuce (Java) to Redis. It worked for simple commands such as TS.Create but I couldn't get slightly more complicated commands to work (such TS.ADD which takes key, score, value as args) or TS.Range (which takes args and returns List) to work.
Redis is running on Linux (Ubuntu running on Windows 10 thru WSL), RedisTimeSeries is installed onto Redis. Redis and RedisTimeSeries commands have been tested using Redis-cli on linux, they work fine. I use VS Code + JDK 13.0 + Maven to build and test a Java client for Redis. So far Redis commands supported by Lettuce are working thru the client, plus some simple RedisTimeSeries commands.
Code snippet:
RedisCommands<String, String> syncCommands = MyRedisClient.getSyncCommands(connection);
// this works:
RedisCodec<String, String> codec = StringCodec.UTF8;
String result = syncCommands.dispatch(TS.CREATE, new StatusOutput<>(codec),new CommandArgs<>(codec).addKey("myTS"));
System.out.println("Custom Command TS.CREATE " + result);
//custom command definition:
public enum TS implements ProtocolKeyword{
CREATE;
public final byte[] bytes;
private TS() {
bytes = "TS.CREATE".getBytes(StandardCharsets.US_ASCII);
}
#Override
public byte[] getBytes() {
return bytes;
}
}
But when I switched everything to test TS.ADD, it's doesn't work even though I added additional args accordingly.
e.g.
String result = syncCommands.dispatch(TS.ADD, new StatusOutput<>(codec),new CommandArgs<>(codec).addKey("myTS").addValue("1000001").addValue("2.199"));
Here is the exception from the run:
Exception in thread "main" io.lettuce.core.RedisException: java.lang.IllegalStateException
at io.lettuce.core.LettuceFutures.awaitOrCancel(LettuceFutures.java:129)
at io.lettuce.core.FutureSyncInvocationHandler.handleInvocation(FutureSyncInvocationHandler.java:69)
at io.lettuce.core.internal.AbstractInvocationHandler.invoke(AbstractInvocationHandler.java:80)
at com.sun.proxy.$Proxy0.dispatch(Unknown Source)
at MyRedisClient.main(MyRedisClient.java:72)
Sorry for seeing this so late. If you haven't already found a solution I had initially implemented RediSearch commands using the dynamic commands.
public interface RediSearchCommands extends Commands {
#Command("FT.SUGADD ?0 ?1 ?2")
Long sugadd(String key, String string, double score);
...
}
public void testSuggestions() {
RedisCommandFactory factory = new RedisCommandFactory(client.connect());
RediSearchCommands commands = factory.getCommands(RediSearchCommands.class);
commands.sugadd(key, "Herbie Hancock", 1.0);
}
Full source: https://github.com/RediSearch/lettusearch/commit/567de42c147e0f07184df444cd1ae9798ae2514e

Is there a way to conect the input/output of a console application to the output/input of another program

I have an application i cannot edit that reads from the console and writes to it and i want to know how i can read what the program is saying and write back commands to the program.
This is for a minecraft server where i want to read what the players are saying and run commands acoording to what is said. (the server is the application i cannot edit)
I cannot create a modification for the server, because i am using a mod that checks if there are any other modifications done to the files and fails to load if that is the case.
I wrote a simple app in c# to get started with, to redirect the I/O streams you need to start the application (in this case the server) within your own application.
First we create a new instance of the System.Diagnostics.Process class
var process = new Process();
then we specify the start info
process.StartInfo = new ProcessStartInfo
{
FileName = Console.ReadLine(), //Reads executable path from console
RedirectStandardOutput = true,
RedirectStandardInput = true,
UseShellExecute = false
};
then we add an event handler, in this example it's just writes the lines with a "> " prefix
process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => Console.WriteLine($"> {e.Data}");
and now we can start the process by calling Process#Start()
process.Start();
and finally we can call Process#BeginOutputReadLine() without this the OutputDataReceived event will never trigger
process.BeginOutputReadLine();
To send commands you can use the process' StandardInput stream
process.StandardInput.WriteLine("command");
The fully working code with example output (tested with cmd.exe, but it's must work with MC servers)
Code:
static void Main(string[] args)
{
Console.Write("Enter executable path: ");
var process = new Process();
process.StartInfo = new ProcessStartInfo
{
FileName = Console.ReadLine(), //Reads executable path, for example cmd is the input
RedirectStandardOutput = true,
RedirectStandardInput = true,
UseShellExecute = false
};
process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => Console.WriteLine($"> {e.Data}");
process.Start();
process.BeginOutputReadLine();
process.StandardInput.WriteLine("echo a");
//Prevent closing
Console.ReadKey();
}
Output:
Enter executable path: cmd
> Microsoft Windows [Version 10.0.18362.239]
> (c) 2019 Microsoft Corporation. Minden jog fenntartva.
>
> F:\VisualStudio\StackOverflow\StackOverflow\bin\Debug\netcoreapp2.1>echo a
> a
>

Converting a doc to a pdf in a mvc c# environment

Hi I've got a c# MVC application running under a particular user (app.pool user).
I need to convert a doc or docx file to a pdf.
I thought a good option would be to use libreoffice to fire a process that would start this.
To make life easier for myself (and if libreoffice shouldn't work) I used a batch file.
echo on
SET var1=%2
IF "%var1:~-1%"=="\" SET var1=%var1:~0,-1%
cd %var1%
echo %1
echo %var1%
start /wait "" "C:\Program Files (x86)\LibreOffice 4\program\soffice" -headless -convert-to pdf %1 -outdir %var1%
My code for starting this is as follows.
var ba = #"C:\inetpub\wwwroot\apps\xxxxxxxxx\Services\convert.bat";
fullPath = #"C:\inetpub\wwwroot\apps\xxxxxxxxx\Files\Temp\636295920370843147.doc";
var tempPath = #"C:\inetpub\wwwroot\apps\xxxxxxxxx\Files\Temp";
string command = ba;
//Process.Start(command, fullPath + " " + tempPath);
var processInfo = new ProcessStartInfo("cmd.exe", "/c " + command + " "+ fullPath+ " "+ tempPath);
processInfo.CreateNoWindow = false;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardError = true;
processInfo.RedirectStandardOutput = true;
var process = Process.Start(processInfo);
process.OutputDataReceived += (object sender, DataReceivedEventArgs e) =>
Trace.WriteLine("output>>" + e.Data);
process.BeginOutputReadLine();
process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) =>
Trace.WriteLine("error>>" + e.Data);
process.BeginErrorReadLine();
process.WaitForExit();
Trace.WriteLine("ExitCode: {0}", process.ExitCode.ToString());
process.Close();
This does seem to work manually but when I run the code I can see the whole thing just stalls around the conversion. Looking at the threads and it seems to load the gdiplus.dll which I think is a graphics module which doesn't seem right.
The process though when I copy and paste that into my 'run' box in windows works fine and the pdf is made.
I've checked that the app.pool user has access to both libreoffice and also the folder with the files.
I've ran this as the app.pool user, in the c# it just stalls on the process.WaitForExit();
line. Until I kill the process.
Any ideas?
I've also tried many different ways of executing the soffice conversion. just straight from the c# - libreoffice 4,5.
I've seen some people use libreoffice as a service, is this an option? If so how?
Richard
EDIT
Ah, just changed the app Pool user to myself and now it works, so there is a permissions thing with the standard app pool user. How to find out what....
I added the user into the administrators group on the computer and restarted the machine, then it worked.
It might not be the best solution but after 2 days of trying to get this to work I'm not going to argue.
Richard

Dart file copy in Windows

The File class in the dart:io library doesn't yet include copy() and move() methods.
To tide me over until they arrive, I'm trying to roll my own copy function. I'm using the code below on Windows, but it just creates a 0kb file.
void copyFile(String input, String output) {
var inFile = new File(input), outFile = new File(output);
if (outFile.existsSync()) outFile.deleteSync(); // I realize this isn't required
var inStream = null, outStream = null;
try {
inStream = inFile.openInputStream();
outStream = outFile.openOutputStream(FileMode.WRITE);
inStream.pipe(outStream);
} finally {
if (outStream != null && !outStream.closed) outStream.close();
if (inStream != null && !inStream.closed) inStream.close();
}
}
I've also tried replacing the pipe line with print(inStream.read(100).toString()); and I get null. The input file does exist (otherwise I'd get a FileIOException). Am I doing something wrong, or are input streams broken under Windows?
I'm using:
Dart Editor version 0.3.1_r17463
Dart SDK version 0.3.1.2_r17463
Edit: The following works (although it doesn't "chunk"). Am I using the streams above incorrectly?
void copyFile(String input, String output) {
var inFile = new File(input), outFile = new File(output);
if (outFile.existsSync()) outFile.deleteSync(); // I realize this isn't required
outFile.writeAsBytesSync(inFile.readAsBytesSync(), FileMode.WRITE);
}
With your first code snippet, you get an empty file because pipe is not a synchronous method. Thus, the copy of inputStream to outputStream has not started when the finally block is execute. By closing the streams in this finally block, you stop the pipe before it even starts. Without that finally block the copy is done correctly.
void copyFile(String input, String output) {
final inStream = new File(input).openInputStream();
final outStream = new File(output).openOutputStream(FileMode.WRITE);
inStream.pipe(outStream);
}
Finally, you don't have to worry about closing streams because pipe close streams by default once achieved. See InputStream.pipe.
For synchronous copy, use:
File(sourceFile).copySync(destinationFile);
For asynchronous copy, use:
File(sourceFile).copy(destinationFile);

How to Read a pre-built Text File in a Windows Phone Application

I've been trying to read a pre-built file with Car Maintenance tips, there's one in each line of my "Tips.txt" file. I've tried to follow around 4 or 5 different approaches but It's not working, it compiles but I get an exception. Here's what I've got:
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
using (StreamReader sr = new StreamReader(store.OpenFile("Tips.txt", FileMode.Open, FileAccess.Read)))
{
string line;
while ((line = sr.ReadLine()) != null)
{
(App.Current as App).MyTips.Insert(new DoubleNode(line));
}
}
}
I'm getting this "Operation not permitted on IsolatedStorageFileStream", from the info inside the 2nd using statement. I tried with the build action of my "Tips.txt" set to resource, and content, yet I get the same result.
Thanks in advance.
Since you've added it to your project directory, you can't read it using Isolated Storage methods. There are various ways you can load the file. One way would be to set the text file's build type to Resource, then read it in as a stream:
//Replace 'MyProject' with the name of your XAP/Project
Stream txtStream = Application.GetResourceStream(new Uri("/MyProject;component/myTextFile.txt",
UriKind.Relative)).Stream;
using(StreamReader sr = new StreamReader(txtStream))
{
//your code
}