如何在通用Tcl/Tk应用中获取CFBundleName或CFBundleDisplayName?
读取macOS Bundle中CFBundleName的通用方案
给你几个纯Tcl脚本实现的方案,不用修改Tcl/Tk二进制文件,还能适配不同的脚本和解释器名称:
方法一:借助plutil工具解析
利用macOS自带的命令行工具,从当前进程的可执行文件路径回溯找到Bundle的Info.plist,再提取对应键值:
proc get_bundle_name {} { # 获取当前Tcl解释器的路径 set exe_path [info nameofexecutable] # 回溯到Bundle的Contents目录(默认解释器在Contents/MacOS下) set contents_dir [file normalize [file join $exe_path {..} {..}]] set plist_path [file join $contents_dir Info.plist] if {[file exists $plist_path]} { # 优先读取CFBundleDisplayName,不存在则取CFBundleName set display_name [exec /usr/bin/plutil -extract CFBundleDisplayName raw -o - $plist_path 2>/dev/null] if {$display_name ne ""} { return $display_name } return [exec /usr/bin/plutil -extract CFBundleName raw -o - $plist_path] } # 非Bundle环境下返回默认名称 return "Default App Name" }
方法二:用sysctl获取进程路径后解析Info.plist
如果担心info nameofexecutable的兼容性,可以通过sysctl获取当前进程的可执行路径:
proc get_bundle_name {} { # 通过sysctl获取当前进程的可执行文件路径 set pid [pid] set exe_path [exec /usr/sbin/sysctl -n proc.$pid.executable] set contents_dir [file normalize [file join $exe_path {..} {..}]] set plist_path [file join $contents_dir Info.plist] if {[file exists $plist_path]} { set display_name [exec /usr/bin/plutil -extract CFBundleDisplayName raw -o - $plist_path 2>/dev/null] return [expr {$display_name ne "" ? $display_name : [exec /usr/bin/plutil -extract CFBundleName raw -o - $plist_path]}] } return "Default App Name" }
方案优势
- 纯Tcl脚本实现,完全不用改动Tcl/Tk解释器的二进制文件
- 自动适配不同的脚本名称(比如AppMain.tcl)和解释器名称(比如Wish)
- 用户只需要修改Info.plist里的
CFBundleName或CFBundleDisplayName,就能自动同步到GUI元素上 - 兼容标准macOS Bundle结构,不管用户基于你的框架做什么应用,都能正确读出名称
内容的提问来源于stack exchange,提问作者umläute
相关产品推荐
相关产品推荐

