跳转到主要内容

让powershell成为编程的强力助手

主标签

此文最早发表于明经论坛上:

让powershell成为编程的强力助手(调用dll,通用对话框,加解密,DEEPSEEK接口等) 

看到论坛上好几篇利用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.txt (2.41 KB)

注意,我这里选择的是deepseek-reasoner ,AI模型可以选择deepseek-chat.

5、高级对话框

对lisp编程来说,最弱的一块就是其对话框,因为其控件数量少,功能比较单一。
现在有了powershell,就可以助力其 对话框的设计了。
下面是我调用powershell编写的高级对话框,包括了lisp对话框不具备的一些功能:
进度条、定时器、选项卡、右键上下文菜单、菜单、面板容器、数据表格、列表视图、树形结构视图、图像控件、日期控件等等。
使用这些控件无疑极大地丰富和扩充了DCL。
当然你也可以利用powershell做出非模态对话框。
下面是其代码实现:

文档

注意记得改后缀名为lsp。
动画演示如下:

高级对话框

其它有什么好的功能继续补充。

顺便说明一下,现在的AI编程已经很强大了,国产的deepseek更是不输国外的AI。
如果要让powershell实现什么功能,问一下ai,基本能给出答案。

powershell还能为lisp编程做更多事情。下面是一些介绍:
PowerShell脚本:快速入门-CSDN博客
Powershell 编写和运行脚本 – PowerShell 中文博客