PowerShell - 将 OBJECTS 传递给 start-job - 反序列化 [英] PowerShell - Passing OBJECTS to start-job - deserialize

查看:35
本文介绍了PowerShell - 将 OBJECTS 传递给 start-job - 反序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道通过 start-job 执行的脚本块无法看到脚本块之外的变量.要传递变量,请使用 -arguments 参数.不过,从我读过的 doco 来看,如果没有 序列化.显然这是因为作业的工作方式 - 当使用 Start-job 时,PowerShell 创建一个新进程并在那里运行命令;为了将对象传输到它需要序列化的另一个进程,然后另一个 exe 将在导入时反序列化它.当您想使用带有 start-job 的对象时,这会带来问题.

I know that a script block executed via start-job cannot see the variables outside of the script block. To pass variables in you use the -arguments paramater. From the doco I've read though, jobs can't pass objects to each other without serialising them. Apparently this is because of how jobs works - when using Start-job, PowerShell creates a new process and runs the commands there; in order to transfer the object to the other process it needs to serialise it, then the other exe will deserialise it when it gets imported. This poses a problem when you want to use objects with start-job.

注意:以下是演示我的问题的示例 - 我运行的实际 cmdlet 和脚本完全不同且更复杂,所以如果您想知道为什么我什至会运行这些命令请记住,我不会,它们只是演示我的问题的简单命令.

NOTE: The below are examples to demonstrate my problem - the actual cmdlets and scripts I am running are completely different and more complex, so in case you are wondering why I would even run these commands this way just bear in mind I wouldn't, they are just easy commands to demonstrate my issue.

这是我用于简单 Get-aduser 命令的语法示例

Here is an example of the syntax I've used for a simple Get-aduser command

$user = get-aduser samaccount

当我们输出 $user 时,我们看到对象的类型是 ADUser

When we output $user we see that the object is of type ADUser

$user|GM
TypeName: Microsoft.ActiveDirectory.Management.ADUser

现在让我们序列化对象(以模拟 start-job 的作用)

Let's now serialise the object (to simulate what start-job does)

$user| Export-Clixml C:\temp\test.xml

现在重建它(反序列化)

And now rebuild it (deserialise)

$user = Import-Clixml C:\temp\test.xml

现在当我们查看它的类型时,它是不同的.它前面有反序列化"这个词.

Now when when we view it's type it is different. It has the word 'derserialzed' in front.

 $user|GM
TypeName: Deserialized.Microsoft.ActiveDirectory.Management.ADUser

我现在遇到的问题是它不是原始对象的真实表示.即使所有属性和设置都相同,我们仍然存在对象类型不同的问题.现在来演示为什么这是一个问题.

The problem I now have is that it isn't a true representation of the orignal object. Even if all the properties and settings were identical we still have the problem that the object type is different. Now to demonstrate why this is a problem.

Get-aduser 接受一个字符串作为输入(第一个例子),但它也会接受一个有效的 ADuser 对象.但是当我们现在运行时:

Get-aduser accepts a string as the input (very first example) but it also will accept a valid ADuser object. But when we now run:

get-aduser $user

我们收到以下错误:

"Cannot convert the "AD_distinguishedname_here. I have omitted this for security reasons" value of type 
"Deserialized.Microsoft.ActiveDirectory.Management.ADUser" to type "Microsoft.ActiveDirectory.Management.ADUser"."

此错误是因为 Get-aduser 希望您提供 Microsoft.ActiveDirectory.Management.ADUser 类型的对象,但我们提供了 Deserialized.Microsoft.ActiveDirectory.Management.ADUser> 它不知道如何转换它.这正是通过 start-job 运行命令时会发生的情况,以及无法将对象传递给作业的原因.

This error is because Get-aduser expects you to provide an object of type Microsoft.ActiveDirectory.Management.ADUser but we provided Deserialized.Microsoft.ActiveDirectory.Management.ADUserand it doesn't know how to convert it. This is exactly what happens when you run command via start-job and why you can't pass objects to a job.

正如我上面所说,我没有在我的实际代码中使用 get-aduser,我只是使用这个每个人都可以访问的简单命令来演示问题.在我的实际代码中,我必须为作业提供一个对象.

As I said above, I am not using get-aduser in my real code, I am just using this simple command everyone has access to, to demonstrate the issue. In my real code I must provide an object to the job.

所以我的问题是,有没有人知道您如何解决这个问题或知道如何以原始形式重建对象?

So my question is, does anyone know how you get around this or know how to rebuild the object in it's original form?

推荐答案

在这条直线上花了 8 个小时后,我终于弄清楚发生了什么.这是一个很长的故事,但 TLDR 版本是您无法使用任何本机工具解决这个问题 - 您必须在启动作业脚本块内重新构建对象,如果您有一个大型复杂对象,这就是不可行的.我最终找到了一个可以下载的模块,它通过启动线程而不是启动作业运行命令,并且不使用序列化.此处指南 到 DL 并安装它.这在我测试时有效

After spending 8 hours on this straight I finally figured out what is going on. It's a long story but thr TLDR version is that you cannot get around this with any native tools - you have to essentially rebuild the object inside the start-job script block, and if you have a large complex object this just isn't feasible. I ended up findind a module you can download which runs commands via start-thread instead of the start-job and this does not use serialisation. Guide here to DL and install it. This worked when I tested it

要获取 PowerShell 模块,请转到 PowerShell 库并搜索start-thread"

To get the PowerShell module, go to PowerShell gallery and search for "start-thread"

这篇关于PowerShell - 将 OBJECTS 传递给 start-job - 反序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆