====== Strata Tray: значок в трее для запуска и остановки Strata (Windows) ======
===== Введение =====
**Strata Tray** — маленькая программа для Windows, которая висит в трее (возле часов) и:
* показывает статус локального сервера Strata цветом значка;
* по **правому клику** даёт меню **Запустить / Остановить**;
* запускается вместе с Windows (модель при этом **не** запускается — только значок);
* показывает уведомления: «Strata запущена», «остановлена», «не запустилась» с последними строками журнала, а также если сервер неожиданно упал.
Написана на PowerShell + WinForms: ничего доустанавливать не нужно. Работает поверх пресета Strata из инструкции [[:truenas:application:strata_qwen_goose|Qwen3.8-Flash-Next на Strata + Goose Desktop]].
===== Требования =====
* Windows 10/11, Windows PowerShell 5.1 (есть в системе).
* Установленная Strata (''%LOCALAPPDATA%\Strata\terminal\current\bin\strata.cmd'').
* Сохранённый пресет Strata — по умолчанию ''Goose IQ3_S official 8081'' (порт 8081).
===== Как это выглядит =====
^ Значок ^ Состояние ^
| зелёный «S» | Strata работает, модель загружена |
| жёлтый «S» | запускается / загружает модель / останавливается |
| серый «S» | остановлена |
Подсказка при наведении: ''Strata: работает · порт 8081''. Двойной клик — уведомление с моделью, адресом API и размером контекста.
Меню по правому клику:
Strata: работает (статус)
qwen3.8-flash-next-iq3_s · http://127.0.0.1:8081
───────────────
Запустить (активно, когда Strata остановлена)
Остановить (активно, когда Strata работает)
───────────────
Монитор Strata (strata monitor в окне консоли)
Журнал запуска/остановки (actions.log в Блокноте)
Папка логов движка
───────────────
✓ Запускать вместе с Windows (включить/выключить автозапуск)
Выход (Strata продолжит работать)
===== Как работает =====
* Каждые 5 секунд запрашивает ''http://127.0.0.1:8081/v1/models''. Ответ со статусом ''loaded'' — «работает»; сервер не отвечает — «остановлена». Ответ 401/403 (включён API-ключ) тоже считается «работает».
* **Запустить** выполняет в скрытом окне: ''strata launch --preset "Goose IQ3_S official 8081" --no-tui'' (загрузка ~1 минута).
* **Остановить**: ''strata launch --stop --preset "Goose IQ3_S official 8081"'' — освобождает VRAM и ~50 GB RAM.
* Весь вывод этих команд дописывается в ''%LOCALAPPDATA%\StrataTray\actions.log''.
* Автозапуск — ярлык ''Strata Tray.lnk'' в папке «Автозагрузка» (''shell:startup''), он запускает ''wscript.exe StrataTray.vbs'', а тот — PowerShell без окна консоли.
* Запущена только одна копия (повторный запуск ничего не делает).
* **Выход** закрывает только значок, сама Strata продолжает работать.
===== Шаг 1: Файлы программы =====
Создайте папку, например ''F:\projects\inst\strata-tray'', и сохраните в неё четыре файла ниже (у каждого блока кода есть ссылка для скачивания — имя файла над блоком) плюс ''settings.json''.
**Важно:** Windows PowerShell 5.1 читает ''.ps1'' без BOM в кодировке ANSI, и русские строки превращаются в кракозябры. После скачивания пересохраните ''.ps1'' в UTF-8 **с BOM** (в Блокноте: «Сохранить как» → кодировка «UTF-8 с BOM») или выполните в папке с файлами:
Get-ChildItem *.ps1 | ForEach-Object { $t = [IO.File]::ReadAllText($_.FullName, [Text.Encoding]::UTF8); [IO.File]::WriteAllText($_.FullName, $t, (New-Object Text.UTF8Encoding($true))) }
==== settings.json — настройки ====
{
"Preset": "Goose IQ3_S official 8081",
"Port": 8081,
"PollSeconds": 5
}
* ''Preset'' — имя пресета Strata (список: ''strata launch --list-presets'').
* ''Port'' — порт API этого пресета.
* ''PollSeconds'' — как часто проверять статус.
После установки настройки лежат в ''%LOCALAPPDATA%\StrataTray\app\settings.json''; после правки — «Выход» в меню значка и запустить снова (или перезагрузить ПК).
==== StrataTray.ps1 — основная программа ====
# Strata Tray: значок в трее, который показывает статус Strata и запускает/останавливает её.
# Запуск без окна: StrataTray.vbs. Проверка без интерфейса: StrataTray.ps1 -SelfTest [-Cycle]
param(
[switch]$SelfTest, # вывести статус в консоль и выйти
[switch]$Cycle # вместе с -SelfTest: остановить и снова запустить Strata теми же командами, что и меню
)
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# ---------- настройки ----------
$AppDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$Cfg = @{ Preset = 'Goose IQ3_S official 8081'; Port = 8081; PollSeconds = 5 }
$CfgPath = Join-Path $AppDir 'settings.json'
if (Test-Path $CfgPath) {
try {
$j = Get-Content $CfgPath -Raw -Encoding UTF8 | ConvertFrom-Json
foreach ($p in $j.PSObject.Properties) { $Cfg[$p.Name] = $p.Value }
} catch { }
}
$Strata = Join-Path $env:LOCALAPPDATA 'Strata\terminal\current\bin\strata.cmd'
$BaseUrl = "http://127.0.0.1:$($Cfg.Port)"
$DataDir = Join-Path $env:LOCALAPPDATA 'StrataTray'
$ActionLog = Join-Path $DataDir 'actions.log'
$EngineLogDir = Join-Path $env:LOCALAPPDATA 'Strata\launch'
$StartupLnk = Join-Path ([Environment]::GetFolderPath('Startup')) 'Strata Tray.lnk'
New-Item -ItemType Directory -Force $DataDir | Out-Null
# ---------- состояние ----------
$script:Proc = $null # процесс strata launch / --stop, который сейчас выполняется
$script:Pending = $null # 'start' | 'stop' | $null
$script:LastState = $null # 'running' | 'loading' | 'stopped' | 'starting' | 'stopping'
$script:LastStatus = @{ Up = $false }
function Write-ActionLog([string]$text) {
try { Add-Content -Path $ActionLog -Value $text -Encoding UTF8 } catch { }
}
function Get-StrataStatus {
try {
$req = [System.Net.HttpWebRequest]::Create("$BaseUrl/v1/models")
$req.Timeout = 2000; $req.ReadWriteTimeout = 2000; $req.Proxy = $null
$resp = $req.GetResponse()
try {
$body = (New-Object IO.StreamReader($resp.GetResponseStream())).ReadToEnd()
} finally { $resp.Close() }
$m = ($body | ConvertFrom-Json).data | Select-Object -First 1
return @{ Up = $true; Model = $m.id; Loaded = ($m.status.value -eq 'loaded'); Ctx = $m.meta.n_ctx }
} catch {
$e = $_.Exception
while ($e -and -not ($e -is [System.Net.WebException])) { $e = $e.InnerException }
if ($e -and $e.Response) {
# сервер ответил ошибкой HTTP (например 401 при включённом API-ключе) — значит он работает
return @{ Up = $true; Model = '?'; Loaded = $true; Ctx = $null }
}
return @{ Up = $false }
}
}
function Start-StrataCommand([string]$argLine, [string]$kind) {
if (-not (Test-Path $Strata)) { return "Не найден $Strata — Strata не установлена?" }
Write-ActionLog "`r`n==== $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') ${kind}: strata $argLine"
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $env:ComSpec
$psi.Arguments = '/d /c ""' + $Strata + '" ' + $argLine + ' >> "' + $ActionLog + '" 2>&1"'
$psi.UseShellExecute = $false
$psi.CreateNoWindow = $true
$script:Proc = [System.Diagnostics.Process]::Start($psi)
$script:Pending = $kind
return $null
}
function Start-Strata { Start-StrataCommand ('launch --preset "' + $Cfg.Preset + '" --no-tui') 'start' }
function Stop-Strata { Start-StrataCommand ('launch --stop --preset "' + $Cfg.Preset + '"') 'stop' }
function Get-LogTail([int]$n = 4) {
try {
$lines = Get-Content $ActionLog -Tail 40 -Encoding UTF8 | Where-Object { $_.Trim() }
return (($lines | Select-Object -Last $n) -join "`n")
} catch { return '' }
}
function Set-Autostart([bool]$on) {
if ($on) {
$sh = New-Object -ComObject WScript.Shell
$l = $sh.CreateShortcut($StartupLnk)
$l.TargetPath = Join-Path $env:WINDIR 'System32\wscript.exe'
$l.Arguments = '"' + (Join-Path $AppDir 'StrataTray.vbs') + '"'
$l.WorkingDirectory = $AppDir
$l.Description = 'Strata Tray — статус и запуск Strata'
$l.Save()
} elseif (Test-Path $StartupLnk) {
Remove-Item $StartupLnk -Force
}
}
# ---------- режим проверки без интерфейса ----------
if ($SelfTest) {
function Wait-Proc { while ($script:Proc -and -not $script:Proc.HasExited) { Start-Sleep -Milliseconds 500 }; " код выхода: $($script:Proc.ExitCode)" }
$s = Get-StrataStatus
"Статус: Up=$($s.Up) Model=$($s.Model) Loaded=$($s.Loaded) Ctx=$($s.Ctx) ($BaseUrl, пресет '$($Cfg.Preset)')"
"Автозапуск: $(Test-Path $StartupLnk) ($StartupLnk)"
if ($Cycle) {
"Остановка..."; $err = Stop-Strata; if ($err) { $err; exit 1 }; Wait-Proc
$s = Get-StrataStatus; " после остановки: Up=$($s.Up)"
"Запуск..."; $t0 = Get-Date; $err = Start-Strata; if ($err) { $err; exit 1 }; Wait-Proc
$s = Get-StrataStatus; " после запуска: Up=$($s.Up) Loaded=$($s.Loaded) за $([int]((Get-Date) - $t0).TotalSeconds) с"
"Хвост журнала:"; Get-LogTail 6
}
exit 0
}
# ---------- один экземпляр ----------
$created = $false
$script:Mutex = New-Object System.Threading.Mutex($true, 'Local\StrataTray', [ref]$created)
if (-not $created) { exit 0 }
# ---------- значки ----------
function New-StatusIcon([System.Drawing.Color]$color) {
$size = 32
$bmp = New-Object System.Drawing.Bitmap($size, $size)
$g = [System.Drawing.Graphics]::FromImage($bmp)
$g.SmoothingMode = 'AntiAlias'
$g.TextRenderingHint = 'AntiAliasGridFit'
$g.FillEllipse((New-Object System.Drawing.SolidBrush($color)), 1, 1, $size - 2, $size - 2)
$g.DrawEllipse((New-Object System.Drawing.Pen([System.Drawing.Color]::FromArgb(90, 0, 0, 0), 1.5)), 1, 1, $size - 3, $size - 3)
$font = New-Object System.Drawing.Font('Segoe UI', 17, [System.Drawing.FontStyle]::Bold, [System.Drawing.GraphicsUnit]::Pixel)
$fmt = New-Object System.Drawing.StringFormat
$fmt.Alignment = 'Center'; $fmt.LineAlignment = 'Center'
$g.DrawString('S', $font, [System.Drawing.Brushes]::White, (New-Object System.Drawing.RectangleF(0, 1, $size, $size)), $fmt)
$g.Dispose()
return [System.Drawing.Icon]::FromHandle($bmp.GetHicon())
}
$Icons = @{
running = New-StatusIcon ([System.Drawing.Color]::FromArgb(46, 160, 67)) # зелёный
starting = New-StatusIcon ([System.Drawing.Color]::FromArgb(212, 160, 23)) # жёлтый
loading = New-StatusIcon ([System.Drawing.Color]::FromArgb(212, 160, 23))
stopping = New-StatusIcon ([System.Drawing.Color]::FromArgb(212, 160, 23))
stopped = New-StatusIcon ([System.Drawing.Color]::FromArgb(128, 128, 128)) # серый
}
$StateText = @{
running = 'работает'
loading = 'загружает модель'
starting = 'запускается…'
stopping = 'останавливается…'
stopped = 'остановлена'
}
# ---------- значок и меню ----------
$Notify = New-Object System.Windows.Forms.NotifyIcon
$Notify.Icon = $Icons.stopped
$Notify.Text = 'Strata: проверка…'
$Notify.Visible = $true
$Menu = New-Object System.Windows.Forms.ContextMenuStrip
$miStatus = $Menu.Items.Add('Strata: проверка…'); $miStatus.Enabled = $false
$miModel = $Menu.Items.Add(''); $miModel.Enabled = $false
[void]$Menu.Items.Add('-')
$miStart = $Menu.Items.Add('Запустить')
$miStop = $Menu.Items.Add('Остановить')
[void]$Menu.Items.Add('-')
$miMonitor = $Menu.Items.Add('Монитор Strata')
$miLog = $Menu.Items.Add('Журнал запуска/остановки')
$miEngine = $Menu.Items.Add('Папка логов движка')
[void]$Menu.Items.Add('-')
$miAuto = New-Object System.Windows.Forms.ToolStripMenuItem('Запускать вместе с Windows')
$miAuto.CheckOnClick = $true
$miAuto.Checked = (Test-Path $StartupLnk)
[void]$Menu.Items.Add($miAuto)
$miExit = $Menu.Items.Add('Выход (Strata продолжит работать)')
$miStart.Font = New-Object System.Drawing.Font($miStart.Font, [System.Drawing.FontStyle]::Bold)
$Notify.ContextMenuStrip = $Menu
function Show-Balloon([string]$title, [string]$text, [string]$kind = 'Info') {
if (-not $text) { $text = ' ' }
$Notify.ShowBalloonTip(5000, $title, $text, [System.Windows.Forms.ToolTipIcon]::$kind)
}
function Update-Ui {
try {
$s = Get-StrataStatus
$script:LastStatus = $s
# завершилась команда запуска/остановки
if ($script:Pending -and $script:Proc -and $script:Proc.HasExited) {
$code = $script:Proc.ExitCode
if ($script:Pending -eq 'start') {
if ($s.Up) { Show-Balloon 'Strata запущена' "$($s.Model) — $BaseUrl" }
else { Show-Balloon "Strata не запустилась (код $code)" (Get-LogTail 3) 'Error' }
} else {
if (-not $s.Up) { Show-Balloon 'Strata остановлена' 'Видеопамять и RAM освобождены' }
else { Show-Balloon "Strata не остановилась (код $code)" (Get-LogTail 3) 'Warning' }
}
$script:Pending = $null
$script:Proc = $null
}
$state = if ($script:Pending -eq 'start') { 'starting' }
elseif ($script:Pending -eq 'stop') { 'stopping' }
elseif ($s.Up -and $s.Loaded) { 'running' }
elseif ($s.Up) { 'loading' }
else { 'stopped' }
# неожиданная остановка (упала или остановлена из консоли)
if ($script:LastState -eq 'running' -and $state -eq 'stopped') {
Show-Balloon 'Strata остановилась' 'Сервер больше не отвечает' 'Warning'
}
$script:LastState = $state
$Notify.Icon = $Icons[$state]
$tip = "Strata: $($StateText[$state])"
if ($s.Up -and $s.Model) { $tip += " · порт $($Cfg.Port)" }
$Notify.Text = if ($tip.Length -gt 63) { $tip.Substring(0, 63) } else { $tip }
$miStatus.Text = "Strata: $($StateText[$state])"
$miModel.Text = if ($s.Up) { "$($s.Model) · $BaseUrl" } else { "пресет: $($Cfg.Preset)" }
$busy = [bool]$script:Pending
$miStart.Enabled = (-not $busy) -and (-not $s.Up)
$miStop.Enabled = (-not $busy) -and $s.Up
$miAuto.Checked = (Test-Path $StartupLnk)
} catch {
Write-ActionLog "[tray] ошибка обновления: $($_.Exception.Message)"
}
}
$miStart.add_Click({
$err = Start-Strata
if ($err) { Show-Balloon 'Strata' $err 'Error' } else { Show-Balloon 'Strata' 'Запуск… загрузка модели занимает около минуты' }
Update-Ui
})
$miStop.add_Click({
$err = Stop-Strata
if ($err) { Show-Balloon 'Strata' $err 'Error' }
Update-Ui
})
$miMonitor.add_Click({
if (Test-Path $Strata) {
Start-Process -FilePath $env:ComSpec -ArgumentList ('/k ""' + $Strata + '" monitor --url ' + $BaseUrl + '"')
}
})
$miLog.add_Click({
if (-not (Test-Path $ActionLog)) { Write-ActionLog '' }
Start-Process notepad.exe -ArgumentList ('"' + $ActionLog + '"')
})
$miEngine.add_Click({ if (Test-Path $EngineLogDir) { Start-Process explorer.exe -ArgumentList ('"' + $EngineLogDir + '"') } })
$miAuto.add_Click({
try { Set-Autostart $miAuto.Checked } catch { Show-Balloon 'Strata Tray' "Не удалось изменить автозапуск: $($_.Exception.Message)" 'Error' }
$miAuto.Checked = (Test-Path $StartupLnk)
})
$miExit.add_Click({
$Timer.Stop()
$Notify.Visible = $false
$Notify.Dispose()
[System.Windows.Forms.Application]::Exit()
})
$Notify.add_DoubleClick({
$s = $script:LastStatus
if ($s.Up) { Show-Balloon "Strata: $($StateText[$script:LastState])" "$($s.Model)`n$BaseUrl/v1 · контекст $($s.Ctx)" }
else { Show-Balloon "Strata: $($StateText[$script:LastState])" "Пресет: $($Cfg.Preset)`nПравый клик → Запустить" }
})
$Menu.add_Opening({ Update-Ui })
$Timer = New-Object System.Windows.Forms.Timer
$Timer.Interval = [int]$Cfg.PollSeconds * 1000
$Timer.add_Tick({ Update-Ui })
$Timer.Start()
Update-Ui
[System.Windows.Forms.Application]::Run()
$script:Mutex.ReleaseMutex()
==== StrataTray.vbs — запуск без окна консоли ====
' Runs StrataTray.ps1 without a console window (used by the autostart shortcut).
Set fso = CreateObject("Scripting.FileSystemObject")
dir = fso.GetParentFolderName(WScript.ScriptFullName)
CreateObject("WScript.Shell").Run "powershell.exe -NoProfile -ExecutionPolicy Bypass -STA -WindowStyle Hidden -File """ & dir & "\StrataTray.ps1""", 0, False
==== install.ps1 — установка и автозапуск ====
# Установка Strata Tray: копирует программу в %LOCALAPPDATA%\StrataTray\app, включает автозапуск и запускает значок.
# Запуск: powershell -ExecutionPolicy Bypass -File install.ps1
$ErrorActionPreference = 'Stop'
$src = Split-Path -Parent $MyInvocation.MyCommand.Path
$dst = Join-Path $env:LOCALAPPDATA 'StrataTray\app'
$lnk = Join-Path ([Environment]::GetFolderPath('Startup')) 'Strata Tray.lnk'
# остановить уже запущенный значок
Get-CimInstance Win32_Process -Filter "Name='powershell.exe'" |
Where-Object { $_.CommandLine -like '*StrataTray.ps1*' } |
ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
New-Item -ItemType Directory -Force $dst | Out-Null
Copy-Item (Join-Path $src 'StrataTray.ps1'), (Join-Path $src 'StrataTray.vbs') $dst -Force
if (-not (Test-Path (Join-Path $dst 'settings.json'))) { Copy-Item (Join-Path $src 'settings.json') $dst }
$sh = New-Object -ComObject WScript.Shell
$l = $sh.CreateShortcut($lnk)
$l.TargetPath = Join-Path $env:WINDIR 'System32\wscript.exe'
$l.Arguments = '"' + (Join-Path $dst 'StrataTray.vbs') + '"'
$l.WorkingDirectory = $dst
$l.Description = 'Strata Tray — статус и запуск Strata'
$l.Save()
Start-Process (Join-Path $env:WINDIR 'System32\wscript.exe') -ArgumentList ('"' + (Join-Path $dst 'StrataTray.vbs') + '"')
Write-Host "Установлено в $dst"
Write-Host "Автозапуск: $lnk"
Write-Host 'Значок S появится в трее (может быть скрыт под стрелкой ^).'
==== uninstall.ps1 — удаление ====
# Удаление Strata Tray (сама Strata и модель не затрагиваются).
$app = Join-Path $env:LOCALAPPDATA 'StrataTray'
$lnk = Join-Path ([Environment]::GetFolderPath('Startup')) 'Strata Tray.lnk'
Get-CimInstance Win32_Process -Filter "Name='powershell.exe'" |
Where-Object { $_.CommandLine -like '*StrataTray.ps1*' } |
ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
if (Test-Path $lnk) { Remove-Item $lnk -Force }
if (Test-Path $app) { Remove-Item $app -Recurse -Force }
Write-Host 'Strata Tray удалён. Strata не остановлена и не удалена.'
===== Шаг 2: Установка =====
В PowerShell, в папке с файлами:
powershell -NoProfile -ExecutionPolicy Bypass -File .\install.ps1
Установлено в C:\Users\<пользователь>\AppData\Local\StrataTray\app
Автозапуск: C:\Users\<пользователь>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\Strata Tray.lnk
Значок S появится в трее (может быть скрыт под стрелкой ^).
Установщик:
- останавливает уже запущенный значок (если был);
- копирует ''StrataTray.ps1'' и ''StrataTray.vbs'' в ''%LOCALAPPDATA%\StrataTray\app'' (''settings.json'' — только если его там ещё нет, ваши настройки не затираются);
- создаёт ярлык автозапуска;
- запускает значок.
Чтобы значок всегда был виден, а не прятался под стрелкой: Параметры → Персонализация → Панель задач → Другие значки в области уведомлений → включить ''Windows PowerShell'' (значок запускается от имени PowerShell).
===== Шаг 3: Проверка без интерфейса =====
Режим самопроверки печатает статус в консоль (Strata не трогается):
powershell -NoProfile -ExecutionPolicy Bypass -File "$env:LOCALAPPDATA\StrataTray\app\StrataTray.ps1" -SelfTest
Статус: Up=True Model=qwen3.8-flash-next-iq3_s Loaded=True Ctx=131072 (http://127.0.0.1:8081, пресет 'Goose IQ3_S official 8081')
Автозапуск: True (C:\Users\...\Startup\Strata Tray.lnk)
С ключом ''-Cycle'' программа **останавливает и снова запускает Strata** теми же командами, что и меню (проверено: остановка — код 0, запуск — код 0, модель ответила через 66 с):
powershell -NoProfile -ExecutionPolicy Bypass -File "$env:LOCALAPPDATA\StrataTray\app\StrataTray.ps1" -SelfTest -Cycle
===== Удаление =====
powershell -NoProfile -ExecutionPolicy Bypass -File .\uninstall.ps1
Удаляет ярлык автозапуска и папку ''%LOCALAPPDATA%\StrataTray''. Strata и модель не затрагиваются.
===== Проблемы и решения =====
==== Значок не появился ====
* Посмотрите под стрелкой ''^'' в трее.
* Проверьте, что процесс запущен:
Get-CimInstance Win32_Process -Filter "Name='powershell.exe'" | Where-Object { $_.CommandLine -like '*StrataTray.ps1*' } | Select-Object ProcessId
* Запустите вручную с окном, чтобы увидеть ошибку:
powershell -NoProfile -ExecutionPolicy Bypass -STA -File "$env:LOCALAPPDATA\StrataTray\app\StrataTray.ps1"
==== Русские надписи — кракозябры ====
Файл ''.ps1'' сохранён без BOM — см. «Шаг 1», пересохраните в UTF-8 с BOM.
==== «Strata не запустилась» ====
Откройте «Журнал запуска/остановки» в меню — там полный вывод ''strata launch''. Частые причины: порт занят другим процессом, не хватает свободной RAM (закройте тяжёлые программы), неверное имя пресета в ''settings.json''. Подробнее — раздел «Проблемы и решения» на странице [[:truenas:application:strata_qwen_goose|Strata + Goose]].
==== Сменил модель / пресет ====
Поменяйте ''Preset'' и ''Port'' в ''%LOCALAPPDATA%\StrataTray\app\settings.json'', затем «Выход» в меню значка и запустите заново:
wscript.exe "$env:LOCALAPPDATA\StrataTray\app\StrataTray.vbs"
===== Шпаргалка =====
^ Что ^ Где ^
| Программа | ''%LOCALAPPDATA%\StrataTray\app\'' |
| Настройки | ''%LOCALAPPDATA%\StrataTray\app\settings.json'' |
| Журнал запуска/остановки | ''%LOCALAPPDATA%\StrataTray\actions.log'' |
| Автозапуск | ''shell:startup\Strata Tray.lnk'' |
| Исходники | ''F:\projects\inst\strata-tray\'' |