关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复239或者20161203可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong.me 。

以前我出过一个悬赏题目,就是定制Dynamics CRM标准的导出功能,让某些列不能导出,比如这些列可能包括敏感信息,比如消费者的姓名和电话等等,如何定制呢?我到现在还没有收到答案。某个周末的晚上,我研究了一下,初步有些效果,所以本博文记下来。
最容易想到的是注册插件,与导出有关的消息至少有四个,分别是Export, ExportAll, ExportCompressed 和ExportCompressedAll,可是注册在这四个消息上不管用。于是想到了在RetrieveMultiple消息上动刀,这个消息经常使用,除了根据主键和备用键查询数据以外,应该都是通过这个消息查询数据,导出也要查询数据。可是如果每次查询数据都执行的话,很消耗性能,后来我发现导出的时候执行的这个消息和普通的查询似乎有一个区别,就是导出的时候执行这个消息的上下文的Depth属性值为2,所以可以利用这个属性做点文章,尽量少执行点代码。
我先使用如下代码来查看打开一个普通的视图,插件中获取的各种参数,我这个代码是注册在罗勇测试实体RetrieveMultiple的Pre阶段。
using System;
using Microsoft.Xrm.Sdk;
using System.Text;
using Microsoft.Xrm.Sdk.Query;
using System.Linq;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO; namespace CrmVSSolution.Plugins
{
public class PreTestRetrieveMultiple : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
// Extract the tracing service for use in debugging sandboxed plug-ins.
// If you are not registering the plug-in in the sandbox, then you do
// not have to add any tracing service related code.
ITracingService tracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService)); // Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext)); IOrganizationServiceFactory serviceFactory =
(IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); StringBuilder sb = new StringBuilder();
sb.Append("Depth=");
sb.Append(context.Depth);
sb.Append(";PrimaryEntityName=");
sb.Append(context.PrimaryEntityName);
sb.Append(";PrimaryEntityId=");
sb.Append(context.PrimaryEntityId);
sb.Append(";BusinessUnitId=");
sb.Append(context.BusinessUnitId);
sb.Append(";InitiatingUserId=");
sb.Append(context.InitiatingUserId);
sb.Append(";IsExecutingOffline");
sb.Append(context.IsExecutingOffline);
sb.Append(";IsInTransaction=");
sb.Append(context.IsInTransaction);
sb.Append(";IsOfflinePlayback=");
sb.Append(context.IsOfflinePlayback);
sb.Append(";IsolationMode=");
sb.Append(context.IsolationMode);
sb.Append(";MessageName=");
sb.Append(context.MessageName);
sb.Append(";OperationId=");
sb.Append(context.OperationId);
sb.Append(";OrganizationId=");
sb.Append(context.OrganizationId);
sb.Append(";OrganizationName=");
sb.Append(context.OrganizationName);
sb.Append(";OutputParameters=");
if (context.OutputParameters != null)
{
sb.Append("{");
foreach (var outputpara in context.OutputParameters)
{
sb.Append(outputpara.Key);
sb.Append("=");
sb.Append(outputpara.Value.ToString());
}
sb.Append("}");
}
else
{
sb.Append("null");
}
sb.Append(";OwningExtension=");
if (context.OwningExtension != null)
{
sb.Append("{LogicalName=");
sb.Append(context.OwningExtension.LogicalName);
sb.Append(";Name=");
sb.Append(context.OwningExtension.Name);
sb.Append(";Id=");
sb.Append(context.OwningExtension.Id);
}
else
{
sb.Append("null");
}
sb.Append(";ParentContext=");
if (context.ParentContext != null)
{
sb.Append(context.ParentContext.ToString());
}
else
{
sb.Append("null");
}
sb.Append(";PostEntityImages=");
if (context.PostEntityImages != null)
{
sb.Append("{");
foreach (var postimg in context.PostEntityImages)
{
sb.Append("Key=");
sb.Append(postimg.Key);
sb.Append(";Value.Id=");
sb.Append(postimg.Value.Id);
sb.Append(";Value.LogicalName=");
sb.Append(postimg.Value.LogicalName);
foreach (var attr in postimg.Value.Attributes)
{
sb.Append("Attr=");
sb.Append(attr.Key);
sb.Append(";Value=");
sb.Append(attr.Value.ToString());
}
}
sb.Append("}");
}
else
{
sb.Append("null");
}
sb.Append(";PreEntityImages=");
if (context.PreEntityImages != null)
{
sb.Append("{");
foreach (var preimg in context.PreEntityImages)
{
sb.Append("Key=");
sb.Append(preimg.Key);
sb.Append(";Value.Id=");
sb.Append(preimg.Value.Id);
sb.Append(";Value.LogicalName=");
sb.Append(preimg.Value.LogicalName);
foreach (var attr in preimg.Value.Attributes)
{
sb.Append("Attr=");
sb.Append(attr.Key);
sb.Append(";Value=");
sb.Append(attr.Value.ToString());
}
}
sb.Append("}");
}
else
{
sb.Append("null");
}
sb.Append(";SecondaryEntityName=");
sb.Append(context.SecondaryEntityName);
sb.Append(";RequestId=");
sb.Append(context.RequestId.HasValue ? context.RequestId.Value.ToString() : "null");
sb.Append(";Stage=");
sb.Append(context.Stage);
sb.Append(";UserId=");
sb.Append(context.UserId);
sb.Append(";InputParameters=");
if (context.InputParameters != null)
{
sb.Append("{");
foreach (var inputpara in context.InputParameters)
{
sb.Append(inputpara.Key);
sb.Append("=");
sb.Append(inputpara.Value.ToString());
if (inputpara.Key == "Query")
{
var queryexp = inputpara.Value as QueryExpression;
sb.Append("ColumnSet={");
foreach (var col in queryexp.ColumnSet.Columns)
{
sb.Append(col);
sb.Append(",");
}
sb.Append("}");
sb.Append("LinkEntities={");
if (queryexp.LinkEntities != null)
{
sb.Append("LinkEntity={");
foreach (var linkentity in queryexp.LinkEntities.Where(x => x.LinkToEntityName == "ly_test"))
{
sb.Append("LinkToEntityName=");
sb.Append(linkentity.LinkToEntityName);
sb.Append(";LinkFromEntityName=");
sb.Append(linkentity.LinkFromEntityName);
sb.Append(";LinkColumnSet={");
sb.Append(string.Join(",", linkentity.Columns.Columns));
sb.Append("}");
}
sb.Append("}");
}
else
{
sb.Append("null");
}
sb.Append("}");
}
}
sb.Append("}");
}
else
{
sb.Append("null");
}
sb.Append("当前用户拥有角色:");
sb.Append(string.Join(",", GetUserRoles(service, context.UserId)));
if (context.InputParameters.Contains("Query") && context.InputParameters["Query"] is QueryExpression)
{
//throw new InvalidPluginExecutionException("不是管理员不能导出!");//这个错误提示不会展示在前台给用户看到
QueryExpression objQueryExpression = (QueryExpression)context.InputParameters["Query"];
sb.Append("查找的主实体是:");
sb.Append(objQueryExpression.EntityName);
sb.Append("查询表达式是:");
XmlSerializer xmlSerializer = new XmlSerializer(objQueryExpression.GetType());
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, objQueryExpression);
sb.Append(textWriter.ToString());
}
}
var entity = new Entity("annotation");
entity["subject"] = "execute retrievemultiple";
entity["objectid"] = new EntityReference("ly_test", Guid.Parse("B707DE1B-CF99-E611-8161-000D3A80C8B8"));
entity["notetext"] = sb.ToString();
service.Create(entity);
} public IEnumerable<string> GetUserRoles(IOrganizationService service, Guid userId)
{
string fetchXml = string.Format(@"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='true' no-lock='true'>
<entity name='role'>
<attribute name='name' />
<link-entity name='systemuserroles' from='roleid' to='roleid' visible='false' intersect='true'>
<link-entity name='systemuser' from='systemuserid' to='systemuserid' alias='ad'>
<filter type='and'>
<condition attribute='systemuserid' operator='eq' value='{0}' />
</filter>
</link-entity>
</link-entity>
</entity>
</fetch>", userId);
EntityCollection entities = service.RetrieveMultiple(new FetchExpression(fetchXml));
return entities.Entities.Select(x => x.GetAttributeValue<string>("name"));
}
}
}
 
得到的结果如下:
Depth=1;PrimaryEntityName=ly_test;PrimaryEntityId=00000000-0000-0000-0000-000000000000;BusinessUnitId=487cdd4b-26a3-e511-80c6-000d3a807ec7;InitiatingUserId=e9cd027f-26a3-e511-80c6-000d3a807ec7;IsExecutingOffline:False;IsInTransaction=False;IsOfflinePlayback=False;IsolationMode=2;MessageName=RetrieveMultiple;OperationId=00000000-0000-0000-0000-000000000000;OrganizationId=bd2a5c49-6b08-4eda-8a15-84159d9fd349;OrganizationName=Demo;OutputParameters={};OwningExtension={LogicalName=sdkmessageprocessingstep;Name=CrmVSSolution.Plugins.PreTestRetrieveMultiple: RetrieveMultiple of ly_test;Id=544ba42f-baae-e611-816e-000d3a80c8b8;ParentContext=null;PostEntityImages={};PreEntityImages={};SecondaryEntityName=none;RequestId=null;Stage=20;UserId=e9cd027f-26a3-e511-80c6-000d3a807ec7;InputParameters={Query=Microsoft.Xrm.Sdk.Query.QueryExpressionColumnSet={ly_name,modifiedon,ly_minutessincecreated,createdon,ly_testid,processid,ly_name,ly_minutessincecreated,modifiedon,createdon,}LinkEntities={LinkEntity={}}}当前用户拥有角色:System Customizer,计划经理,计划员,系统管理员;查找的主实体是:ly_test;查询表达式是:<?xml version="1.0" encoding="utf-16"?>
<QueryExpression _tmplitem="3" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ExtensionData _tmplitem="3" ></ExtensionData>
<Distinct _tmplitem="3" >false</Distinct>
<NoLock _tmplitem="3" >true</NoLock>
<PageInfo _tmplitem="3" >
<PageNumber _tmplitem="3" >1</PageNumber>
<Count _tmplitem="3" >50</Count>
<ReturnTotalRecordCount _tmplitem="3" >true</ReturnTotalRecordCount>
<ExtensionData _tmplitem="3" ></ExtensionData>
</PageInfo>
<LinkEntities _tmplitem="3" >
<LinkEntity _tmplitem="3" >
<LinkFromAttributeName _tmplitem="3" >processid</LinkFromAttributeName>
<LinkFromEntityName _tmplitem="3" >ly_test</LinkFromEntityName>
<LinkToEntityName _tmplitem="3" >workflow</LinkToEntityName>
<LinkToAttributeName _tmplitem="3" >workflowid</LinkToAttributeName>
<JoinOperator _tmplitem="3" >LeftOuter</JoinOperator>
<LinkCriteria _tmplitem="3" >
<FilterOperator _tmplitem="3" >And</FilterOperator>
<Conditions _tmplitem="3" ></Conditions>
<Filters _tmplitem="3" ></Filters>
<IsQuickFindFilter _tmplitem="3" >false</IsQuickFindFilter>
<ExtensionData _tmplitem="3" ></ExtensionData>
</LinkCriteria>
<LinkEntities _tmplitem="3" />
<Columns _tmplitem="3" >
<AllColumns _tmplitem="3" >false</AllColumns>
<Columns _tmplitem="3" >
<string _tmplitem="3" >versionnumber</string>
</Columns>
<ExtensionData _tmplitem="3" ></ExtensionData>
</Columns>
<EntityAlias _tmplitem="3" >processidworkflowworkflowid</EntityAlias>
<Orders _tmplitem="3" ></Orders>
<ExtensionData _tmplitem="3" ></ExtensionData>
</LinkEntity>
</LinkEntities>
<Criteria _tmplitem="3" >
<FilterOperator _tmplitem="3" >And</FilterOperator>
<Conditions _tmplitem="3" ></Conditions>
<Filters _tmplitem="3" ></Filters>
<IsQuickFindFilter _tmplitem="3" >false</IsQuickFindFilter>
<ExtensionData _tmplitem="3" ></ExtensionData>
</Criteria>
<Orders _tmplitem="3" >
<OrderExpression _tmplitem="3" >
<AttributeName _tmplitem="3" >ly_name</AttributeName>
<OrderType _tmplitem="3" >Ascending</OrderType>
<ExtensionData _tmplitem="3" ></ExtensionData>
</OrderExpression>
</Orders>
<EntityName _tmplitem="3" >ly_test</EntityName>
<ColumnSet _tmplitem="3" >
<AllColumns _tmplitem="3" >false</AllColumns>
<Columns _tmplitem="3" >
<string _tmplitem="3" >ly_name</string>
<string _tmplitem="3" >modifiedon</string>
<string _tmplitem="3" >ly_minutessincecreated</string>
<string _tmplitem="3" >createdon</string>
<string _tmplitem="3" >ly_testid</string>
<string _tmplitem="3" >processid</string>
<string _tmplitem="3" >ly_name</string>
<string _tmplitem="3" >ly_minutessincecreated</string>
<string _tmplitem="3" >modifiedon</string>
<string _tmplitem="3" >createdon</string>
</Columns>
<ExtensionData _tmplitem="3" ></ExtensionData>
</ColumnSet>
<TopCount _tmplitem="3" xsi:nil="true" ></TopCount>
</QueryExpression>
然后到主题了,我这假设限制罗勇测试实体的十进制数列(ly_decimal)不允许导出,就在这个实体的RetrieveMultiple消息的Pre阶段使用如下代码,当然我还做了个限制,没有系统管理员角色不能导出,只是为了证明这里面可以做很多事情,用权限来控制导出功能,很简单吧:
using System;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System.Linq;
using System.Collections.Generic; namespace CrmVSSolution.Plugins
{
public class PreTestRetrieveMultiple : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
ITracingService tracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService)); IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext)); IOrganizationServiceFactory serviceFactory =
(IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); //context.Depth = 2是导出的时候执行
if (context.Depth == && context.InputParameters.Contains("Query") && context.InputParameters["Query"] is QueryExpression)
{
if (!GetUserRoles(service, context.UserId).Contains("系统管理员"))
{
throw new InvalidPluginExecutionException("不是管理员不能导出!");//这个错误提示不会展示在前台给用户看到
}
QueryExpression objQueryExpression = (QueryExpression)context.InputParameters["Query"];
objQueryExpression.ColumnSet = new ColumnSet(objQueryExpression.ColumnSet.Columns.Where(col => col != "ly_decimal").ToArray());
}
} public IEnumerable<string> GetUserRoles(IOrganizationService service, Guid userId)
{
string fetchXml = string.Format(@"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='true' no-lock='true'>
<entity name='role'>
<attribute name='name' />
<link-entity name='systemuserroles' from='roleid' to='roleid' visible='false' intersect='true'>
<link-entity name='systemuser' from='systemuserid' to='systemuserid' alias='ad'>
<filter type='and'>
<condition attribute='systemuserid' operator='eq' value='{0}' />
</filter>
</link-entity>
</link-entity>
</entity>
</fetch>", userId);
EntityCollection entities = service.RetrieveMultiple(new FetchExpression(fetchXml));
return entities.Entities.Select(x => x.GetAttributeValue<string>("name"));
}
}
}
在界面上可以看到十进制数列有值:
导出来的时候这个列就没有值:
这样虽然可以导出罗勇测试实体的时候不到处十进制字段,但是我如果查询的是它的子实体,然后加上这个实体的十进制字段显示,这个用高级查找很容易做到,导出的话就可以看到这个列了。
 
这个时候我需要在这个实体的1:N关系的子实体中也在RetrieveMultiple消息的Pre阶段注册类似如下插件代码即可:
using System;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System.Linq; namespace CrmVSSolution.Plugins
{
public class PreTestSubRetrieveMultiple : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
ITracingService tracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService)); IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext)); IOrganizationServiceFactory serviceFactory =
(IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); //context.Depth=2是导出的时候执行
if (context.Depth == && context.InputParameters.Contains("Query") && context.InputParameters["Query"] is QueryExpression)
{
QueryExpression objQueryExpression = (QueryExpression)context.InputParameters["Query"];
if (objQueryExpression.LinkEntities != null) //当这个不能导出的实体作为关联的父实体加入了视图列,也需要过滤
{
foreach (var linkentity in objQueryExpression.LinkEntities.Where(x => x.LinkToEntityName == "ly_test"))
{
linkentity.Columns = new ColumnSet(linkentity.Columns.Columns.Where(col => col != "ly_decimal").ToArray());
}
}
}
}
}
}

然后我可以看到效果,这个列的值导不出来了。

根据 Distinguish page load and Export to Excel in CRM 2015 的答案,最好是查看其ParentContext是否为null,若不为null再看其名称是否为ExportToExcel或者ExportDynamicToExcel,这个应该更加靠谱。
public void Execute(IServiceProvider serviceProvider)
{
var executionContext = serviceProvider.GetService<IPluginExecutionContext>();
var parentContext = executionContext.ParentContext;
if (parentContext != null &&
(parentContext.MessageName == "ExportToExcel" ||
parentContext.MessageName == "ExportDynamicToExcel"))
{
// Place your logic here
}
}
当然可能还有其他方法可以导出,我说的利用标准的功能不需要开发,欢迎各位看官提出来,看看能否封堵住。
 

定制Dynamics CRM标准导出功能:不能导出指定列的值的更多相关文章

  1. Dynamics CRM的Associate功能

    Dynamics CRM有一种特殊的关联关系叫Associate,一般常见于为用户分配角色.给团队添加用户.团队添加角色.队列添加用户等等.在一些特定场景下我们不可能把所有的操作都通过手动来完成尤其是 ...

  2. Dynamics CRM 通过RetrieveEntityRibbonRequest和RetrieveApplicationRibbonRequest导出实体的Ribbon XML

    今天看到勇哥的博客介绍了两个request指令用来导出实体的Ribbon XML,在没有工具之前编辑ribbon都是手工导出xml然后编辑的对于很多一开始接触CRM就用工具的人可能不是很熟悉.查了下这 ...

  3. Dynamics CRM 插件Plugin中获取和更新时间字段值的准确转换

    前面两篇介绍了后台代码通过组织服务获取更新时间字段.窗体javascript通过Odata获取更新时间字段,最后篇来实验下在插件中的获取和更新时间字段是否需要时制的转化,为何说是最后篇呢,因为在CRM ...

  4. oracle导入导出功能

    1.普通版:oracle导入导出功能:导出exp 用户名/密码@SID file=f:\xx.dmp owner=用户名 导入imp 用户名/密码@SID full=y file=f:\xx.dmp ...

  5. Dynamics CRM 2016 的新特性

    新版本CRM (2016 with update 0.1) 发布已有几个月了,总结一下新特性,从几个方面来看: 1. 针对整合功能的新特性 (1) 增加了CRM App for Outlook. 这个 ...

  6. Dynamics CRM实体系列之图表

    本节开始讲解Dynamics CRM的图表功能.任何产品基本上都会有数据分析的工具,Dynamics CRM当然也不例外,作为一个专门做销售管理的软件数据分析自然也是对于销售管理者的决策有很大的作用的 ...

  7. Dynamics CRM导出数据到Excel

    原创地址:http://www.cnblogs.com/jfzhu/p/4276212.html 转载请注明出处 Pivot Table是微软BI的一个重要工具,所以这里讲一下Dynamics CRM ...

  8. Dynamics CRM 报表导出EXCEL 列合并问题的解决方法

    CRM中的报表导出功能提供了多种格式,excel就是其中之一,这次遇到的问题是导出后打开excel列明合并的问题,具体如下看着相当不美观,物料名称字段占了AB两列,品牌占了CD两列等等. 该问题的源头 ...

  9. Dynamics CRM 修改Excel 最大导出记录限制及 最大上传文件限制

    CRM默认的Excel最大导出记录是10000条,最大上传文件限制为5m. 这样的限制可以满足少量数据的批量更新,但是如果数据量比较大的话需要修改最大的导出记录限制,和上传文件的大小,网上有的是直接修 ...

随机推荐

  1. 【xmind】 使用 Java 生成思维导图

    前言 在日常的工作与学习中,我们经常会使用思维导图这个工具,来把抽象而又无形的思考转换成有形并且具体的图像,是理清思路,梳理逻辑的一大神器. 准确的说,思维导图并不是一个具体的工具,而是一种方法.是道 ...

  2. Winform中怎样在工具类中对窗体中多个控件进行操作(赋值)

    场景 需求是在窗体加载完成后掉用工具类的方法,工具类中获取窗体的多个控件对象进行赋值. 注: 博客主页: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 ...

  3. 对python中等值和大小比较

    等值.大小比较 在python中,只要两个对象的类型相同,且它们是内置类型(字典除外),那么这两个对象就能进行比较.关键词:内置类型.同类型.所以,两个对象如果类型不同,就没法比较,比如数值类型的数值 ...

  4. 【C++常用函数】头文件<algorithm>中的常用函数(绝对值,交换,比较)

    swap(a,b) 用于交换a,b两个变量的值: max(a,b) 返回a,b中的最大值: min(a,b) 返回a,b中的最小值: abs(x) 返回x的绝对值,x必须是整数:

  5. 结对编程项目复盘:带UI的小初高数学学习软件

    实现个人项目时,由于我当时的Java GUI编程基础还比较薄弱,所以我选择通过命令行实现,并将编程开发的重点放到了算法效率上去.没能设计出用户体验更佳的UI成为了我在个人项目阶段最大的遗憾. 在这次结 ...

  6. js实现防抖函数和节流函数

    防抖函数(debounce) 含义:防抖函数指的是在特定的时间内没有再次触发,才得以进行接下来的函数运行: 用途:当window.onresize不断的调整大小的时候,为了避免不断的重排与重绘,可以用 ...

  7. 【一】Gradle 初识

    1.Gradle和Maven的对比 gradle 使用groovy语言,可以进行逻辑判断,maven基于xml,无法进行逻辑判断. gradle 可以在一个项目中,根据需求,生成2个不同的jar, m ...

  8. Nuget使用时遇到的问题,Solved

    在VS的程序包管理控制台中输入Install-package MySql.Data时,默认安装最新的版本8.0.18, 但是安装完成后,发现包并没有添加到项目的引用列表中, 在解决方案的package ...

  9. Day8 - Python基础8 异常处理、反射、单例模式

    本节内容: 1:异常处理 2:反射 3:单例模式 1.异常处理  1.异常简介 在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户 ...

  10. SPOJ2829 TLE-Time Limit Exceeded

    题目链接--SPOJ 题目链接--洛谷 problem 给出n,m和一个长度为n的数列c.求有多少个数列a满足以下条件: \(1\le a_i < 2^m\) \(a_i\&a_{i-1 ...