diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..407f45e --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +# 行尾约定: .bat/.cmd 交给 cmd.exe 解析, 必须是 CRLF —— 裸 LF 会让 cmd 误解析 +# (踩过: 工具写文件默认 LF, 导致 `if not defined X (` 被拆成乱码命令, 批处理直接失败)。 +# 下面显式声明, 避免 checkout 后又被转成 LF。 +*.bat text eol=crlf +*.cmd text eol=crlf +# PowerShell 脚本走 PS 解析, 行尾不敏感, 保持平台默认 +*.ps1 text diff --git a/_start_all.bat b/_start_all.bat index 22ccc6d..706fd4d 100644 --- a/_start_all.bat +++ b/_start_all.bat @@ -27,7 +27,17 @@ start "GenServer" /min "%~dp0bin\GenServer.exe" "%~dp0genserver-local\genserver- ping -n 3 127.0.0.1 >nul echo [4/6] start NX worker ... -start "NXworker" /min "C:\Program Files\Siemens\NX2506\NXBIN\run_journal.exe" "%~dp0sample-data\tools\worker_journal.vb" +rem NX 路径自动探测 (环境变量 ONEBOT_NXBIN > 项目内 nxbin.txt > C:\Program Files\Siemens\NX*) +rem 多版本共存时取版本号最大者, 便于 2506/2512 换机不用改脚本 +set "NXBIN=" +for /f "usebackq delims=" %%i in (`powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0tools\find-nxbin.ps1" -Quiet`) do set "NXBIN=%%i" +if not defined NXBIN ( + echo [WARN] 未找到 NX ^(run_journal.exe^), 跳过 NX worker ^(网页/GenServer 不受影响^) + echo 可手动指定: set ONEBOT_NXBIN=D:\path\to\NXBIN 或写一行到 nxbin.txt +) else ( + echo NX: %NXBIN% + start "NXworker" /min "%NXBIN%\run_journal.exe" "%~dp0sample-data\tools\worker_journal.vb" +) ping -n 3 127.0.0.1 >nul echo [5/6] start web server (port 8080, 后台无窗口) ... diff --git a/tools/find-nxbin.ps1 b/tools/find-nxbin.ps1 new file mode 100644 index 0000000..8d2eb25 --- /dev/null +++ b/tools/find-nxbin.ps1 @@ -0,0 +1,80 @@ +# 探测 Siemens NX 的 NXBIN 目录 (含 run_journal.exe), 供启动脚本调用。 +# 用法: +# powershell -NoProfile -ExecutionPolicy Bypass -File tools\find-nxbin.ps1 # 输出 NXBIN 绝对路径 +# powershell ... -File tools\find-nxbin.ps1 -Quiet # 只输出路径, 失败无输出 +# powershell ... -File tools\find-nxbin.ps1 -Explain # 输出探测过程 +# +# 探测顺序 (先到先用): +# 1. 环境变量 ONEBOT_NXBIN —— 手动指定优先, 便于自定义安装路径 +# 2. 项目内 nxbin.txt (单行路径) —— 便于把结果固化到部署机器 +# 3. C:\Program Files\Siemens\NX*\NXBIN —— 官方默认安装位置, 多版本取版本号最大者 +# +# 退出码: 0 = 找到 (stdout 为路径); 1 = 未找到 (stdout 为空) +param( + [switch]$Quiet, + [switch]$Explain +) + +$ErrorActionPreference = 'SilentlyContinue' +function Say($m) { if (-not $Quiet) { Write-Output $m } } + +function Test-NxBin($dir) { + if ([string]::IsNullOrWhiteSpace($dir)) { return $false } + return Test-Path (Join-Path $dir 'run_journal.exe') +} + +# 1) 环境变量 +$env_dir = $env:ONEBOT_NXBIN +if ($env_dir) { + Say ("[1] 环境变量 ONEBOT_NXBIN = " + $env_dir) + if (Test-NxBin $env_dir) { Write-Output $env_dir; exit 0 } + Say " 该目录下没有 run_journal.exe, 继续探测" +} else { + Say "[1] 环境变量 ONEBOT_NXBIN 未设置" +} + +# 2) 项目内 nxbin.txt +$root = Split-Path $PSScriptRoot -Parent +$cfg = Join-Path $root 'nxbin.txt' +if (Test-Path $cfg) { + $line = (Get-Content $cfg -TotalCount 1) + if ($line) { $line = $line.Trim() } + Say ("[2] nxbin.txt = " + $line) + if (Test-NxBin $line) { Write-Output $line; exit 0 } + Say " 该目录下没有 run_journal.exe, 继续探测" +} else { + Say "[2] 无 nxbin.txt" +} + +# 3) 扫描官方安装位置 (多版本取版本号最大的) +$roots = @( + (Join-Path ${env:ProgramFiles} 'Siemens'), + (Join-Path ${env:ProgramFiles(x86)} 'Siemens'), + 'C:\Program Files\Siemens' +) | Where-Object { $_ -and (Test-Path $_) } | Select-Object -Unique + +$cands = @() +foreach ($r in $roots) { + Say ("[3] 扫描 " + $r) + foreach ($ver in (Get-ChildItem $r -Directory -Filter 'NX*' -ErrorAction SilentlyContinue)) { + $bin = Join-Path $ver.FullName 'NXBIN' + if (Test-NxBin $bin) { + $cands += $bin + Say (" 找到 " + $bin) + } + } +} + +if ($cands.Count -gt 0) { + # 按 NX 后面的版本号排序取最大 (如 NX2506 < NX2512); 无版本号的排最后 + $best = $cands | Sort-Object { + $m = [regex]::Match($_, 'NX(\d+)') + if ($m.Success) { [long]$m.Groups[1].Value } else { 0 } + } -Descending | Select-Object -First 1 + Write-Output $best + exit 0 +} + +Say "未找到 NX (含 run_journal.exe 的 NXBIN 目录)" +Say "可手动指定: set ONEBOT_NXBIN=D:\path\to\NXBIN 或 写一行到 nxbin.txt" +exit 1 diff --git a/tools/fix-lineend.ps1 b/tools/fix-lineend.ps1 new file mode 100644 index 0000000..63c1013 --- /dev/null +++ b/tools/fix-lineend.ps1 @@ -0,0 +1,36 @@ +# 把 .bat/.cmd 的行尾统一为 CRLF —— cmd.exe 必须用 CRLF, 裸 LF 会让它误解析。 +# 症状: `if not defined X (` 被拆成 `'ned' 不是内部或外部命令` 之类的乱码报错。 +# 触发场景: 用工具/编辑器写 .bat 时默认写成 LF (本项目踩过)。 +# +# 幂等: 已是 CRLF 的文件不会被改动。 +# 用法: +# powershell -NoProfile -ExecutionPolicy Bypass -File tools\fix-lineend.ps1 # 处理项目根 + tools 下全部 .bat/.cmd +# powershell ... -File tools\fix-lineend.ps1 -Files "a.bat","b.cmd" # 只处理指定文件 +param([string[]]$Files) + +if (-not $Files) { + $root = Split-Path $PSScriptRoot -Parent + $Files = @() + $Files += Get-ChildItem (Join-Path $root '*.bat') -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName } + $Files += Get-ChildItem (Join-Path $root '*.cmd') -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName } + $Files += Get-ChildItem (Join-Path $PSScriptRoot '*.bat') -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName } + $Files += Get-ChildItem (Join-Path $PSScriptRoot '*.cmd') -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName } +} + +foreach ($f in $Files) { + if (-not (Test-Path $f)) { Write-Output ("跳过(不存在): " + $f); continue } + $bytes = [System.IO.File]::ReadAllBytes($f) + # 统一成 CRLF: 先把 CRLF 归一为 LF, 再把 LF 展开为 CRLF + $text = [System.Text.Encoding]::UTF8.GetString($bytes) + $text = $text -replace "`r`n", "`n" + $text = $text -replace "`r", "`n" + $new = $text -replace "`n", "`r`n" + if ($new -eq [System.Text.Encoding]::UTF8.GetString($bytes)) { + Write-Output ("已是 CRLF: " + (Split-Path $f -Leaf)) + } else { + # 不加 BOM (cmd 对 BOM 敏感, 且 .bat 无需 BOM) + $enc = New-Object System.Text.UTF8Encoding($false) + [System.IO.File]::WriteAllText($f, $new, $enc) + Write-Output ("已修正为 CRLF: " + (Split-Path $f -Leaf)) + } +}