编译Cmdlet中如何从线程作业输出错误且保留原始PositionMessage?
当自定义编译Cmdlet输出线程作业错误时,若想实现和Receive-Job一致的效果,保留原始错误的PositionMessage,核心是正确传递错误记录的InvocationInfo信息,具体实现方式如下:
直接传递原始ErrorRecord
从线程作业中获取到原始错误记录后,无需创建新的ErrorRecord对象,直接将其传入Cmdlet.WriteError()方法。这样PowerShell会完整保留原始错误的InvocationInfo,自然会显示正确的PositionMessage。示例C#代码:
// 假设jobError是从线程作业中捕获的原始ErrorRecord实例 WriteError(jobError);手动复用原始InvocationInfo(需创建新ErrorRecord时)
如果必须基于原始错误创建新的ErrorRecord(比如需要添加自定义错误ID或额外上下文),一定要将原始错误的InvocationInfo完整复制到新对象中,不要使用当前Cmdlet的MyInvocation属性。示例C#代码:
// 获取原始错误的InvocationInfo var originalInvocation = jobError.InvocationInfo; // 基于原始错误创建新的ErrorRecord var customError = new ErrorRecord( jobError.Exception, "CustomErrorId_JobFailure", // 自定义错误ID jobError.CategoryInfo.Category, jobError.TargetObject ); // 替换为原始错误的InvocationInfo,保留位置信息 customError.InvocationInfo = originalInvocation; // 输出自定义错误 WriteError(customError);禁止覆盖原始InvocationInfo
不要在自定义Cmdlet中手动将新ErrorRecord的InvocationInfo设置为this.MyInvocation,这会覆盖原始错误的位置信息,导致显示Cmdlet自身的执行位置而非作业内的错误行。
原理说明
Receive-Job内部直接传递了线程作业执行过程中生成的原始ErrorRecord,没有修改其InvocationInfo属性,因此能完整保留错误发生时的原始位置信息。自定义Cmdlet出现位置信息错误,本质是错误地用自身的调用信息覆盖了原始错误的InvocationInfo。
内容的提问来源于stack exchange,提问作者alx9r

