Buy Me a Coffee

.NET 6 當 ProcessStartInfo username無法在 Linux 上使用

最近在移植 CSharp .NET Framework 到 .NET 6 並且在 Linux 上呼叫批次程式時,遇到一個難題那就是沒辦法更換身分。要如何讓.NET在Linux 上轉換身分執行程式,這時候就只能改寫既有程式,以符合Linux規則。

程式範例如下

  • RedirectStandardInput 一定要設為 true,我們要模擬使用者逐一輸入指令
  • 程式為 /bin/bash
  • 轉換身分後逐一輸入指令
using System;
using System.Diagnostics;

namespace SuUserAndReloadProfile
{
    class Program
    {
        static void Main(string[] args)
        {
            string targetUser = "other_user"; // Replace this with the target user's username.
            string targetUserPassword = "password"; // Replace this with the target user's password.

            // Create the process start info.
            ProcessStartInfo processStartInfo = new ProcessStartInfo
            {
                FileName = "/bin/bash",
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };

            // Start the process.
            Process process = new Process { StartInfo = processStartInfo };
            process.Start();

            // Execute the commands as the target user.
            process.StandardInput.WriteLine($"echo {targetUserPassword} | su - {targetUser}"); // Run command as the target user.
            process.StandardInput.WriteLine("source ~/.profile"); // Reload the profile.
            process.StandardInput.WriteLine("whoami"); // Print the current user's name.
            process.StandardInput.WriteLine("exit"); // Exit the su session.

            // Read the output.
            string output = process.StandardOutput.ReadToEnd();
            string errorOutput = process.StandardError.ReadToEnd();

            // Wait for the process to exit.
            process.WaitForExit();

            // Display the output and error output (if any).
            Console.WriteLine("Output:");
            Console.WriteLine(output);
            if (!string.IsNullOrEmpty(errorOutput))
            {
                Console.WriteLine("Error Output:");
                Console.WriteLine(errorOutput);
            }

            // Close the process.
            process.Close();

            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

同場加映

Async Task 中執行 Thread

使用Async加上Thread,使得程式可同時擁有兩種特性的好處。

using System;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncTaskWithThreadExample
{
    class Program
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine("Main thread: Starting the async operation...");

            // Start the async operation.
            await AsyncTaskWithThread();

            Console.WriteLine("Main thread: Async operation completed.");
            Console.ReadKey();
        }

        private static async Task AsyncTaskWithThread()
        {
            Console.WriteLine("AsyncTaskWithThread: Starting the task...");

            // Start a new thread using Task.Run().
            var task = Task.Run(() => ThreadOperation());

            // Wait for the thread to complete.
            await task;

            Console.WriteLine("AsyncTaskWithThread: Task completed.");
        }

        private static void ThreadOperation()
        {
            Console.WriteLine("ThreadOperation: Executing on a separate thread.");

            // Simulate some work.
            Thread.Sleep(2000);

            Console.WriteLine("ThreadOperation: Work completed on the separate thread.");
        }
    }
}

取得 Async 執行結果

要獲得async task的結果,您可以在C#中使用await關鍵字。 await關鍵字與返回Task的async一起使用,其中TResult是結果的類型。在等待的任務完成之後,該方法將繼續執行,並將任務的結果存儲在result 變數中。

using System;
using System.Threading.Tasks;

namespace GetAsyncTaskResultExample
{
    class Program
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine("Main thread: Starting the async operation...");

            // Call the async method and get the result.
            int result = await GetResultAsync();

            Console.WriteLine($"Main thread: Async operation completed with result: {result}");
            Console.ReadKey();
        }

        private static async Task<int> GetResultAsync()
        {
            Console.WriteLine("GetResultAsync: Starting the task...");

            // Simulate some work by delaying the task.
            await Task.Delay(2000);

            // Set a result value.
            int result = 42;

            Console.WriteLine("GetResultAsync: Task completed.");

            // Return the result.
            return result;
        }
    }
}