# todo: Убрать автовыбор нескольких базовых лицензий Add-Type -AssemblyName "PresentationFramework" Add-Type -AssemblyName "System.Windows.Forms" Add-Type -AssemblyName "System.Drawing" <# # Глобальные объекты необходимы для метода-заглушки CreoLaunching.LicenseUserRestrict($user). # Где: # # $tableLicenseName - таблица дополнительных модулей: Код = Наименование # $tableLicenseBase - таблица базовых модулей: Код = Наименование # $tableLicenseServ - таблица серверов лицензий: Псевдоним = Порт@Адрес # $tableLicenseLink - таблица ссылок на описание дополнительных модулей: Наименование = Ссылка # # При настоящей реализации получения списка ограничений для пользователя в методе CreoLaunching.LicenseUserRestrict($user) # глобальные объекты и файл с таблицами могут быть удалены. #> $Global:tableLicenseName = New-Object HashtableMods -ArgumentList '.\CreoLauncher.txt', 'tableLicenseName' $Global:tableLicenseLink = New-Object HashtableMods -ArgumentList '.\CreoLauncher.txt', 'tableLicenseLink' $Global:tableLicenseBase = New-Object HashtableMods -ArgumentList '.\CreoLauncher.txt', 'tableLicenseBase' $Global:tableLicenseServ = New-Object HashtableMods -ArgumentList '.\CreoLauncher.txt', 'tableLicenseServ' <# # Объекты выполняют роль конфигурации. # Добавление/удаление записей таблиц, а также изменение содержимого записей, повлияет на логику выполнения. #> $creoPackageSpecs = New-Object CreoParamSpec @{ 'CreoDir' = "$env:ProgramFiles\PTC\Creo*\Parametric\bin" 'CreoVer' = "0.0.0.0" 'CreoExe' = "parametric.exe" 'CreoPsf' = "\Parametric\bin\parametric.psf" 'CreoLnk' = "$env:ProgramData\Microsoft\Windows\Start Menu\Programs\PTC" 'CreoIco' = "\Parametric\install\nt\creologo.ico" 'LicExe' = "\Common Files\x86e_win64\obj\plpf_status.exe" 'LicRes' = "\Common Files\text\licensing\license.res" 'RegExpCreoVer' = "\d.\d.\d.\d" 'RegExpLicense' = "^\s+(?\S+)\s+(?\d+)\s+(?\d+)" 'EnvLicense' = "PTC_D_LICENSE_FILE" 'EnvLicsRes' = "PRO_LICENSE_RES" 'EnvFeature' = "CREOPMA_FEATURE_NAME" 'EnvDescPsf' = "DESC" } $tableMessageENUS = New-Object HashtableMods @{ 'MsgSelectInvite' = 'Select the required modules' 'MsgSelectAvaile' = 'Available' 'MsgWinHeadError' = 'ERROR!' 'MsgErrCreoParam' = 'Not found Creo Parametric or its components on this computer' 'MsgRunCreoParam' = 'Start Creo Parametric' 'MsgRunPTCStatus' = 'Show license status' } $tableMessageRURU = New-Object HashtableMods @{ 'MsgSelectInvite' = 'Выберите необходимые модули' 'MsgSelectAvaile' = 'Доступно' 'MsgWinHeadError' = 'ОШИБКА!' 'MsgErrCreoParam' = 'Не найден Creo Parametric или его компоненты на этом компьютере' 'MsgRunCreoParam' = 'Запуск Creo Parametric' 'MsgRunPTCStatus' = 'Отобразить все лицензии' } class ExecuteObject { [System.Object] hidden $info [System.Object] hidden $proc ExecuteObject([System.String]$execPath, [System.String]$execArgs){ $this.info = New-Object System.Diagnostics.ProcessStartInfo $this.info.FileName = $execPath $this.info.Arguments = $execArgs $this.info.RedirectStandardError = $true $this.info.RedirectStandardOutput = $true $this.info.UseShellExecute = $false $this.info.WindowStyle = 'Hidden' $this.info.CreateNoWindow = $true } [PSCustomObject] Start(){ $this.proc = New-Object System.Diagnostics.Process Try{ $this.proc.StartInfo = $this.info $this.proc.Start() | Out-Null Return [PSCustomObject]@{ stdout = $this.proc.StandardOutput.ReadToEnd() stderr = $this.proc.StandardError.ReadToEnd() ExitCode = $this.proc.ExitCode } } Catch { Exit } } } class HashtableMods { [System.Collections.Hashtable] $hashtable HashtableMods ([System.Collections.Hashtable]$table){ $this.hashtable = $table } HashtableMods ([System.String]$path, [System.String]$block){ $table = @{} $save = $false Foreach ($line in $(Get-Content -Path $path)){ if (($line -match "\[") -and ($line -match "$block")){ $save = $true } elseif ($line -match "\["){ $save = $false } elseif ($save -and ($line -notmatch "^\s*#") -and ($line -match "=")){ $key = $line.Split("=")[0].Trim() $val = $($line.Split(";")[0] -replace "$($key)\s*=\s*","").Trim() try { $table.Add($key, $val) } catch { $table.Remove($key) $table.Add($key, $val) } } } $this.hashtable = $table } [System.String] ToString(){ Return $this.ToString($false, $null) } [System.String] ToString([System.Boolean]$fromKey){ Return $this.ToString($fromKey, $null) } [System.String] ToString([System.Boolean]$fromKey, [System.String]$separator){ $string = "" Foreach ($key in $this.hashtable.Keys){ if ($FromKey){ $string += $key.ToString() } else { $string += $this.hashtable[$key].ToString() } $string += $separator } Return $string.TrimEnd($separator) } [HashtableMods] Filtrate([System.Boolean]$fromKey, [System.String]$target){ $filtrated = New-Object HashtableMods @{} if ($FromKey){ Foreach ($element in $($this.hashtable.GetEnumerator() | Where-Object {$_.Key -eq $target})){ $filtrated.hashtable.Add($element.Name,$this.hashtable[$element.Name]) } } else { Foreach ($element in $($this.hashtable.GetEnumerator() | Where-Object {$_.Value -eq $target})){ $filtrated.hashtable.Add($element.Name,$this.hashtable[$element.Name]) } } Return $filtrated } } class UserInterface { [System.Object] hidden $form [System.Object] hidden $wordsFont [System.Object] hidden $titleFont [System.Int32] hidden $wordsSize = 10 [System.Int32] hidden $titleSize = $this.wordsSize * 1.5 [System.Int32] hidden $linesStep = $this.titleSize * 1.5 [System.Int32] hidden $linesNext = 0 [System.Int32] hidden $colmnStep = 0 [System.Int32] hidden $colmnNext = $this.titleSize * 1.5 UserInterface ([System.String]$header){ $this.wordsFont = New-Object System.Drawing.Font("Arial", $this.wordsSize <#, [System.Drawing.FontStyle]::Regular#>) $this.titleFont = New-Object System.Drawing.Font("Arial", $this.titleSize <#, [System.Drawing.FontStyle]::Bold#>) $this.form = New-Object System.Windows.Forms.Form $this.form.AutoScroll = $true $this.form.AutoSize = $true $this.form.Text = $header } [System.Void] AddIcon ([System.String]$path){ $this.form.Icon = New-Object System.Drawing.Icon $path } [System.Void] AddSpaceVertical(){ $this.linesNext += $this.linesStep * 1.5 } [PSCustomObject] AddTitle([System.String]$text){ $title = New-Object System.Windows.Forms.Label $title.Location = New-Object System.Drawing.Size($this.colmnNext, $this.linesNext) $title.Font = $this.titleFont $title.Text = $text $title.AutoSize = $true $this.form.Controls.Add($title) Return [PSCustomObject]@{ Width = $title.Width Height = $title.Height } } [PSCustomObject] AddText([System.String]$text){ $txt = New-Object System.Windows.Forms.Label $txt.Location = New-Object System.Drawing.Size($this.colmnNext, $this.linesNext) $txt.Font = $this.wordsFont $txt.Text = $text $txt.AutoSize = $true $this.form.Controls.Add($txt) Return [PSCustomObject]@{ Width = $txt.Width Height = $txt.Height } } [PSCustomObject] AddLink([System.String]$text, $function){ $lnk = New-Object System.Windows.Forms.LinkLabel $lnk.Location = New-Object System.Drawing.Size($this.colmnNext, $this.linesNext) $lnk.add_Click($function) $lnk.Font = $this.wordsFont $lnk.LinkColor = "BLUE" $lnk.ActiveLinkColor = "BLACK" $lnk.Text = $text $lnk.AutoSize = $true $this.form.Controls.Add($lnk) Return [PSCustomObject]@{ Width = $lnk.Width Height = $lnk.Height } } [PSCustomObject] AddCheckbox([System.String]$name, [System.String]$text, $function){ $checkbox = New-Object System.Windows.Forms.CheckBox $checkbox.Location = New-Object System.Drawing.Size($this.colmnNext, $this.linesNext) $checkbox.Add_Click($function) $checkbox.Font = $this.wordsFont $checkbox.Text = $text $checkbox.Name = $name $checkbox.AutoSize = $true $this.form.Controls.Add($checkbox) Return [PSCustomObject]@{ Width = $checkbox.Width Height = $checkbox.Height } } [PSCustomObject] AddButton([System.String]$text, $function){ $button = New-Object System.Windows.Forms.Button $button.Location = New-Object System.Drawing.Size($this.colmnNext, $this.linesNext) $button.Add_Click($function) $button.Font = $this.wordsFont $button.Text = $text $button.AutoSize = $true $this.form.Controls.Add($button) Return [PSCustomObject]@{ Width = $button.Width Height = $button.Height } } [System.Void] Show(){ $this.form.ShowDialog() } [HashtableMods] GetStateCheckbox(){ $state = New-Object HashtableMods @{} Foreach ($checkbox in $this.form.Controls | Where-Object {$_.GetType() -like 'System.Windows.Forms.CheckBox'}){ $state.hashtable.Add($checkbox.Name, $($checkbox.Checked)) } Return $state } } class CreoParamSpec { [System.String] $CreoDir [System.String] $CreoVer [System.String] $CreoExe [System.String] $CreoPsf [System.String] $CreoLnk [System.String] $CreoIco [System.String] $LicExe [System.String] $LicRes [System.String] $RegExpCreoVer [System.String] $RegExpLicense [System.String] $EnvLicense [System.String] $EnvLicsRes [System.String] $EnvFeature [System.String] $EnvDescPsf CreoParamSpec ([HashtableMods]$creoSpec){ Try{ $this.SpecToProperty($creoSpec.hashtable) $this.AdjustProperty() } Catch{ $this.CreoDir = $null $this.CreoVer = $null $this.CreoExe = $null $this.CreoPsf = $null $this.CreoLnk = $null $this.CreoIco = $null $this.LicExe = $null $this.LicRes = $null $this.RegExpCreoVer = $null $this.RegExpLicense = $null $this.EnvLicense = $null $this.EnvFeature = $null } } [System.Void] hidden SpecToProperty([System.Collections.Hashtable]$table){ $properties = $this | Get-Member -MemberType Properties -Force | Where-Object {$_.Name -notcontains 'pstypenames'} Foreach ($property in $properties){ if (!$table.ContainsKey($property.Name)){ Write-Host 'SPEC' $this.RaiseException() } else{ $this.$($property.Name) = $table[$property.Name] } } } [System.Void] hidden AdjustProperty(){ if (!(Test-Path -Path $this.CreoDir -ErrorAction SilentlyContinue)){ $this.RaiseException("Not found CREO DIRECTORY") } else{ $found = Get-ChildItem -Path $this.CreoDir -Filter $this.CreoExe -Recurse Foreach ($result in $found){ if (($result.FullName.ToString() -match $this.RegExpCreoVer) -and ($matches[0] -gt $this.CreoVer)){ $this.CreoVer = $matches[0] $this.CreoExe = $result.FullName $this.CreoDir = Split-Path -Path $result.FullName | Split-Path -Parent | Split-Path -Parent } } $this.CreoPsf = $this.CreoDir + $this.CreoPsf if (!(Test-Path -Path $this.CreoPsf -ErrorAction SilentlyContinue)){ $this.RaiseException("Not found CREO START FILE") } $this.LicExe = $this.CreoDir + $this.LicExe if (!(Test-Path -Path $this.LicExe -ErrorAction SilentlyContinue)){ $this.RaiseException("Not found LICENSE STATUS EXE") } $this.LicRes = $this.CreoDir + $this.LicRes if (!(Test-Path -Path $this.LicRes -ErrorAction SilentlyContinue)){ $this.RaiseException("Not found LICENSE RESOURCES FILE") } $this.CreoIco = $this.CreoDir + $this.CreoIco if (!(Test-Path -Path $this.CreoIco -ErrorAction SilentlyContinue)){ $this.RaiseException("Not found CREO ICON") } $WshShell = $(New-Object -comObject WScript.Shell) $this.CreoLnk = $WshShell.CreateShortcut($this.CreoLnk + "\Creo Parametric $($this.CreoVer).lnk").WorkingDirectory if (!(Test-Path -Path $this.CreoLnk -ErrorAction SilentlyContinue)){ $this.RaiseException("Not found CREO LINK WITH WORKDIR") } } } [System.Void] hidden RaiseException($message){ throw $message } } class CreoLaunching : UserInterface { [System.String] hidden $user [CreoParamSpec] hidden $creo [HashtableMods] hidden $mesg [HashtableMods[]] hidden $licenseRestricts [HashtableMods] hidden $licenseAvailable CreoLaunching([CreoParamSpec]$creoSpec, [System.String]$userName, [HashtableMods]$locale) : base("Creo $($creoSpec.CreoVer) Launcher"){ $this.user = $username $this.creo = $creoSpec $this.mesg = $locale $this.AddIcon($this.creo.CreoIco) $chboxPosX = $this.colmnNext $buttnPosX = $this.colmnNext $buttnPosY = $this.linesNext $element = $this.AddTitle($($this.mesg.hashtable['MsgSelectInvite'])) $this.linesNext += $this.linesStep * 2 if (($sizeX = $element.Width + $this.colmnNext) -gt $this.colmnStep){ $this.colmnStep = $sizeX } $servrPosY = $this.linesNext $this.colmnStep = $chboxPosX $this.licenseRestricts = $this.LicenseUserRestrict($this.user) $this.licenseAvailable = $this.LicenseServerStatus($this.licenseRestricts[0], $this.licenseRestricts[1], $this.licenseRestricts[2]) $licenseServ = $this.licenseRestricts[2].hashtable $licenseName = $this.licenseRestricts[0].hashtable Foreach ($servKey in $licenseServ.Keys){ $this.colmnNext = $this.colmnStep $this.linesNext = $servrPosY $element = $this.AddText($servKey) $this.linesNext += $element.Height if (($sizeX = $element.Width + $this.colmnNext) -gt $this.colmnStep){ $this.colmnStep = $sizeX } $chboxPosY = $this.linesNext $linksPosX = $this.colmnNext Foreach($licKey in $($this.licenseAvailable.hashtable.Keys | Where-Object {$_ -match $servKey})){ $licName = $licKey.Split(':')[1] if ($licenseName.ContainsKey($licName)){ $licName = $licenseName[$licName] } $checkboxText = "$($this.mesg.hashtable['MsgSelectAvaile']) $($this.licenseAvailable.hashtable[$licKey]):" $element = $this.AddCheckbox($licKey, $checkboxText, {$launcher.ExamCheckboxesState($this, $_)}) $this.linesNext += $this.linesStep * 1.5 if (($sizeX = $element.Width + $this.colmnNext) -gt $this.colmnStep){ $this.colmnStep = $sizeX } if (($sizeX = $element.Width + $this.colmnNext) -gt $linksPosX){ $linksPosX = $sizeX } } $this.colmnNext = $linksPosX $this.linesNext = $chboxPosY Foreach($licKey in $($this.licenseAvailable.hashtable.Keys | Where-Object {$_ -match $servKey})){ $licName = $licKey.Split(':')[1] if ($licenseName.ContainsKey($licName)){ $licName = $licenseName[$licName] } if ($this.licenseRestricts[3].hashtable.ContainsKey($licName)){ $element = $this.AddLink($licName, {$launcher.OpenLinkExternalApp($this)}) } else { $element = $this.AddText($licName) } $this.linesNext += $this.linesStep * 1.5 if (($sizeX = $element.Width + $this.colmnNext) -gt $this.colmnStep){ $this.colmnStep = $sizeX } } if ($this.linesNext -gt $buttnPosY){ $buttnPosY = $this.linesNext } } $this.colmnNext = $buttnPosX $this.linesNext = $buttnPosY $element = $this.AddButton($($this.mesg.hashtable['MsgRunCreoParam']), {$launcher.StartCreoParametric()}) $this.linesNext += $this.linesStep * 1.5 if (($sizeX = $element.Width + $this.colmnNext) -gt $this.colmnStep){ $this.colmnStep = $sizeX } } [HashtableMods[]] hidden LicenseUserRestrict([System.String]$user){ <# # Метод является заглушкой и использует глобальные переменные. # Реализация настоящего запроса списка ограничений пользователя должна возвращать массив объектов HashtableMods. # Где элементы массива: # [0] - таблица дополнительных модулей в виде хеш-таблицы (словаря): Код = Наименование # [1] - таблица базовых модулей в виде хеш-таблицы (словаря): Код = Наименование # [2] - таблица серверов лицензий в виде хеш-таблицы (словаря): Псевдоним = Порт@Адрес # [3] - таблица ссылок на описание дополнительных модулей в виде хеш-таблицы (словаря): Наименование = Ссылка #> [HashtableMods[]] $restrict = $Global:tableLicenseName, $Global:tableLicenseBase, $Global:tableLicenseServ, $Global:tableLicenseLink Return $restrict } [HashtableMods] hidden LicenseServerStatus([HashtableMods]$licenseName, [HashtableMods]$licenseBase, [HashtableMods]$licenseServ){ $licAvailable = New-Object HashtableMods @{} $exeArguments = '-a' if (($licenseBase) -and ($licenseName)){ $exeArguments = '-f ' + $licenseBase.ToString($true, ' ') + ' ' + $licenseName.ToString($true, ' ') } Foreach ($servKey in $licenseServ.hashtable.Keys){ Remove-Item -Path Env:$($this.creo.EnvLicsRes) -ErrorAction SilentlyContinue Set-Item -Path Env:$($this.creo.EnvLicense) -Value $licenseServ.hashtable[$servKey] $response = $(New-Object ExecuteObject -ArgumentList $this.creo.LicExe, $exeArguments).Start() Foreach ($line in $response.stdout.Split(@("`r`n", "`r", "`n"), [StringSplitOptions]::None)){ if (($line -match $this.creo.RegExpLicense) -and ($line -notmatch "\(\S+\)")){ $licKey = "$($servKey):$($matches['License'].Replace('*',''))" $licVal = $matches['Free'] if (!$licAvailable.hashtable.ContainsKey($licKey)){ if ($licVal -gt 0){ $licAvailable.hashtable.Add($LicKey, $licVal) } } else { $licAvailable.hashtable[$licKey] = [System.String]([System.Int32]$licAvailable.hashtable[$licKey] + [System.Int32]$licVal) } } } } Return $licAvailable } [System.Void] hidden ExamCheckboxesState($element, $event){ $servKey = $element.Name.Split(':')[0] $licBase = $this.licenseRestricts[1].ToString($true, '|') Foreach ($checkbox in $this.form.Controls | Where-Object {$_.GetType() -match 'System.Windows.Forms.CheckBox'}){ if ($checkbox.Name -notmatch $servKey){ $checkbox.Checked = $false } elseif ($checkbox.Name -match $servKey -and $checkbox.Name.Split(':')[1] -match "$licBase"){ $checkbox.Checked = $true } } } [System.String[]] hidden GeneratingStartFile(){ $selectedServer = "" $selectedBaseLic = "" $selectedFeature = "" $checkboxState = $this.GetStateCheckbox().Filtrate($false, 'True') if ($checkboxState.hashtable.Count -gt 0){ $foreseenBaseLic = $this.licenseRestricts[1].ToString($true, '|') Foreach ($key in $checkboxState.hashtable.Keys){ $selectedServer = $this.licenseRestricts[2].hashtable[$key.Split(':')[0]] $checkedFeature = $key.Split(':')[1] if ($checkedFeature -match $foreseenBaseLic){ $selectedBaseLic += $checkedFeature + ' ' } else { $selectedFeature += $checkedFeature + ' ' } } $startFileData = Get-Content -Path $this.creo.CreoPsf | Select-String -NotMatch $this.creo.EnvFeature, $this.creo.EnvLicense, $this.creo.EnvDescPsf $startFileData += "DESC=Creo Parametric ($($this.user))" $startFileData += "ENV=$($this.creo.EnvLicense)-=$($selectedServer)" $startFileData += "ENV=$($this.creo.EnvFeature)=$($selectedBaseLic)($($selectedFeature.Trim()))" Return $startFileData } Return Get-Content -Path $this.creo.CreoPsf } [System.Void] hidden StartCreoParametric(){ $startFileBack = Get-Content -Path $this.creo.CreoPsf $startFileData = $this.GeneratingStartFile() Set-Content -Path $this.creo.CreoPsf -Value $startFileData -Force Start-Process -FilePath $this.creo.CreoExe -WorkingDirectory $this.creo.CreoLnk $this.form.Close() Sleep 60 Set-Content -Path $this.creo.CreoPsf -Value $startFileBack -Force } [System.Void] hidden OpenLinkExternalApp($element){ [System.Diagnostics.Process]::Start($this.licenseRestricts[3].hashtable[$element.Text]) } } $locale = $tableMessageENUS if ((Get-Culture).Name -eq 'ru-RU'){ $locale = $tableMessageRURU } if ($creoPackageSpecs.CreoExe -ne ''){ $launcher = New-Object CreoLaunching -ArgumentList $creoPackageSpecs, "$env:USERNAME@$env:USERDNSDOMAIN", $locale $launcher.Show() } else { [System.Windows.MessageBox]::Show($locale.hashtable['MsgErrCreoParam'], $locale.hashtable['MsgWinHeadError'],'OK','Error') }