• MaxScript与外部程序通讯


    最近项目要求通过java给max发送任务指令,max接收指令执行任务,并且返回执行的结果。不管为什么会有这样的需求,有就要去实现。

    1、OLE开启

    Max本身提供了一个方式,它可以将自己注册成一个Ole自动化对象,默认是没有开启的,开启这个接口只需要操作注册表即可。将该脚本存放的max的安装路径下的ScriptsStartUp,即max启动时会默认加载的脚本。保证max启动以后会执行该脚本。

    关于脚本中内容具体请参考Maxscript的自带文档 OLE Automation 章节。

     1 (
     2     /* Dynamically writes the necessary Registry information to allow
     3         Simon Felton's MXSCOM bridge to work.
     4         IF RUNNING THIS SCRIPT ON AN VERSION OF MAX OLDER THAN MAX 10
     5         THE AVG EXTENSION *MUST* BE INSTALLED
     6     */
     7 
     8     local reg_key
     9     local max_version = ((maxVersion())[1] / 1000) as string
    10 
    11     fn create_reg_key hkey key_name &reg_key key_value_name key_value_type key_value =
    12     (
    13         registry.createKey hkey key_name key:&reg_key
    14         registry.setValue reg_key key_value_name key_value_type key_value
    15     )
    16 
    17     fn write_sub_key_data reg_key sub_key_name sub_key_type sub_key_value =
    18     (
    19         local sub_key
    20         registry.createKey reg_key sub_key_name key:&sub_key
    21         registry.setValue sub_key "" sub_key_type sub_key_value
    22     )
    23 
    24 
    25     -- Establish a root key for generalized Max data
    26     create_reg_key HKEY_CURRENT_USER @"SoftwareClassesMAX.Application" &reg_key "" #REG_SZ "OLE Automation MAX Application"
    27 
    28     -- Add the Clsid information
    29     write_sub_key_data reg_key "Clsid" #REG_SZ "{7FA22CB1-D26F-11d0-B260-00A0240CEEA3}"
    30 
    31     -- Add the CurVer information
    32     write_sub_key_data reg_key "CurVer" #REG_SZ ("MAX.Application." + max_version)
    33 
    34     -- Establish a new root key for the version of Max being used
    35     create_reg_key HKEY_CURRENT_USER (@"SoftwareClassesMAX.Application." + max_version) &reg_key "" #REG_SZ ("OLE Automation MAX " + max_version + ".0 Application")
    36 
    37     -- Add the Clsid information
    38     write_sub_key_data reg_key "Clsid" #REG_SZ "{7FA22CB1-D26F-11d0-B260-00A0240CEEA3}"
    39 
    40     -- Make a new root key for the CLSID data
    41     create_reg_key HKEY_CURRENT_USER @"SoftwareClassesCLSID{7FA22CB1-D26F-11d0-B260-00A0240CEEA3}" &reg_key "" #REG_SZ ("OLE Automation MAX " + max_version + ".0 Application")
    42 
    43     -- Add sub key data
    44     write_sub_key_data reg_key "ProgID" #REG_SZ ("MAX.Application." + max_version)
    45     write_sub_key_data reg_key "VersionIndependentProgID" #REG_SZ "MAX.Application"
    46 
    47     -- Register the running of files and executing script code to OLE.
    48     registerOLEInterface #( filein, execute, edit, encryptscript )
    49 
    50 )
    ole开启脚本

    2、编写socket通讯dll(C#)

    为什么要开启ole,是因为该dll用到了ole。为什么用C#写dll通信,是因为我对C#比较熟悉,还有就是maxscript中虽然可以调用donet的方法,但是语法上写起来很别扭,之前也写过ms一版,有些问题在ms中不好解决,比如在在调用ms中的执行了“importFile (strIn) #noPrompt” 时会发生未知错误。下面会贴上C#和ms两个版本的socket通讯代码(都是demo版本,仅供参考)。这里max都是做服务端,需要循环监听客户端的消息。

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Net;
      5 using System.Net.Sockets;
      6 using System.Reflection;
      7 using System.Text;
      8 using System.Threading;
      9 using System.Web.Script.Serialization;
     10 
     11 namespace SocketTest
     12 {
     13     public class SocketServer
     14     {
     15         //承载接收数据
     16         private static byte[] result = new byte[1024];
     17         //端口
     18         private static int myProt = 8889;
     19 
     20         private static Socket serverSocket;
     21         public static void InitSocket()
     22         {
     23             //创建通讯对象
     24             serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     25             //绑定IP地址:端口
     26             serverSocket.Bind(new IPEndPoint(IPAddress.Any, myProt));
     27             //设定最多10个排队连接请求
     28             serverSocket.Listen(5);
     29             //通过Clientsoket发送数据
     30             Thread myThread = new Thread(ListenClientConnect);
     31             myThread.Start();
     32         }
     33         /// <summary>
     34         /// 监听客户端连接
     35         /// </summary>
     36         private static void ListenClientConnect()
     37         {
     38             while (true)
     39             {
     40                 Socket clientSocket = serverSocket.Accept();
     41                 try
     42                 {
     43                     clientSocket.Send(Encoding.UTF8.GetBytes("第一次握手"));
     44                     Thread receiveThread = new Thread(ReceiveMessage);
     45                     receiveThread.Start(clientSocket);
     46                 }
     47                 catch (Exception)
     48                 {
     49 
     50                     clientSocket.Shutdown(SocketShutdown.Both);
     51                     clientSocket.Close();
     52                 }
     53 
     54             }
     55         }
     56 
     57         /// <summary>
     58         /// 接收消息
     59         /// </summary>
     60         /// <param name="clientSocket"></param>
     61         private static void ReceiveMessage(object clientSocket)
     62         {
     63             Socket myClientSocket = (Socket)clientSocket;
     64             while (true)
     65             {
     66                 try
     67                 {
     68                     //通过clientSocket接收数据
     69                     int receiveNumber = myClientSocket.Receive(result);
     70                     //返回给客户端的字典对象
     71                     Dictionary<string, object> dicTemp = new Dictionary<string, object>();
     72                     if (receiveNumber > 0)
     73                     {
     74                         try
     75                         {
     76                             //将客户端消息转换成字符
     77                             string clientResult = Encoding.UTF8.GetString(result, 0, receiveNumber);
     78                             //json字符串转换成字典对象
     79                             Dictionary<string, object> dicResult = GetDicByJson(clientResult);
     80                            
     81                             if (dicResult.Keys.Contains("code"))
     82                             {
     83                                 //判断是否为java轮询监听
     84                                 if (dicResult["code"].ToString().Equals("0100"))
     85                                 {
     86                                     //返回正常运行消息
     87                                     dicTemp.Add("code", "0002");
     88 
     89                                 }
     90                                 //执行任务文件处理的任务命令
     91                                 else if (dicResult["code"].ToString().Equals("0101"))
     92                                 {
     93                                     try
     94                                     {
     95                                         //获取输入输出路径
     96                                         string inFilePath = dicResult["in"].ToString();
     97                                         string outFilePath = dicResult["out"].ToString();
     98                                         //判断文件是否存在
     99                                         //if (File.Exists(inFilePath))
    100                                         //{
    101                                         //获取max ole对象
    102                                         var com_type = Type.GetTypeFromProgID("Max.Application");
    103                                         dynamic com_obj = Activator.CreateInstance(com_type);
    104                                         //构建执行参数
    105                                         object[] parameter = new object[1];
    106                                         //Fncreathouse 自定义ms中的方法 测试的时候可以用box()来替代  sname是参数名称 inFilePath是java传过来的参数值
    107                                         parameter[0] = "Fncreathouse sName:"" + inFilePath + """;
    108                                         //执行方法
    109                                         object result = com_type.InvokeMember("execute", BindingFlags.InvokeMethod | BindingFlags.Instance, System.Type.DefaultBinder, com_obj, parameter);
    110                                         dicTemp.Add("code", result.ToString());
    111                                         //myClientSocket.Send(Encoding.UTF8.GetBytes("成功了" + result.ToString()));
    112                                         //string filepath = "D:\2017\3DMAX\MXSPyCOM-master\hello_world.ms";
    113                                         //com_obj.FileIn(filepath);
    114                                         //}
    115                                         //else
    116                                         //{
    117                                         //    //文件不存在
    118                                         //    dicTemp.Add("code", "0004");
    119                                         //}
    120                                     }
    121                                     catch (Exception)
    122                                     {
    123                                         dicTemp.Add("code", "0005");
    124                                     }
    125                                 }
    126                             }
    127                             else
    128                             {
    129 
    130                             }
    131                         }
    132                         catch (Exception)
    133                         {
    134 
    135                             dicTemp.Add("code", "0005"); 
    136                         }
    137                         //将结果转换成json字符串,返回给客户端
    138                         string returnStr = GetJsonStrByDic(dicTemp);
    139                         myClientSocket.Send(Encoding.UTF8.GetBytes(returnStr));
    140                     }
    141                     else
    142                     {
    143                         //关闭客户端的连接
    144                         myClientSocket.Shutdown(SocketShutdown.Both);
    145                         myClientSocket.Close();
    146                         break;
    147                     }
    148 
    149 
    150                 }
    151                 catch (Exception)
    152                 {
    153                     myClientSocket.Shutdown(SocketShutdown.Both);
    154                     myClientSocket.Close();
    155                     break;
    156                 }
    157             }
    158         }
    159 
    160         /// <summary>
    161         /// 将字符串转换成字典
    162         /// </summary>
    163         /// <param name="jsonString"></param>
    164         /// <returns></returns>
    165         public static Dictionary<string, object> GetDicByJson(string jsonString)
    166         {
    167             Dictionary<string, object> JsonData = new Dictionary<string, object>();
    168             try
    169             {
    170                 JavaScriptSerializer s = new JavaScriptSerializer();
    171                 JsonData = (Dictionary<string, object>)s.DeserializeObject(jsonString);
    172             }
    173             catch (Exception)
    174             {
    175             }
    176             return JsonData;
    177         }
    178         /// <summary>
    179         /// 字典转换成简单json
    180         /// </summary>
    181         /// <param name="dic"></param>
    182         /// <returns></returns>
    183         public static string GetJsonStrByDic(Dictionary<string, object> dic)
    184         {
    185             string json = string.Empty;
    186             try
    187             {
    188                 if (dic.Keys.Count > 0)
    189                 {
    190                     json = "{";
    191                     foreach (var item in dic.Keys)
    192                     {
    193                         //如果是最后一个不加逗号
    194                         if (item.Equals(dic.Keys.Last()))
    195                         {
    196                             json = json + """ + item + "":"" + dic[item].ToString() + """;
    197                         }
    198                         else
    199                         {
    200                             json = json + """ + item + "":"" + dic[item].ToString() + "",";
    201                         }
    202                     }
    203                     json = json + "}";
    204                 }
    205             }
    206             catch (Exception)
    207             {
    208 
    209             }
    210             return json;
    211         }
    212     }
    213 }
    C# Socket通讯
      1 /*
      2     后台监听7457端口消息
      3 */
      4 Global Encoding,IPAddress
      5 (
      6     Fn fntest    =(
      7         --print("准创建box")
      8             box()
      9                 --print("创建完box")
     10                 
     11             exportfile  "f:\box.fbx" #noPrompt
     12 
     13             --print("保存文件")
     14             
     15                 )
     16     Fn ExecutionOfTasks = 
     17     (
     18         --theIPAddress = IPAddress.Parse "127.0.0.1"
     19         mainTcpListener = DotNetObject "System.Net.Sockets.TcpListener" IPAddress.Any 7455
     20         --承载数据接收
     21         mainByteStream = DotNetObject "System.Byte[]" 1024
     22         
     23         mainTcpListener.Start()
     24         while true do
     25         (
     26             
     27             try
     28             (
     29                 --获取客户端
     30                 theSocket = mainTcpListener.AcceptSocket()
     31                 --与客户端第一次握手
     32                 theSocket.Send(Encoding.UTF8.GetBytes("I am 3dmax"))
     33                 while true do
     34                 (
     35                     --获取客户端数
     36                     num= theSocket.Receive mainByteStream
     37                     if num>0 then
     38                     (
     39                         --解码客户端数据
     40                         theString = Encoding.UTF8.GetString(mainByteStream)
     41                         
     42                         print("收到客户端的消息:"+theString)
     43                     
     44                         /*
     45                         for i=1 to 10000000 do
     46                         (
     47                             str="fuck"
     48                         )*/
     49                         --给客户端发送数据*
     50                         fntest()
     51                         print("创建box完成")
     52                         theSocket.Send(Encoding.UTF8.GetBytes("我是主线程"))
     53                     )
     54                     else
     55                     (
     56                         theSocket.Close()
     57                         exit
     58                     )
     59                         
     60                 )
     61             
     62             )
     63             catch
     64             (
     65                 theSocket.Close()
     66                         
     67             )
     68         )
     69     
     70             
     71     )
     72 
     73     Fn  ListenerTasks  = 
     74     (
     75         theTcpListener = DotNetObject "System.Net.Sockets.TcpListener" IPAddress.Any 7456
     76         --承载数据接收
     77         secondaryByteStream = DotNetObject "System.Byte[]" 1024
     78         
     79         theTcpListener.Start()
     80         while true do
     81         (
     82             
     83             try
     84             (
     85                 --获取客户端
     86                 theSocket = theTcpListener.AcceptSocket()
     87                 --与客户端第一次握手
     88                 theSocket.Send(Encoding.UTF8.GetBytes("I am 3dmax"))
     89                 while true do
     90                 (
     91                     --获取客户端数
     92                     num= theSocket.Receive secondaryByteStream
     93                     if num>0 then
     94                     (
     95                         --解码客户端数据
     96                         theString = Encoding.UTF8.GetString(secondaryByteStream)
     97                         print("收到客户端的消息:"+theString)
     98                         --给客户端发送数据
     99                         theSocket.Send(Encoding.UTF8.GetBytes("我辅助线程"))
    100                     )
    101                     else
    102                     (
    103                         theSocket.Close()
    104                         exit
    105                     )
    106                         
    107                 )
    108             
    109             )
    110             catch
    111             (
    112                 theSocket.Close()
    113                         
    114             )
    115         )
    116     
    117             
    118     )
    119     --IP地址
    120     IPAddress = DotNetClass "System.Net.IPAddress"
    121     --定义编码解码对象
    122     Encoding = DotnetClass  "System.Text.Encoding"
    123     
    124     MainThread  = DotNetObject "System.ComponentModel.BackgroundWorker"
    125     DotNet.AddEventHandler MainThread  "DoWork" ExecutionOfTasks
    126     MainThread.WorkerSupportsCancellation = true
    127     --异步运行
    128     MainThread.RunWorkerAsync()
    129     
    130     SecondaryThread  = DotNetObject "System.ComponentModel.BackgroundWorker"
    131     DotNet.AddEventHandler SecondaryThread  "DoWork" ListenerTasks
    132     SecondaryThread.WorkerSupportsCancellation = true
    133     --异步运行
    134     SecondaryThread.RunWorkerAsync()
    135     
    136     
    137     --异步运行
    138 
    139     /*
    140     windows.processPostedMessages()
    141     BackgroundWorker.CancelAsync()
    142     BackgroundWorker.Dispose()
    143     */
    144 )
    ms Socket通讯

    3、使用ms加载dll

    下面的脚本要在max启动的时候执行,建议放在max的安装目录下的ScriptsStartUp

     1 Fn GetDotNetAssemblyByFile dllFileName = 
     2 (
     3     local result
     4     DotNetAssembly = dotNetClass "System.Reflection.Assembly"
     5     
     6     tempFolder = SysInfo.TempDir
     7     sourceFileName = GetFilenameFile dllFileName
     8     tempPrefix = (GenClassID returnValue:true)[1] as string
     9     tempFileName = tempFolder + tempPrefix + sourceFileName + GetFilenameType dllFileName
    10     CopyFile dllFileName tempFileName
    11     result = DotNetAssembly.LoadFile tempFileName
    12     result
    13 )
    14 
    15 DotNetActivator = DotNetClass "System.Activator"
    16 --根据实际路径填写
    17 TestAssembly = GetDotNetAssemblyByFile @"C:Program FilesAutodesk3ds Max 2016scriptsStartupSocketBy3DMAX.dll"
    18 TestClassType = TestAssembly.GetType("SocketTest.SocketServer")
    19 TestClassObject = DotNetActivator.CreateInstance TestClassType
    20 TestClassObject.InitSocket()
    ms加载dll
  • 相关阅读:
    tee & vim
    xml ui
    Maven多模块项目打包前的一些注意事项(打包失败)
    jdk11+ spring5+ 报反射错误的屏蔽方法
    Plugin 'org.springframework.boot:spring-boot-maven-plugin:' not found 用IDEA创建springboot项目的时候遇到的一些坑
    如何在Zynq-7000上烧写PL Image
    python3 使用ssl安全连接发送邮件
    Centos7 启动指定docker容器报错
    Linux下多进程编程
    make的变量及赋值运算
  • 原文地址:https://www.cnblogs.com/he-xiang/p/7993782.html
Copyright © 2020-2023  润新知