Archive

Posts Tagged ‘C#’

sudo for Windows with C#


Working with PowerShell or the Windows Command Console is always a pain in the ass when it comes to running programs with administrative privileges. Sure you can use “runas”. But “runas” does not redirect its output to the current console and its syntax is a bit too much of typing. Yes I am lazy. That is why I though of programming a simple Linux-style sudo command. And here it is:
using System;
using System.Diagnostics;
using System.IO;
using System.Security;
using System.Threading;

namespace sudo
{
    class Program
    {
        static void Main(string[] args)
        {
            string command = Environment.CommandLine;
            int i = command.IndexOf("  ",0);

            if (i > 0)
                StartProcess("cmd" ,"/C \"" + command.Substring(i, command.Length - i).Trim() + "\"");
            else
            {
                Console.WriteLine("========SUDO Settings========");
                Console.Write("Default Domain: ");
                sudo.Properties.Settings.Default.Domain = Console.ReadLine();
                Console.Write("Default Administrator: ");
                sudo.Properties.Settings.Default.UserName = Console.ReadLine();

                if (sudo.Properties.Settings.Default.Domain.Length == 0) sudo.Properties.Settings.Default.Domain = Environment.UserDomainName;
                if (sudo.Properties.Settings.Default.UserName.Length == 0) sudo.Properties.Settings.Default.UserName = Environment.UserName;

                sudo.Properties.Settings.Default.Save();
            }
        }

        private static void StartProcess(string filename, string args = "")
        {
            ProcessStartInfo processinfo = new ProcessStartInfo();

            processinfo.FileName = filename;
            processinfo.Arguments = args;
            processinfo.UseShellExecute = false;
            processinfo.WindowStyle = ProcessWindowStyle.Hidden;
            processinfo.CreateNoWindow = false;
            processinfo.RedirectStandardOutput = true;
            processinfo.RedirectStandardError = true;
            processinfo.RedirectStandardInput = true;
            processinfo.LoadUserProfile = false;
            processinfo.WorkingDirectory = Directory.GetCurrentDirectory();
            processinfo.UserName = sudo.Properties.Settings.Default.UserName;
            processinfo.Domain = sudo.Properties.Settings.Default.Domain;
             Console.Write("Password for {0}: ", processinfo.UserName + "@" + processinfo.Domain);
            processinfo.Password = GetPassword();
            Console.WriteLine("===============================================\n");

            try
            {
                using (Process process = Process.Start(processinfo))
                {
                    process.OutputDataReceived += process_OutputDataReceived;
                    process.ErrorDataReceived += process_OutputDataReceived;

                    //Thread.Sleep(100);
                    //WinAPI.ShowWindow(process.MainWindowHandle, 5);

                    process.BeginErrorReadLine();
                    process.BeginOutputReadLine();

                    StreamWriter streamWriter = process.StandardInput;
                    streamWriter.AutoFlush = true;

                    while (!process.HasExited)
                    {
                        foreach (ProcessThread thread in process.Threads)
                        {
                            if (thread.ThreadState == System.Diagnostics.ThreadState.Wait && thread.WaitReason == ThreadWaitReason.UserRequest)
                            {
                                /*
                                consolekey = Console.ReadKey();
                                if (consolekey.Key == ConsoleKey.Enter)
                                    streamWriter.WriteLine(consolekey.KeyChar);
                                    //streamWriter.Flush();
                                else
                                    streamWriter.Write(consolekey.KeyChar);*/
                                streamWriter.WriteLine(Console.ReadLine());
                            }
                        }
                    }

                    process.WaitForExit();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

        static void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            Console.WriteLine(e.Data);
        }
    }
}

As you can see its not perfect. I have big problems with the input redirection and the command window visibility. I tried hours until I gave up. Its just not possible to hide the command window. Maybe someone knows a better way.

By the way… You can find the SecureString GetPassword() method there –> MSDN
You will also have to add two settings in your Project –> Domain and UserName, both are strings.

 

Kategorien:.NET Schlagwörter: