本帖最后由 highflybird 于 2025-3-1 07:22 编辑
看到论坛上好几篇利用powershell来助力autolisp编程的帖子。这里我也贴出几个例子:
1、利用powershell实现文件选择对话框。
文件选择一直是lisp的缺陷,特别是多文件选择。现在可以通过powershell来实现,下面是代码:
单个文件选择:
 - ;;;单个文件选择对话框
- (defun hfb:fileDlg (/ myCommand wsh txt)
- (setq myCommand
- (strcat
- "powershell.exe -Command " ;这里可能需要powershell.exe全路径
- "Add-Type -AssemblyName System.Windows.Forms;"
- "$dialog = New-Object System.Windows.Forms.OpenFileDialog;"
- "$dialog.Title = '请选择文本文件\';" ;这里修改表标题
- "$dialog.InitialDirectory = [Environment]::GetFolderPath('Desktop');" ;这里修改起始目录
- "$dialog.Filter = '文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*';" ;这里修改过滤类型
- "$dialog.Multiselect = $false;"
- "$result = $dialog.ShowDialog();"
- "if ($result -eq [System.Windows.Forms.DialogResult]::OK) { $dialog.FileName}"
- )
- )
-
- (setq wsh (vlax-create-object "wscript.shell"))
- (setq res (vlax-invoke wsh 'exec myCommand))
- (setq txt (vlax-invoke (vlax-get res 'stdout) 'readall))
- (setq txt (vl-string-subst "" "\r\n" txt))
- (vlax-release-object wsh)
- txt
- )
多个文件选择:
 - ;;;多个文件选择对话框
- (defun hfb:filesDlg (/ myCommand wsh txt lst)
- (setq myCommand
- (strcat
- "powershell.exe -Command "
- "Add-Type -AssemblyName System.Windows.Forms;"
- "$dialog = New-Object System.Windows.Forms.OpenFileDialog;"
- "$dialog.Multiselect = $true;"
- "$dialog.Title = '请选择多个文件\';"
- "$dialog.InitialDirectory = '$HOME\Documents';"
- "$dialog.Filter = '文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*';"
- "$dialogResult = $dialog.ShowDialog();"
- "if ($dialogResult -eq [System.Windows.Forms.DialogResult]::OK) {$selectedFiles = $dialog.FileNames ; $selectedFiles | ForEach-Object {Write-Host $_}}"
- )
- )
-
- (setq wsh (vlax-create-object "wscript.shell"))
- (setq res (vlax-invoke wsh 'exec myCommand))
- (setq txt (vlax-invoke (vlax-get res 'stdout) 'readall))
- (setq lst (mysplit txt "\n"))
- (setq lst (vl-remove "" lst))
- (vlax-release-object wsh)
- lst
- )
- ;;;分割字符串
- (defun mysplit (str delim / lst i len)
- (setq len (strlen delim))
- (setq ch (ascii delim))
- (while (setq i (vl-string-position ch str)) ;(vl-string-search delim str)
- (setq lst (cons (substr str 1 i) lst))
- (setq str (substr str (+ 1 len i)))
- )
- (setq lst (cons str lst))
- (reverse lst)
- )
使用举例:
(hfb:filesDlg)
当然,你可以修改初始目录和过滤类型。
2、调用winAPI或者其它DLL等文件的函数。
能调用系统api或者dll里面的函数,无疑会使得autolisp强大很多。
利用powershell的优势是,不借助内部函数等,不采用其它插件就能完成要求。
注: 如果遇到了” 无法加载文件 xxxx.ps1,因为在此系统上禁止运行脚本。”
处理方案在提示中有,可以通过访问链接查看:https:\go.microsoft.com\fwlink\?LinkID=135170
核心是power shell的安全策略,将 命令视为了不安全脚本,不允许执行。只需要放开权限就行。
我们通过管理员权限运行power shell,然后输入命令
set-ExecutionPolicy RemoteSigned
具体可以查看:
https://zhuanlan.zhihu.com/p/493496089
下面就来一个简单的例子:
 - (defun CallMessageBox (/ wsh file f pscode res txt)
- (setq wsh (vlax-create-object "wscript.shell"))
- (setq file (vl-filename-mktemp "d:\\myapp.ps1"))
- (setq f (open file "w"))
- (princ
- "Add-Type -TypeDefinition @\"
- using System;
- using System.Runtime.InteropServices;
- public class User32 {
- [DllImport(\"user32.dll\", CharSet = CharSet.Unicode)]
- public static extern int MessageBoxW(IntPtr hWnd, string text, string caption, uint type);}
- \"@
- $nullPtr = [IntPtr]::Zero
- $messageText = \"这是一个 PowerShell 调用的 MessageBox!\"
- $messageCaption = \"PowerShell 提示\"
- $messageType = 3
- $result = [User32]::MessageBoxW($nullPtr, $messageText, $messageCaption, $messageType)
- Write-Host $result"
- f
- )
- (close f)
- (setq pscode (strcat "powershell.exe \"" file "\""))
- ;(vlax-invoke wsh 'Run pscode 0 1);;此种方法不弹窗
- (setq res (vlax-invoke wsh 'exec pscode))
- (setq txt (vlax-invoke (vlax-get res 'stdout) 'readall))
- (setq txt (vl-string-subst "" "\n" txt))
- (vlax-release-object wsh)
- (vl-file-delete file)
- txt
- )
;; 调用示例:
(setq result (CallMessageBox))
(princ (strcat "用户选择代码: " result))
既然能调用dll,那还有什么不能完成呢?
3、MD5编码
下面是代码:
 - ;;;获取md5
- (defun hfb:getMD5 (str / myCommand wsh txt)
- (setq myCommand
- (strcat
- "powershell.exe -Command "
- "$stringToHash = '"
- str
- "';"
- "$encoding = [System.Text.Encoding]::UTF8;"
- "$stringBytes = $encoding.GetBytes($stringToHash);"
- "$md5 = [System.Security.Cryptography.MD5]::Create();"
- "$hashBytes = $md5.ComputeHash($stringBytes);"
- "$hashString = [System.BitConverter]::ToString($hashBytes).Replace('-', '').ToLower();"
- "Write-Host $hashString"
- )
- )
-
- (setq wsh (vlax-create-object "wscript.shell"))
- (setq res (vlax-invoke wsh 'exec myCommand))
- (setq txt (vlax-invoke (vlax-get res 'stdout) 'readall))
- (setq txt (vl-string-subst "" "\n" txt))
- (vlax-release-object wsh)
- txt
- )
- (hfb:getMD5 "中文字符测试")
甚至可以对文件等进行md5之类的加密。
4、和DEEPSEEK接口
我们可以利用powershell脚本,把DEEPSEEK接口到CAD里面来;
要达到这个目的,首先确保你已经有了 deepseek 的API key.
然后设置环境变量: $env:DEEPSEEK_API_KEY = 'your-api-key'
另外要保证powershell是7.0以上的。
可以到官网下载最新版本的powershell:
在 Windows 上安装 PowerShell - PowerShell | Microsoft Learn
因为低版本的powershell对转码支持不好,而且似乎这个问题无法解决。deepseek接口是UTF-8的。
 - (defun deepseek (content / wsh file pscode res txt)
- (setq wsh (vlax-create-object "wscript.shell"))
- (setq file "D:/Programming/C/deepseek/deepseek.ps1")
- (setq pscode (strcat "pwsh.exe " file " -prompt '" content "'")) ;一般来说powershell 7.0及以上的程序名为pwsh.exe
- (setq res (vlax-invoke wsh 'exec pscode))
- (setq txt (vlax-invoke (vlax-get res 'stdout) 'readall))
- (vlax-release-object wsh)
- txt
- )
例如: - (deepseek "请给我一段求交点的autolisp代码")
可能要等下,才能看到结果。
如果你把deepseek部署在本地了,估计速度会更快。
附件附上powershell的脚本文件。提醒:记得把文件扩展名改为ps1哦。
注意,我这里选择的是deepseek-reasoner ,AI模型可以选择deepseek-chat.
5、高级对话框
对lisp编程来说,最弱的一块就是其对话框,因为其控件数量少,功能比较单一。
现在有了powershell,就可以助力其 对话框的设计了。
下面是我调用powershell编写的高级对话框,包括了lisp对话框不具备的一些功能:
进度条、定时器、选项卡、右键上下文菜单、菜单、面板容器、数据表格、列表视图、树形结构视图、图像控件、日期控件等等。
使用这些控件无疑极大地丰富和扩充了DCL。
当然你也可以利用powershell做出非模态对话框。
下面是其代码实现:
动画演示如下:
其它有什么好的功能继续补充。
顺便说明一下,现在的AI编程已经很强大了,国产的deepseek更是不输国外的AI。
如果要让powershell实现什么功能,问一下ai,基本能给出答案。
powershell还能为lisp编程做更多事情。下面是一些介绍:
PowerShell脚本:快速入门-CSDN博客
Powershell 编写和运行脚本 – PowerShell 中文博客
|