非管理员账户上的Report Viewer 2010问题

8
我在我的Winforms应用程序中使用了ReportViewer控件。报告包含一些表达式,因此它会尝试创建“表达式主机”程序集在临时文件夹中。除非我以管理员特权运行程序(即右键单击,选择'run as admin...'),否则我会收到以下错误消息:
"访问路径'C:\Users\user\AppData\Local\Temp\expression_host_351sf52dsf5.dll'被拒绝"
现在真正的问题在于,在客户的客户端机器上,用户没有访问管理员帐户的权限。我该怎么办?
我已经检查过,上述dll文件是在临时文件夹中创建的,但程序无法访问它。我还在属性窗口的安全选项卡中给了每个人完全控制的权限,但没有成功。
我还尝试在加载报告之前运行以下代码:
reportViewer1.LocalReport.SetBasePermissionsForSandboxAppDomain(new
System.Security.PermissionSet(System.Security.Permissions.PermissionState.Unrestricted));

还有这个:

reportViewer1.LocalReport.SetBasePermissionsForSandboxAppDomain(AppDomain.CurrentDomain.PermissionSet.Copy());

我已经花了几个星期的时间试图解决这个问题。这在我的机器和客户机上都发生过。欢迎任何想法。

编辑: 我注意到报告查看器尝试“删除”该文件,并出现错误。以下是堆栈跟踪:

Microsoft.Reporting.WinForms.LocalProcessingException: An error occurred during local 
report processing. ---> Microsoft.Reporting.DefinitionInvalidException: The definition of the report 'D:\Projects\MyProject\bin\Reports\Report1.rdl' is invalid. ---> Microsoft.ReportingServices.ReportProcessing.ReportProcessingException: An unexpected error occurred in Report Processing. ---> System.UnauthorizedAccessException: Access to the path 'C:\Users\User1\AppData\Local\Temp\expression_host_2bc11a902f7142e9a62bb28fd36c2d26.dll' is denied.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.File.Delete(String path)
   at Microsoft.ReportingServices.RdlExpressions.ExprHostCompiler.InternalCompile(Report report, AppDomain compilationTempAppDomain, Boolean refusePermissions)
   at Microsoft.ReportingServices.RdlExpressions.ExprHostCompiler.<>c__DisplayClass1.<Compile>b__0()
   at Microsoft.ReportingServices.Diagnostics.RevertImpersonationContext.<>c__DisplayClass1.<Run>b__0(Object state)
   at System.Security.SecurityContext.Run(SecurityContext securityContext, ContextCallback callback, Object state)
   at Microsoft.ReportingServices.Diagnostics.RevertImpersonationContext.Run(ContextBody callback)
   at Microsoft.ReportingServices.RdlExpressions.ExprHostCompiler.Compile(Report report, AppDomain compilationTempAppDomain, Boolean refusePermissions)
   at Microsoft.ReportingServices.ReportPublishing.ReportPublishing.Phase3(ICatalogItemContext reportContext, ParameterInfoCollection& parameters, AppDomain compilationTempAppDomain, Boolean generateExpressionHostWithRefusedPermissions, Dictionary`2& groupingExprCountAtScope)
   at Microsoft.ReportingServices.ReportPublishing.ReportPublishing.CreateIntermediateFormat(ICatalogItemContext reportContext, Byte[] definition, IChunkFactory createChunkCallback, CheckSharedDataSource checkDataSourceCallback, ResolveTemporaryDataSource resolveTemporaryDataSourceCallback, DataSourceInfoCollection originalDataSources, PublishingErrorContext errorContext, AppDomain compilationTempAppDomain, Boolean generateExpressionHostWithRefusedPermissions, IDataProtection dataProtection, String& description, String& language, ParameterInfoCollection& parameters, DataSourceInfoCollection& dataSources, UserLocationFlags& userReferenceLocation, ArrayList& dataSetsName, Boolean& hasExternalImages, Boolean& hasHyperlinks)
   at Microsoft.ReportingServices.ReportProcessing.ReportProcessing.CompileOdpReport(ICatalogItemContext reportContext, Byte[] reportDefinition, IChunkFactory createChunkCallback, CheckSharedDataSource checkDataSourceCallback, ResolveTemporaryDataSource resolveTemporaryDataSourceCallback, DataSourceInfoCollection originalDataSources, PublishingErrorContext errorContext, AppDomain compilationTempAppDomain, Boolean generateExpressionHostWithRefusedPermissions, IDataProtection dataProtection, String& reportDescription, String& reportLanguage, ParameterInfoCollection& parameters, DataSourceInfoCollection& dataSources, UserLocationFlags& userReferenceLocation, ArrayList& dataSetsName, Boolean& hasExternalImages, Boolean& hasHyperlinks)
   at Microsoft.ReportingServices.ReportProcessing.ReportProcessing.CreateIntermediateFormat(ICatalogItemContext reportContext, Byte[] reportDefinition, IChunkFactory createChunkFactory, CheckSharedDataSource checkDataSourceCallback, ResolveTemporaryDataSource resolveTemporaryDataSourceCallback, DataSourceInfoCollection originalDataSources, AppDomain compilationTempAppDomain, Boolean generateExpressionHostWithRefusedPermissions, ReportProcessingFlags processingFlags, IDataProtection dataProtection)

File.Delete()ExprHostCompiler.InternalCompile() 中被调用。通过反射查看,可以看到它是这样发生的(在 finally 内的最后代码块中查看):

private byte[] InternalCompile(Report report, AppDomain compilationTempAppDomain, bool refusePermissions)
{
    if (this.m_builder.HasExpressions)
    {
        CompilerParameters options = new CompilerParameters {
            OutputAssembly = string.Format(CultureInfo.InvariantCulture, "{0}{1}.dll", new object[] { Path.GetTempPath(), report.ExprHostAssemblyName }),
            GenerateExecutable = false,
            GenerateInMemory = false,
            IncludeDebugInformation = false
        };
        options.ReferencedAssemblies.Add("System.dll");
        options.ReferencedAssemblies.Add(typeof(ReportObjectModelProxy).Assembly.Location);
        options.CompilerOptions = options.CompilerOptions + this.m_langParser.GetCompilerArguments();
        if (report.CodeModules != null)
        {
            this.ResolveAssemblylocations(report.CodeModules, options, this.m_errorContext, compilationTempAppDomain);
        }
        CompilerResults results = null;
        try
        {
            CodeCompileUnit exprHost = this.m_builder.GetExprHost(report.IntermediateFormatVersion, refusePermissions);
            report.CompiledCodeGeneratedWithRefusedPermissions = refusePermissions;
            CodeDomProvider codeCompiler = this.m_langParser.GetCodeCompiler();
            results = codeCompiler.CompileAssemblyFromDom(options, new CodeCompileUnit[] { exprHost });
            if (Global.Tracer.TraceVerbose)
            {
                try
                {
                    using (MemoryStream stream = new MemoryStream())
                    {
                        IndentedTextWriter writer = new IndentedTextWriter(new StreamWriter(stream), "    ");
                        codeCompiler.GenerateCodeFromCompileUnit(exprHost, writer, new CodeGeneratorOptions());
                        writer.Flush();
                        stream.Position = 0L;
                        Global.Tracer.Trace(new StreamReader(stream).ReadToEnd());
                    }
                }
                catch
                {
                }
            }
            if ((results.NativeCompilerReturnValue != 0) || (results.Errors.Count > 0))
            {
                this.ParseErrors(results, report.CodeClasses);
                return new byte[0];
            }
            using (FileStream stream2 = File.OpenRead(results.PathToAssembly))
            {
                byte[] buffer = new byte[stream2.Length];
                int num = stream2.Read(buffer, 0, (int) stream2.Length);
                Global.Tracer.Assert(num == stream2.Length, "(read == fs.Length)");
                return buffer;
            }
        }
        finally
        {
            if ((results != null) && (results.PathToAssembly != null))
            {
                File.Delete(results.PathToAssembly); //<------- Here!
            }
        }
    }
    return new byte[0];
}

有没有一种方法可以防止它被删除?
2个回答

5
我简直不敢相信,只需点击一下,我的问题就终于解决了!看看这篇博客文章。我禁用了我的杀毒软件,哇!

1
除了病毒防护/防火墙设置配置之外,是否曾经有过其他解决方法?我的公司绝对不允许这样做,所以只能自己想办法解决。 - bjhuffine

3
看起来你已经接近成功,只是还缺少一小部分。
根据LocalReport.SetBasePermissionsForSandboxAppDomain的文档,你必须添加一个Execution权限:“…你应该确保提供的权限集包含执行权限。否则,无法执行任何自定义代码程序集和评估表达式。
请尝试以下步骤:
    PermissionSet permissions = new PermissionSet(PermissionState.None);
    permissions.AddPermission(new FileIOPermission(PermissionState.Unrestricted));
    permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));  // The missing piece

    reportViewer1.LocalReport.SetBasePermissionsForSandboxAppDomain(permissions);

我不小心接受了你的答案,但它并没有真正解决问题。如果我不用“以管理员身份运行”来运行我的exe文件,我仍然会收到以下错误:...System.UnauthorizedAccessException: 拒绝访问路径'C:\Users\MOHAMMAD\AppData\Local\Temp\expression_host_9d7ebefb7d764e00b543df5d190e53e7.dll'。 - Delphi.Boy
同时在VS2010中运行没有错误!这很奇怪,因为VS2010没有以管理员身份运行。 - Delphi.Boy
@Delphi.Boy 如果您想让我们查看堆栈跟踪,请尝试将其编辑到问题中,以便我们更好地查看。在您的评论中,您是指您的系统还是客户机器?您所看到的问题几乎肯定是系统级权限问题。用户没有读/写/执行其自己的临时目录权限很奇怪,但我见过它,尽管我不确定是哪个程序修改了权限。在继续之前,请先导航到Temp目录并检查权限(右键单击,属性,安全性,编辑)。 - B L
谢谢。我编辑了答案并删除了评论。正如我在原始问题中提到的那样,我已经在我的Temp文件夹的安全选项卡中给予“每个人”“完全控制”的权限。 - Delphi.Boy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接