首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在单元测试中模拟CRM插件沙箱隔离模式?

如何在单元测试中模拟CRM插件沙箱隔离模式?
EN

Stack Overflow用户
提问于 2016-06-28 15:09:10
回答 2查看 681关注 0票数 9

上下文

我想写一些针对类的单元测试,这些测试将被CRM 2016 CodeActivity和插件类所使用。最终程序集将以沙箱隔离模式注册。

我想确定在运行单元测试时测试用例是否是绿色的,在注册并在CRM中运行时,它不会在沙箱隔离安全限制中受到更多的限制。

问题

在运行单元测试时,有任何方法来模拟沙箱隔离吗?

EN

回答 2

Stack Overflow用户

发布于 2016-06-29 10:45:12

这真是个好问题。您可以根据这个沙箱实例模拟在沙箱中运行插件程序集和代码活动。

使用该示例,您可以使用一组有限的权限运行代码活动。

现在,CRM在线的确切限制是什么?找到了文章。有一个沙箱限制部分与其中之一。如果你找到另一个,请告诉我。因为我很想把这个特性添加到FakeXrmEasy

干杯,

票数 3
EN

Stack Overflow用户

发布于 2020-07-08 14:31:09

我今天发现了这个:https://github.com/carltoncolter/DynamicsPlugin/blob/master/DynamicsPlugin.Tests/PluginContainer.cs

我曾经把它变成这样:

代码语言:javascript
复制
using System;
using System.Diagnostics;
using System.Globalization;
using System.Net;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;

namespace Core.DLaB.Xrm.Tests.Sandbox
{
    public static class SandboxWrapper
    {
        public static T Instantiate<T>(object[] constructorArguments = null)
        {
            return new SandboxWrapper<T>().Instantiate(constructorArguments);
        }

        public static T InstantiatePlugin<T>(string unsecureConfig = null, string secureConfig = null)
        {
            object[] args = null;
            if (secureConfig == null)
            {
                if (unsecureConfig != null)
                {
                    args = new object[] {unsecureConfig};
                }
            }
            else
            {
                args = new object[]{unsecureConfig, secureConfig};
            }

            return new SandboxWrapper<T>().Instantiate(args);
        }
    }

    public class SandboxWrapper<T> : MarshalByRefObject, IDisposable
    {
        private const string DomainSuffix = "Sandbox";
        /// <summary>
        /// The Sandbox AppDomain to execute the plugin
        /// </summary>
        public AppDomain SandboxedAppDomain { get; private set; }

        public T Instantiate(object[] constructorArguments = null)
        {
            /*
             * Sandboxed plug-ins and custom workflow activities can access the network through the HTTP and HTTPS protocols. This capability provides 
               support for accessing popular web resources like social sites, news feeds, web services, and more. The following web access restrictions
               apply to this sandbox capability.
                * Only the HTTP and HTTPS protocols are allowed.
                * Access to localhost (loopback) is not permitted.
                * IP addresses cannot be used. You must use a named web address that requires DNS name resolution.
                * Anonymous authentication is supported and recommended. There is no provision for prompting the 
                  on user for credentials or saving those credentials.
             */
            constructorArguments = constructorArguments ?? new object[] { };
            var type = typeof(T);
            var source = type.Assembly.Location;
            var sourceAssembly = Assembly.UnsafeLoadFrom(source);

            var setup = new AppDomainSetup
            {
                ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
                ApplicationName = $"{sourceAssembly.GetName().Name}{DomainSuffix}",
                DisallowBindingRedirects = true,
                DisallowCodeDownload = true,
                DisallowPublisherPolicy = true
            };

            var ps = new PermissionSet(PermissionState.None);
            ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.SerializationFormatter));
            ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
            ps.AddPermission(new FileIOPermission(PermissionState.None));
            ps.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess));

            //RegEx pattern taken from: https://msdn.microsoft.com/en-us/library/gg334752.aspx
            ps.AddPermission(new WebPermission(NetworkAccess.Connect,
                new Regex(
                    @"^http[s]?://(?!((localhost[:/])|(\[.*\])|([0-9]+[:/])|(0x[0-9a-f]+[:/])|(((([0-9]+)|(0x[0-9A-F]+))\.){3}(([0-9]+)|(0x[0-9A-F]+))[:/]))).+")));

            // We don't need to add these, but it is important to note that there is no access to the following
            ps.AddPermission(new NetworkInformationPermission(NetworkInformationAccess.None));
            ps.AddPermission(new EnvironmentPermission(PermissionState.None));
            ps.AddPermission(new RegistryPermission(PermissionState.None));
            ps.AddPermission(new EventLogPermission(PermissionState.None));


            SandboxedAppDomain = AppDomain.CreateDomain(DomainSuffix, null, setup, ps, null);

            return Create(constructorArguments);
        }

        private T Create(object[] constructorArguments)
        {
            var type = typeof(T);

            return (T)Activator.CreateInstanceFrom(
                SandboxedAppDomain,
                type.Assembly.ManifestModule.FullyQualifiedName,
                // ReSharper disable once AssignNullToNotNullAttribute
                type.FullName, false, BindingFlags.CreateInstance,
                null, constructorArguments,
                CultureInfo.CurrentCulture, null
            ).Unwrap();
        }

        #region IDisposable Support
        //Implementing IDisposable Pattern: https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/dispose-pattern
        private bool _disposed; // To detect redundant calls

        protected virtual void Dispose(bool disposing)
        {
            if (_disposed) return;

            if (disposing)
            {
                if (SandboxedAppDomain != null)
                {
                    AppDomain.Unload(SandboxedAppDomain);
                    SandboxedAppDomain = null;
                }
            }

            _disposed = true;
        }

        // This code added to correctly implement the disposable pattern.
        void IDisposable.Dispose()
        {
            // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
            Dispose(true);
        }
        #endregion
    }
}

可以这样使用:

代码语言:javascript
复制
SandboxWrapper.InstantiatePlugin<YourPluginType>(unsecureString, secureString)

不确定其中有多少是有效的,但它有效地处理了我对xml和JSON序列化的测试。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38079954

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档