搜索
查看: 1036|回复: 13

关于调用C#程序集问题

[复制链接]

3

主题

16

帖子

88

积分

一级会员

Rank: 2

积分
88
发表于 2017-10-2 23:32:29 | 显示全部楼层 |阅读模式
程序目的:需要在无excel2007软件的环境中生成xlsx文件并写入数据
调用DLL:EPPlus.dll(一款C#下的excel2007格式支持库)
以下是根据范例中 实时编译C#源码的 内容进行修改的

  1. //运行时编译C#
  2. //运行时编译C#
  3. import console;
  4. console.open()

  5. import dotNet;
  6. var clr = dotNet.clr( "v4.0","v2.0" );
  7. if( !clr ){
  8.     console.log("当前系统未安装.Net Framework 2.0 以上版本")
  9.     console.pause();
  10.     return;
  11. }

  12. //创建应用程序域
  13. var appDomain = clr.createAppDomain();

  14. //创建C#语言编译器
  15. var compile = appDomain.createCompiler("C#");
  16. compile.Reference("System.dll")
  17. compile.Reference("/res/EPPlus.dll")

  18. //设置待编译C#源码
  19. compile.Source = /******
  20. using System;
  21. using System.IO;
  22. using System.Reflection;
  23. using OfficeOpenXml;  // namespace for the ExcelPackage assembly
  24. namespace CSharpLibrary  
  25. {
  26.     public class AardioTable  
  27.     {
  28.             private object tObject;
  29.             public AardioTable(object obj){
  30.                     tObject = obj;
  31.             }
  32.             public object GetProperty(string k){
  33.                     return  tObject.GetType().InvokeMember(k, BindingFlags.GetProperty, null, tObject, null);
  34.             }
  35.             public void SetProperty(string k,object v){
  36.                     tObject.GetType().InvokeMember(k, BindingFlags.SetProperty, null, tObject, new object[] { v });
  37.             }
  38.             public object InvokeMember(string k,params/*不定个数参数*/ object[] arg ){
  39.                     return  tObject.GetType().InvokeMember(k, BindingFlags.InvokeMethod, null, tObject, arg );
  40.             }
  41.     }
  42.     public class CSharpObject  
  43.     {   
  44.         public string create(){   
  45.             FileInfo newFile = new FileInfo(@"d:\sample2.xlsx");
  46.             ExcelPackage pck = new ExcelPackage(newFile);
  47.             var ws = pck.Workbook.Worksheets.Add("Content");
  48.             pck.Save();
  49.             return "ok";
  50.         }
  51.         public string test(){
  52.                 return "hello";
  53.         }
  54.     }
  55. }
  56. ******/

  57. //编译并返回程序集  
  58. var assembly = compile.Compile()  
  59. console.log(compile.getLastError())
  60. console.pause()
  61. //调用程序集创建类对象
  62. var cSharpObject = assembly.createInstance("CSharpLibrary.CSharpObject")  
  63. //调用实时编译的C#函数
  64. console.log(cSharpObject.create());
  65. console.log(cSharpObject.test());
  66. console.pause()
复制代码


上述代码在aardio中编译成功,但是调用create()时aardio提示异常、调用test()能够获取字符串hello:



下面为在C#中的代码,测试无问题
  1. using System;
  2. using System.IO;
  3. using System.Windows.Forms;
  4. using OfficeOpenXml;
  5. using System.Reflection;

  6. namespace WindowsFormsApplication1
  7. {
  8.     public partial class Form1 : Form
  9.     {
  10.         public Form1()
  11.         {
  12.             InitializeComponent();
  13.         }

  14.         private void button1_Click(object sender, EventArgs e)
  15.         {
  16.             test();
  17.         }
  18.         private void test() {
  19.             FileInfo newFile = new FileInfo(@"d:\sample1.xlsx");
  20.             ExcelPackage pck = new ExcelPackage(newFile);
  21.             //Add the Content sheet
  22.             var ws = pck.Workbook.Worksheets.Add("Content");
  23.             pck.Save();
  24.         }
  25.     }
  26. }
复制代码


多番搜索,这方面的资料确实太少,所以只能来论坛请教,谢谢!


回复

使用道具 举报

186

主题

2537

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
13937
发表于 2017-10-3 00:43:48 | 显示全部楼层
直接调用EPPlus.dll  这样写:
import dotNet;
var clr = dotNet.clr();

var app = clr.createAppDomain();
var EPPlus = app.loadFile("/EPPlus.dll");
var mscorlib = app.load("mscorlib")

var newFile = mscorlib.createInstance("System.IO.FileInfo","d:\sample.xlsx");
var pck = EPPlus.createInstance("OfficeOpenXml.ExcelPackage",newFile);
pck.Workbook.Worksheets.Add(
"Content");
pck.Save();

execute("pause")


回复

使用道具 举报

3

主题

16

帖子

88

积分

一级会员

Rank: 2

积分
88
 楼主| 发表于 2017-10-2 23:43:13 | 显示全部楼层
漏了epplus的链接 :http://epplus.codeplex.com/downloads/get/1591093
回复

使用道具 举报

186

主题

2537

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
13937
发表于 2017-10-2 23:55:45 | 显示全部楼层
你的代码在aardio中测试完全正常,
没有错误,d:\sample2.xlsx 也正常创建。

如果你在C#中正常,在aardio中就会正常,都是.Net在运行代码。
一般不建议你在aardio中编译C#代码,直接在C#开发环境中编译为DLL,再到aardio中调用DLL就行了。
回复

使用道具 举报

3

主题

16

帖子

88

积分

一级会员

Rank: 2

积分
88
 楼主| 发表于 2017-10-2 23:56:06 | 显示全部楼层
在VS使用下列代码进行封装DLL后,利用范例中调用C#程序集一例也无法运行
  1. using System;
  2. using System.IO;
  3. using OfficeOpenXml;
  4. using System.Runtime.InteropServices;
  5. namespace CSNET2ClassLibrary
  6. {
  7.     [ComVisible(true), ClassInterface(ClassInterfaceType.AutoDual), IDispatchImpl(IDispatchImplType.InternalImpl)]
  8.     public class CSSimpleObject
  9.     {
  10.         public void create()
  11.         {
  12.             FileInfo newFile = new FileInfo(@"d:\sample1.xlsx");
  13.             ExcelPackage pck = new ExcelPackage(newFile);
  14.             //Add the Content sheet
  15.             var ws = pck.Workbook.Worksheets.Add("Content");
  16.             pck.Save();
  17.         }
  18.     }
  19. }
复制代码


aardio代码:
  1. //调用C#程序集
  2. import dotNet;
  3. import console;

  4. import dotNet;
  5. var clr = dotNet.clr();
  6. if( !clr ){
  7.     console.log("当前系统未安装.Net Framework", err )
  8.     console.pause();
  9.     return;
  10. }

  11. //创建应用程序域
  12. var appDomain = clr.createAppDomain();

  13. //引用程序集,注意凡aardio扩展的接口函数首字母小写,凡C#对象提供的接口函数首字母大写
  14. var system = appDomain.load("System");
  15. var CSharpCodeProvider = system.createInstance( "Microsoft.CSharp.CSharpCodeProvider" )

  16. //直接指定文件路径,资源文件路径,或内存数据加载程序集
  17. var Interop = appDomain.loadFile($"~/lib/dotNet/.res/Aardio.InteropServices.dll");
  18. var csProxy = Interop.createInstance("CSharp");//Aardio.InteropServices.CSharp可以省略程序集的名字空间

  19. //加载应用程序目录下的程序集( 或 "/bin/" 目录下的程序集 )
  20. var EPPlus = appDomain.loadFile("EPPlus.dll");
  21. var CSNET2ClassLibrary = appDomain.loadFile("CSNET2ClassLibrary.dll");
  22. var simpleObject = CSNET2ClassLibrary.createInstance("CSSimpleObject") //CSNET2ClassLibrary.CSSimpleObject可以省略程序集的名字空间

  23. //修改.Net对象的值
  24. simpleObject.create();

  25. //卸载应用程序域
  26. appDomain.unload();
  27. console.pause();
复制代码
回复

使用道具 举报

3

主题

16

帖子

88

积分

一级会员

Rank: 2

积分
88
 楼主| 发表于 2017-10-2 23:56:54 | 显示全部楼层
Jacen.He 发表于 2017-10-2 23:55
你的代码在aardio中测试完全正常,
没有错误,d:\sample2.xlsx 也正常创建。

您用我的aardio代码能够创建成功吗?
回复

使用道具 举报

186

主题

2537

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
13937
发表于 2017-10-3 00:02:00 | 显示全部楼层
CriSLyx 发表于 2017-10-2 23:56
您用我的aardio代码能够创建成功吗?

是的。

你可能是在C#中测试的时候,EPPlus.XML放对了位置,
在aardio中测试的时候,你又把 EPPlus.XML 弄丢了。
我试了一下,这样就会报你那样的错误。

或者你找一下其他的原因。
关于 EPPlus.dll 用法的资料应当在网上很多,怎么说找不到呢?!
回复

使用道具 举报

186

主题

2537

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
13937
发表于 2017-10-3 00:04:12 | 显示全部楼层
CriSLyx 发表于 2017-10-2 23:56
在VS使用下列代码进行封装DLL后,利用范例中调用C#程序集一例也无法运行

即然C#的DLL是你自己写的,
那么C#代码中发生的任何错误你都可以捕获,并找出原因。
关于C#的资料应该很多?!

aardio调用C#的DLL是肯定可以的,
毕竟提供了那么多范例。
回复

使用道具 举报

3

主题

16

帖子

88

积分

一级会员

Rank: 2

积分
88
 楼主| 发表于 2017-10-3 00:05:44 | 显示全部楼层
Jacen.He 发表于 2017-10-3 00:02
是的。

你可能是在C#中测试的时候,EPPlus.XML放对了位置,

主要是C#在aardio里的应用资料不多,我现在补上XML也成功了,感谢您的指点!

另外再叨扰您一下,如果我在VS里面把EPPlus的各类操作进行二次封装,在AAR里面引用的时候应该也要把EPPlus.dll一起引用进来,也是通过
  1. var EPPlus = appDomain.loadFile("EPPlus.dll");
复制代码

这样来吗?
回复

使用道具 举报

186

主题

2537

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
13937
发表于 2017-10-3 00:12:47 | 显示全部楼层
CriSLyx 发表于 2017-10-3 00:05
主要是C#在aardio里的应用资料不多,我现在补上XML也成功了,感谢您的指点!

另外再叨扰您一下,如果 ...


aardio调用C#的语法本来就很简单,看看范例就会用了,范例我写的很详细。
类似EPPlus你遇到的这个问题属于单纯的C#应用的问题,直接参考C#、EPPlus的文档就可以了。

你在VS里写的DLL,在aardio里就可以直接调用,并不需要 appDomain.loadFile("EPPlus.dll"); 只要在C#里可以调用的DLL,你在aardio里就可以直接使用。


回复

使用道具 举报

3

主题

16

帖子

88

积分

一级会员

Rank: 2

积分
88
 楼主| 发表于 2017-10-3 00:14:17 | 显示全部楼层
Jacen.He 发表于 2017-10-3 00:12
aardio调用C#的语法本来就很简单,看看范例就会用了,范例我写的很详细。
类似EPPlus你遇到的这个问题属 ...

好的 感谢您 多有打扰 谢谢!
回复

使用道具 举报

3

主题

16

帖子

88

积分

一级会员

Rank: 2

积分
88
 楼主| 发表于 2017-10-3 00:48:46 | 显示全部楼层
Jacen.He 发表于 2017-10-3 00:43
直接调用EPPlus.dll  这样写:

收到!我也使用VS封装dll实现了 再次感谢您的指点!
回复

使用道具 举报

0

主题

4

帖子

55

积分

一级会员

Rank: 2

积分
55
发表于 2018-6-30 23:46:37 | 显示全部楼层
本帖最后由 tmplinshi 于 2018-6-30 23:49 编辑

var myChart = ws.Drawings.AddChart("chart1", 5/*eChartType.Pie*/);
请问上面这行为什么会出错呢?错误提示如下:
---------------------------
aardio:运行时错误
---------------------------
文件:[string "import dotNet; ..."]
错误行号:#14
错误:COM exception
未找到方法“OfficeOpenXml.Drawing.ExcelDrawings.AddChart”。
---------------------------------------------------
调用栈:
        [kernel]: in function 'error'
        ...m Files\aardio\lib\dotNet\appDomain.aardio:270: in function 'AddChart'
        [string "import dotNet; ..."]:14: in main chunk
---------------------------
确定   
---------------------------

测试代码:
  1. import dotNet;
  2. var clr = dotNet.clr();

  3. var app = clr.createAppDomain();
  4. var EPPlus = app.loadFile("~/EPPlus.dll");
  5. var mscorlib = app.load("mscorlib");

  6. var newFile = mscorlib.createInstance("System.IO.FileInfo",".\output.xlsx");
  7. var pck = EPPlus.createInstance("OfficeOpenXml.ExcelPackage",newFile);
  8. var ws = pck.Workbook.Worksheets.Add("Content");

  9. ws.SetValue(1, 1, "This is cell A1");

  10. var myChart = ws.Drawings.AddChart("chart1", 5/*eChartType.Pie*/);
  11. var series = myChart.Series.Add("C2:C4", "B2:B4");
  12. myChart.Title.Text = "My Chart";
  13. myChart.SetSize(400, 400);
  14. myChart.SetPosition(6, 6);

  15. pck.Save();
复制代码


测试文件下载(包含 EPPlus.dll): https://pan.baidu.com/s/1m3G6GaoX5jRELDDH7sIaog

先谢谢了!
回复

使用道具 举报

0

主题

4

帖子

55

积分

一级会员

Rank: 2

积分
55
发表于 2018-7-1 01:28:16 | 显示全部楼层
抱歉,请用这个链接下载测试文件:https://pan.baidu.com/s/1YdgJlokQ6aiUsnvV4z32Zg
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

手机版|未经许可严禁引用或转载本站文章|站长邮箱|aardio.com|aardio官方社区 ( 皖ICP备09012014号 )

GMT+8, 2018-8-21 04:38 , Processed in 0.062501 second(s), 24 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表