install software and make configurations

This commit is contained in:
Julian Freeman
2025-12-05 22:46:17 -04:00
commit 58f026f30f
14 changed files with 796 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
[General]
ConfigVersion=1
UpdateCheckMessageShown=true
RememberLastDatabases=false
RememberLastKeyFiles=false
OpenPreviousDatabasesOnStartup=false
[GUI]
CheckForUpdates=false
TrayIconAppearance=monochrome
[Security]
ClearClipboardTimeout=30
LockDatabaseIdle=true
LockDatabaseIdleSeconds=600

Binary file not shown.

View File

@@ -0,0 +1,274 @@
<?xml version="1.0" encoding="UTF-8"?>
<oor:items xmlns:oor="http://openoffice.org/2001/registry"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="initials" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="sn" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="givenname" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="o" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="street" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="c" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="postalcode" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="l" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="title" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="position" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="facsimiletelephonenumber" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="homephone" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="telephonenumber" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="mail" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.UserProfile/Data">
<prop oor:name="st" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.Setup/L10N">
<prop oor:name="ooLocale" oor:op="fuse">
<value>zh-CN</value>
</prop>
</item>
<item oor:path="/org.openoffice.Setup/Office">
<prop oor:name="FirstStartWizardCompleted" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item
oor:path="/org.openoffice.Setup/Office/Factories/org.openoffice.Setup:Factory['com.sun.star.frame.StartModule']">
<prop oor:name="ooSetupFactoryWindowAttributes" oor:op="fuse">
<value>190,213,1424,714;1;0,0,0,0;</value>
</prop>
</item>
<item oor:path="/org.openoffice.Setup/Office">
<prop oor:name="ooSetupInstCompleted" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Setup/Office">
<prop oor:name="LastCompatibilityCheckID" oor:op="fuse">
<value>4116m3(Build:9816)</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/History">
<prop oor:name="PickListSize" oor:op="fuse">
<value>0</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/I18N/CJK">
<prop oor:name="Ruby" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/I18N/CJK">
<prop oor:name="VerticalCallOut" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/I18N/CJK">
<prop oor:name="JapaneseFind" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/I18N/CJK">
<prop oor:name="EmphasisMarks" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/I18N/CJK">
<prop oor:name="VerticalText" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/I18N/CJK">
<prop oor:name="DoubleLines" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/I18N/CJK">
<prop oor:name="ChangeCaseMap" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/I18N/CJK">
<prop oor:name="CJKFont" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/I18N/CJK">
<prop oor:name="AsianTypography" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Internal">
<prop oor:name="CurrentTempURL" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Misc">
<prop oor:name="PluginsEnabled" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Misc">
<prop oor:name="SymbolSet" oor:op="fuse">
<value>0</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Misc">
<prop oor:name="SymbolStyle" oor:op="fuse">
<value>auto</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Misc">
<prop oor:name="ToolboxStyle" oor:op="fuse">
<value>1</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Misc">
<prop oor:name="UseSystemFileDialog" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Misc">
<prop oor:name="FirstRun" oor:op="fuse">
<value>false</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Misc">
<prop oor:name="UseSystemPrintDialog" oor:op="fuse">
<value>false</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="Confirmation" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="DisableMacrosExecution" oor:op="fuse">
<value>false</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="ExecutePlugins" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="WarnCreatePDF" oor:op="fuse">
<value>false</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="HyperlinksWithCtrlClick" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="MacroSecurityLevel" oor:op="fuse">
<value>2</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="WarnSignDoc" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="OfficeBasic" oor:op="fuse">
<value>1</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="SecureURL" oor:op="fuse">
<value></value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="RecommendPasswordProtection" oor:op="fuse">
<value>false</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="RemovePersonalInfoOnSaving" oor:op="fuse">
<value>true</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="WarnPrintDoc" oor:op="fuse">
<value>false</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="WarnSaveOrSendDoc" oor:op="fuse">
<value>false</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Common/Security/Scripting">
<prop oor:name="Warning" oor:op="fuse">
<value>false</value>
</prop>
</item>
<item oor:path="/org.openoffice.Office.Views/Dialogs">
<node oor:name="17015" oor:op="replace">
<node oor:name="UserData"></node>
<prop oor:name="WindowState" oor:op="fuse">
<value>565,335,,;;,,,;</value>
</prop>
</node>
</item>
</oor:items>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<VeraCrypt>
<configuration>
<config key="OpenExplorerWindowAfterMount">0</config>
<config key="UseDifferentTrayIconIfVolumesMounted">1</config>
<config key="SaveVolumeHistory">0</config>
<config key="CachePasswords">0</config>
<config key="CachePasswordDuringMultipleMount">0</config>
<config key="WipePasswordCacheOnExit">1</config>
<config key="WipeCacheOnAutoDismount">1</config>
<config key="IncludePimInCache">0</config>
<config key="TryEmptyPasswordWhenKeyfileUsed">0</config>
<config key="StartOnLogon">0</config>
<config key="MountDevicesOnLogon">0</config>
<config key="MountFavoritesOnLogon">0</config>
<config key="MountVolumesReadOnly">0</config>
<config key="MountVolumesRemovable">0</config>
<config key="PreserveTimestamps">1</config>
<config key="ShowDisconnectedNetworkDrives">0</config>
<config key="HideWaitingDialog">0</config>
<config key="UseSecureDesktop">0</config>
<config key="UseLegacyMaxPasswordLength">0</config>
<config key="EnableBackgroundTask">1</config>
<config key="CloseBackgroundTaskOnNoVolumes">1</config>
<config key="DismountOnLogOff">1</config>
<config key="DismountOnSessionLocked">0</config>
<config key="DismountOnPowerSaving">0</config>
<config key="DismountOnScreenSaver">0</config>
<config key="ForceAutoDismount">1</config>
<config key="MaxVolumeIdleTime">-60</config>
<config key="HiddenSectorDetectionStatus">0</config>
<config key="UseKeyfiles">0</config>
<config key="CloseSecurityTokenSessionsAfterMount">0</config>
<config key="EMVSupportEnabled">0</config>
<config key="HotkeyModAutoMountDevices">0</config>
<config key="HotkeyCodeAutoMountDevices">0</config>
<config key="HotkeyModDismountAll">0</config>
<config key="HotkeyCodeDismountAll">0</config>
<config key="HotkeyModWipeCache">0</config>
<config key="HotkeyCodeWipeCache">0</config>
<config key="HotkeyModDismountAllWipe">0</config>
<config key="HotkeyCodeDismountAllWipe">0</config>
<config key="HotkeyModForceDismountAllWipe">0</config>
<config key="HotkeyCodeForceDismountAllWipe">0</config>
<config key="HotkeyModForceDismountAllWipeExit">0</config>
<config key="HotkeyCodeForceDismountAllWipeExit">0</config>
<config key="HotkeyModMountFavoriteVolumes">0</config>
<config key="HotkeyCodeMountFavoriteVolumes">0</config>
<config key="HotkeyModShowHideMainWindow">0</config>
<config key="HotkeyCodeShowHideMainWindow">0</config>
<config key="HotkeyModCloseSecurityTokenSessions">0</config>
<config key="HotkeyCodeCloseSecurityTokenSessions">0</config>
<config key="PlaySoundOnHotkeyMountDismount">1</config>
<config key="DisplayMsgBoxOnHotkeyDismount">1</config>
<config key="Language">zh-cn</config>
<config key="SecurityTokenLibrary"></config>
<config key="DefaultPRF">1</config>
</configuration>
</VeraCrypt>

10
assets/vlc/vlcrc Normal file
View File

@@ -0,0 +1,10 @@
[qt] # Qt interface
qt-recentplay=0
qt-privacy-ask=0
qt-updates-notif=0
[core] # core program
video-title-show=0
vout=any
repeat=1
metadata-network-access=0

4
config/adobe_acrobat.reg Normal file
View File

@@ -0,0 +1,4 @@
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Adobe\Adobe Acrobat\DC\AVGeneral]
"iMaxMRUCntToBeStored"=dword:00000000

104
config/apps.json Normal file
View File

@@ -0,0 +1,104 @@
[
{
"Name": "7-Zip",
"Id": "7zip.7zip",
"Version": "",
"PostInstall": [
{
"Type": "Command",
"Command": "del /f /q \"C:\\Program Files\\7-Zip\\7-zip.chm\"",
"Description": "Remove 7-zip.chm file"
}
]
},
{
"Name": "Google Chrome",
"Id": "Google.Chrome",
"Version": "",
"PostInstall": [
{
"Type": "RegImport",
"Path": "./config/chrome.reg"
}
]
},
{
"Name": "OpenOffice",
"Id": "Apache.OpenOffice",
"Version": "4.116.9816",
"PostInstall": [
{
"Type": "Command",
"Command": "\"C:\\Program Files (x86)\\OpenOffice 4\\program\\soffice.exe\" -headless -nologo -nodefault",
"Description": "Run software once to generate the configuration files"
},
{
"Type": "FileCopy",
"Source": "./assets/openoffice/registrymodifications.xcu",
"Destination": "$env:APPDATA\\OpenOffice\\4\\user\\registrymodifications.xcu"
},
{
"Type": "Command",
"Command": "echo y | \"C:\\Program Files (x86)\\OpenOffice 4\\program\\unopkg.com\" add --shared -s \"$PSScriptRoot\\assets\\openoffice\\historymanager2.1.oxt\"",
"Description": "Install history extension"
}
]
},
{
"Name": "KeePassXC",
"Id": "KeePassXCTeam.KeePassXC",
"Version": "2.6.6",
"PostInstall": [
{
"Type": "FileCopy",
"Source": "./assets/keepassxc/keepassxc.ini",
"Destination": "$env:APPDATA\\KeePassXC\\keepassxc.ini"
}
]
},
{
"Name": "VeraCrypt",
"Id": "IDRIX.VeraCrypt",
"Version": "1.26.20",
"PostInstall": [
{
"Type": "FileCopy",
"Source": "./assets/veracrypt/Configuration.xml",
"Destination": "$env:APPDATA\\VeraCrypt\\Configuration.xml"
}
]
},
{
"Name": "File Shredder",
"Id": "PowTools.FileShredder",
"Version": "",
"PostInstall": []
},
{
"Name": "VLC",
"Id": "VideoLAN.VLC",
"Version": "",
"PostInstall": [
{
"Type": "FileCopy",
"Source": "./assets/vlc/vlcrc",
"Destination": "$env:APPDATA\\vlc\\vlcrc"
},
{
"Type": "RegImport",
"Path": "./config/vlc.reg"
}
]
},
{
"Name": "Adobe Acrobat Reader",
"Id": "Adobe.Acrobat.Reader.64-bit",
"Version": "",
"PostInstall": [
{
"Type": "RegImport",
"Path": "./config/adobe_acrobat.reg"
}
]
}
]

49
config/chrome.reg Normal file
View File

@@ -0,0 +1,49 @@
Windows Registry Editor Version 5.00
;uBlock Origin Lite
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome\ExtensionSettings\ddkjiahejlhfcafbddmgiahcphecmpfh]
"installation_mode"="normal_installed"
"update_url"="https://clients2.google.com/service/update2/crx"
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome\Recommended]
"AutofillAddressEnabled"=dword:00000000
"AutofillCreditCardEnabled"=dword:00000000
"DefaultGeolocationSetting"=dword:00000002
"PasswordManagerEnabled"=dword:00000000
"PaymentMethodQueryEnabled"=dword:00000000
"PrivacySandboxAdMeasurementEnabled"=dword:00000000
"PrivacySandboxAdTopicsEnabled"=dword:00000000
"PrivacySandboxPromptEnabled"=dword:00000000
"PrivacySandboxSiteEnabledAdsEnabled"=dword:00000000
; Microsoft Edge (Bonus ;)
;uBlock Origin
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Edge\ExtensionSettings\odfafepnkmbhccpbejgmiehpchacaeak]
"installation_mode"="normal_installed"
"update_url"="https://edge.microsoft.com/extensionwebstorebase/v1/crx"
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Edge\Recommended]
"AlternateErrorPagesEnabled"=dword:00000000
"AutofillAddressEnabled"=dword:00000000
"AutofillCreditCardEnabled"=dword:00000000
"AutofillMembershipsEnabled"=dword:00000000
"ConfigureDoNotTrack"=dword:00000001
"ControlDefaultStateOfAllowExtensionFromOtherStoresSettingEnabled"=dword:00000001
"DefaultGeolocationSetting"=dword:00000002
"DiagnosticData"=dword:00000001
"EdgeShoppingAssistantEnabled"=dword:00000000
"EdgeWalletCheckoutEnabled"=dword:00000000
"PasswordManagerEnabled"=dword:00000000
"PaymentMethodQueryEnabled"=dword:00000000
"PersonalizationReportingEnabled"=dword:00000000
"PrimaryPasswordSetting"=dword:00000003
"RelatedMatchesCloudServiceEnabled"=dword:00000000
"ResolveNavigationErrorsUseWebService"=dword:00000000
"ShowMicrosoftRewards"=dword:00000000
"TabServicesEnabled"=dword:00000000
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Edge\Recommended\ManagedSearchEngines\1]
"is_default"=dword:00000001
"keyword"="google.com"
"name"="Google"
"search_url"="{google:baseURL}search?q={searchTerms}&{google:RLZ}{google:originalQueryForSuggestion}{google:assistedQueryStats}{google:searchboxStats}{google:searchFieldtrialParameter}{google:iOSSearchLanguage}{google:prefetchSource}{google:searchClient}{google:sourceId}{google:contextualSearchVersion}ie={inputEncoding}"

4
config/vlc.reg Normal file
View File

@@ -0,0 +1,4 @@
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\VideoLAN\VLC]
"Lang"="zh_CN"

26
install.bat Normal file
View File

@@ -0,0 +1,26 @@
@echo off
:: ==========================================
:: 自动化装机工具启动器
:: ==========================================
:: 1. 强制切换到当前批处理文件所在的目录
:: 这一步至关重要,防止以管理员身份运行时路径变成了 C:\Windows\System32
cd /d "%~dp0"
:: 2. 检查管理员权限
if not "%1" == "am_admin" (
rem you'd better keep the following line as it is.
powershell start -verb runas '%0' am_admin & exit /b
)
:: ==========================================
:: 3. 核心执行逻辑
:: ==========================================
echo Calling main.ps1...
:: -NoProfile: 不加载用户配置文件,加快启动速度
:: -ExecutionPolicy Bypass: 绕过默认的脚本执行策略限制
:: -File: 指定要运行的脚本文件
powershell.exe -NoExit -NoProfile -ExecutionPolicy Bypass -File ".\main.ps1"

54
lib/invoke-cmdexec.ps1 Normal file
View File

@@ -0,0 +1,54 @@
param(
[Parameter(Mandatory=$true)] [string]$Command,
[string]$WorkDir = $null
)
# 1. 处理工作目录
if ([string]::IsNullOrEmpty($WorkDir)) {
$WorkDir = $PSScriptRoot
} else {
# 如果 WorkDir 里包含变量(如 $env:APPDATA展开它
$WorkDir = $ExecutionContext.InvokeCommand.ExpandString($WorkDir)
}
# 确保目录存在,否则命令会报错
if (-not (Test-Path $WorkDir)) {
Write-Warning "`n[CMD] WARNING: The work dir does not exist, using ($WorkDir)"
$WorkDir = $PSScriptRoot
}
# 2. 处理命令中的环境变量
$ProjectRoot = Split-Path $PSScriptRoot -Parent
# === 替换 $PSScriptRoot 为实际的绝对路径 ===
# 注意:要处理反斜杠转义问题,直接用字符串替换最安全
if ($Command.Contains('$PSScriptRoot')) {
$Command = $Command.Replace('$PSScriptRoot', $ProjectRoot)
}
# 这一步很关键,让你可以写 "echo $env:USERNAME"
$Command = $ExecutionContext.InvokeCommand.ExpandString($Command)
Write-Host "`n[CMD] Execute: $Command" -ForegroundColor Gray
# 3. 启动进程
# /c 表示执行完命令后关闭 cmd 窗口
# /s 开启参数的一般处理(忽略第一个和最后一个引号,为了兼容复杂引号情况)
$processOptions = @{
FilePath = "cmd.exe"
ArgumentList = "/s", "/c", "`"$Command`""
WorkingDirectory = $WorkDir
Wait = $true
NoNewWindow = $true
PassThru = $true
}
try {
$proc = Start-Process @processOptions
# 4. 检查退出代码 (ExitCode)
if ($proc.ExitCode -ne 0) {
Write-Error "`n[CMD] Failed to execute, exit code: $($proc.ExitCode)"
}
} catch {
Write-Error "`n[CMD] Failed to start process: $_"
}

41
lib/invoke-filecopy.ps1 Normal file
View File

@@ -0,0 +1,41 @@
param(
[Parameter(Mandatory=$true)]
[string]$Source,
[Parameter(Mandatory=$true)]
[string]$Destination
)
try {
# 1. 路径预处理:展开环境变量 (例如把 $env:APPDATA 变成 C:\Users\...\AppData\Roaming)
$ResolvedSource = $ExecutionContext.InvokeCommand.ExpandString($Source)
$ResolvedDest = $ExecutionContext.InvokeCommand.ExpandString($Destination)
# 2. 处理相对路径 (针对源文件)
# 如果源路径是相对路径 (./assets/...), 尝试将其转换为绝对路径
# 假设脚本是从项目根目录调用的
if (-not (Test-Path $ResolvedSource) -and (Test-Path "$PWD\$ResolvedSource")) {
$ResolvedSource = Join-Path $PWD $ResolvedSource
}
# 3. 再次检查源文件是否存在
if (-not (Test-Path $ResolvedSource -PathType Leaf)) {
Write-Warning "`n[FileCopy] [Skip] File not found: $ResolvedSource"
return # 退出脚本
}
# 4. 处理目标目录 (自动创建不存在的文件夹)
$DestDir = Split-Path -Path $ResolvedDest -Parent
if (-not (Test-Path $DestDir)) {
Write-Host "`n[FileCopy] Create dir: $DestDir" -ForegroundColor DarkGray
New-Item -Path $DestDir -ItemType Directory -Force | Out-Null
}
# 5. 执行复制 (Force = 覆盖)
Copy-Item -Path $ResolvedSource -Destination $ResolvedDest -Force -ErrorAction Stop
Write-Host "`n[FileCopy] Success: $ResolvedDest" -ForegroundColor Green
} catch {
Write-Error "`n[FileCopy] Fail: $_"
}

37
lib/invoke-regimport.ps1 Normal file
View File

@@ -0,0 +1,37 @@
param(
[Parameter(Mandatory=$true)]
[string]$Path
)
try {
# 1. 路径预处理
# 展开环境变量 (虽然 .reg 路径通常是固定的,但支持一下没坏处)
$ResolvedPath = $ExecutionContext.InvokeCommand.ExpandString($Path)
# 2. 处理相对路径
# 如果路径是相对的 (./assets/...), 转换为绝对路径
if (-not (Test-Path $ResolvedPath) -and (Test-Path "$PWD\$ResolvedPath")) {
$ResolvedPath = Join-Path $PWD $ResolvedPath
}
# 3. 检查文件是否存在
if (-not (Test-Path $ResolvedPath)) {
Write-Warning "`n[RegImport] [Skip] Cannot find: $ResolvedPath"
return
}
Write-Host "`n[RegImport] Importing: $(Split-Path $ResolvedPath -Leaf)" -ForegroundColor Gray
# 4. 调用 reg.exe 导入
# 使用 Start-Process 以获取退出代码
$proc = Start-Process -FilePath "reg.exe" -ArgumentList "import", "`"$ResolvedPath`"" -Wait -PassThru -NoNewWindow
if ($proc.ExitCode -eq 0) {
Write-Host "`n[RegImport] Successfully imported." -ForegroundColor Green
} else {
Write-Error "`n[RegImport] Failed to import: $($proc.ExitCode)"
}
} catch {
Write-Error "`n[RegImport] Failed to start process: $_"
}

119
main.ps1 Normal file
View File

@@ -0,0 +1,119 @@
# 设置严格模式,遇到错误停止,防止错误的命令雪崩
$ErrorActionPreference = "Stop"
#Set-StrictMode -Version Latest
# === 1. 加载依赖库 ===
# 确保 lib 目录存在
if (-not (Test-Path "$PSScriptRoot\lib")) {
Write-Error "Cannot find ./lib, some files missing."
exit 1
}
# === 2. 读取配置 ===
$jsonPath = "$PSScriptRoot\config\apps.json"
if (-not (Test-Path $jsonPath)) {
Write-Error "Cannot find: $jsonPath"
exit 1
}
Write-Host "Reading configurations..." -ForegroundColor Cyan
# 使用 UTF8 读取防止中文乱码
$apps = Get-Content $jsonPath -Encoding UTF8 | ConvertFrom-Json
# === 3. 主循环 ===
foreach ($app in $apps) {
Write-Host "`n==========================================" -ForegroundColor Cyan
Write-Host "Installing: $($app.Name)" -ForegroundColor Yellow
Write-Host "=========================================="
# --- 步骤 A: Winget 安装 ---
$wingetArgs = @(
"install",
"--id", $app.Id,
"-e",
"--silent",
"--accept-package-agreements",
"--accept-source-agreements",
"--disable-interactivity",
"--scope", "machine"
)
# [版本检查逻辑]
# 检查 Version 是否存在且不为空字符串
if (-not [string]::IsNullOrWhiteSpace($app.Version)) {
Write-Host "-> Version: $($app.Version)"
$wingetArgs += "-v"
$wingetArgs += $app.Version
} else {
Write-Host "-> Version: latest"
}
Write-Host "-> Installing via winget..."
# 执行安装
$proc = Start-Process -FilePath "winget" -ArgumentList $wingetArgs -Wait -PassThru -NoNewWindow
# 检查安装结果 (0=成功, -1978335189=已安装)
if ($proc.ExitCode -eq 0) {
Write-Host "[Success]" -ForegroundColor Green
} elseif ($proc.ExitCode -eq -1978335189) {
Write-Host "[Skip] Already installed" -ForegroundColor Yellow
continue # 已经安装的为了避免覆盖配置,也就不配置了
} else {
Write-Error "[Fail] Error code: $($proc.ExitCode)"
continue # 安装失败则跳过后续配置
}
# --- 步骤 B: PostInstall 配置 ---
if ($app.PostInstall -and $app.PostInstall.Count -gt 0) {
Write-Host "`n-> Configuring..." -ForegroundColor Cyan
$stepIndex = 0
foreach ($action in $app.PostInstall) {
# [间隔逻辑] 如果这不是第一步,先等待 2 秒
if ($stepIndex -gt 0) {
Write-Host "(Waiting 2 seconds...)" -ForegroundColor DarkGray
Start-Sleep -Seconds 2
}
try {
switch ($action.Type) {
# 1. 复制文件
"FileCopy" {
& "$PSScriptRoot\lib\invoke-filecopy.ps1" `
-Source $action.Source `
-Destination $action.Destination
}
# 2. 导入注册表
"RegImport" {
& "$PSScriptRoot\lib\invoke-regimport.ps1" `
-Path $action.Path
}
# 3. 执行 CMD
"Command" {
& "$PSScriptRoot\lib\invoke-cmdexec.ps1" `
-Command $action.Command `
-WorkDir $action.WorkDir
}
Default {
Write-Warning "`nUnknown action: $($action.Type)"
}
}
} catch {
Write-Error "`nFailed to operate step $($stepIndex + 1): $_"
}
$stepIndex++
}
} else {
Write-Host "-> No configurations." -ForegroundColor DarkGray
}
}
Write-Host "`n=== Done ===" -ForegroundColor Green
Pause