Initial commit

This commit is contained in:
IRBorisov 2024-06-07 20:21:38 +03:00
commit 83d8edd133
32 changed files with 1414 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
~$*
src/logs/*

BIN
distr/!README.docx Normal file

Binary file not shown.

View File

@ -0,0 +1,18 @@
$version = Get-Content VERSION
$config = @{
'Path' = '.\ConceptDeploy\ConceptDeploy.psd1'
'Author' = 'IRBorisov'
'CompanyName' = 'CIHT Concept'
'ModuleVersion' = "$version"
'RootModule' = 'ConceptDeploy.psm1'
'FunctionsToExport' = @('Initialize-Python', 'Install-PythonLibs', 'Install-PSLatest', 'Push-PythonPackage', 'Push-DLL', 'Expand-TarGZ'
'Get-ExchangePath', 'Get-ProjectsPath', 'Get-ServerDistr', 'Get-ConceptLocal',
'Save-DistrManifest', 'Open-DistrManifest', 'Install-Product', 'Enable-Product', 'Disable-Product')
'CmdletsToExport' = @()
'VariablesToExport' = ''
'AliasesToExport' = @()
'Description' = 'CIHT Concept tools deployment module'
}
New-ModuleManifest @config

10
src/CD_Install.ps1 Normal file
View File

@ -0,0 +1,10 @@
# Install ConceptDeploy module for current user
Set-Variable -Name MODULE_NAME -Value 'ConceptDeploy' -Option Constant
$modulePath = "$env:USERPROFILE\Documents\WindowsPowerShell\modules\$MODULE_NAME"
if (Test-Path -Path $modulePath) {
Remove-Item $modulePath -Recurse -Force
}
New-Item -Path $modulePath -ItemType Directory -Force | Out-Null
Copy-Item -Path "$PSScriptRoot\$MODULE_NAME\*" -Destination $modulePath -Recurse

9
src/CD_Tests.ps1 Normal file
View File

@ -0,0 +1,9 @@
$VerbosePreference="Continue"
Import-Module -Name .\ConceptDeploy -Force
# $python = Initialize-Python
# $python = 'python'
# Install-PythonLibs -Python $python
# & $python -m pip list
# Push-DLL

Binary file not shown.

View File

@ -0,0 +1,9 @@
$localPath = $script:MyInvocation.MyCommand.Path
Get-ChildItem (Split-Path $localPath) -Filter '*.ps1' -Recurse | ForEach-Object {
. $_.FullName
}
Get-ChildItem "$(Split-Path $localPath)" -Filter '*.ps1' -Recurse | ForEach-Object {
Export-ModuleMember -Function $_.BaseName
}

View File

@ -0,0 +1,44 @@
function Disable-Product {
[CmdletBinding()]
Param(
[string] $product
)
if ($product -eq 'ExcelHelper') {
return RemoveExcelAddin 'CONCEPT.xlam'
} elseif ($product -eq 'WordHelper') {
return RemoveWordAddin 'CONCEPT.dotm'
} elseif ($product -eq 'Concept-Reports') {
return RemoveExcelAddin 'ConceptReport.xlam'
} elseif ($product -eq 'Concept-Maket') {
return RemoveWordAddin '_Maket.dotm'
} elseif ($product -eq 'Concept-NPA') {
return RemoveWordAddin '_Concept-NPA.dotm'
} elseif ($product -eq 'Concept-Mining') {
return RemoveWordAddin 'Parsers.dotm'
} elseif ($product -eq 'Concept-Markup') {
return RemoveWordAddin 'MARKUP.dotm'
}
return $false
}
function TryDelete($fullName) {
try {
Remove-Item -Path $fullName
return $true
} catch {
return $false
}
}
function RemoveExcelAddin($fileName) {
$fullName = "$($Env:APPDATA)\Microsoft\Excel\XLSTART\$fileName"
Write-Host "Removing addin $fullName"
return TryDelete $fullName
}
function RemoveWordAddin($fileName) {
$fullName = "$($Env:APPDATA)\Microsoft\Word\STARTUP\$fileName"
Write-Host "Removing addin $fullName"
return TryDelete $fullName
}

View File

@ -0,0 +1,47 @@
function Enable-Product {
[CmdletBinding()]
Param(
[string] $product,
[string] $localTools
)
if ($product -eq 'ExcelHelper') {
return CopyExcelAddin "$localTools\optional" 'CONCEPT.xlam'
} elseif ($product -eq 'WordHelper') {
return CopyWordAddin "$localTools\optional" 'CONCEPT.dotm'
} elseif ($product -eq 'Concept-Reports') {
return CopyExcelAddin "$localTools\optional" 'ConceptReport.xlam'
} elseif ($product -eq 'Concept-Maket') {
return CopyWordAddin "$localTools\optional" '_Maket.dotm'
} elseif ($product -eq 'Concept-NPA') {
return CopyWordAddin "$localTools\optional" '_Concept-NPA.dotm'
} elseif ($product -eq 'Concept-Mining') {
return CopyWordAddin "$localTools\optional" 'Parsers.dotm'
} elseif ($product -eq 'Concept-Markup') {
return CopyWordAddin "$localTools\optional" 'MARKUP.dotm'
}
return $false
}
function TryCopy($source, $destination) {
try {
Copy-Item -Path $source -Destination $destination -Force -Recurse -ErrorAction Stop
return $true
} catch {
return $false
}
}
function CopyExcelAddin($location, $fileName) {
$source = "$location\$fileName"
$destination = "$($Env:APPDATA)\Microsoft\Excel\XLSTART\"
Write-Host "Copying addin $fileName to $destination"
return TryCopy $source $destination
}
function CopyWordAddin($location, $fileName) {
$source = "$location\$fileName"
$destination = "$($Env:APPDATA)\Microsoft\Word\STARTUP\"
Write-Host "Copying addin $fileName to $destination"
return TryCopy $source $destination
}

View File

@ -0,0 +1,44 @@
Function Expand-TarGZ {
[CmdletBinding()]
Param(
[string] $inFile,
[string] $outFolder = ($inFile -replace '\.tar.gz$','')
)
$tarFile = Expand-GZ -InFile $inFile
if (-not $tarFile) {
Write-Error "Cannot unpack gzip $inFile into $tarFile"
Exit
}
if (-not (Get-Command Expand-7Zip -ErrorAction Ignore)) {
Install-Package -Scope CurrentUser -Force 7Zip4PowerShell > $null
}
Expand-7Zip $tarFile $outFolder
Remove-Item $tarFile -Recurse -Force
return $outFolder
}
Function Expand-GZ([string] $inFile) {
$outFile = ($inFile -replace '\.gz$','')
if (Test-Path -Path $outFile -PathType leaf) {
Remove-Item -Path $outFile -Force
}
$BUFFER_SIZE = 1024
$inputStream = New-Object System.IO.FileStream $inFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read)
$outputStream = New-Object System.IO.FileStream $outFile, ([IO.FileMode]::Create), ([IO.FileAccess]::Write), ([IO.FileShare]::None)
$gzipStream = New-Object System.IO.Compression.GzipStream $inputStream, ([IO.Compression.CompressionMode]::Decompress)
$buffer = New-Object byte[]($BUFFER_SIZE)
while($true) {
$read = $gzipstream.Read($buffer, 0, $BUFFER_SIZE)
if ($read -le 0){break}
$outputStream.Write($buffer, 0, $read)
}
$gzipStream.Close()
$outputStream.Close()
$inputStream.Close()
return $outFile
}

View File

@ -0,0 +1,4 @@
# Return path to local Concept CIHT files
function Get-ConceptLocal {
return "$Env:USERPROFILE\.concept"
}

View File

@ -0,0 +1,10 @@
# Get exchange server folder for CIHT CONCEPT
function Get-ExchangePath {
$server = '\\fs1.concept.ru\Exchange'
if (-not (Test-Path -Path $server)) {
Write-Error "Failed to locate server $server. Ensure VPN is running"
Exit
} else {
return $server
}
}

View File

@ -0,0 +1,10 @@
# Get projects server folder for CIHT CONCEPT
function Get-ProjectsPath {
$server = '\\fs1.concept.ru\projects'
if (-not (Test-Path -Path $server)) {
Write-Error "Failed to locate server $server. Ensure VPN is running"
Exit
} else {
return $server
}
}

View File

@ -0,0 +1,10 @@
# Get server code distribution folder for CIHT CONCEPT
function Get-ServerDistr {
$server = '\\fs1.concept.ru\projects\10 Автоматизация деятельности\!Concept'
if (-not (Test-Path -Path $server)) {
Write-Error "Failed to locate server $server. Ensure VPN is running"
Exit
} else {
return $server
}
}

View File

@ -0,0 +1,165 @@
function Initialize-Python {
[CmdletBinding()]
Param(
[string] $minimalVersion = '3.12.2',
[string] $installPath = 'C:\Tools\Python312-venv',
[string] $pythonInstall = 'C:\Tools\Python312',
[string] $pythonDistr = ''
)
$python = SearchInstalledEnvironment -TargetPath $installPath -MinimalVersion $minimalVersion
if ($python -ne '') {
return $python
}
$python = SearchLocalInstallation -TargetPath $pythonInstall -MinimalVersion $minimalVersion
if ($python -eq '') {
Write-Host "Failed to locate local installation of python"
$python = SearchUserPath -MinimalVersion $minimalVersion
}
if ($python -eq '') {
Write-Host "Failed to locate python in PATH variable"
$python = SearchUserRegistry -MinimalVersion $minimalVersion
}
if ($python -eq '') {
Write-Host "Failed to locate python in Windows registry"
$python = InstallLocalPython -Version $minimalVersion -TargetPath $pythonInstall -PythonDistr $pythonDistr
}
if ($python -eq '') {
return ''
}
CreateVirtualEnvironment -Python $python -TargetPath $installPath
return "$installPath\Scripts\python.exe"
}
function SearchInstalledEnvironment($targetPath, $minimalVersion) {
$python = "$targetPath\Scripts\python.exe"
if (-not (Test-Path -Path $python -PathType Leaf)) {
Write-Host "Failed to locate Python venv at $targetPath"
return ''
}
$installedVersion = GetPythonVersion $python
if(!$installedVersion -or
$installedVersion -eq '' -or
[System.Version] $installedVersion -lt [System.Version] $minimalVersion) {
Write-Host "Removing invalid python env: $targetPath" -ForegroundColor DarkRed
Remove-Item $targetPath -Recurse
return ''
} else {
Write-Host "Found Python environment $installedVersion : $python"
return $python
}
}
function SearchLocalInstallation($targetPath, $minimalVersion) {
$python = "$targetPath\python.exe"
if (-not (Test-Path -Path $python -PathType Leaf)) {
return ''
}
$installedVersion = GetPythonVersion $python
if(!$installedVersion -or
$installedVersion -eq '' -or
[System.Version] $installedVersion -ne [System.Version] $minimalVersion) {
return ''
}
Write-Host "Found installed python $installedVersion : $python"
return $python
}
function SearchUserPath($minimalVersion) {
$globalVersion = GetPythonVersion 'python'
if(!$globalVersion -or
$globalVersion -eq '' -or
[System.Version] $globalVersion -ne [System.Version] $minimalVersion) {
return ''
}
Write-Host "Found globally installed python: $globalVersion"
return 'python'
}
function SearchUserRegistry($minimalVersion) {
if ([Environment]::Is64BitProcess) {
$pythonRegistry = 'HKCU:\SOFTWARE\Python\PythonCore\3.12\InstallPath'
if(!$pythonRegistry) {
$pythonRegistry = 'HKLM:\SOFTWARE\Python\PythonCore\3.12\InstallPath'
}
} else {
$pythonRegistry = 'HKCU:\SOFTWARE\WOW6432Node\Python\PythonCore\3.12-32\InstallPath'
if(!$pythonRegistry) {
$pythonRegistry = 'HKLM:\SOFTWARE\WOW6432Node\Python\PythonCore\3.12-32\InstallPath'
}
}
$python = Get-ItemPropertyValue -Path $pythonRegistry -Name 'ExecutablePath' -ErrorAction 'SilentlyContinue'
if (-not $python) {
return ''
}
$version = GetPythonVersion $python
if(!$version -or
$version -eq '' -or
[System.Version] $version -lt [System.Version] $minimalVersion) {
return ''
}
Write-Host "Found installed local python: $python" -ForegroundColor DarkGreen
return $python
}
function InstallLocalPython($version, $targetPath, $pythonDistr = '') {
if ($pythonDistr -eq '') {
$installer = DowloadPython $version
} else {
$installer = $pythonDistr
}
$arguments = "/quiet InstallAllUsers=0 Include_test=0 Include_doc=0 Include_launcher=0 TargetDir=$targetPath"
$process = (Start-Process -FilePath $installer -ArgumentList $arguments -PassThru -NoNewWindow)
$process.WaitForExit()
if ($pythonDistr -eq '') {
Remove-Item $installer -ErrorAction SilentlyContinue
}
$python = "$targetPath\python.exe"
if (-not (Test-Path -Path $python -PathType Leaf)) {
Write-Error "Failed to install local python: $installer"
return ''
} else {
Write-Host "Installed local python: $targetPath" -ForegroundColor DarkGreen
return $python
}
}
function GetPythonVersion($pythonExe) {
$eap = $ErrorActionPreference
$ErrorActionPreference = 'SilentlyContinue'
$version = & $pythonExe --version
$ErrorActionPreference = $eap
if (!$version -or $version -eq '' -or $LASTEXITCODE -ne 0) {
return ''
} else {
return $version.Split(' ')[1]
}
}
function DowloadPython($version) {
$pythonUrl = GetPythonURL $version
$pythonTemp = "$Env:TEMP\installer-python-$version.exe"
Write-Host "Downloading python installer to $pythonTemp"
try {
(New-Object System.Net.WebClient).DownloadFile($pythonUrl, $pythonTemp)
} catch [System.Net.WebException] {
Write-Error "An exception was caught when trying to download Python: $($_.Exception.Message)"
Exit
}
return $pythonTemp
}
function CreateVirtualEnvironment($python, $targetPath) {
& $python -m venv $targetPath
Write-Host "Created virtual environment $targetPath" -ForegroundColor DarkGreen
}
function GetPythonURL($version) {
if ([Environment]::Is64BitProcess) {
return "https://www.python.org/ftp/python/$version/python-$version-amd64.exe"
} else {
return = "https://www.python.org/ftp/python/$version/python-$version.exe"
}
}

View File

@ -0,0 +1,4 @@
# Download and install latest version of powershell
function Install-PSLatest {
Invoke-Expression "& { $(Invoke-RestMethod https://aka.ms/install-powershell.ps1) } -UseMSI -Quiet"
}

View File

@ -0,0 +1,122 @@
# Install concept product
function Install-Product {
[CmdletBinding()]
Param(
[string] $product,
[string] $distr,
[string] $localTemplates,
[string] $localTools
)
if ($product -eq 'ExcelHelper') {
return InstallExcelAddinOptional $distr 'CONCEPT.xlam' $localTools
} elseif ($product -eq 'WordHelper') {
return $(InstallWordAddinOptional $distr 'CONCEPT.dotm' $localTools -and
InstallUserModel $distr 'banned-words.txt')
} elseif ($product -eq 'Concept-Maket') {
return InstallWordAddinOptional $distr '_Maket.dotm' $localTools
} elseif ($product -eq 'Concept-Reports') {
return InstallExcelAddinOptional $distr "ConceptReport.xlam" $localTools
} elseif ($product -eq 'Concept-Hierarchy') {
return InstallTemplate $distr '30 Иерархизатор.vstm' $localTemplates
} elseif ($product -eq 'Concept-Blocks') {
return $(InstallTemplate $distr '20 Концепт-Блоки.vstm' $localTemplates -and
InstallTemplate $distr 'Технологии\Блоки-Excel.xltx' $localTemplates -and
InstallTemplate $distr 'Технологии\Блоки-Word.dotx' $localTemplates)
} elseif ($product -eq 'Concept-Defs') {
return $(InstallTemplate $distr '22 Карта понятий.vstm' $localTemplates -and
InstallTemplate $distr 'Технологии\Определения-Excel.xltx' $localTemplates)
} elseif ($product -eq 'Concept-NPA') {
Write-Host "Copying file !Реестр НПА.xlsm"
Copy-Item -Path "$distr\data\!Реестр НПА.xlsm" -Destination "$localTools\optional\" -Force
return $(InstallTemplate $distr '60 НПА UI.xltm' $localTemplates -and
InstallTemplate $distr '21 Схема Реестра НПА.vstm' $localTemplates -and
InstallWordAddinOptional $distr '_Concept-NPA.dotm' $localTools)
} elseif ($product -eq 'Concept-Mining') {
return $(InstallTemplate $distr '55 Майнинг.xltm' $localTemplates -and
InstallWordAddinOptional $distr 'Parsers.dotm' $localTools -and
InstallLocalModel $distr 'ActionVerbs.txt' $localTools)
} elseif ($product -eq 'Concept-Markup') {
return $(InstallTemplate $distr 'Разметка' $localTemplates -and
InstallWordAddinOptional $distr 'MARKUP.dotm' $localTools)
}
return $false
}
function TryCopy($source, $destination) {
try {
Copy-Item -Path $source -Destination $destination -Force -Recurse -ErrorAction Stop
return $true
} catch {
return $false
}
}
function InstallUserModel($distr, $fileName) {
$source = "$distr\models\$fileName"
$destination = "$(Get-ConceptLocal)\models\"
Write-Host "Update user model $fileName at $destination"
return TryCopy $source $destination
}
function InstallLocalModel($distr, $fileName, $localTools) {
$source = "$distr\models\$fileName"
$destination = "$localTools\models\"
Write-Host "Copying model file $fileName to $destination"
return TryCopy $source $destination
}
function InstallTemplate($distr, $fileName, $templates) {
$source = "$distr\data\Templates\$fileName"
$destination = "$templates\"
Write-Host "Copying template $fileName to $destination"
return TryCopy $source $destination
}
function InstallExcelAddin($distr, $fileName) {
$source = "$distr\data\Add-ins\Excel\$fileName"
$destination = "$($Env:APPDATA)\Microsoft\Excel\XLSTART\"
Write-Host "Copying addin $fileName to $destination"
return TryCopy $source $destination
}
function InstallExcelAddinOptional($distr, $fileName, $localTools) {
$source = "$distr\data\Add-ins\Excel\$fileName"
$destination1 = "$localTools\optional\"
Write-Host "Copying optional addin $fileName to $destination1"
if (-not (TryCopy $source $destination1)) {
return $false
}
$destination2 = "$($Env:APPDATA)\Microsoft\Excel\XLSTART\"
if (Test-Path -Path "$destination2\$fileName" -PathType Leaf) {
Write-Host "Copying optional addin $fileName to $destination2"
return TryCopy $source $destination2
}
return $true
}
function InstallWordAddin($distr, $fileName) {
$source = "$distr\data\Add-ins\Word\$fileName"
$destination = "$($Env:APPDATA)\Microsoft\Word\STARTUP\"
Write-Host "Copying addin $fileName to $destination"
return TryCopy $source $destination
}
function InstallWordAddinOptional($distr, $fileName, $localTools) {
$source = "$distr\data\Add-ins\Word\$fileName"
$destination1 = "$localTools\optional\"
Write-Host "Copying optional addin $fileName to $destination1"
if (-not (TryCopy $source $destination1)) {
return $false
}
$destination2 = "$($Env:APPDATA)\Microsoft\Word\STARTUP\"
if (Test-Path -Path "$destination2\$fileName" -PathType Leaf) {
Write-Host "Copying optional addin $fileName to $destination2"
return TryCopy $source $destination2
}
return $true
}

View File

@ -0,0 +1,42 @@
# Install Python libraries used by CIHT CONCEPT tools
$global:globalLibs = @(
'pywin32',
'pandas'
)
$global:localLibs = @(
'cctext',
'vbatopy'
)
function Install-PythonLibs {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string]$python,
[string]$localDistr = ''
)
Write-Host "`nUpgrading pip tools..." -ForegroundColor DarkGreen
& $python -m pip install --upgrade pip
InstallGlobalLibs
InstallLocalLibs -libsPath $localDistr
}
function InstallGlobalLibs {
foreach ($lib in $globalLibs) {
Write-Host "`nInstalling from global repo: $lib" -ForegroundColor DarkGreen
& $python -m pip install -U $lib
}
}
function InstallLocalLibs([string]$libsPath) {
if ($libsPath -eq '') {
. "$PSScriptRoot\Get-ServerDistr.ps1"
$libsPath = "$(Get-ServerDistr)\src"
}
foreach ($lib in $localLibs) {
Write-Host "`nInstalling from local folder: $libsPath\$lib" -ForegroundColor DarkGreen
& $python -m pip install -U "$libsPath\$lib"
}
}

View File

@ -0,0 +1,16 @@
function Open-DistrManifest() {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string] $fileName
)
Write-Host "Open distribution manifest ... $fileName"
$result = [ordered] @{}
if (-not (Test-Path -Path $fileName -PathType Leaf)) {
return $result
}
$jsonObj = Get-Content -Path $fileName -Raw | ConvertFrom-Json
$jsonObj.PSObject.Properties | ForEach-Object { $result[$_.Name] = $_.Value }
return $result
}

View File

@ -0,0 +1,22 @@
# Push Dynamic library to server and distr
function Push-DLL {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string] $dllName,
[Parameter(Mandatory=$true)]
[string] $dllPath,
[bool] $pushServer = $true,
[bool] $pushDistr = $true
)
. "$PSScriptRoot\Get-ServerDistr.ps1"
. "$PSScriptRoot\Get-ExchangePath.ps1"
if ($pushServer) {
Copy-Item -Path "$dllPath\$dllName.dll" -Destination "$(Get-ServerDistr)\dll\"
}
if ($pushDistr) {
Copy-Item -Path "$dllPath\$dllName.dll" -Destination "$(Get-ExchangePath)\ConceptDistr\dll\"
}
}

View File

@ -0,0 +1,49 @@
# Push python module to Concept server and distr
function Push-PythonPackage {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string] $packageName,
[Parameter(Mandatory=$true)]
[string] $packageRoot,
[bool] $pushServer = $true,
[bool] $pushDistr = $true
)
. "$PSScriptRoot\Get-ServerDistr.ps1"
. "$PSScriptRoot\Get-ExchangePath.ps1"
if ($pushServer) {
UpdatePythonIn -PackageName $packageName -PackageRoot $packageRoot -ServerRoot "$(Get-ServerDistr)\src"
}
if ($pushDistr) {
UpdatePythonIn -PackageName $packageName -PackageRoot $packageRoot -ServerRoot "$(Get-ExchangePath)\ConceptDistr\src"
}
}
function UpdatePythonIn($packageName, $packageRoot, $serverRoot) {
. "$PSScriptRoot\Expand-TarGZ.ps1"
$targz = Get-Childitem -Path "$packageRoot\output\$packageName\*.tar.gz" -Name
if (-not $targz) {
Write-Error "Cannot find unique source distribution in $packageRoot\output\$packageName\"
Exit
}
$targz = "$packageRoot\output\$packageName\$targz"
$destination = "$serverRoot\$packageName"
if (Test-Path -Path $destination) {
Remove-Item $destination -Recurse -Force
}
$unpacked = Expand-TarGZ -InFile $targz
if (-not $unpacked) {
Write-Error "Cannot unpack $targz"
Exit
}
Move-Item -Path "$unpacked\$packageName-*\*" -Destination "$unpacked"
Remove-Item -Path "$unpacked\$packageName-*"
Move-Item -Path "$unpacked" -Destination "$destination"
}

View File

@ -0,0 +1,12 @@
function Save-DistrManifest() {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
$manifestData,
[Parameter(Mandatory=$true)]
[string] $fileName
)
Write-Host "Save distribution manifest ... $fileName"
$manifestData | ConvertTo-Json | Out-File -Encoding "UTF8" $fileName
}

View File

@ -0,0 +1,68 @@
# Prepare and deploy distribution files for standalone distributive
Set-StrictMode -Version 3.0
Set-Variable -Name PYTHON_DOWNLOAD_VERSION -Value '3.12.2'
Set-Variable -Name MODULE_NAME -Value 'ConceptDeploy'
function DeployDistributives {
& .\CD_GenerateManifest.ps1
Import-Module -Name ".\$MODULE_NAME" -Force
Write-Host "Preparing python environment clone..."
$preparedEnvironment = PrepareEnvironemnt
Write-Host "Creating python packages archive from local environment..."
$envZip = 'C:\Tools\Python312-venv.zip'
Compress-Archive -Path "$preparedEnvironment\*" -DestinationPath $envZip -Force
Remove-Item $preparedEnvironment -Recurse -Force
Write-Host "Downloading python $PYTHON_DOWNLOAD_VERSION installer..."
$pythonDistr = DowloadPython $PYTHON_DOWNLOAD_VERSION
$destination = "$(Get-ExchangePath)\ConceptDistr\distr"
if (-not (Test-Path -Path $destination)) {
New-Item -Path $destination -ItemType Directory -Force | Out-Null
}
Write-Host "Moving files to destination... $destination"
Copy-Item -Path $pythonDistr -Destination "$destination\" -Force
Copy-Item -Path $envZip -Destination "$destination\" -Force
Remove-Item $pythonDistr -Force
Remove-Item $envZip -Force
}
function PrepareEnvironemnt {
$coreFiles = 'activate', 'activate.bat', 'Activate.ps1', 'deactivate.bat', 'python.exe', 'pythonw.exe', 'pythonw_d.exe', 'python_d.exe'
$tools = 'C:\Tools'
$original = "$tools\Python312-venv"
$envClone = "$tools\Python312-cln"
if (-not (Test-Path -Path $original)) {
Exit 1
}
if (Test-Path -Path $envClone) {
Remove-Item $envClone -Recurse -Force
}
New-Item -Path $envClone -ItemType Directory -Force | Out-Null
Copy-Item -Path "$original\Include" -Destination "$envClone\Include" -Recurse
Copy-Item -Path "$original\Lib" -Destination "$envClone\Lib" -Recurse
Copy-Item -Path "$original\Scripts" -Destination "$envClone\Scripts" -Recurse
Get-ChildItem $envClone -Recurse | Where-Object{$_.Name.EndsWith('.pyc')} | Remove-Item
Get-ChildItem -Path "$envClone\Scripts\*" -Recurse -Include $coreFiles | Remove-Item
return $envClone
}
function DowloadPython($version) {
$pythonUrl = "https://www.python.org/ftp/python/$version/python-$version-amd64.exe"
$pythonTemp = "$Env:TEMP\python-$version-amd64.exe"
try {
(New-Object System.Net.WebClient).DownloadFile($pythonUrl, $pythonTemp)
} catch [System.Net.WebException] {
Write-Error "An exception was caught when trying to download Python: $($_.Exception.Message)"
Exit
}
return $pythonTemp
}
DeployDistributives

34
src/DeployServer.ps1 Normal file
View File

@ -0,0 +1,34 @@
# Deploy ConceptDeploy module files to server storage
Set-StrictMode -Version 3.0
Set-Variable -Name MODULE_NAME -Value 'ConceptDeploy'
& .\CD_GenerateManifest.ps1
Import-Module -Name ".\$MODULE_NAME" -Force
$conceptServer = "$(Get-ServerDistr)"
$serverSrc = "$conceptServer\src\$MODULE_NAME"
if (Test-Path -Path $serverSrc) {
Remove-Item $serverSrc -Recurse -Force
}
New-Item -Path "$serverSrc\$MODULE_NAME" -ItemType Directory -Force | Out-Null
Copy-Item -Path "$PSScriptRoot\CD_Install.ps1" -Destination "$serverSrc\"
Copy-Item -Path "$PSScriptRoot\VERSION" -Destination "$serverSrc\"
Copy-Item -Path "$PSScriptRoot\$MODULE_NAME\*" -Destination "$serverSrc\$MODULE_NAME" -Recurse
$distr = "$(Get-ExchangePath)\ConceptDistr"
$exchangeSrc = "$distr\src\$MODULE_NAME"
if (Test-Path -Path $exchangeSrc) {
Remove-Item $exchangeSrc -Recurse -Force
}
New-Item -Path $exchangeSrc -ItemType Directory -Force | Out-Null
Copy-Item -Path "$PSScriptRoot\InstallAllProducts.ps1" -Destination "$distr\"
Copy-Item -Path "$PSScriptRoot\UpdateConceptProducts.ps1" -Destination "$distr\"
Copy-Item -Path "$PSScriptRoot\UninstallConceptProducts.ps1" -Destination "$distr\"
Copy-Item -Path "$PSScriptRoot\install_launcher.bat" -Destination "$distr\install.bat"
Copy-Item -Path "$PSScriptRoot\uninstall.bat" -Destination "$distr\uninstall.bat"
Copy-Item -Path "$PSScriptRoot\install_from_server.bat" -Destination "$distr\install_from_server.bat"
Copy-Item -Path "$PSScriptRoot\install_standalone.bat" -Destination "$distr\install_standalone.bat"
Copy-Item -Path "$PSScriptRoot\..\distr\!README.docx" -Destination "$distr\!README.docx"
Copy-Item -Path "$serverSrc\*" -Destination $exchangeSrc -Recurse

344
src/InstallAllProducts.ps1 Normal file
View File

@ -0,0 +1,344 @@
# Install Concept products from local distr
# Setup constants
Set-Variable -Name OFFICE_REGISTRY -Value 'HKCU:\SOFTWARE\Microsoft\Office\16.0' -Option Constant
Set-Variable -Name DOMAINS_REGISTRY -Value 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains' -Option Constant
Set-Variable -Name SERVER_PATH -Value '\\fs1.concept.ru\' -Option Constant
Set-Variable -Name TEMPLATES_PATH -Value "$Env:APPDATA\Microsoft\Шаблоны" -Option Constant
Set-Variable -Name TEMPLATES_NORMAL_PATH -Value "$Env:APPDATA\Microsoft\Templates" -Option Constant
$word = If (Test-Path "${OFFICE_REGISTRY}\Word") {"${OFFICE_REGISTRY}\Word"} Else {''}
$excel = If (Test-Path "${OFFICE_REGISTRY}\Excel") {"${OFFICE_REGISTRY}\Excel"} Else {''}
$visio = If (Test-Path "${OFFICE_REGISTRY}\Visio") {"${OFFICE_REGISTRY}\Visio"} Else {''}
function InstallAllProducts {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string] $distrPath,
[switch] $skipShortcuts = $false,
[switch] $standalone = $false
)
Set-StrictMode -Version 3.0
if (-not (Test-Path -Path $distrPath)) {
Write-Error "Distribution path does not exist: $distrPath"
Exit 1
}
$InformationPreference="Continue"
StartLog
Write-Host "Starting installation procedure for Concept technologies" -ForegroundColor DarkGreen
Write-Host "Sources: $distrPath"
Write-Host "Skip shortcuts: $skipShortcuts`n"
Write-Host "Dependencies status:" -ForegroundColor DarkGreen
StateSystemStatus
$driveLetter = MountPathDrive $distrPath
$distr = "${driveLetter}`:"
$localHome = "C:\Tools"
Write-Host "`nEnsure core is updated..." -ForegroundColor DarkGreen
PrepareCore $distr $distrPath $standalone $localHome
Write-Host "`nSetup SecureLocation options for $SERVER_PATH" -ForegroundColor DarkGreen
SetupTrustedLocations $SERVER_PATH
Write-Host "`nInitializing template path for Office applications: $TEMPLATES_PATH" -ForegroundColor DarkGreen
InitializeTemplates $TEMPLATES_PATH
Write-Host "Update templates at $TEMPLATES_PATH" -ForegroundColor DarkGreen
UpdateTemplates "${distr}\data\Templates" $TEMPLATES_PATH $localHome
Copy-Item -Path "$TEMPLATES_PATH\Normal.dotm" -Destination "${TEMPLATES_NORMAL_PATH}\Normal.dotm"
Copy-Item -Path "$TEMPLATES_PATH\NormalEmail.dotm" -Destination "${TEMPLATES_NORMAL_PATH}\NormalEmail.dotm"
Write-Host "`nUpdating products..." -ForegroundColor DarkGreen
UpdateProducts $distr $TEMPLATES_PATH $localHome
if (-not ($skipShortcuts)) {
Write-Host "`nInstalling desktop shortcuts" -ForegroundColor DarkGreen
Copy-Item -Path "${distr}\data\Shortcuts\*" `
-Destination "$($Env:USERPROFILE)\Desktop\" `
-Exclude (Get-ChildItem "$($Env:USERPROFILE)\Desktop") -Force -Recurse
}
Write-Host "`nClean up procedure ..." -ForegroundColor Blue
Remove-PSDrive -Name $driveLetter
Write-Host "`nInstallation complete" -ForegroundColor Green
StopLog
}
function StartLog {
$ErrorActionPreference='SilentlyContinue'
Stop-Transcript | Out-Null
$ErrorActionPreference = "Continue"
$dateSuffix = (Get-Date -UFormat "%Y%m%d_%I-%M-%S").ToString()
$logFile = "${PSScriptRoot}\logs\${dateSuffix}_$($Env:USERNAME).txt"
Start-Transcript -Path $logFile -IncludeInvocationHeader
}
function StopLog {
Stop-Transcript
}
function CheckProcess($processName) {
$app = Get-Process $processName -ErrorAction SilentlyContinue
return -not ($null -eq $app)
}
function StateSystemStatus() {
if ($word) {
Write-Host "Word running: $(CheckProcess 'WINWORD')"
} else {
Write-Host 'Word not found' -ForegroundColor DarkRed
}
if ($excel) {
Write-Host "Excel running: $(CheckProcess 'EXCEL')"
} else {
Write-Host 'Excel not found' -ForegroundColor DarkRed
}
if ($visio) {
Write-Host "Visio running: $(CheckProcess 'VISIO')"
} else {
Write-Host 'Visio not found' -ForegroundColor DarkRed
}
}
function MountPathDrive($targetPath) {
Write-Host "`nCreating temporary drive for ${targetPath}" -ForegroundColor DarkGreen
[char[]] $takenDrive = (Get-PSDrive -Name [E-Z]).Name
$driveLetter = ([char[]] (69..90)).Where({ $_ -notin $takenDrive }, 'First')[0]
if (!$driveLetter) {
Write-Error "No available drive letter"
Exit 1
}
New-PSDrive -Name $driveLetter -PSProvider FileSystem -Root $targetPath -Scope Global | Out-Null
Write-Host "Drive ${driveLetter} mounted"
return $driveLetter
}
function UpdateTemplates($source, $destination, $localHome) {
Copy-Item -Path "${source}\*" -Destination "$destination\" -Force -Recurse
$templatesFile = "${localHome}\script\templates_list.txt"
$sourcePrefix = $(Resolve-Path $source).ProviderPath
Write-Host "Save temapltes list to $templatesFile"
Get-ChildItem -Recurse $source | Where-Object { ! $_.PSIsContainer } | Select-Object FullName `
| ForEach-Object { $_.FullName.Replace("$sourcePrefix\",'') } `
| Out-File -Encoding "UTF8" $templatesFile
}
function UpdateProducts($distr, $templates, $localHome) {
$serverManifest = "${distr}\distribution_manifest.json"
$serverJSON = Open-DistrManifest $serverManifest
$localManifest = "C:\Tools\distribution_manifest.json"
$localJSON = Open-DistrManifest $localManifest
$firstRun = $localJSON.Count -eq 0
Write-Host "`n"
foreach ($product in $serverJSON.Keys) {
$serverVersion = [System.Version] $serverJSON.$product
if ($localJSON.Contains($product)) {
$localVersion = [System.Version] $localJSON.$product
} else {
$localVersion = [System.Version] "0.0.0"
}
if ($serverVersion -eq $localVersion) {
Write-Host "Product ${product}: ${serverVersion} ... up to date`n" -ForegroundColor Gray
} elseif (Install-Product $product $distr $templates $localHome) {
Write-Host "Product ${product}: ${serverVersion} ... updated from ${localVersion}`n" -ForegroundColor DarkGreen
$localJSON[$product] = $serverJSON.$product
} else {
Write-Host "Product ${product}: ${serverVersion} ... failed to update from ${localVersion}`n" -ForegroundColor DarkRed
}
}
if ($firstRun) {
Write-Host "`nFirst time run. Enabling default addins" -ForegroundColor DarkGreen
Enable-Product 'WordHelper' $localHome | Out-Null
Enable-Product 'ExcelHelper' $localHome | Out-Null
Enable-Product 'Concept-Reports' $localHome | Out-Null
}
Save-DistrManifest $localJSON $localManifest
}
function PrepareCore($distrMount, $distrPath, $standalone, $localHome) {
if (CheckConceptDeploy $distrMount) {
Import-Module -Name ConceptDeploy
Write-Host "ConceptDeploy already installed: $((Get-Module -Name 'ConceptDeploy').Version)" -ForegroundColor Gray
} else {
Write-Host "Installing Powershell library: ConceptDeploy" -ForegroundColor DarkGreen
. "$distrMount\src\ConceptDeploy\CD_Install.ps1"
Import-Module -Name ConceptDeploy
Write-Host "Installed version: ConceptDeploy $((Get-Module -Name 'ConceptDeploy').Version)"
}
if (-not (Test-Path -Path "${localHome}\script\")) {
New-Item -Path "${localHome}\script\" -ItemType Directory -Force | Out-Null
}
Copy-Item -Path "${distrMount}\UpdateConceptProducts.ps1" -Destination "${localHome}\script\"
Copy-Item -Path "${distrMount}\UninstallConceptProducts.ps1" -Destination "${localHome}\script\"
Copy-Item -Path "${distrMount}\uninstall.bat" -Destination "${localHome}\script\uninstall-concept.bat"
Write-Host "Installed scripts to $localHome\script\" -ForegroundColor Gray
Write-Host "`nEnsure Python environement is updated..." -ForegroundColor DarkGreen
$python = ''
if ($standalone) {
if ([Environment]::Is64BitProcess) {
$python = Initialize-Python -PythonDistr "${distrPath}\distr\python-3.12.2-amd64.exe"
} else {
Write-Host "32-bit system do not support Standalone installation mode" -ForegroundColor Red
}
} else {
$python = Initialize-Python
}
if ($python -eq '') {
Write-Host "Skip python libraries because could not initialize python" -ForegroundColor DarkRed
} elseif ($standalone) {
$pythonFolder = (Get-item $python).Directory.Parent.FullName
Expand-Archive -Path "${distrMount}\distr\Python312-venv.zip" -DestinationPath $pythonFolder -Force
} else {
Install-PythonLibs -python $python -localDistr "${distrPath}\src"
}
Write-Host "`nUpdate dynamic libraries at ${localHome}" -ForegroundColor DarkGreen
if (-not (Test-Path -Path "${localHome}\dll")) {
New-Item -Path "${localHome}\dll" -ItemType Directory -Force | Out-Null
}
Copy-Item -Path "${distrMount}\dll" -Destination "${localHome}\" -Force -Recurse
$conceptLocal = Get-ConceptLocal
if (-not (Test-Path -Path "${conceptLocal}\models")) {
New-Item -Path "${conceptLocal}\models" -ItemType Directory -Force | Out-Null
}
if (-not (Test-Path -Path "${localHome}\optional")) {
New-Item -Path "${localHome}\optional" -ItemType Directory -Force | Out-Null
}
if (-not (Test-Path -Path "${localHome}\models")) {
New-Item -Path "${localHome}\models" -ItemType Directory -Force | Out-Null
}
}
function CheckConceptDeploy($distr) {
$currentModule = Get-Module -ListAvailable ConceptDeploy
if (!$currentModule) {
return $false
}
$newVersion = [System.Version] (Get-Content -Path "${distr}\src\ConceptDeploy\VERSION")
$oldVersion = $currentModule.Version
return $oldVersion -ge $newVersion
}
function InitializeTemplates($templates) {
$eap = $ErrorActionPreference
$ErrorActionPreference = 'SilentlyContinue'
if (-not (Test-Path -Path $templates)) {
New-Item -ItemType Directory -Path $templates -Force | Out-Null
Write-Host "Created office templates directory: ${templates}"
}
if ($word) {
if(-not (
Get-ItemProperty "${word}\Options" |
ForEach-Object { if ($_ -like '*PersonalTemplates*') { return $true } }
)) {
New-ItemProperty -Path "${word}\Options" -Name 'PersonalTemplates' -Value $templates -PropertyType ExpandString -Force
} else {
Set-ItemProperty -Path "${word}\Options" -Name 'PersonalTemplates' -Value $templates
}
}
if ($excel) {
if(-not (
Get-ItemProperty "${excel}\Options" |
ForEach-Object { if ($_ -like '*PersonalTemplates*') { return $true } }
)) {
New-ItemProperty -Path "${excel}\Options" -Name 'PersonalTemplates' -Value $templates -PropertyType ExpandString -Force
} else {
Set-ItemProperty -Path "${excel}\Options" -Name 'PersonalTemplates' -Value $templates
}
}
if ($visio) {
if(-not (
Get-ItemProperty "${visio}\Application" |
ForEach-Object { if ($_ -like '*PersonalTemplates*') { return $true } }
)) {
New-ItemProperty -Path "${visio}\Options" -Name 'PersonalTemplates' -Value $templates -PropertyType ExpandString -Force
} else {
Set-ItemProperty -Path "${visio}\Application" -Name 'PersonalTemplates' -Value $templates
}
}
$ErrorActionPreference = $eap
}
function SetupTrustedLocations($serverLocation) {
if ($word) {
if (AddTrustedLocation $word $serverLocation) {
Write-Host 'Word ... DONE'
} else {
Write-Host 'Word ... EXISTS'
}
}
if ($excel) {
if (AddTrustedLocation $excel $serverLocation) {
Write-Host 'Excel ... DONE'
} else {
Write-Host 'Excel ... EXISTS'
}
}
if ($visio) {
if (AddTrustedLocation $visio $serverLocation) {
Write-Host 'Visio ... DONE'
} else {
Write-Host 'Visio ... EXISTS'
}
}
$conceptDomain = "${DOMAINS_REGISTRY}\concept.ru\fs1"
if (Test-Path -Path $conceptDomain) {
Write-Host 'Intranet settings ... EXISTS'
} else {
New-Item -Path "${DOMAINS_REGISTRY}\concept.ru" -ItemType Directory | Out-Null
New-Item -Path $conceptDomain -ItemType Directory | Out-Null
New-ItemProperty -Path $conceptDomain -Name 'file' -Value 1 | Out-Null
Write-Host 'Intranet settings ... DONE'
}
}
function AddTrustedLocation($target, $location) {
$registryPath = "${target}\Security\Trusted Locations"
if (-not(Test-Path -Path $registryPath)) {
if (-not(Test-Path -Path "${target}\Security")){
New-Item -Path "${target}\Security" -ItemType Directory | Out-Null
}
New-Item -Path $registryPath -ItemType Directory | Out-Null
}
Set-ItemProperty -Path $registryPath -Name 'AllowNetworkLocations' -Value 1
if (
Get-ChildItem -Path $registryPath -Recurse |
ForEach-Object { if ($_.GetValue('Path') -eq $location) { return $true } }
) {
return $false
} else {
$index = 3
while (Test-Path -Path "${registryPath}\Location${index}") { $index++ }
$folder = "${registryPath}\Location${index}"
New-Item -Path $folder -ItemType Directory | Out-Null
New-ItemProperty -Path $folder -Name 'Path' -Value $location | Out-Null
New-ItemProperty -Path $folder -Name 'Description' -Value 'Сетевой путь КОНЦЕПТ' | Out-Null
New-ItemProperty -Path $folder -Name 'AllowSubfolders' -Value 1 | Out-Null
return $true
}
}
# InstallAllProducts "D:\test\ConceptDistr"
# SetupTrustedLocations \\fs1.concept.ru\

View File

@ -0,0 +1,127 @@
# Uninstall Concept products
function UninstallConceptProducts {
[CmdletBinding()]
Param(
)
Set-StrictMode -Version 3.0
$InformationPreference="Continue"
StartLog
Write-Host "Starting uninstallation procedure for Concept technologies`n" -ForegroundColor DarkGreen
PrepareExternalProcesses
if (-not (Get-Module -ListAvailable ConceptDeploy)) {
Write-Host "Missing ConceptDeploy library"
Exit 1
}
Import-Module -Name ConceptDeploy
$localHome = "C:\Tools"
Write-Host "`nRemoving Concept Products" -ForegroundColor DarkGreen
$localJSON = Open-DistrManifest "$localHome\distribution_manifest.json"
foreach ($product in $localJSON.Keys) {
Disable-Product $product | Out-Null
Write-Host "Product $product has been removed`n" -ForegroundColor Gray
}
TryRemove "$localHome\optional\"
TryRemove "$localHome\models\"
TryRemove "$localHome\distribution_manifest.json"
Write-Host "`nRemoving user specific files" -ForegroundColor DarkGreen
TryRemove "$(Get-ConceptLocal)\"
$templates = GetTemplatesFolder
$fileList = Get-Content "$localHome\script\templates_list.txt"
Write-Host "Remove templates at $templates" -ForegroundColor DarkGreen
foreach ($file in $fileList) {
if ($file -ne 'Normal.dotm' -and $file -ne 'NormalEmail.dotm') {
TryRemove "$templates\$file"
}
}
TryRemove "$localHome\script\templates_list.txt"
Write-Host "`nRemoving core files"
TryRemove "$localHome\script\UpdateConceptProducts.ps1"
TryRemove "$localHome\script\UninstallConceptProducts.ps1"
TryRemove "$localHome\script\uninstall-concept.bat"
TryRemove "$localHome\Python312-venv\"
TryRemove "$localHome\dll\"
Write-Host "`nRemoving ConceptDeploy library" -ForegroundColor DarkGreen
Remove-Module -Name ConceptDeploy
TryRemove "$env:USERPROFILE\Documents\WindowsPowerShell\modules\ConceptDeploy"
Write-Host "`nRemoving desktop shortcuts" -ForegroundColor DarkGreen
TryRemove "$($Env:USERPROFILE)\Desktop\Everything - поиск по имени.lnk"
TryRemove "$($Env:USERPROFILE)\Desktop\DocFetcher - поиск по содержимому.lnk"
TryRemove "$($Env:USERPROFILE)\Desktop\Double Commander.lnk"
Write-Host "`nUninstallation complete" -ForegroundColor Green
StopLog
}
function StartLog {
$ErrorActionPreference="SilentlyContinue"
Stop-Transcript | Out-Null
$ErrorActionPreference = "Continue"
$dateSuffix = (Get-Date -UFormat "%Y%m%d_%I-%M-%S").ToString()
$logFile = "$PSScriptRoot\logs\$($dateSuffix)_CP-uninstall_$($Env:USERNAME).txt"
Start-Transcript -Path $logFile -IncludeInvocationHeader
}
function StopLog {
Stop-Transcript
}
function CheckProcess($processName) {
$app = Get-Process $processName -ErrorAction SilentlyContinue
return -not ($null -eq $app)
}
function TryRemove($path) {
if (Test-Path -Path $path) {
Write-Host "Removing $path..." -ForegroundColor Gray
Remove-Item -Path $path -Recurse -Force
} else {
Write-Host "Failed to locate $path..." -ForegroundColor Red
}
}
function PrepareExternalProcesses {
Write-Host "Close blocking applications..." -ForegroundColor DarkGreen
if ($(CheckProcess WINWORD)) {
Stop-Process -Name WINWORD -Force
}
if ($(CheckProcess EXCEL)) {
Stop-Process -Name EXCEL -Force
}
if ($(CheckProcess VISIO)) {
Stop-Process -Name VISIO -Force
}
if ($(CheckProcess Exteor)) {
Stop-Process -Name Exteor -Force
}
Write-Host "Word running: $(CheckProcess WINWORD)"
Write-Host "Excel running: $(CheckProcess EXCEL)"
Write-Host "Visio running: $(CheckProcess VISIO)"
Write-Host "Exteor running: $(CheckProcess Exteor)"
}
function GetTemplatesFolder {
$officeRK = 'HKCU:\SOFTWARE\Microsoft\Office\16.0'
$defaultTemplates = "$($Env:APPDATA)\Microsoft\Шаблоны"
$templates = Get-ItemPropertyValue -Path "$officeRK\Word\Options" -Name 'PersonalTemplates' -ErrorAction 'SilentlyContinue'
if (!$templates -or [string]::IsNullOrWhiteSpace($templates)) {
$templates = $defaultTemplates
}
return $templates
}
# UninstallConceptProducts

View File

@ -0,0 +1,162 @@
# Install Concept products from local distr
function UpdateConceptProducts {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[string] $distrPath,
[string[]] $products = $(, 'all')
)
Set-StrictMode -Version 3.0
if ($products.Count -lt 1) {
Write-Host 'Missing products list'
Exit 1
}
StartLog
Write-Host "Starting update procedure for Concept technologies" -ForegroundColor DarkGreen
Write-Host "Sources: $distrPath"
Write-Host "Requested products: $products"
$updates = New-Object System.Collections.Generic.List[System.Object]
$enable_products = New-Object System.Collections.Generic.List[System.Object]
$disable_products = New-Object System.Collections.Generic.List[System.Object]
if ($products[0] -eq 'all') {
$updates.Add('all')
} else {
foreach ($p in $products) {
if ($p.EndsWith('-') -or $p.EndsWith('+')) {
$product_id = $p.Substring(0, $p.Length - 1)
} else {
$product_id = $p
}
if ($p.EndsWith('-')) {
$disable_products.Add($product_id)
} else {
$updates.Add($product_id)
$enable_products.Add($product_id)
}
}
}
Write-Host "Check updates: $updates"
Write-Host "Enable products: $enable_products"
Write-Host "Disable products: $disable_products"
if (Test-Path -Path "filesystem::$distrPath\distribution_manifest.json") {
Write-Host "Check path $distrPath\distribution_manifest.json ... ACCESS GRANTED" -ForegroundColor DarkGreen
UpdateProducts $distrPath $updates
} else {
Write-Host "Check path $distrPath\distribution_manifest.json ... NO ACCESS" -ForegroundColor DarkRed
Write-Host "Skipping product updates..." -ForegroundColor DarkRed
}
$tools = 'C:\Tools'
foreach ($product in $enable_products) {
if (Enable-Product $product $tools) {
Write-Host "Product $($product): enabled`n" -ForegroundColor DarkGreen
} else {
Write-Host "Product $($product): failed to enable`n" -ForegroundColor DarkRed
}
}
$tools = 'C:\Tools'
foreach ($product in $disable_products) {
if (Disable-Product $product) {
Write-Host "Product $($product): disabled`n" -ForegroundColor DarkGreen
} else {
Write-Host "Product $($product): failed to disable`n" -ForegroundColor DarkRed
}
}
Write-Host "`nUpdate complete" -ForegroundColor Green
StopLog
}
function StartLog {
$ErrorActionPreference="SilentlyContinue"
Stop-Transcript | Out-Null
$ErrorActionPreference = "Continue"
$dateSuffix = (Get-Date -UFormat "%Y%m%d_%I-%M-%S").ToString()
$logFile = "$PSScriptRoot\logs\$($dateSuffix)_CP-update_$($Env:USERNAME).txt"
Start-Transcript -Path $logFile -IncludeInvocationHeader
}
function StopLog {
Stop-Transcript
}
function UpdateProducts($distrPath, $products) {
$driveLetter = MountPathDrive $distrPath
$distr = "$driveLetter`:"
if (-not(CheckConceptDeploy $distr)) {
Write-Host "Installing Powershell library: ConceptDeploy" -ForegroundColor DarkGreen
. "$driveLetter\src\ConceptDeploy\CD_Install.ps1"
}
Import-Module -Name ConceptDeploy
Write-Host "Using ConceptDeploy: $((Get-Module -Name 'ConceptDeploy').Version)" -ForegroundColor Gray
if ($products.Count -ne 0) {
$serverManifest = "$distr\distribution_manifest.json"
$serverJSON = Open-DistrManifest $serverManifest
$localManifest = "C:\Tools\distribution_manifest.json"
$localJSON = Open-DistrManifest $localManifest
if ($products[0] -eq 'all') {
$products = $serverJSON.Keys
}
foreach ($product in $products) {
$serverVersion = [System.Version] $serverJSON.$product
if ($localJSON.Contains($product)) {
$localVersion = [System.Version] $localJSON.$product
} else {
$localVersion = [System.Version] "0.0.0"
}
if ($serverVersion -eq $localVersion) {
Write-Host "Product $($product): $serverVersion ... up to date`n" -ForegroundColor Gray
} elseif (Install-Product $product $distr $templates $localTools) {
Write-Host "Product $($product): $serverVersion ... updated from $localVersion`n" -ForegroundColor DarkGreen
$localJSON[$product] = $serverJSON.$product
} else {
Write-Host "Product $($product): $serverVersion ... failed to update from $localVersion`n" -ForegroundColor DarkRed
}
}
Save-DistrManifest $localJSON $localManifest
}
Write-Host "`nUnmount $driveLetter" -ForegroundColor DarkGreen
Remove-PSDrive -Name $driveLetter
}
function MountPathDrive($targetPath) {
Write-Host "`nCreating temporary drive for $targetPath" -ForegroundColor DarkGreen
[char[]] $takenDrive = (Get-PSDrive -Name [E-Z]).Name
$driveLetter = ([char[]] (69..90)).Where({ $_ -notin $takenDrive }, 'First')[0]
if (!$driveLetter) {
Write-Error "No available drive letter"
Exit 1
}
New-PSDrive -Name $driveLetter -PSProvider FileSystem -Root $targetPath -Scope Global | Out-Null
Write-Host "Drive $driveLetter mounted"
return $driveLetter
}
function CheckConceptDeploy($distr) {
$currentModule = Get-Module -ListAvailable ConceptDeploy
if (!$currentModule) {
return $false
}
$newVersion = [System.Version] (Get-Content -Path "$distr\src\ConceptDeploy\VERSION")
$oldVersion = $currentModule.Version
return $oldVersion -ge $newVersion
}
# UpdateConceptProducts -DistrPath '\\fs1.concept.ru\Exchange\ConceptDistr' 'Concept-Maket-', 'Concept-Mining+'

1
src/VERSION Normal file
View File

@ -0,0 +1 @@
3.0.1

View File

@ -0,0 +1,7 @@
@echo off
@pushd %~dp0
PowerShell -NoProfile -ExecutionPolicy Bypass -Command ". "%cd%\InstallAllProducts.ps1"; InstallAllProducts \\fs1.concept.ru\Exchange\ConceptDistr;"
@popd
pause

7
src/install_launcher.bat Normal file
View File

@ -0,0 +1,7 @@
@echo off
@pushd %~dp0
PowerShell -NoProfile -ExecutionPolicy Bypass -Command ". "%cd%\InstallAllProducts.ps1"; InstallAllProducts %cd%;"
@popd
pause

View File

@ -0,0 +1,7 @@
@echo off
@pushd %~dp0
PowerShell -NoProfile -ExecutionPolicy Bypass -Command ". "%cd%\InstallAllProducts.ps1"; InstallAllProducts %cd% -Standalone -SkipShortcuts;"
@popd
pause

7
src/uninstall.bat Normal file
View File

@ -0,0 +1,7 @@
@echo off
@pushd %~dp0
PowerShell -NoProfile -ExecutionPolicy Bypass -Command ". "%cd%\UninstallConceptProducts.ps1"; UninstallConceptProducts;"
@popd
pause