Keyence VR-6000 Series Software + USB driver deployment
- shopfloor-setup/Keyence/09-Setup-Keyence.ps1: populate placeholder with
MSI install via msiexec and driver install via pnputil. Idempotent on
ProductCode {058E7194-...} and DriverStore entry. Logs to C:\Logs\Keyence\.
- shopfloor-setup/Keyence/installers/VR-6000 Series Software.msi: main
product (1.7 MB; pulled from Keyence6000.exe Inno wrapper's Windows
Installer cache, built with InstallShield 2019).
- shopfloor-setup/Keyence/drivers/: KEYENCE VR Series USB driver
package (.inf + .cat + Wdf/WinUsb co-installers). 2.7 MB, pulled from
DriverStore\FileRepository\keyence_vr_series.inf_amd64_b5e5eb0924d7b4ce.
- preinstall.json: add VC++ 2013 x64 Min + Add entries (PCTypes: ["*"])
as prereqs for VR-6000. GUIDs {A749D8E6-B613-...} and {929FBD26-9020-...}.
Staging footprint for non-Keyence PCs is unchanged (the 4.4 MB Keyence
payload lives under shopfloor-setup/Keyence/ which startnet.cmd only
xcopies for PCTYPE=Keyence). Rollout still requires dropping the two
VC++ 2013 x64 MSIs into \$PXE_IMAGES_DIR/dependencies/vcredist/2013-x64-{min,add}/
on the workstation running sync-preinstall.sh.
Rationale for bundling the MSI + driver locally rather than running
Keyence6000.exe: the Inno wrapper calls an InstallShield child (Setup.exe)
without silent flags, which hangs indefinitely in session 0 during
automated imaging. msiexec + pnputil from the extracted bundle runs
fully non-interactive.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,140 @@
|
||||
# 09-Setup-Keyence.ps1 - Keyence-specific setup (runs after Shopfloor baseline)
|
||||
# 09-Setup-Keyence.ps1 - Keyence type setup (runs during shopfloor-setup phase).
|
||||
#
|
||||
# PLACEHOLDER: add type-specific app installs when details are finalized.
|
||||
# This script will be called by Run-ShopfloorSetup.ps1 as part of the
|
||||
# type-specific phase, after all baseline scripts have completed.
|
||||
# Installs the VR-6000 Series Software MSI and the KEYENCE VR Series USB driver
|
||||
# package. Both payloads ship inside this directory (shopfloor-setup\Keyence\)
|
||||
# and are staged by startnet.cmd during WinPE, so they exist locally on disk
|
||||
# when this script runs - no share mapping required.
|
||||
#
|
||||
# For share-based installs, copy the pattern from CMM/09-Setup-CMM.ps1
|
||||
# (credential lookup + share mount + install from share).
|
||||
# Layout (sibling to this .ps1):
|
||||
# installers\VR-6000 Series Software.msi
|
||||
# drivers\keyence_vr_series.inf
|
||||
# drivers\KEYENCE_VR_SERIES.cat
|
||||
# drivers\amd64\WdfCoInstaller01009.dll
|
||||
# drivers\amd64\WinUsbCoinstaller2.dll
|
||||
#
|
||||
# Prereqs (installed earlier by 00-PreInstall-MachineApps.ps1 via preinstall.json):
|
||||
# - Microsoft Visual C++ 2010 x86 + x64
|
||||
# - Microsoft Visual C++ 2013 x86 + x64 (Min + Add)
|
||||
# - Microsoft Visual C++ 2017/2022 x86 (UCRT covers 2015-2022)
|
||||
#
|
||||
# Idempotent: skips the MSI if the product GUID is already registered, skips
|
||||
# the driver if the package is already in the DriverStore.
|
||||
#
|
||||
# Log: C:\Logs\Keyence\09-Setup-Keyence.log
|
||||
|
||||
Write-Host "=== Keyence Setup ==="
|
||||
Write-Host " (no type-specific apps configured yet)"
|
||||
Write-Host "=== Keyence Setup Complete ==="
|
||||
$ErrorActionPreference = 'Continue'
|
||||
|
||||
$logDir = 'C:\Logs\Keyence'
|
||||
$transcriptLog = Join-Path $logDir '09-Setup-Keyence.log'
|
||||
|
||||
$installerDir = Join-Path $PSScriptRoot 'installers'
|
||||
$msiPath = Join-Path $installerDir 'VR-6000 Series Software.msi'
|
||||
$msiLog = Join-Path $logDir 'VR-6000-msiexec.log'
|
||||
$driverDir = Join-Path $PSScriptRoot 'drivers'
|
||||
$driverInf = Join-Path $driverDir 'keyence_vr_series.inf'
|
||||
|
||||
# Product registration - ProductCode read from the MSI via msiinfo: must match
|
||||
# the value baked in, so idempotency works after a successful install.
|
||||
$productCode = '{058E7194-BDF8-4FA2-9D69-978BB0F25214}'
|
||||
$expectedVersion = '4.3.7'
|
||||
$uninstallRegPaths = @(
|
||||
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$productCode",
|
||||
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$productCode"
|
||||
)
|
||||
|
||||
if (-not (Test-Path $logDir)) {
|
||||
New-Item -Path $logDir -ItemType Directory -Force | Out-Null
|
||||
}
|
||||
|
||||
try { Start-Transcript -Path $transcriptLog -Append -Force | Out-Null } catch {}
|
||||
|
||||
function Write-KeyenceLog {
|
||||
param([string]$Message, [string]$Level = 'INFO')
|
||||
$stamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
||||
Write-Host "[$stamp] [$Level] $Message"
|
||||
}
|
||||
|
||||
Write-KeyenceLog "================================================================"
|
||||
Write-KeyenceLog "=== Keyence Setup session start (PID $PID) ==="
|
||||
Write-KeyenceLog "Running as: $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)"
|
||||
Write-KeyenceLog "Script root: $PSScriptRoot"
|
||||
Write-KeyenceLog "================================================================"
|
||||
|
||||
# --- Detection: skip MSI if already installed at expected version ---
|
||||
$msiAlreadyInstalled = $false
|
||||
foreach ($regPath in $uninstallRegPaths) {
|
||||
if (Test-Path $regPath) {
|
||||
$installed = (Get-ItemProperty $regPath -ErrorAction SilentlyContinue).DisplayVersion
|
||||
if ($installed -eq $expectedVersion) {
|
||||
Write-KeyenceLog "MSI already installed (DisplayVersion=$installed at $regPath) - skipping"
|
||||
$msiAlreadyInstalled = $true
|
||||
break
|
||||
} else {
|
||||
Write-KeyenceLog "MSI registered but at version '$installed' (expected $expectedVersion) - will reinstall" "WARN"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# --- Install MSI ---
|
||||
if (-not $msiAlreadyInstalled) {
|
||||
if (-not (Test-Path $msiPath)) {
|
||||
Write-KeyenceLog "MSI not found at $msiPath - aborting MSI install" "ERROR"
|
||||
} else {
|
||||
$msiSize = [math]::Round((Get-Item $msiPath).Length / 1MB, 1)
|
||||
Write-KeyenceLog "Installing VR-6000 Series Software MSI ($msiSize MB)"
|
||||
$msiArgs = @(
|
||||
'/i', "`"$msiPath`"",
|
||||
'/qn', '/norestart',
|
||||
'ALLUSERS=1', 'REBOOT=ReallySuppress',
|
||||
'/L*v', "`"$msiLog`""
|
||||
)
|
||||
$sw = [Diagnostics.Stopwatch]::StartNew()
|
||||
$proc = Start-Process -FilePath 'msiexec.exe' -ArgumentList $msiArgs -Wait -PassThru -NoNewWindow
|
||||
$sw.Stop()
|
||||
# msiexec exit codes we tolerate: 0 = success, 3010 = success w/ reboot recommended
|
||||
if ($proc.ExitCode -eq 0 -or $proc.ExitCode -eq 3010) {
|
||||
Write-KeyenceLog "MSI install succeeded (exit=$($proc.ExitCode), elapsed=$([int]$sw.Elapsed.TotalSeconds)s)"
|
||||
} else {
|
||||
Write-KeyenceLog "MSI install FAILED (exit=$($proc.ExitCode)). See $msiLog" "ERROR"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# --- Detection: skip driver if already in DriverStore ---
|
||||
$driverAlreadyStaged = $false
|
||||
try {
|
||||
$pnpOut = & pnputil.exe /enum-drivers 2>&1 | Out-String
|
||||
if ($pnpOut -match 'keyence_vr_series\.inf') {
|
||||
Write-KeyenceLog "Keyence USB driver already in DriverStore - skipping"
|
||||
$driverAlreadyStaged = $true
|
||||
}
|
||||
} catch {
|
||||
Write-KeyenceLog "pnputil /enum-drivers failed ($($_.Exception.Message)); attempting install anyway" "WARN"
|
||||
}
|
||||
|
||||
# --- Install driver ---
|
||||
if (-not $driverAlreadyStaged) {
|
||||
if (-not (Test-Path $driverInf)) {
|
||||
Write-KeyenceLog "Driver INF not found at $driverInf - aborting driver install" "ERROR"
|
||||
} else {
|
||||
Write-KeyenceLog "Adding KEYENCE VR Series USB driver to DriverStore via pnputil"
|
||||
$pnp = Start-Process -FilePath 'pnputil.exe' `
|
||||
-ArgumentList '/add-driver', "`"$driverInf`"", '/install' `
|
||||
-Wait -PassThru -NoNewWindow `
|
||||
-RedirectStandardOutput (Join-Path $logDir 'pnputil-stdout.log') `
|
||||
-RedirectStandardError (Join-Path $logDir 'pnputil-stderr.log')
|
||||
# pnputil exit codes: 0 = ok, 3010 = ok (reboot recommended),
|
||||
# 259 = ERROR_NO_MORE_ITEMS (no INFs matched)
|
||||
if ($pnp.ExitCode -eq 0 -or $pnp.ExitCode -eq 3010) {
|
||||
Write-KeyenceLog "Driver install succeeded (exit=$($pnp.ExitCode))"
|
||||
} else {
|
||||
Write-KeyenceLog "Driver install FAILED (exit=$($pnp.ExitCode))" "ERROR"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-KeyenceLog "================================================================"
|
||||
Write-KeyenceLog "=== Keyence Setup session end ==="
|
||||
Write-KeyenceLog "================================================================"
|
||||
|
||||
try { Stop-Transcript | Out-Null } catch {}
|
||||
|
||||
BIN
playbook/shopfloor-setup/Keyence/drivers/KEYENCE_VR_SERIES.cat
Normal file
BIN
playbook/shopfloor-setup/Keyence/drivers/KEYENCE_VR_SERIES.cat
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,94 @@
|
||||
[Version]
|
||||
Signature = "$Windows NT$"
|
||||
DriverPackageDisplayName=%DESC%
|
||||
Class = KeyenceUSB
|
||||
ClassGuid={EE304F37-F588-45FC-91FE-B76873981AD1}
|
||||
Provider = %ProviderName%
|
||||
CatalogFile=KEYENCE_VR_SERIES.cat
|
||||
DriverVer=03/26/2020,1.0.0.0
|
||||
|
||||
; ================== Class section ==================
|
||||
|
||||
[ClassInstall32]
|
||||
Addreg=KeyenceClassReg
|
||||
|
||||
[KeyenceClassReg]
|
||||
HKR,,,0,%ClassName%
|
||||
HKR,,Icon,,-5
|
||||
|
||||
; ========== Manufacturer/Models sections ===========
|
||||
|
||||
[Manufacturer]
|
||||
%ProviderName% = KEYENCE,NTamd64
|
||||
|
||||
[KEYENCE.NTamd64]
|
||||
%USB\KeyenceDevice.DeviceDesc% =USB_Install,USB\VID_0720&PID_102C
|
||||
|
||||
; =================== Installation ===================
|
||||
|
||||
;[1]
|
||||
[USB_Install]
|
||||
Include=winusb.inf
|
||||
Needs=WINUSB.NT
|
||||
|
||||
;[2]
|
||||
[USB_Install.Services]
|
||||
Include=winusb.inf
|
||||
AddService=WinUSB,0x00000002,WinUSB_ServiceInstall
|
||||
|
||||
;[3]
|
||||
[WinUSB_ServiceInstall]
|
||||
DisplayName = %WinUSB_SvcDesc%
|
||||
ServiceType = 1
|
||||
StartType = 3
|
||||
ErrorControl = 1
|
||||
ServiceBinary = %12%\WinUSB.sys
|
||||
|
||||
;[4]
|
||||
[USB_Install.Wdf]
|
||||
KmdfService=WINUSB, WinUsb_Install
|
||||
|
||||
[WinUSB_Install]
|
||||
KmdfLibraryVersion=1.9
|
||||
|
||||
;[5]
|
||||
[USB_Install.HW]
|
||||
AddReg=Dev_AddReg
|
||||
|
||||
[Dev_AddReg]
|
||||
HKR,,DeviceInterfaceGUIDs,0x10000,"{B708995F-18C9-4D52-8D29-41FF2BFBF215}"
|
||||
|
||||
;[6]
|
||||
[USB_Install.CoInstallers]
|
||||
AddReg=CoInstallers_AddReg
|
||||
CopyFiles=CoInstallers_CopyFiles
|
||||
|
||||
[CoInstallers_AddReg]
|
||||
HKR,,CoInstallers32,0x00010000,"WdfCoInstaller01009.dll,WdfCoInstaller","WinUsbCoinstaller2.dll"
|
||||
|
||||
[CoInstallers_CopyFiles]
|
||||
WdfCoInstaller01009.dll
|
||||
WinUsbCoinstaller2.dll
|
||||
|
||||
[DestinationDirs]
|
||||
CoInstallers_CopyFiles=11
|
||||
|
||||
; ================= Source Media Section =====================
|
||||
;[7]
|
||||
|
||||
[SourceDisksNames]
|
||||
1 = %DISK_NAME%,,,\amd64
|
||||
|
||||
[SourceDisksFiles.amd64]
|
||||
WinUSBCoInstaller2.dll=1
|
||||
WdfCoInstaller01009.dll=1
|
||||
|
||||
; =================== Strings ===================
|
||||
|
||||
[Strings]
|
||||
ProviderName="KEYENCE"
|
||||
DESC="VR Series USB-Driver"
|
||||
WinUSB_SvcDesc="WinUSB.sys : KEYENCE USB Device"
|
||||
DISK_NAME="KEYENCE USB Driver Installation Disk"
|
||||
ClassName="KEYENCE USB Device Class"
|
||||
USB\KeyenceDevice.DeviceDesc="VR Series"
|
||||
Binary file not shown.
Reference in New Issue
Block a user