C#远程执行PowerShell脚本下载解压文件无结果问题排查
远程PowerShell执行下载脚本失败(C#调用无文件下载,本地运行正常)
问题核心原因
你的问题本质是C#远程调用的PowerShell会话,与手动登录VM后运行的PowerShell会话,执行上下文存在关键差异,具体拆解为以下几点:
1. 工作目录不匹配
远程WSMan会话(C#调用依赖的PowerShell会话)默认工作目录是C:\Windows\System32,而你手动登录VM后默认工作目录是C:\Users\<你的用户名>。脚本中使用的相对路径Downloads\xp.zip会指向C:\Windows\System32\Downloads——这个目录大概率不存在,或者当前账号无写入权限,直接导致下载失败。
2. 未捕获PowerShell错误输出
当前C#代码仅收集了PowerShell的成功输出,但脚本执行中的错误(如路径不存在、权限不足、网络访问失败)不会触发C#异常,也未被记录,导致你无法定位具体问题。
3. 权限/网络上下文差异
- 远程会话账号可能没有
C:\Windows\System32目录的写入权限; - 远程会话的网络环境与用户登录后的环境不同(比如缺少代理配置),导致无法访问内部下载地址。
解决方案
步骤1:修改PowerShell脚本,使用绝对路径并添加前置检查
$url = "https://<internal website>/xp.zip" # 获取用户主目录的绝对路径,避免工作目录差异问题 $userProfileDir = [Environment]::GetFolderPath('UserProfile') $zipFile = Join-Path -Path $userProfileDir -ChildPath "Downloads\xp.zip" $targetDir = Join-Path -Path $userProfileDir -ChildPath "Downloads\UnZipFiles\" # 提前创建所需目录,避免因目录不存在导致的写入失败 if (-not (Test-Path -Path (Split-Path -Path $zipFile -Parent))) { New-Item -ItemType Directory -Path (Split-Path -Path $zipFile -Parent) -Force | Out-Null } if (-not (Test-Path -Path $targetDir)) { New-Item -ItemType Directory -Path $targetDir -Force | Out-Null } # 强制抛出错误,便于C#捕获异常 Invoke-WebRequest -Uri $url -OutFile $zipFile -ErrorAction Stop Expand-Archive -Path $zipFile -DestinationPath $targetDir -Force -ErrorAction Stop
步骤2:修改C#代码,捕获PowerShell错误输出
在原代码中添加对ps.Streams.Error的处理,获取脚本执行中的错误详情:
public static string RemotePSExecution(string ipAddress, string username, string password, string psFilePath) { string result = string.Empty; var securePassword = new SecureString(); foreach (Char c in password) { securePassword.AppendChar(c); } PSCredential creds = new PSCredential(username, securePassword); WSManConnectionInfo connectionInfo = new WSManConnectionInfo(); connectionInfo.ComputerName = ipAddress; connectionInfo.Credential = creds; String psProg = File.ReadAllText(psFilePath); Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo); runspace.Open(); using (PowerShell ps = PowerShell.Create()) { ps.Runspace = runspace; ps.AddScript(psProg); StringBuilder sb = new StringBuilder(); try { var results = ps.Invoke(); // 收集成功输出 foreach (var x in results) { sb.AppendLine(x.ToString()); } // 收集错误输出,用于排查问题 if (ps.Streams.Error.Count > 0) { sb.AppendLine("=== 脚本执行错误详情 ==="); foreach (var error in ps.Streams.Error) { sb.AppendLine(error.ToString()); } } result = sb.ToString().Trim(); } catch (Exception e) { throw new Exception("PowerShell脚本执行异常", e.InnerException); } } runspace.Close(); return result; }
步骤3:(可选)处理网络代理问题
如果是网络访问失败,可在PowerShell脚本中添加代理配置:
# 复用系统代理配置 $proxy = [System.Net.WebRequest]::GetSystemWebProxy() $proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials Invoke-WebRequest -Uri $url -OutFile $zipFile -Proxy $proxy -ErrorAction Stop
内容的提问来源于stack exchange,提问作者TLe
相关产品推荐
相关产品推荐

