|
@@ -5,7 +5,7 @@
|
|
|
#Requires -Version 5.1
|
|
#Requires -Version 5.1
|
|
|
#Requires -RunAsAdministrator
|
|
#Requires -RunAsAdministrator
|
|
|
|
|
|
|
|
-$ErrorActionPreference = 'Stop'
|
|
|
|
|
|
|
+$ErrorActionPreference = 'Continue'
|
|
|
|
|
|
|
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
|
|
|
|
|
@@ -41,9 +41,43 @@ $DllCandidates = @(
|
|
|
Join-Path $ScriptDir "..\build\Debug\x64\CommModifyKit.dll"
|
|
Join-Path $ScriptDir "..\build\Debug\x64\CommModifyKit.dll"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+# 检查 DLL 架构(32位服务必须使用32位DLL)
|
|
|
|
|
+function Test-PeArch {
|
|
|
|
|
+ param([string]$Path)
|
|
|
|
|
+ if (-not (Test-Path $Path)) { return 0 }
|
|
|
|
|
+ # 只读前 512 字节(PE 头足够)
|
|
|
|
|
+ try {
|
|
|
|
|
+ $fs = [System.IO.File]::OpenRead($Path)
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ return 0 # 文件被锁定或无法访问
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ $bytes = New-Object byte[] 512
|
|
|
|
|
+ $read = $fs.Read($bytes, 0, 512)
|
|
|
|
|
+ if ($read -lt 64) { return 0 }
|
|
|
|
|
+ $peOffset = [System.BitConverter]::ToInt32($bytes, 60)
|
|
|
|
|
+ if ($peOffset -eq 0 -or $peOffset + 6 -gt $read) { return 0 }
|
|
|
|
|
+ $machine = [System.BitConverter]::ToUInt16($bytes, $peOffset + 4)
|
|
|
|
|
+ return $machine # 0x14c=i386(32bit), 0x8664=x64
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ $fs.Close()
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
$DriverSys = $DriverSysCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
|
$DriverSys = $DriverSysCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
|
|
$DriverInf = $DriverInfCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
|
$DriverInf = $DriverInfCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
|
|
-$DllPath = $DllCandidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
|
|
|
|
|
|
+
|
|
|
|
|
+# 查找 32 位 DLL(跳过 64 位)
|
|
|
|
|
+$DllPath = $null
|
|
|
|
|
+foreach ($candidate in $DllCandidates) {
|
|
|
|
|
+ if (Test-Path $candidate) {
|
|
|
|
|
+ $arch = Test-PeArch $candidate
|
|
|
|
|
+ if ($arch -eq 0x14c) {
|
|
|
|
|
+ $DllPath = $candidate
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
if (-not $DriverSys) {
|
|
if (-not $DriverSys) {
|
|
|
Write-Error "未找到 CommModifyKit.sys,请先用 WDK + VS2019 编译 driver 项目"
|
|
Write-Error "未找到 CommModifyKit.sys,请先用 WDK + VS2019 编译 driver 项目"
|
|
@@ -53,68 +87,282 @@ if (-not $DriverInf) {
|
|
|
Write-Error "未找到 CommModifyKit.inf"
|
|
Write-Error "未找到 CommModifyKit.inf"
|
|
|
exit 1
|
|
exit 1
|
|
|
}
|
|
}
|
|
|
-Write-Host "驱动 .sys: $DriverSys" -ForegroundColor Green
|
|
|
|
|
|
|
+
|
|
|
|
|
+# 校验驱动 .sys 必须为 64 位(x64),32 位驱动无法在 64 位内核加载
|
|
|
|
|
+$driverArch = Test-PeArch $DriverSys
|
|
|
|
|
+if ($driverArch -ne 0x8664) {
|
|
|
|
|
+ $archName = switch ($driverArch) {
|
|
|
|
|
+ 0x14c { 'i386 (32-bit)' }
|
|
|
|
|
+ 0 { 'unknown/unreadable' }
|
|
|
|
|
+ default { "0x$('{0:X4}' -f $driverArch)" }
|
|
|
|
|
+ }
|
|
|
|
|
+ Write-Error "CommModifyKit.sys 架构为 $archName,必须为 x64 (64-bit)。请检查 driver 项目平台配置。"
|
|
|
|
|
+ exit 1
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+Write-Host "驱动 .sys: $DriverSys (x64)" -ForegroundColor Green
|
|
|
Write-Host "驱动 .inf: $DriverInf" -ForegroundColor Green
|
|
Write-Host "驱动 .inf: $DriverInf" -ForegroundColor Green
|
|
|
if ($DllPath) {
|
|
if ($DllPath) {
|
|
|
- Write-Host "用户态 DLL: $DllPath" -ForegroundColor Green
|
|
|
|
|
|
|
+ Write-Host "用户态 DLL: $DllPath (32-bit)" -ForegroundColor Green
|
|
|
} else {
|
|
} else {
|
|
|
- Write-Warning "未找到 CommModifyKit.dll(可后续单独编译 dll 项目)"
|
|
|
|
|
|
|
+ Write-Warning "未找到 32 位 CommModifyKit.dll,请编译 Win32 平台"
|
|
|
}
|
|
}
|
|
|
Write-Host ""
|
|
Write-Host ""
|
|
|
|
|
|
|
|
# ============================================================================
|
|
# ============================================================================
|
|
|
# 2. 拷贝驱动文件到 System32\drivers
|
|
# 2. 拷贝驱动文件到 System32\drivers
|
|
|
# ============================================================================
|
|
# ============================================================================
|
|
|
-$TargetDriverDir = Join-Path $env:windir "System32\drivers"
|
|
|
|
|
-$TargetDriverSys = Join-Path $TargetDriverDir "CommModifyKit.sys"
|
|
|
|
|
-$TargetDriverInf = Join-Path $TargetDriverDir "CommModifyKit.inf"
|
|
|
|
|
|
|
+# 检测 32 位 PowerShell(WoW64 会将 System32 重定向到 SysWOW64)
|
|
|
|
|
+$Is32bitPS = ([System.IntPtr]::Size -eq 4)
|
|
|
|
|
+
|
|
|
|
|
+# 文件操作路径(32 位 PowerShell 需用 Sysnative 绕过 WoW64 重定向)
|
|
|
|
|
+$FileDriverDir = if ($Is32bitPS) {
|
|
|
|
|
+ Write-Warning "检测到 32 位 PowerShell,文件操作使用 Sysnative 路径"
|
|
|
|
|
+ Join-Path $env:windir "Sysnative\drivers"
|
|
|
|
|
+} else {
|
|
|
|
|
+ Join-Path $env:windir "System32\drivers"
|
|
|
|
|
+}
|
|
|
|
|
+$TargetDriverSys = Join-Path $FileDriverDir "CommModifyKit.sys"
|
|
|
|
|
+$TargetDriverInf = Join-Path $FileDriverDir "CommModifyKit.inf"
|
|
|
|
|
|
|
|
-Write-Host "拷贝驱动文件到 $TargetDriverDir ..."
|
|
|
|
|
-Copy-Item -Force $DriverSys $TargetDriverSys
|
|
|
|
|
-Copy-Item -Force $DriverInf $TargetDriverInf
|
|
|
|
|
-Write-Host " 完成" -ForegroundColor Green
|
|
|
|
|
|
|
+# 服务 binPath 路径(始终 System32\drivers,SCM/内核为 64 位,不识别 Sysnative)
|
|
|
|
|
+$ServiceBinPath = Join-Path $env:windir "System32\drivers\CommModifyKit.sys"
|
|
|
|
|
+
|
|
|
|
|
+# 先停止已存在的服务,避免 .sys 文件被锁定
|
|
|
|
|
+$existingSvc = Get-Service -Name 'CommModifyKit' -ErrorAction SilentlyContinue
|
|
|
|
|
+if ($existingSvc -and $existingSvc.Status -eq 'Running') {
|
|
|
|
|
+ Write-Host "停止现有驱动服务..."
|
|
|
|
|
+ sc.exe stop CommModifyKit 2>&1 | Out-Null
|
|
|
|
|
+ Start-Sleep 2
|
|
|
|
|
+ # 检查是否真的停止了
|
|
|
|
|
+ $svcAfterStop = Get-Service -Name 'CommModifyKit' -ErrorAction SilentlyContinue
|
|
|
|
|
+ if ($svcAfterStop -and $svcAfterStop.Status -eq 'Running') {
|
|
|
|
|
+ Write-Warning "驱动服务无法停止(可能被设备栈引用),.sys 文件可能被锁定"
|
|
|
|
|
+ Write-Host "请先运行 uninstall.ps1 移除 UpperFilters,重启后再安装" -ForegroundColor Yellow
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+Write-Host "拷贝驱动文件到 $FileDriverDir ..."
|
|
|
|
|
+$copyOk = $true
|
|
|
|
|
+try {
|
|
|
|
|
+ Copy-Item -Force $DriverSys $TargetDriverSys -ErrorAction Stop
|
|
|
|
|
+ Copy-Item -Force $DriverInf $TargetDriverInf -ErrorAction Stop
|
|
|
|
|
+ Write-Host " 完成" -ForegroundColor Green
|
|
|
|
|
+} catch {
|
|
|
|
|
+ Write-Warning "拷贝失败: $_"
|
|
|
|
|
+ Write-Warning ".sys 文件被锁定,请先卸载驱动并重启"
|
|
|
|
|
+ $copyOk = $false
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (-not $copyOk) {
|
|
|
|
|
+ # 仍然继续尝试创建服务等步骤(可能旧 .sys 仍可用)
|
|
|
|
|
+ Write-Host "继续安装(使用现有 .sys 文件)..." -ForegroundColor Yellow
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# ============================================================================
|
|
|
|
|
+# 2.5 注册驱动包到驱动存储区(关键步骤!)
|
|
|
|
|
+# ============================================================================
|
|
|
|
|
+# 先检查测试签名状态,pnputil 要求驱动有签名
|
|
|
|
|
+# bcdedit 输出 "testsigning Yes" 或 "test signing Yes"(不同本地化版本)
|
|
|
|
|
+$TestSigningEnabled = (bcdedit /enum | Select-String 'test\s*signing\s+Yes' -Quiet)
|
|
|
|
|
+if (-not $TestSigningEnabled) {
|
|
|
|
|
+ Write-Host ""
|
|
|
|
|
+ Write-Warning "测试签名未启用,驱动无法加载"
|
|
|
|
|
+ Write-Host "正在启用测试签名..." -ForegroundColor Yellow
|
|
|
|
|
+ bcdedit /set testsigning on | Out-Null
|
|
|
|
|
+ Write-Host "测试签名已启用" -ForegroundColor Green
|
|
|
|
|
+ Write-Warning "需要重启计算机才能生效!"
|
|
|
|
|
+ Write-Host ""
|
|
|
|
|
+ Write-Host "请重启后再次运行此脚本" -ForegroundColor Yellow
|
|
|
|
|
+ exit 0
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# 对驱动进行测试签名(如果未签名)
|
|
|
|
|
+Write-Host "检查驱动签名状态..."
|
|
|
|
|
+$sigState = (Get-AuthenticodeSignature $TargetDriverSys).Status
|
|
|
|
|
+if ($sigState -ne 'Valid') {
|
|
|
|
|
+ Write-Host "驱动未签名,使用测试证书签名..." -ForegroundColor Yellow
|
|
|
|
|
+
|
|
|
|
|
+ # 创建或获取测试证书(用 Subject 匹配,检查未过期)
|
|
|
|
|
+ $testCert = Get-ChildItem -Path Cert:\LocalMachine\My -ErrorAction SilentlyContinue | Where-Object { $_.Subject -match "CommModifyKitTest" -and $_.NotAfter -gt (Get-Date) } | Select-Object -First 1
|
|
|
|
|
+ if (-not $testCert) {
|
|
|
|
|
+ # 清理过期的旧证书
|
|
|
|
|
+ Get-ChildItem -Path Cert:\LocalMachine\My -ErrorAction SilentlyContinue | Where-Object { $_.Subject -match "CommModifyKitTest" } | Remove-Item -Force -ErrorAction SilentlyContinue
|
|
|
|
|
+ Write-Host "创建测试证书(有效期 10 年)..."
|
|
|
|
|
+ $testCert = New-SelfSignedCertificate -Subject "CN=CommModifyKitTest" -CertStoreLocation "Cert:\LocalMachine\My" -Type CodeSigningCert -KeyExportPolicy Exportable -KeyLength 2048 -KeyAlgorithm RSA -KeyUsage DigitalSignature -NotAfter (Get-Date).AddYears(10)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ # 将证书添加到 Trusted Root(测试签名模式下必须)
|
|
|
|
|
+ $rootCert = Get-ChildItem -Path Cert:\LocalMachine\Root -ErrorAction SilentlyContinue | Where-Object { $_.Subject -match "CommModifyKitTest" } | Select-Object -First 1
|
|
|
|
|
+ if (-not $rootCert) {
|
|
|
|
|
+ Write-Host "添加证书到受信任的根证书颁发机构..."
|
|
|
|
|
+ $certPath = Join-Path $env:TEMP "CommModifyKitTest.cer"
|
|
|
|
|
+ Export-Certificate -Cert $testCert -FilePath $certPath -Force | Out-Null
|
|
|
|
|
+
|
|
|
|
|
+ # 尝试方法 1: Import-Certificate
|
|
|
|
|
+ $importSuccess = $false
|
|
|
|
|
+ try {
|
|
|
|
|
+ Import-Certificate -FilePath $certPath -CertStoreLocation "Cert:\LocalMachine\Root" -ErrorAction Stop | Out-Null
|
|
|
|
|
+ $importSuccess = $true
|
|
|
|
|
+ Write-Host " 完成(Import-Certificate)" -ForegroundColor Green
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ Write-Warning "Import-Certificate 失败: $($_.Exception.Message)"
|
|
|
|
|
+
|
|
|
|
|
+ # 尝试方法 2: certutil.exe
|
|
|
|
|
+ Write-Host " 尝试使用 certutil..."
|
|
|
|
|
+ $certutilResult = & certutil.exe -addstore -f "Root" $certPath 2>&1
|
|
|
|
|
+ if ($LASTEXITCODE -eq 0) {
|
|
|
|
|
+ $importSuccess = $true
|
|
|
|
|
+ Write-Host " 完成(certutil)" -ForegroundColor Green
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Write-Warning "certutil 导入失败: $certutilResult"
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ # 清理临时证书文件(仅在成功导入后)
|
|
|
|
|
+ if ($importSuccess) {
|
|
|
|
|
+ Remove-Item $certPath -Force -ErrorAction SilentlyContinue
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Write-Warning "无法将测试证书添加到受信任的根证书颁发机构"
|
|
|
|
|
+ Write-Host "证书文件已保留: $certPath" -ForegroundColor Yellow
|
|
|
|
|
+ Write-Host "请手动导入证书:" -ForegroundColor Yellow
|
|
|
|
|
+ Write-Host " 1. 双击 $certPath" -ForegroundColor Yellow
|
|
|
|
|
+ Write-Host " 2. 选择 '安装证书' → '本地计算机' → '将所有的证书都放入下列存储' → '受信任的根证书颁发机构'" -ForegroundColor Yellow
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ # 签名驱动:先尝试带时间戳,失败则不带时间戳,再失败用 signtool
|
|
|
|
|
+ Write-Host "签名驱动..."
|
|
|
|
|
+ $signOk = $false
|
|
|
|
|
+
|
|
|
|
|
+ # 尝试 1: Set-AuthenticodeSignature 带时间戳
|
|
|
|
|
+ $signResult = Set-AuthenticodeSignature -FilePath $TargetDriverSys -Certificate $testCert -TimeStampServer "http://timestamp.digicert.com" -HashAlgorithm SHA256
|
|
|
|
|
+ if ($signResult.Status -eq 'Valid' -or $signResult.Status -eq 'UnknownError') {
|
|
|
|
|
+ Write-Host " 完成(带时间戳)" -ForegroundColor Green
|
|
|
|
|
+ $signOk = $true
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ # 尝试 2: Set-AuthenticodeSignature 不带时间戳
|
|
|
|
|
+ if (-not $signOk) {
|
|
|
|
|
+ Write-Host " 时间戳服务器不可达,尝试不带时间戳..."
|
|
|
|
|
+ $signResult = Set-AuthenticodeSignature -FilePath $TargetDriverSys -Certificate $testCert -HashAlgorithm SHA256
|
|
|
|
|
+ if ($signResult.Status -eq 'Valid' -or $signResult.Status -eq 'UnknownError') {
|
|
|
|
|
+ Write-Host " 完成(无时间戳)" -ForegroundColor Green
|
|
|
|
|
+ $signOk = $true
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ # 尝试 3: signtool(如果安装了 Windows SDK)
|
|
|
|
|
+ if (-not $signOk) {
|
|
|
|
|
+ $signtoolPaths = @(
|
|
|
|
|
+ "${env:ProgramFiles(x86)}\Windows Kits\10\bin\10.0.22621.0\x64\signtool.exe",
|
|
|
|
|
+ "${env:ProgramFiles(x86)}\Windows Kits\10\bin\10.0.22000.0\x64\signtool.exe",
|
|
|
|
|
+ "${env:ProgramFiles(x86)}\Windows Kits\10\bin\10.0.19041.0\x64\signtool.exe"
|
|
|
|
|
+ )
|
|
|
|
|
+ $signtool = $signtoolPaths | Where-Object { Test-Path $_ } | Select-Object -First 1
|
|
|
|
|
+ # 通配符后备搜索
|
|
|
|
|
+ if (-not $signtool) {
|
|
|
|
|
+ $signtool = Get-ChildItem "${env:ProgramFiles(x86)}\Windows Kits\10\bin\*\x64\signtool.exe" -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName
|
|
|
|
|
+ }
|
|
|
|
|
+ if ($signtool) {
|
|
|
|
|
+ Write-Host " 尝试 signtool..."
|
|
|
|
|
+ # 用 /sha1 指纹精确指定证书,避免 /n 子串匹配选到过期的同名证书
|
|
|
|
|
+ & $signtool sign /s MY /sha1 "$($testCert.Thumbprint)" /fd SHA256 $TargetDriverSys 2>&1 | Out-Null
|
|
|
|
|
+ if ($LASTEXITCODE -eq 0) {
|
|
|
|
|
+ Write-Host " 完成(signtool)" -ForegroundColor Green
|
|
|
|
|
+ $signOk = $true
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (-not $signOk) {
|
|
|
|
|
+ Write-Warning "签名失败: $($signResult.Status) - $($signResult.StatusMessage)"
|
|
|
|
|
+ Write-Warning "驱动可能无法加载,请确认测试签名已启用并重启"
|
|
|
|
|
+ }
|
|
|
|
|
+} else {
|
|
|
|
|
+ Write-Host "驱动已签名" -ForegroundColor Green
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# pnputil /add-driver 需要 .cat 目录文件,开发阶段通常没有
|
|
|
|
|
+# 失败后通过 sc.exe create 直接加载驱动(测试签名模式)
|
|
|
|
|
+Write-Host "尝试注册驱动包到驱动存储区..."
|
|
|
|
|
+try {
|
|
|
|
|
+ $result = pnputil /add-driver $DriverInf /install 2>&1
|
|
|
|
|
+ if ($LASTEXITCODE -eq 0) {
|
|
|
|
|
+ Write-Host " 完成" -ForegroundColor Green
|
|
|
|
|
+ if ($result -match '(oem\d+\.inf)') {
|
|
|
|
|
+ Write-Host " 驱动包: $($matches[1])" -ForegroundColor Green
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Write-Host " pnputil 注册失败(无 .cat 目录文件,属正常),将通过 sc.exe 直接加载" -ForegroundColor Yellow
|
|
|
|
|
+ }
|
|
|
|
|
+} catch {
|
|
|
|
|
+ Write-Host " pnputil 不可用,将通过 sc.exe 直接加载" -ForegroundColor Yellow
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
# ============================================================================
|
|
# ============================================================================
|
|
|
# 3. 创建并启动驱动服务
|
|
# 3. 创建并启动驱动服务
|
|
|
# ============================================================================
|
|
# ============================================================================
|
|
|
$ServiceName = 'CommModifyKit'
|
|
$ServiceName = 'CommModifyKit'
|
|
|
-$ExistingService = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
|
|
|
|
|
|
|
|
|
|
|
+# 先删除旧服务(可能配置不一致)
|
|
|
|
|
+$ExistingService = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
|
|
|
if ($ExistingService) {
|
|
if ($ExistingService) {
|
|
|
- Write-Host "服务 $ServiceName 已存在,状态: $($ExistingService.Status)"
|
|
|
|
|
- if ($ExistingService.Status -ne 'Running') {
|
|
|
|
|
- Write-Host "启动服务..."
|
|
|
|
|
- Start-Service -Name $ServiceName
|
|
|
|
|
- Write-Host " 完成" -ForegroundColor Green
|
|
|
|
|
|
|
+ if ($ExistingService.Status -eq 'Running') {
|
|
|
|
|
+ sc.exe stop $ServiceName 2>&1 | Out-Null
|
|
|
|
|
+ Start-Sleep 2
|
|
|
}
|
|
}
|
|
|
-} else {
|
|
|
|
|
- Write-Host "创建服务 $ServiceName ..."
|
|
|
|
|
- sc.exe create $ServiceName binPath= $TargetDriverSys type= kernel start= demand error= normal | Out-Null
|
|
|
|
|
|
|
+ sc.exe delete $ServiceName 2>&1 | Out-Null
|
|
|
|
|
+ Start-Sleep 1
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+Write-Host "创建服务 $ServiceName ..."
|
|
|
|
|
+sc.exe create $ServiceName binPath= $ServiceBinPath type= kernel start= demand error= normal | Out-Null
|
|
|
|
|
+if ($LASTEXITCODE -eq 0) {
|
|
|
Write-Host " 完成" -ForegroundColor Green
|
|
Write-Host " 完成" -ForegroundColor Green
|
|
|
Write-Host "启动服务..."
|
|
Write-Host "启动服务..."
|
|
|
- sc.exe start $ServiceName | Out-Null
|
|
|
|
|
- Write-Host " 完成" -ForegroundColor Green
|
|
|
|
|
|
|
+ sc.exe start $ServiceName 2>&1 | Out-Null
|
|
|
|
|
+ if ($LASTEXITCODE -eq 0) {
|
|
|
|
|
+ Write-Host " 完成" -ForegroundColor Green
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Write-Warning " 启动失败(可能需要重启后由 PnP 自动加载)"
|
|
|
|
|
+ }
|
|
|
|
|
+} else {
|
|
|
|
|
+ Write-Warning " 创建服务失败"
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
# ============================================================================
|
|
# ============================================================================
|
|
|
# 3.5 注册为 Ports 类 UpperFilters
|
|
# 3.5 注册为 Ports 类 UpperFilters
|
|
|
|
|
+# 注意:仅当驱动服务确认运行中时才注册 UpperFilters,否则会导致 PnP 尝试
|
|
|
|
|
+# attach 一个不存在的过滤器,使所有 Ports 类设备启动失败(mode 显示
|
|
|
|
|
+# "访问设备失败")。
|
|
|
# ============================================================================
|
|
# ============================================================================
|
|
|
-$PortsClassGuid = "{4D36E978-E325-11CE-BFC1-08002BE10318}"
|
|
|
|
|
-$ClassKey = "HKLM:\SYSTEM\CurrentControlSet\Control\Class\$PortsClassGuid"
|
|
|
|
|
-$currentFilters = @()
|
|
|
|
|
-$existingFilters = (Get-ItemProperty -Path $ClassKey -Name "UpperFilters" -ErrorAction SilentlyContinue)
|
|
|
|
|
-if ($existingFilters) {
|
|
|
|
|
- $currentFilters = @($existingFilters.UpperFilters)
|
|
|
|
|
-}
|
|
|
|
|
-if ($currentFilters -notcontains "CommModifyKit") {
|
|
|
|
|
- $newFilters = @($currentFilters) + "CommModifyKit"
|
|
|
|
|
- Set-ItemProperty -Path $ClassKey -Name "UpperFilters" -Value $newFilters -Type MultiString
|
|
|
|
|
- Write-Host "已将 CommModifyKit 添加到 Ports 类 UpperFilters" -ForegroundColor Green
|
|
|
|
|
- # 重新枚举设备使 UpperFilter 生效
|
|
|
|
|
- pnputil /scan-devices | Out-Null
|
|
|
|
|
- Write-Host "已触发设备重新枚举" -ForegroundColor Green
|
|
|
|
|
|
|
+# 先确认服务确实在运行(避免驱动加载失败时污染 UpperFilters)
|
|
|
|
|
+$svcState = (Get-Service -Name $ServiceName -ErrorAction SilentlyContinue).Status
|
|
|
|
|
+if ($svcState -ne 'Running') {
|
|
|
|
|
+ Write-Warning "驱动服务未运行(状态: $svcState),跳过 UpperFilters 注册"
|
|
|
|
|
+ Write-Host "请检查驱动签名/测试签名模式,重启后再次运行此脚本" -ForegroundColor Yellow
|
|
|
|
|
+ Write-Host "未注册 UpperFilters,串口不会被过滤,但驱动也未生效" -ForegroundColor Yellow
|
|
|
} else {
|
|
} else {
|
|
|
- Write-Host "CommModifyKit 已在 UpperFilters 中" -ForegroundColor Green
|
|
|
|
|
|
|
+ $PortsClassGuid = "{4D36E978-E325-11CE-BFC1-08002BE10318}"
|
|
|
|
|
+ $ClassKey = "HKLM:\SYSTEM\CurrentControlSet\Control\Class\$PortsClassGuid"
|
|
|
|
|
+ # 读取现有 UpperFilters,过滤掉空字符串(历史遗留的空字符串会导致
|
|
|
|
|
+ # PnP 加载空名称过滤器,使所有 Ports 类设备启动失败)
|
|
|
|
|
+ $currentFilters = @()
|
|
|
|
|
+ $existingFilters = (Get-ItemProperty -Path $ClassKey -Name "UpperFilters" -ErrorAction SilentlyContinue)
|
|
|
|
|
+ if ($existingFilters -and $existingFilters.UpperFilters) {
|
|
|
|
|
+ $currentFilters = @($existingFilters.UpperFilters | Where-Object { $_ -and $_.Trim() -ne '' })
|
|
|
|
|
+ }
|
|
|
|
|
+ if ($currentFilters -notcontains "CommModifyKit") {
|
|
|
|
|
+ $newFilters = @($currentFilters) + "CommModifyKit"
|
|
|
|
|
+ Set-ItemProperty -Path $ClassKey -Name "UpperFilters" -Value $newFilters -Type MultiString
|
|
|
|
|
+ Write-Host "已将 CommModifyKit 添加到 Ports 类 UpperFilters" -ForegroundColor Green
|
|
|
|
|
+ # 重新枚举设备使 UpperFilter 生效
|
|
|
|
|
+ pnputil /scan-devices | Out-Null
|
|
|
|
|
+ Write-Host "已触发设备重新枚举" -ForegroundColor Green
|
|
|
|
|
+ } else {
|
|
|
|
|
+ Write-Host "CommModifyKit 已在 UpperFilters 中" -ForegroundColor Green
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
# ============================================================================
|
|
# ============================================================================
|
|
@@ -132,7 +380,9 @@ if ($DllPath) {
|
|
|
if ($ServiceExe) {
|
|
if ($ServiceExe) {
|
|
|
$ServiceDir = Split-Path -Parent $ServiceExe
|
|
$ServiceDir = Split-Path -Parent $ServiceExe
|
|
|
$TargetDll = Join-Path $ServiceDir "CommModifyKit.dll"
|
|
$TargetDll = Join-Path $ServiceDir "CommModifyKit.dll"
|
|
|
- if ((Resolve-Path $DllPath -ErrorAction SilentlyContinue).Path -eq (Resolve-Path $TargetDll -ErrorAction SilentlyContinue).Path) {
|
|
|
|
|
|
|
+ $srcReal = (Resolve-Path $DllPath -ErrorAction SilentlyContinue).Path
|
|
|
|
|
+ $dstReal = if (Test-Path $TargetDll) { (Resolve-Path $TargetDll).Path } else { $null }
|
|
|
|
|
+ if ($srcReal -and $dstReal -and $srcReal -eq $dstReal) {
|
|
|
Write-Host "DLL 已在目标目录,跳过拷贝" -ForegroundColor Green
|
|
Write-Host "DLL 已在目标目录,跳过拷贝" -ForegroundColor Green
|
|
|
} else {
|
|
} else {
|
|
|
Write-Host "拷贝 DLL 到 $TargetDll ..."
|
|
Write-Host "拷贝 DLL 到 $TargetDll ..."
|
|
@@ -144,23 +394,13 @@ if ($DllPath) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-# ============================================================================
|
|
|
|
|
-# 5. 启用测试签名(开发期需要)
|
|
|
|
|
-# ============================================================================
|
|
|
|
|
-$TestSigningEnabled = (bcdedit /enum | Select-String 'testsigning' -Quiet)
|
|
|
|
|
-if (-not $TestSigningEnabled) {
|
|
|
|
|
- Write-Host ""
|
|
|
|
|
- Write-Warning "检测到测试签名未启用,驱动可能无法加载"
|
|
|
|
|
- Write-Host "执行: bcdedit /set testsigning on" -ForegroundColor Yellow
|
|
|
|
|
- bcdedit /set testsigning on | Out-Null
|
|
|
|
|
- Write-Warning "测试签名已启用,需要重启计算机才能生效"
|
|
|
|
|
-} else {
|
|
|
|
|
- Write-Host "测试签名已启用" -ForegroundColor Green
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
Write-Host ""
|
|
Write-Host ""
|
|
|
Write-Host '=== 安装完成 ===' -ForegroundColor Cyan
|
|
Write-Host '=== 安装完成 ===' -ForegroundColor Cyan
|
|
|
-Write-Host "请确认:"
|
|
|
|
|
-Write-Host " 1. 计算机已重启(启用测试签名后)"
|
|
|
|
|
-Write-Host " 2. CommModifyKit.dll 已拷贝到 CommModifyService.exe 所在目录"
|
|
|
|
|
-Write-Host " 3. config.json 中 'comm.use_dll' 设为 true"
|
|
|
|
|
|
|
+Write-Host ""
|
|
|
|
|
+Write-Host "验证步骤:" -ForegroundColor Yellow
|
|
|
|
|
+Write-Host " 1. 确认驱动服务: sc.exe query CommModifyKit"
|
|
|
|
|
+Write-Host " 2. 确认串口可用: mode"
|
|
|
|
|
+Write-Host " 3. 确认 UpperFilters: reg query ""HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E978-E325-11CE-BFC1-08002BE10318}"" /v UpperFilters"
|
|
|
|
|
+Write-Host ""
|
|
|
|
|
+Write-Host "如果串口显示 '访问设备失败',请重启计算机使 UpperFilters 生效" -ForegroundColor Yellow
|
|
|
|
|
+Write-Host " 重启命令: shutdown /r /t 0" -ForegroundColor Yellow
|