c# - 从 PowerShell 调用时无法在 dll 中转换透明代理,但在 C# 控制台应用程序中成功

标签 c# powershell appdomain marshalbyrefobject

我正在尝试创建一个 open source library生成一个新的 AppDomain 并在其中运行一个 PowerShell 脚本。我有一个静态方法,它采用 powershell 文件的名称和 AppDomain 的名称。当从 C# 控制台应用调用时,该方法成功执行,但不是 PowerShell

我知道由于 this entry in the fusionlog,dll 正在第二个应用程序域中加载.

类声明和构造函数如下所示。

public class AppDomainPoshRunner : MarshalByRefObject{

    public AppDomainPoshRunner (){
        Console.WriteLine("Made it here.");
    }
}

当我调用 CreateInstanceFromAndUnwrap 时,构造函数中的消息得到输出我是从 C# 控制台应用程序还是从 PowerShell 应用程序运行 dll。

当我在下面的静态方法中将 CreateInstanceFromAndUnwrap 返回的值转换为 AppDomainPoshRunner 时发生故障。

    public static string[] RunScriptInAppDomain(string fileName, string appDomainName = "Unamed")
    {
        var assembly = Assembly.GetExecutingAssembly();

        var setupInfo = new AppDomainSetup
                            {
                                ApplicationName = appDomainName,
                                // TODO: Perhaps we should setup an even handler to reload the AppDomain similar to ASP.NET in IIS.
                                ShadowCopyFiles = "true"
                            };
        var appDomain = AppDomain.CreateDomain(string.Format("AppDomainPoshRunner-{0}", appDomainName), null, setupInfo);
        try {
            var runner = appDomain.CreateInstanceFromAndUnwrap(assembly.Location, typeof(AppDomainPoshRunner).FullName);
            if (RemotingServices.IsTransparentProxy(runner))
                Console.WriteLine("The unwrapped object is a proxy.");
            else
                Console.WriteLine("The unwrapped object is not a proxy!");  
            Console.WriteLine("The unwrapped project is a {0}", runner.GetType().FullName);
            /* This is where the error happens */
            return ((AppDomainPoshRunner)runner).RunScript(fileName);
        }
        finally
        {
            AppDomain.Unload(appDomain);
        }
    }

在 PowerShell 中运行时,我得到一个 InvalidCastException 消息 Unable to cast transparent proxy to type JustAProgrammer.ADPR.AppDomainPoshRunner

我做错了什么?

最佳答案

我遇到了同样的问题:我创建了仅具有执行权限(最小权限)的沙箱,以便在非常受限的环境中执行不受信任的代码。所有这些在 C# 应用程序中都运行良好,但在起点是创建 .NET COM 对象的 vbs 脚本时不起作用(相同的转换异常)。我认为 PowerShell 也使用 COM。我找到了使用 AppDomain.DoCallBack 的解决方法,它避免了从 appdomain 获取代理。这是代码。 如果您找到更好的选择,请发布。在 GAC 中注册对我来说不是一个好的解决方案...

    class Test
    {
        /*
         create appdomain as usually
        */

        public static object Execute(AppDomain appDomain, Type type, string method, params object[] parameters)
        {
            var call = new CallObject(type, method, parameters);
            appDomain.DoCallBack(call.Execute);
            return call.GetResult();
        }
    }
    [Serializable]
    public class CallObject
    {
        internal CallObject(Type type, string method, object[] parameters)
        {
            this.type = type;
            this.method = method;
            this.parameters = parameters;
        }

        [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
        public void Execute()
        {
            object instance = Activator.CreateInstance(this.type);
            MethodInfo target = this.type.GetMethod(this.method);
            this.result.Data = target.Invoke(instance, this.parameters);
        }

        internal object GetResult()
        {
            return result.Data;
        }

        private readonly string method;
        private readonly object[] parameters;
        private readonly Type type;
        private readonly CallResult result = new CallResult();

        private class CallResult : MarshalByRefObject
        {
            internal object Data { get; set; }
        }
    }

关于c# - 从 PowerShell 调用时无法在 dll 中转换透明代理,但在 C# 控制台应用程序中成功,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7536619/

相关文章:

c# - 关闭上传流的 FtpWebRequest 卡在大文件上

c# - 如何将 ListView 项上下文菜单绑定(bind)到 ICommand

events - 在 DownloadProgressChanged 事件期间从 DownloadFileAsync 对事件处理程序的更新缓慢

c# - 一个appdomain可以限制在一个目录吗?

c# - 为什么当 Assembly 在 CurrentDomain 中时会调用 AssemblyResolve?

.net - 什么是 .NET 应用程序域?

c# - 为什么文本在 RichTextBox 中消失了?

c# - 使用通过 HTTPS 传输的 system.net.socket 检查接收到的数据

Powershell - 在其他两个节点之间插入节点

powershell - Exchange 2010 PowerShell : Cannot bind argument