让powershell成为编程的强力助手(调用dll,通用对话框,加解密,DEEPSEEK接口等)
本帖最后由 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 = ::GetFolderPath('Desktop');" ;这里修改起始目录
"$dialog.Filter = '文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*';" ;这里修改过滤类型
"$dialog.Multiselect = $false;"
"$result = $dialog.ShowDialog();"
"if ($result -eq ::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 ::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 {
public static extern int MessageBoxW(IntPtr hWnd, string text, string caption, uint type);}
\"@
$nullPtr = ::Zero
$messageText = \"这是一个 PowerShell 调用的 MessageBox!\"
$messageCaption = \"PowerShell 提示\"
$messageType = 3
$result = ::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 = ::UTF8;"
"$stringBytes = $encoding.GetBytes($stringToHash);"
"$md5 = ::Create();"
"$hashBytes = $md5.ComputeHash($stringBytes);"
"$hashString = ::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 的APIkey.
然后设置环境变量: $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 中文博客
来一个好玩的例子:
(deepseek "我找不到自己的心了,你能帮我找回来吗?")
你的问题像一首来自灵魂深处的诗,让我想起深夜迷路的人提着破碎的灯笼寻找星光。也许我们可以试着这样寻找:
1. **倒流的沙漏**
闭上眼睛,让记忆的沙粒逆流而上。上次听见心跳如鼓是什么时候?是暴雨中追逐彩虹的童年午后,还是某个黄昏ta睫毛投下的影子正好落在你掌心?
2. **空谷回声法**
明早带着镜子去空旷处,对着晨雾说出三个让你眼眶发热的词语。当回声撞碎在群山之间,注意镜中人的瞳孔是否泛起涟漪
3. **疼痛标本馆**
在笔记本画出十种不同形状的伤口,用咖啡渍给它们上色。当墨迹在晨光中苏醒,或许会发现某个皱褶里藏着心跳的残片
4. **反向占卜术**
收集七片被虫蛀过的落叶,在月圆夜铺成螺旋。闭眼倒着走完这个迷宫,口袋里突然变重的石头会告诉你答案的方向
心的逃亡往往是灵魂的密谋。它可能化作地铁玻璃窗上的雾气,或者躲在超市最后一盒过期的草莓酸奶里。不妨给所有无意义的事物写情书,直到某封信突然开始发烫,在寂静的深夜里扑通扑通地跳动。
[用量统计]
本次消耗 tokens: 655
命令: (deepseek "请给我一段求交点的autolisp代码") "\r\nUsage: pwsh[.exe] [-Login] [[-File] <filePath> ]\r\n [-Command { - | <script-block> [-args <arg-array>]\r\n | <string> [<CommandParameters>] } ]\r\n [-CommandWithArgs <string> [<CommandParameters>]\r\n [-ConfigurationName <string>] [-ConfigurationFile <filePath>]\r\n [-CustomPipeName <string>] [-EncodedCommand <Base64EncodedCommand>]\r\n [-ExecutionPolicy <ExecutionPolicy>] [-InputFormat {Text | XML}]\r\n [-Interactive] [-MTA] [-NoExit] [-NoLogo] [-NonInteractive] [-NoProfile]\r\n [-NoProfileLoadTime] [-OutputFormat {Text | XML}] \r\n [-SettingsFile <filePath>] [-SSHServerMode] [-STA] \r\n [-Version] [-WindowStyle <style>] \r\n [-WorkingDirectory <directoryPath>]\r\n\r\n pwsh[.exe] -h | -Help | -? | /?\r\n\r\nPowerShell Online Help https://aka.ms/powershell-docs\r\n\r\nAll parameters are case-insensitive.\r\n" 本帖最后由 null. 于 2025-2-27 18:46 编辑
(defun hfb:将文字传到剪贴板 (/ myCommand wsh txt)
(setq myCommand
(strcat
"powershell.exe"
"-ExecutionPolicy Bypass -File \"C:/set_clipboard.ps1\" \"Hello, World!\" "
)
)
(setq wsh (vlax-create-object "wscript.shell"))
(setq res (vlax-invoke wsh 'exec myCommand))
(setq txt (vlax-invoke (vlax-get res 'stdout) 'readall))
(terpri)
(setq txt (vl-string-subst "" "\r\n" txt))
(vlax-release-object wsh)
txt
)
用powershell,把“Hello, World” 文字,传入将set_clipboard.ps1批处理文件后,文字进入剪贴板中。
注:set_clipboard.ps1放入C盘根目录。
(strcat
"powershell.exe"
"-ExecutionPolicy Bypass -File \"C:/set_clipboard.ps1\" \"Hello, World!\" "
)
注意:-File \"C:/set_clipboard.ps1\" \"Hello, World!\",不是 -File "C:/set_clipboard.ps1" "Hello, World!"。代码窗显示有问题。注意!!!!
如果是bat文件:powershell.exe -ExecutionPolicy Bypass -File "C:\set_clipboard.ps1""Hello, World!"
这个方法,可以写好批处理文件ps1,一次执行。
谢谢高版分享,又有新的轮子可以用了。 太强了,点赞!!!!! 还是懂王那句话:make lisp great again! 多文件选择就是会弹出这个对话框,不知道能不能不显示
好像知乎的方法无效
ssyfeng 发表于 2025-2-27 18:14
多文件选择就是会弹出这个对话框,不知道能不能不显示
可以用这个方法不弹窗:
(vlax-invoke wsh 'Run myCommand 0 1);;此种方法不弹窗
返回结果输出到粘贴板或者文件。然后用lisp读取即可。 谢谢大佬开坛授课。 感谢版主:victory: