【问题标题】:System.Threading.Timer kills the PowerShell consoleSystem.Threading.Timer 杀死 PowerShell 控制台
【发布时间】:2018-12-14 23:37:24
【问题描述】:

当我在 PowerShell 控制台中运行它时:

$callback = [System.Threading.TimerCallback]{
    param($state)
}

$timer = [System.Threading.Timer]::new($callback, $null,
    [timespan]::Zero,
    [timespan]::FromSeconds(1))

然后一旦$callback 被调用(我确定这是根本原因,通过将dueTime constructor's parameter[timespan]::Zero 更改为更长的延迟),整个控制台进程崩溃,说powershell has stopped working

可能是什么原因?我该如何克服呢?

【问题讨论】:

    标签: powershell


    【解决方案1】:

    错误是:

    在此线程中没有可用于运行脚本的运行空间。你可以 在 DefaultRunspace 属性中提供一个 System.Management.Automation.Runspaces.Runspace 类型。

    而源于

    System.Management.Automation.ScriptBlock.GetContextFromTLS()
    

    委托是问题所在。这就是我的工作方式:

    $helper = @'
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Management.Automation.Runspaces;
    
    public class RunspacedDelegateFactory
    {
        public static Delegate NewRunspacedDelegate(Delegate _delegate, Runspace runspace)
        {
            Action setRunspace = () => Runspace.DefaultRunspace = runspace;
    
            return ConcatActionToDelegate(setRunspace, _delegate);
        }
    
        private static Expression ExpressionInvoke(Delegate _delegate, params Expression[] arguments)
        {
            var invokeMethod = _delegate.GetType().GetMethod("Invoke");
    
            return Expression.Call(Expression.Constant(_delegate), invokeMethod, arguments);
        }
    
        public static Delegate ConcatActionToDelegate(Action a, Delegate d)
        {
            var parameters =
                d.GetType().GetMethod("Invoke").GetParameters()
                .Select(p => Expression.Parameter(p.ParameterType, p.Name))
                .ToArray();
    
            Expression body = Expression.Block(ExpressionInvoke(a), ExpressionInvoke(d, parameters));
    
            var lambda = Expression.Lambda(d.GetType(), body, parameters);
    
            var compiled = lambda.Compile();
    
            return compiled;
        }
    }
    '@
    
    add-type -TypeDefinition $helper
    
    $runspacedDelegate = [RunspacedDelegateFactory]::NewRunspacedDelegate($callback, [Runspace]::DefaultRunspace)
    
    $timer = [System.Threading.Timer]::new(
        $runspacedDelegate,
        $null,
        [timespan]::Zero,
        [timespan]::FromSeconds(1))
    

    我借用了 NewRunspacedDelegate

    https://www.powershellgallery.com/packages/ContainerTools/0.0.1

    【讨论】:

    • 哇,大惊小怪……令人印象深刻,但不确定是否值得……为什么要这么难,只是为了派代表?
    • 顺便说一句,你是如何设法得到这个错误的?控制台只是为我崩溃了。
    • 记录在事件日志中。也就是说,全文错误是从 PowerShell 6 输出的。
    猜你喜欢
    • 2018-03-09
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-15
    相关资源
    最近更新 更多