C# 操作系统常用命令操作完全指南
一、引言
在C#应用程序开发中,经常需要与操作系统进行交互,执行各种系统命令和操作。无论是文件管理、进程控制、网络操作还是系统信息获取,C#都提供了强大的类库来简化这些任务。本文将全面介绍在C#中执行操作系统常用命令的各种方法和技术,涵盖从基础到高级的完整解决方案。
二、System.Diagnostics.Process 类基础
2.1 基本命令执行
csharp
using System; using System.Diagnostics; public class BasicCommandExecutor { /// <summary> /// 执行简单命令并获取输出 /// </summary> public static string ExecuteCommand(string command, string arguments = "") { try { ProcessStartInfo startInfo = new ProcessStartInfo { FileName = command, Arguments = arguments, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden }; using (Process process = new Process()) { process.StartInfo = startInfo; process.Start(); // 异步读取输出,避免死锁 string output = process.StandardOutput.ReadToEnd(); string error = process.StandardError.ReadToEnd(); process.WaitForExit(); if (!string.IsNullOrEmpty(error)) { return $"错误: {error}\n输出: {output}"; } return output; } } catch (Exception ex) { return $"执行命令时发生错误: {ex.Message}"; } } /// <summary> /// 执行带超时控制的命令 /// </summary> public static (bool Success, string Output, string Error) ExecuteCommandWithTimeout( string command, string arguments, int timeoutMilliseconds = 30000) { try { using (Process process = new Process()) { process.StartInfo = new ProcessStartInfo { FileName = command, Arguments = arguments, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; process.Start(); // 异步读取输出 string output = process.StandardOutput.ReadToEnd(); string error = process.StandardError.ReadToEnd(); bool exited = process.WaitForExit(timeoutMilliseconds); if (!exited) { process.Kill(); return (false, output, "命令执行超时"); } return (true, output, error); } } catch (Exception ex) { return (false, string.Empty, $"执行错误: {ex.Message}"); } } }2.2 异步命令执行
csharp
using System; using System.Diagnostics; using System.Threading.Tasks; public class AsyncCommandExecutor { /// <summary> /// 异步执行命令 /// </summary> public static async Task<CommandResult> ExecuteCommandAsync( string command, string arguments, CancellationToken cancellationToken = default) { var result = new CommandResult(); try { using (Process process = new Process()) { process.StartInfo = new ProcessStartInfo { FileName = command, Arguments = arguments, RedirectStandardOutput = true, RedirectStandardError = true, RedirectStandardInput = true, UseShellExecute = false, CreateNoWindow = true, StandardOutputEncoding = System.Text.Encoding.UTF8, StandardErrorEncoding = System.Text.Encoding.UTF8 }; // 输出和错误数据收集 var outputBuilder = new StringBuilder(); var errorBuilder = new StringBuilder(); process.OutputDataReceived += (sender, e) => { if (!string.IsNullOrEmpty(e.Data)) { outputBuilder.AppendLine(e.Data); } }; process.ErrorDataReceived += (sender, e) => { if (!string.IsNullOrEmpty(e.Data)) { errorBuilder.AppendLine(e.Data); } }; process.Start(); // 开始异步读取 process.BeginOutputReadLine(); process.BeginErrorReadLine(); // 等待进程退出(支持取消) await process.WaitForExitAsync(cancellationToken); result.ExitCode = process.ExitCode; result.Output = outputBuilder.ToString(); result.Error = errorBuilder.ToString(); result.Success = process.ExitCode == 0; } } catch (OperationCanceledException) { result.WasCancelled = true; result.Error = "命令执行被取消"; } catch (Exception ex) { result.Error = $"执行错误: {ex.Message}"; } return result; } public class CommandResult { public bool Success { get; set; } public int ExitCode { get; set; } public string Output { get; set; } = string.Empty; public string Error { get; set; } = string.Empty; public bool WasCancelled { get; set; } } } // Process 扩展方法,支持异步等待 public static class ProcessExtensions { public static Task WaitForExitAsync(this Process process, CancellationToken cancellationToken = default) { var tcs = new TaskCompletionSource<bool>(); process.EnableRaisingEvents = true; process.Exited += (sender, args) => tcs.TrySetResult(true); if (cancellationToken != default) { cancellationToken.Register(() => tcs.TrySetCanceled()); } return process.HasExited ? Task.CompletedTask : tcs.Task; } }三、常用操作系统命令实现
3.1 文件和目录操作命令
csharp
using System; using System.Collections.Generic; using System.IO; using System.Linq; public class FileSystemCommands { /// <summary> /// 实现 dir/ls 命令功能 /// </summary> public static string ListDirectoryContents(string path = ".", bool showDetails = false) { try { if (!Directory.Exists(path)) return $"目录不存在: {path}"; var directories = Directory.GetDirectories(path); var files = Directory.GetFiles(path); var result = new List<string>(); if (showDetails) { // 详细列表模式 result.Add($"目录: {Path.GetFullPath(path)}"); result.Add($"创建时间: {Directory.GetCreationTime(path)}"); result.Add(""); // 目录列表 foreach (var dir in directories) { var info = new DirectoryInfo(dir); result.Add($"{info.CreationTime:yyyy-MM-dd HH:mm:ss} <DIR> {info.Name}"); } // 文件列表 foreach (var file in files) { var info = new FileInfo(file); result.Add($"{info.CreationTime:yyyy-MM-dd HH:mm:ss} {info.Length,15:N0} {info.Name}"); } result.Add(""); result.Add($"总计: {directories.Length} 个目录, {files.Length} 个文件"); } else { // 简单列表模式 foreach (var dir in directories) { result.Add($"[{Path.GetFileName(dir)}]"); } foreach (var file in files) { result.Add(Path.GetFileName(file)); } } return string.Join(Environment.NewLine, result); } catch (Exception ex) { return $"错误: {ex.Message}"; } } /// <summary> /// 复制文件/目录 /// </summary> public static (bool Success, string Message) Copy(string source, string destination, bool recursive = false) { try { // 如果是目录 if (Directory.Exists(source)) { if (!recursive) return (false, "复制目录需要使用 -r 参数"); // 创建目标目录 Directory.CreateDirectory(destination); // 复制所有文件 foreach (var file in Directory.GetFiles(source)) { var destFile = Path.Combine(destination, Path.GetFileName(file)); File.Copy(file, destFile, true); } // 递归复制子目录 if (recursive) { foreach (var dir in Directory.GetDirectories(source)) { var destDir = Path.Combine(destination, Path.GetFileName(dir)); Copy(dir, destDir, true); } } return (true, $"目录复制成功: {source} -> {destination}"); } // 如果是文件 else if (File.Exists(source)) { File.Copy(source, destination, true); return (true, $"文件复制成功: {source} -> {destination}"); } else { return (false, $"源不存在: {source}"); } } catch (Exception ex) { return (false, $"复制失败: {ex.Message}"); } } /// <summary> /// 删除文件/目录 /// </summary> public static (bool Success, string Message) Delete(string path, bool recursive = false, bool force = false) { try { if (Directory.Exists(path)) { if (recursive) { Directory.Delete(path, true); return (true, $"目录删除成功: {path}"); } else { // 检查目录是否为空 if (Directory.GetFiles(path).Length == 0 && Directory.GetDirectories(path).Length == 0) { Directory.Delete(path); return (true, $"目录删除成功: {path}"); } else { return (false, "目录非空,请使用 -r 参数强制删除"); } } } else if (File.Exists(path)) { File.Delete(path); return (true, $"文件删除成功: {path}"); } else { return (false, $"路径不存在: {path}"); } } catch (Exception ex) { return (false, $"删除失败: {ex.Message}"); } } /// <summary> /// 创建目录 /// </summary> public static (bool Success, string Message) CreateDirectory(string path, bool createParents = false) { try { if (createParents) { Directory.CreateDirectory(path); } else { // 检查父目录是否存在 var parent = Path.GetDirectoryName(path); if (!Directory.Exists(parent)) return (false, $"父目录不存在: {parent}"); Directory.CreateDirectory(path); } return (true, $"目录创建成功: {path}"); } catch (Exception ex) { return (false, $"创建目录失败: {ex.Message}"); } } }3.2 系统信息命令
csharp
using System; using System.Diagnostics; using System.Management; using System.Net.NetworkInformation; using System.Runtime.InteropServices; public class SystemInfoCommands { /// <summary> /// 获取系统信息(类似 systeminfo 命令) /// </summary> public static string GetSystemInformation() { var info = new System.Text.StringBuilder(); try { // 操作系统信息 info.AppendLine("操作系统信息:"); info.AppendLine($" 系统名称: {RuntimeInformation.OSDescription}"); info.AppendLine($" 系统架构: {RuntimeInformation.OSArchitecture}"); info.AppendLine($" 框架描述: {RuntimeInformation.FrameworkDescription}"); info.AppendLine(); // 内存信息 info.AppendLine("内存信息:"); var memoryStatus = GetMemoryStatus(); info.AppendLine($" 物理内存总量: {memoryStatus.TotalPhysicalMB:N0} MB"); info.AppendLine($" 可用物理内存: {memoryStatus.AvailablePhysicalMB:N0} MB"); info.AppendLine($" 虚拟内存总量: {memoryStatus.TotalVirtualMB:N0} MB"); info.AppendLine($" 可用虚拟内存: {memoryStatus.AvailableVirtualMB:N0} MB"); info.AppendLine(); // CPU信息 info.AppendLine("处理器信息:"); var cpuInfo = GetCpuInfo(); info.AppendLine($" 处理器: {cpuInfo.Name}"); info.AppendLine($" 核心数: {cpuInfo.CoreCount}"); info.AppendLine($" 线程数: {cpuInfo.LogicalProcessorCount}"); info.AppendLine(); // 磁盘信息 info.AppendLine("磁盘信息:"); foreach (var drive in DriveInfo.GetDrives()) { if (drive.IsReady) { info.AppendLine($" {drive.Name} ({drive.DriveType})"); info.AppendLine($" 总容量: {drive.TotalSize / (1024 * 1024 * 1024):N2} GB"); info.AppendLine($" 可用空间: {drive.TotalFreeSpace / (1024 * 1024 * 1024):N2} GB"); info.AppendLine($" 文件系统: {drive.DriveFormat}"); } } info.AppendLine(); // 网络信息 info.AppendLine("网络适配器信息:"); foreach (var nic in NetworkInterface.GetAllNetworkInterfaces()) { if (nic.OperationalStatus == OperationalStatus.Up) { info.AppendLine($" {nic.Name} ({nic.NetworkInterfaceType})"); info.AppendLine($" MAC地址: {nic.GetPhysicalAddress()}"); foreach (var ip in nic.GetIPProperties().UnicastAddresses) { info.AppendLine($" IP地址: {ip.Address}"); } } } } catch (Exception ex) { info.AppendLine($"获取系统信息时出错: {ex.Message}"); } return info.ToString(); } private static (long TotalPhysicalMB, long AvailablePhysicalMB, long TotalVirtualMB, long AvailableVirtualMB) GetMemoryStatus() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // Windows 系统使用 PerformanceCounter 或 WMI try { using (var pc = new PerformanceCounter("Memory", "Available MBytes")) { var availableMB = pc.NextValue(); // 注意:这里需要其他方法获取总内存,简化处理 return (16384, (long)availableMB, 32768, 16384); // 示例值 } } catch { return (0, 0, 0, 0); } } else { // Linux/Mac 系统 return (0, 0, 0, 0); // 简化处理 } } private static (string Name, int CoreCount, int LogicalProcessorCount) GetCpuInfo() { try { var name = "Unknown"; var coreCount = Environment.ProcessorCount; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Processor")) { foreach (ManagementObject obj in searcher.Get()) { name = obj["Name"].ToString(); break; } } } return (name, coreCount, coreCount); // 简化处理,实际需要区分物理核心和逻辑核心 } catch { return ("Unknown", Environment.ProcessorCount, Environment.ProcessorCount); } } /// <summary> /// 获取进程列表(类似 tasklist 命令) /// </summary> public static string GetProcessList(bool showDetails = false) { var processes = Process.GetProcesses(); var result = new System.Text.StringBuilder(); if (showDetails) { result.AppendLine("进程名\tPID\t内存使用(MB)\t启动时间"); result.AppendLine(new string('-', 60)); foreach (var proc in processes.OrderBy(p => p.ProcessName)) { try { var memoryMB = proc.WorkingSet64 / (1024 * 1024); var startTime = proc.StartTime; result.AppendLine($"{proc.ProcessName}\t{proc.Id}\t{memoryMB:N0}\t{startTime:yyyy-MM-dd HH:mm:ss}"); } catch { // 无权限访问某些进程信息 result.AppendLine($"{proc.ProcessName}\t{proc.Id}\tN/A\tN/A"); } } } else { foreach (var proc in processes.OrderBy(p => p.ProcessName)) { result.AppendLine($"{proc.ProcessName} ({proc.Id})"); } } result.AppendLine(); result.AppendLine($"总计: {processes.Length} 个进程"); return result.ToString(); } }3.3 网络相关命令
csharp
using System; using System.Diagnostics; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Threading.Tasks; public class NetworkCommands { /// <summary> /// Ping 命令实现 /// </summary> public static async Task<string> PingHost(string host, int count = 4, int timeout = 1000) { var result = new System.Text.StringBuilder(); using (var ping = new System.Net.NetworkInformation.Ping()) { result.AppendLine($"正在 Ping {host} 具有 32 字节的数据:"); int successCount = 0; long totalTime = 0; long minTime = long.MaxValue; long maxTime = 0; for (int i = 0; i < count; i++) { try { var reply = await ping.SendPingAsync(host, timeout); if (reply.Status == IPStatus.Success) { successCount++; totalTime += reply.RoundtripTime; if (reply.RoundtripTime < minTime) minTime = reply.RoundtripTime; if (reply.RoundtripTime > maxTime) maxTime = reply.RoundtripTime; result.AppendLine($"来自 {reply.Address} 的回复: 字节=32 时间={reply.RoundtripTime}ms TTL={128}"); } else { result.AppendLine($"请求超时。"); } // 等待1秒 await Task.Delay(1000); } catch (Exception ex) { result.AppendLine($"Ping 请求失败: {ex.Message}"); } } // 统计信息 result.AppendLine(); result.AppendLine($"{host} 的 Ping 统计信息:"); result.AppendLine($" 数据包: 已发送 = {count}, 已接收 = {successCount}, 丢失 = {count - successCount} ({(count - successCount) * 100.0 / count}% 丢失)"); if (successCount > 0) { result.AppendLine($"往返行程的估计时间(以毫秒为单位):"); result.AppendLine($" 最短 = {minTime}ms,最长 = {maxTime}ms,平均 = {totalTime / successCount}ms"); } return result.ToString(); } } /// <summary> /// 端口扫描(简单实现) /// </summary> public static async Task<string> ScanPorts(string host, int startPort = 1, int endPort = 1024, int timeout = 100) { var result = new System.Text.StringBuilder(); result.AppendLine($"正在扫描 {host} 的端口 {startPort}-{endPort}..."); int openPorts = 0; var tasks = new List<Task>(); // 限制并发数 var semaphore = new System.Threading.SemaphoreSlim(100); for (int port = startPort; port <= endPort; port++) { await semaphore.WaitAsync(); tasks.Add(Task.Run(async () => { try { using (var client = new TcpClient()) { var task = client.ConnectAsync(host, port); if (await Task.WhenAny(task, Task.Delay(timeout)) == task) { if (client.Connected) { lock (result) { result.AppendLine($"端口 {port}: 开放"); openPorts++; } client.Close(); } } } } catch { // 端口关闭 } finally { semaphore.Release(); } })); } await Task.WhenAll(tasks); result.AppendLine(); result.AppendLine($"扫描完成。发现 {openPorts} 个开放端口。"); return result.ToString(); } /// <summary> /// 获取网络配置信息(类似 ipconfig) /// </summary> public static string GetNetworkConfiguration() { var result = new System.Text.StringBuilder(); try { var interfaces = NetworkInterface.GetAllNetworkInterfaces(); foreach (var ni in interfaces) { result.AppendLine($"适配器: {ni.Name}"); result.AppendLine($" 描述: {ni.Description}"); result.AppendLine($" 类型: {ni.NetworkInterfaceType}"); result.AppendLine($" 物理地址: {ni.GetPhysicalAddress()}"); result.AppendLine($" 状态: {ni.OperationalStatus}"); result.AppendLine($" 速度: {ni.Speed / 1000000} Mbps"); var ipProperties = ni.GetIPProperties(); // DNS 服务器 foreach (var dns in ipProperties.DnsAddresses) { result.AppendLine($" DNS 服务器: {dns}"); } // IP 地址 foreach (var ip in ipProperties.UnicastAddresses) { result.AppendLine($" IP 地址: {ip.Address}"); result.AppendLine($" 子网掩码: {ip.IPv4Mask}"); } // 网关 foreach (var gateway in ipProperties.GatewayAddresses) { result.AppendLine($" 网关: {gateway.Address}"); } result.AppendLine(); } // 获取公共IP地址 try { using (var webClient = new WebClient()) { string publicIP = webClient.DownloadString("https://api.ipify.org"); result.AppendLine($"公共IP地址: {publicIP}"); } } catch { result.AppendLine("无法获取公共IP地址"); } } catch (Exception ex) { result.AppendLine($"获取网络配置时出错: {ex.Message}"); } return result.ToString(); } }3.4 进程和服务管理命令
csharp
using System; using System.Diagnostics; using System.Linq; using System.ServiceProcess; public class ProcessServiceCommands { /// <summary> /// 启动进程 /// </summary> public static (bool Success, string Message) StartProcess( string fileName, string arguments = "", bool runAsAdmin = false) { try { var startInfo = new ProcessStartInfo { FileName = fileName, Arguments = arguments, UseShellExecute = true }; if (runAsAdmin) { startInfo.Verb = "runas"; } var process = Process.Start(startInfo); return process != null ? (true, $"进程启动成功: {fileName}") : (false, "进程启动失败"); } catch (Exception ex) { return (false, $"启动进程失败: {ex.Message}"); } } /// <summary> /// 停止进程 /// </summary> public static (bool Success, string Message) StopProcess(string processName, bool force = false) { try { var processes = Process.GetProcessesByName(processName); if (processes.Length == 0) return (false, $"未找到进程: {processName}"); foreach (var process in processes) { try { if (force) { process.Kill(); } else { process.CloseMainWindow(); if (!process.WaitForExit(5000)) { process.Kill(); } } } catch (Exception ex) { return (false, $"停止进程 {process.ProcessName} ({process.Id}) 失败: {ex.Message}"); } } return (true, $"成功停止进程: {processName}"); } catch (Exception ex) { return (false, $"停止进程失败: {ex.Message}"); } } /// <summary> /// 服务管理 /// </summary> public static (bool Success, string Message) ManageService( string serviceName, ServiceAction action, int timeoutMilliseconds = 30000) { try { using (var service = new ServiceController(serviceName)) { switch (action) { case ServiceAction.Start: if (service.Status == ServiceControllerStatus.Running) return (false, "服务已经在运行"); service.Start(); service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromMilliseconds(timeoutMilliseconds)); break; case ServiceAction.Stop: if (service.Status == ServiceControllerStatus.Stopped) return (false, "服务已经停止"); service.Stop(); service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromMilliseconds(timeoutMilliseconds)); break; case ServiceAction.Restart: service.Stop(); service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromMilliseconds(timeoutMilliseconds)); service.Start(); service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromMilliseconds(timeoutMilliseconds)); break; case ServiceAction.Pause: if (service.CanPauseAndContinue) { service.Pause(); service.WaitForStatus(ServiceControllerStatus.Paused, TimeSpan.FromMilliseconds(timeoutMilliseconds)); } else { return (false, "服务不支持暂停"); } break; case ServiceAction.Continue: if (service.CanPauseAndContinue) { service.Continue(); service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromMilliseconds(timeoutMilliseconds)); } else { return (false, "服务不支持继续"); } break; } return (true, $"服务 {serviceName} {action} 操作成功"); } } catch (InvalidOperationException ex) { return (false, $"服务不存在或无权限: {ex.Message}"); } catch (Exception ex) { return (false, $"服务操作失败: {ex.Message}"); } } public enum ServiceAction { Start, Stop, Restart, Pause, Continue } /// <summary> /// 获取服务列表 /// </summary> public static string GetServiceList(ServiceState stateFilter = ServiceState.All) { var services = ServiceController.GetServices(); var result = new System.Text.StringBuilder(); result.AppendLine("服务名称\t显示名称\t状态"); result.AppendLine(new string('-', 80)); foreach (var service in services) { bool include = false; switch (stateFilter) { case ServiceState.All: include = true; break; case ServiceState.Running: include = service.Status == ServiceControllerStatus.Running; break; case ServiceState.Stopped: include = service.Status == ServiceControllerStatus.Stopped; break; case ServiceState.Paused: include = service.Status == ServiceControllerStatus.Paused; break; } if (include) { result.AppendLine($"{service.ServiceName}\t{service.DisplayName}\t{service.Status}"); } } result.AppendLine(); result.AppendLine($"总计: {services.Count(s => stateFilter == ServiceState.All || (stateFilter == ServiceState.Running && s.Status == ServiceControllerStatus.Running) || (stateFilter == ServiceState.Stopped && s.Status == ServiceControllerStatus.Stopped) || (stateFilter == ServiceState.Paused && s.Status == ServiceControllerStatus.Paused))} 个服务"); return result.ToString(); } public enum ServiceState { All, Running, Stopped, Paused } }四、跨平台兼容性处理
csharp
using System; using System.Runtime.InteropServices; public class CrossPlatformCommandExecutor { /// <summary> /// 根据操作系统选择合适的命令解释器 /// </summary> public static (string Shell, string ArgumentPrefix) GetPlatformShell() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return ("cmd.exe", "/c"); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return ("/bin/bash", "-c"); } else { throw new PlatformNotSupportedException("不支持的操作系统"); } } /// <summary> /// 执行跨平台命令 /// </summary> public static async Task<string> ExecuteCrossPlatformCommand(string command) { var (shell, argPrefix) = GetPlatformShell(); return await AsyncCommandExecutor.ExecuteCommandAsync(shell, $"{argPrefix} \"{command}\""); } /// <summary> /// 平台特定的常用命令 /// </summary> public static class PlatformCommands { public static string ListFiles() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return ExecuteCommandSync("cmd.exe", "/c dir"); } else { return ExecuteCommandSync("/bin/ls", "-la"); } } public static string GetSystemInfo() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return ExecuteCommandSync("cmd.exe", "/c systeminfo"); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { return ExecuteCommandSync("uname", "-a") + ExecuteCommandSync("cat", "/etc/os-release"); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return ExecuteCommandSync("sw_vers", ""); } else { return "未知操作系统"; } } private static string ExecuteCommandSync(string command, string arguments) { try { return BasicCommandExecutor.ExecuteCommand(command, arguments); } catch { return string.Empty; } } } }五、安全最佳实践
csharp
using System; using System.Security; using System.Security.Principal; using System.Text.RegularExpressions; public class SecureCommandExecutor { /// <summary> /// 安全的命令执行,防止命令注入 /// </summary> public static string ExecuteSecureCommand(string command, params string[] args) { // 验证命令是否在白名单中 if (!IsCommandAllowed(command)) { throw new SecurityException($"命令不被允许: {command}"); } // 验证参数安全性 foreach (var arg in args) { if (!IsArgumentSafe(arg)) { throw new SecurityException($"参数包含不安全字符: {arg}"); } } // 检查执行权限 if (RequiresElevation(command) && !IsRunningAsAdministrator()) { throw new SecurityException("需要管理员权限执行此命令"); } // 构建安全的命令参数 var safeArguments = BuildSafeArguments(args); return BasicCommandExecutor.ExecuteCommand(command, safeArguments); } /// <summary> /// 命令白名单验证 /// </summary> private static bool IsCommandAllowed(string command) { // 定义允许的命令白名单 var allowedCommands = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "ping", "tracert", "ipconfig", "netstat", "dir", "ls", "cd", "copy", "move", "del", "rm", "echo", "type", "cat", "find", "grep" }; // 提取命令名称(去除路径) var commandName = Path.GetFileNameWithoutExtension(command); return allowedCommands.Contains(commandName); } /// <summary> /// 参数安全性验证 /// </summary> private static bool IsArgumentSafe(string argument) { // 定义危险字符模式 string dangerousPatterns = @"[;&|<>$`']"; return !Regex.IsMatch(argument, dangerousPatterns); } /// <summary> /// 检查是否需要管理员权限 /// </summary> private static bool RequiresElevation(string command) { var elevatedCommands = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "net", "sc", "reg", "bcdedit", "diskpart" }; var commandName = Path.GetFileNameWithoutExtension(command); return elevatedCommands.Contains(commandName); } /// <summary> /// 检查当前是否以管理员身份运行 /// </summary> private static bool IsRunningAsAdministrator() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { using (WindowsIdentity identity = WindowsIdentity.GetCurrent()) { WindowsPrincipal principal = new WindowsPrincipal(identity); return principal.IsInRole(WindowsBuiltInRole.Administrator); } } // 在Linux/Mac上,检查是否为root用户 return Environment.UserName == "root"; } /// <summary> /// 构建安全的命令行参数 /// </summary> private static string BuildSafeArguments(string[] args) { // 对参数进行适当的转义和引用 var safeArgs = args.Select(arg => { // 如果参数包含空格,用双引号括起来 if (arg.Contains(" ")) { return $"\"{arg.Replace("\"", "\\\"")}\""; } return arg; }); return string.Join(" ", safeArgs); } /// <summary> /// 安全的文件路径验证 /// </summary> public static bool IsValidFilePath(string path, string[] allowedExtensions = null) { try { // 检查路径遍历攻击 if (path.Contains("..") || path.Contains("~")) return false; // 获取完整路径 var fullPath = Path.GetFullPath(path); // 检查是否在允许的目录中 var allowedDirectories = new[] { Environment.CurrentDirectory, Path.GetTempPath(), AppDomain.CurrentDomain.BaseDirectory }; bool isInAllowedDirectory = allowedDirectories .Any(dir => fullPath.StartsWith(dir, StringComparison.OrdinalIgnoreCase)); if (!isInAllowedDirectory) return false; // 检查文件扩展名 if (allowedExtensions != null && allowedExtensions.Length > 0) { var extension = Path.GetExtension(fullPath); if (string.IsNullOrEmpty(extension) || !allowedExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) { return false; } } return true; } catch { return false; } } }六、高级应用:构建命令解释器
csharp
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; public class CommandInterpreter { private readonly Dictionary<string, CommandHandler> _commands; public CommandInterpreter() { _commands = new Dictionary<string, CommandHandler>(StringComparer.OrdinalIgnoreCase); RegisterBuiltInCommands(); } /// <summary> /// 注册内置命令 /// </summary> private void RegisterBuiltInCommands() { RegisterCommand("help", HelpCommand, "显示帮助信息"); RegisterCommand("exit", ExitCommand, "退出程序"); RegisterCommand("clear", ClearCommand, "清屏"); RegisterCommand("echo", EchoCommand, "显示消息"); RegisterCommand("cd", ChangeDirectoryCommand, "更改当前目录"); RegisterCommand("pwd", PrintWorkingDirectoryCommand, "显示当前目录"); RegisterCommand("ls", ListDirectoryCommand, "列出目录内容"); RegisterCommand("dir", ListDirectoryCommand, "列出目录内容"); } /// <summary> /// 注册命令处理器 /// </summary> public void RegisterCommand(string name, CommandHandler handler, string description = "") { _commands[name] = handler; if (!string.IsNullOrEmpty(description)) { // 存储命令描述 } } /// <summary> /// 执行命令 /// </summary> public async Task<CommandResult> Execute(string input) { if (string.IsNullOrWhiteSpace(input)) return CommandResult.Empty; var parts = ParseCommandLine(input); if (parts.Length == 0) return CommandResult.Empty; var commandName = parts[0]; var args = parts.Skip(1).ToArray(); if (_commands.TryGetValue(commandName, out var handler)) { return await handler(args); } else { // 尝试作为系统命令执行 return await ExecuteSystemCommand(commandName, args); } } /// <summary> /// 解析命令行 /// </summary> private string[] ParseCommandLine(string commandLine) { var result = new List<string>(); var current = new System.Text.StringBuilder(); bool inQuotes = false; for (int i = 0; i < commandLine.Length; i++) { char c = commandLine[i]; if (c == '"') { inQuotes = !inQuotes; } else if (c == ' ' && !inQuotes) { if (current.Length > 0) { result.Add(current.ToString()); current.Clear(); } } else { current.Append(c); } } if (current.Length > 0) { result.Add(current.ToString()); } return result.ToArray(); } /// <summary> /// 执行系统命令 /// </summary> private async Task<CommandResult> ExecuteSystemCommand(string command, string[] args) { try { var arguments = string.Join(" ", args.Select(arg => arg.Contains(" ") ? $"\"{arg}\"" : arg)); var result = await AsyncCommandExecutor.ExecuteCommandAsync(command, arguments); return new CommandResult { Success = result.Success, Output = result.Output, Error = result.Error }; } catch (Exception ex) { return new CommandResult { Success = false, Error = $"执行命令失败: {ex.Message}" }; } } // 内置命令实现 private async Task<CommandResult> HelpCommand(string[] args) { var helpText = new System.Text.StringBuilder(); helpText.AppendLine("可用命令:"); helpText.AppendLine(); foreach (var cmd in _commands.OrderBy(c => c.Key)) { helpText.AppendLine($" {cmd.Key,-15} - 获取命令描述"); } helpText.AppendLine(); helpText.AppendLine("系统命令也可以直接使用"); return new CommandResult { Success = true, Output = helpText.ToString() }; } private Task<CommandResult> ExitCommand(string[] args) { Environment.Exit(0); return Task.FromResult(new CommandResult { Success = true }); } private Task<CommandResult> ClearCommand(string[] args) { Console.Clear(); return Task.FromResult(new CommandResult { Success = true }); } private Task<CommandResult> EchoCommand(string[] args) { return Task.FromResult(new CommandResult { Success = true, Output = string.Join(" ", args) }); } private Task<CommandResult> ChangeDirectoryCommand(string[] args) { if (args.Length == 0) { return Task.FromResult(new CommandResult { Success = false, Error = "用法: cd <目录>" }); } try { Directory.SetCurrentDirectory(args[0]); return Task.FromResult(new CommandResult { Success = true, Output = $"当前目录: {Directory.GetCurrentDirectory()}" }); } catch (Exception ex) { return Task.FromResult(new CommandResult { Success = false, Error = $"cd 失败: {ex.Message}" }); } } private Task<CommandResult> PrintWorkingDirectoryCommand(string[] args) { return Task.FromResult(new CommandResult { Success = true, Output = Directory.GetCurrentDirectory() }); } private Task<CommandResult> ListDirectoryCommand(string[] args) { bool showDetails = args.Contains("-l") || args.Contains("/l"); var output = FileSystemCommands.ListDirectoryContents(".", showDetails); return Task.FromResult(new CommandResult { Success = true, Output = output }); } public delegate Task<CommandResult> CommandHandler(string[] args); public class CommandResult { public bool Success { get; set; } public string Output { get; set; } = string.Empty; public string Error { get; set; } = string.Empty; public static CommandResult Empty => new CommandResult(); } } // 使用示例 public class CommandInterpreterDemo { public static async Task Run() { var interpreter = new CommandInterpreter(); Console.WriteLine("命令解释器已启动。输入 'help' 查看可用命令。"); Console.WriteLine("输入 'exit' 退出。"); Console.WriteLine(); while (true) { Console.Write($"{Directory.GetCurrentDirectory()}> "); var input = Console.ReadLine(); if (string.IsNullOrWhiteSpace(input)) continue; var result = await interpreter.Execute(input); if (!string.IsNullOrEmpty(result.Output)) { Console.WriteLine(result.Output); } if (!string.IsNullOrEmpty(result.Error)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(result.Error); Console.ResetColor(); } Console.WriteLine(); } } }七、性能优化和最佳实践
7.1 命令执行性能优化
csharp
public class OptimizedCommandExecutor { private static readonly ConcurrentDictionary<string, ProcessStartInfo> _commandCache = new ConcurrentDictionary<string, ProcessStartInfo>(); /// <summary> /// 使用缓存的ProcessStartInfo执行命令 /// </summary> public static async Task<string> ExecuteCachedCommand(string command, string arguments) { var cacheKey = $"{command}|{arguments}"; if (!_commandCache.TryGetValue(cacheKey, out var startInfo)) { startInfo = new ProcessStartInfo { FileName = command, Arguments = arguments, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true, StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8 }; _commandCache[cacheKey] = startInfo; } return await ExecuteWithStartInfo(startInfo); } private static async Task<string> ExecuteWithStartInfo(ProcessStartInfo startInfo) { try { using (var process = new Process()) { process.StartInfo = startInfo; process.Start(); var outputTask = process.StandardOutput.ReadToEndAsync(); var errorTask = process.StandardError.ReadToEndAsync(); await process.WaitForExitAsync(); var output = await outputTask; var error = await errorTask; if (!string.IsNullOrEmpty(error)) { return $"错误: {error}\n输出: {output}"; } return output; } } catch (Exception ex) { return $"执行命令时发生错误: {ex.Message}"; } } /// <summary> /// 批量命令执行优化 /// </summary> public static async Task<List<CommandResult>> ExecuteBatchCommands( IEnumerable<(string Command, string Arguments)> commands, int maxConcurrency = 5) { var results = new List<CommandResult>(); var semaphore = new SemaphoreSlim(maxConcurrency); var tasks = commands.Select(async cmd => { await semaphore.WaitAsync(); try { var result = await AsyncCommandExecutor.ExecuteCommandAsync(cmd.Command, cmd.Arguments); lock (results) { results.Add(result); } return result; } finally { semaphore.Release(); } }); await Task.WhenAll(tasks); return results; } }7.2 资源管理和清理
csharp
public class ResourceAwareCommandExecutor : IDisposable { private readonly List<Process> _activeProcesses = new List<Process>(); private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); private bool _disposed = false; /// <summary> /// 执行命令并自动管理资源 /// </summary> public async Task<CommandResult> ExecuteCommandWithResourceManagement( string command, string arguments, int timeoutMilliseconds = 30000) { var process = new Process(); _activeProcesses.Add(process); try { process.StartInfo = new ProcessStartInfo { FileName = command, Arguments = arguments, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; process.Start(); var outputTask = process.StandardOutput.ReadToEndAsync(); var errorTask = process.StandardError.ReadToEndAsync(); // 使用带超时的等待 var completedTask = await Task.WhenAny( Task.WhenAll(outputTask, errorTask, process.WaitForExitAsync(_cancellationTokenSource.Token)), Task.Delay(timeoutMilliseconds, _cancellationTokenSource.Token) ); if (completedTask == Task.Delay(timeoutMilliseconds, _cancellationTokenSource.Token).Result) { process.Kill(); return new CommandResult { Success = false, Error = "命令执行超时" }; } return new CommandResult { Success = process.ExitCode == 0, Output = await outputTask, Error = await errorTask, ExitCode = process.ExitCode }; } finally { _activeProcesses.Remove(process); process.Dispose(); } } /// <summary> /// 停止所有正在执行的命令 /// </summary> public void StopAllCommands() { _cancellationTokenSource.Cancel(); foreach (var process in _activeProcesses.ToArray()) { try { if (!process.HasExited) { process.Kill(); } } catch { // 忽略清理过程中的异常 } } _activeProcesses.Clear(); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { StopAllCommands(); _cancellationTokenSource.Dispose(); } _disposed = true; } } ~ResourceAwareCommandExecutor() { Dispose(false); } }八、总结
本文详细介绍了在C#中执行操作系统命令的多种方法和技术,涵盖了:
基础命令执行:使用Process类执行基本命令,支持同步和异步操作
常用命令实现:文件操作、系统信息、网络命令、进程管理等
跨平台兼容:处理不同操作系统的差异
安全性考虑:防止命令注入,实施权限检查
高级应用:构建完整的命令解释器
性能优化:缓存、批量处理和资源管理
在实际开发中,应根据具体需求选择合适的方法。对于简单的命令执行,可以使用基本的Process类;对于需要复杂交互的场景,建议使用异步方法和资源管理;对于安全性要求高的应用,必须实施严格的安全检查。
记住,执行系统命令时始终要:
验证用户输入
实施最小权限原则
处理异常情况
清理所有资源
记录重要操作
通过本文介绍的技术和最佳实践,您可以在C#应用程序中安全、高效地执行各种操作系统命令,构建功能强大的系统管理工具。