You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从C#运行PowerShell脚本与直接运行结果不一致问题求助

解决C#调用PowerShell获取文件属性部分为空的问题

我之前也碰到过类似的情况——直接在PowerShell里跑脚本能拿到全量文件属性,但用C#的Runspace调用时就会有部分属性为空,大概率是COM对象运行上下文或权限差异导致的,下面给你几个可行的解决思路:

核心问题分析:Shell.Application的运行环境差异

Shell.Application是依赖桌面会话的COM组件,交互式PowerShell默认运行在**STA(单线程单元)模式下,而且是当前用户的桌面上下文,能加载所有注册的shell扩展来获取完整属性。但C#创建的Runspace默认是MTA(多线程单元)**模式,如果程序不是在桌面会话里运行(比如服务、后台程序),会缺少必要的上下文,导致部分属性无法读取。

解决方案1:将Runspace设置为STA模式

这是最常见的修复手段,只需要在打开Runspace前添加一行代码,把单元模式改成STA:

Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.ApartmentState = System.Threading.ApartmentState.STA; // 关键:切换为STA模式
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(script);
pipeline.Commands.Add("Out-String");
Collection<PSObject> results = pipeline.Invoke();
runspace.Close();

改完之后再测试,大部分属性应该就能正常获取了。

解决方案2:确保运行身份一致

如果还是不行,检查你的C#程序和交互式PowerShell是不是用同一个用户身份运行的:

  • 如果是控制台应用,右键选择「以管理员身份运行」试试,或者切换到和交互式PowerShell相同的用户账户启动程序
  • 检查目标文件的权限,确保程序运行的账户有读取该文件完整属性的权限(包括扩展属性)

解决方案3:改用.NET原生API替代Shell.Application

如果依赖COM对象的方式始终有问题,建议直接用.NET自带的API或者Windows API Code Pack来获取文件属性,避免上下文依赖:

基本属性用FileInfo

using System.IO;

var fileInfo = new FileInfo(@"C:\Temp\Indexing\Asm1.asm");
Console.WriteLine($"文件名: {fileInfo.Name}");
Console.WriteLine($"创建时间: {fileInfo.CreationTime}");
Console.WriteLine($"文件大小: {fileInfo.Length} bytes");
// 更多基本属性可直接从fileInfo对象获取

扩展属性用Windows API Code Pack

如果需要获取作者、标题这类扩展属性,可以引用Windows API Code Pack(NuGet包:WindowsAPICodePack-Shell):

using Microsoft.WindowsAPICodePack.Shell;

var shellFile = ShellFile.FromFilePath(@"C:\Temp\Indexing\Asm1.asm");
// 获取作者
var author = shellFile.Properties.System.Author.Value;
// 获取文件标题
var title = shellFile.Properties.System.Title.Value;
Console.WriteLine($"作者: {author ?? "无"}");
Console.WriteLine($"标题: {title ?? "无"}");
// 其他扩展属性可通过shellFile.Properties.System下的对应属性访问

额外注意:PowerShell执行策略和版本

确保C#调用的PowerShell版本和你交互式使用的一致,也可以在脚本开头临时设置执行策略,避免脚本被阻止:

$script = @"
Set-ExecutionPolicy RemoteSigned -Scope Process -Force
# 原脚本内容
$path = 'C:\Temp\Indexing\Asm1.asm' 
$shell = New-Object -COMObject Shell.Application 
$folder = Split-Path $path 
$file = Split-Path $path -Leaf 
$shellfolder = $shell.Namespace($folder) 
$shellfile = $shellfolder.ParseName($file) 
0..500 | Foreach-Object { '{0} = {1}' -f $shellfolder.GetDetailsOf($null, $_), $shellfolder.GetDetailsOf($shellfile, $_).toString()}
"@

先试试设置STA模式,这应该能解决大部分问题,如果还是有异常再排查权限或者改用.NET原生API。

内容的提问来源于stack exchange,提问作者Gil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 18:19:07