Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7fc0602818 | ||
|
|
3039562e91 | ||
|
|
91208323ab |
2
dist/setup.ps1
vendored
2
dist/setup.ps1
vendored
File diff suppressed because one or more lines are too long
447
setup.ps1
447
setup.ps1
@@ -62,6 +62,7 @@ $CommonDesktopDir = [Environment]::GetFolderPath('CommonDesktopDirectory')
|
|||||||
$CommonProgramsDir = [Environment]::GetFolderPath('CommonPrograms')
|
$CommonProgramsDir = [Environment]::GetFolderPath('CommonPrograms')
|
||||||
$DesktopShortcutPath = Join-Path $CommonDesktopDir "$CatalogDisplayName.lnk"
|
$DesktopShortcutPath = Join-Path $CommonDesktopDir "$CatalogDisplayName.lnk"
|
||||||
$StartMenuShortcutPath = Join-Path $CommonProgramsDir "$CatalogDisplayName.lnk"
|
$StartMenuShortcutPath = Join-Path $CommonProgramsDir "$CatalogDisplayName.lnk"
|
||||||
|
$script:DaemonPostResponseWorkers = @()
|
||||||
|
|
||||||
# ----------------------------
|
# ----------------------------
|
||||||
# Utility functions
|
# Utility functions
|
||||||
@@ -710,6 +711,28 @@ function Start-QueueWorker {
|
|||||||
Start-SoftwarekatalogWorker -WorkerMode ProcessQueue
|
Start-SoftwarekatalogWorker -WorkerMode ProcessQueue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Add-DaemonPostResponseWorker {
|
||||||
|
param([Parameter(Mandatory)][ValidateSet('ApplyPolicy','ProcessQueue')][string]$WorkerMode)
|
||||||
|
|
||||||
|
if (-not $script:DaemonPostResponseWorkers) {
|
||||||
|
$script:DaemonPostResponseWorkers = @()
|
||||||
|
}
|
||||||
|
$script:DaemonPostResponseWorkers = @($script:DaemonPostResponseWorkers + $WorkerMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-DaemonPostResponseWorkers {
|
||||||
|
foreach ($workerMode in @($script:DaemonPostResponseWorkers | Select-Object -Unique)) {
|
||||||
|
try {
|
||||||
|
Start-SoftwarekatalogWorker -WorkerMode $workerMode
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Log "Could not start post-response worker '$workerMode': $($_.Exception.Message)" 'WARN'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$script:DaemonPostResponseWorkers = @()
|
||||||
|
}
|
||||||
|
|
||||||
function Get-WingetPath {
|
function Get-WingetPath {
|
||||||
$candidates = @()
|
$candidates = @()
|
||||||
|
|
||||||
@@ -841,13 +864,17 @@ function Invoke-CatalogDaemon {
|
|||||||
)
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
`$client.Connect(60000)
|
`$client.Connect(10000)
|
||||||
`$reader = New-Object System.IO.StreamReader(`$client, `$encoding)
|
`$reader = New-Object System.IO.StreamReader(`$client, `$encoding)
|
||||||
`$writer = New-Object System.IO.StreamWriter(`$client, `$encoding)
|
`$writer = New-Object System.IO.StreamWriter(`$client, `$encoding)
|
||||||
`$writer.AutoFlush = `$true
|
`$writer.AutoFlush = `$true
|
||||||
`$writer.WriteLine(`$json)
|
`$writer.WriteLine(`$json)
|
||||||
|
|
||||||
`$line = `$reader.ReadLine()
|
`$readTask = `$reader.ReadLineAsync()
|
||||||
|
if (-not `$readTask.Wait(15000)) {
|
||||||
|
throw 'Zeitüberschreitung beim Warten auf Antwort des Softwarekatalog-Dienstes.'
|
||||||
|
}
|
||||||
|
`$line = `$readTask.Result
|
||||||
if ([string]::IsNullOrWhiteSpace(`$line)) {
|
if ([string]::IsNullOrWhiteSpace(`$line)) {
|
||||||
throw 'Der Softwarekatalog-Dienst hat keine Antwort gesendet.'
|
throw 'Der Softwarekatalog-Dienst hat keine Antwort gesendet.'
|
||||||
}
|
}
|
||||||
@@ -1047,13 +1074,17 @@ function Invoke-CatalogDaemon {
|
|||||||
)
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
`$client.Connect(60000)
|
`$client.Connect(10000)
|
||||||
`$reader = New-Object System.IO.StreamReader(`$client, `$encoding)
|
`$reader = New-Object System.IO.StreamReader(`$client, `$encoding)
|
||||||
`$writer = New-Object System.IO.StreamWriter(`$client, `$encoding)
|
`$writer = New-Object System.IO.StreamWriter(`$client, `$encoding)
|
||||||
`$writer.AutoFlush = `$true
|
`$writer.AutoFlush = `$true
|
||||||
`$writer.WriteLine(`$json)
|
`$writer.WriteLine(`$json)
|
||||||
|
|
||||||
`$line = `$reader.ReadLine()
|
`$readTask = `$reader.ReadLineAsync()
|
||||||
|
if (-not `$readTask.Wait(15000)) {
|
||||||
|
throw 'Zeitüberschreitung beim Warten auf Antwort des Softwarekatalog-Dienstes.'
|
||||||
|
}
|
||||||
|
`$line = `$readTask.Result
|
||||||
if ([string]::IsNullOrWhiteSpace(`$line)) {
|
if ([string]::IsNullOrWhiteSpace(`$line)) {
|
||||||
throw 'Der Softwarekatalog-Dienst hat keine Antwort gesendet.'
|
throw 'Der Softwarekatalog-Dienst hat keine Antwort gesendet.'
|
||||||
}
|
}
|
||||||
@@ -1462,6 +1493,319 @@ function Load-AppList {
|
|||||||
`$stateRefreshTimer = New-Object System.Windows.Forms.Timer
|
`$stateRefreshTimer = New-Object System.Windows.Forms.Timer
|
||||||
`$stateRefreshTimer.Interval = 500
|
`$stateRefreshTimer.Interval = 500
|
||||||
`$script:StateRefreshPending = `$false
|
`$script:StateRefreshPending = `$false
|
||||||
|
`$script:RequestWorkerBusy = `$false
|
||||||
|
`$script:RunspaceJobs = @()
|
||||||
|
`$script:CatalogClosing = `$false
|
||||||
|
|
||||||
|
function Remove-CatalogRunspaceJob {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=`$true)]`$Job,
|
||||||
|
[switch]`$Stop
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (`$null -ne `$Job.Timer) {
|
||||||
|
`$Job.Timer.Stop()
|
||||||
|
`$Job.Timer.Dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (`$Stop -and `$null -ne `$Job.PowerShell -and `$null -ne `$Job.AsyncResult -and -not `$Job.AsyncResult.IsCompleted) {
|
||||||
|
`$null = `$Job.PowerShell.BeginStop(`$null, `$null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
try { `$Job.PowerShell.Stop() } catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (`$null -ne `$Job.PowerShell) { `$Job.PowerShell.Dispose() }
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (`$null -ne `$Job.Runspace) { `$Job.Runspace.Dispose() }
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
}
|
||||||
|
|
||||||
|
`$remainingJobs = @()
|
||||||
|
foreach (`$existingJob in @(`$script:RunspaceJobs)) {
|
||||||
|
if (-not [object]::ReferenceEquals(`$existingJob, `$Job)) {
|
||||||
|
`$remainingJobs += `$existingJob
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`$script:RunspaceJobs = `$remainingJobs
|
||||||
|
}
|
||||||
|
|
||||||
|
function Start-CatalogDaemonRunspaceRequest {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=`$true)][string]`$Command,
|
||||||
|
[string]`$Alias,
|
||||||
|
`$Context,
|
||||||
|
[Parameter(Mandatory=`$true)][scriptblock]`$OnCompleted
|
||||||
|
)
|
||||||
|
|
||||||
|
`$runspace = [runspacefactory]::CreateRunspace()
|
||||||
|
`$powershell = [powershell]::Create()
|
||||||
|
`$timer = New-Object System.Windows.Forms.Timer
|
||||||
|
`$timer.Interval = 100
|
||||||
|
|
||||||
|
`$job = [pscustomobject]@{
|
||||||
|
PowerShell = `$powershell
|
||||||
|
Runspace = `$runspace
|
||||||
|
AsyncResult = `$null
|
||||||
|
Timer = `$timer
|
||||||
|
Context = `$Context
|
||||||
|
OnCompleted = `$OnCompleted
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
`$runspace.ApartmentState = 'MTA'
|
||||||
|
`$runspace.ThreadOptions = 'ReuseThread'
|
||||||
|
`$runspace.Open()
|
||||||
|
`$runspace.SessionStateProxy.SetVariable('PipeName', `$PipeName)
|
||||||
|
`$runspace.SessionStateProxy.SetVariable('Command', `$Command)
|
||||||
|
`$runspace.SessionStateProxy.SetVariable('Alias', `$Alias)
|
||||||
|
|
||||||
|
`$powershell.Runspace = `$runspace
|
||||||
|
[void]`$powershell.AddScript({
|
||||||
|
Set-StrictMode -Version Latest
|
||||||
|
`$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
`$payload = [ordered]@{
|
||||||
|
Command = `$Command
|
||||||
|
AppAlias = `$Alias
|
||||||
|
}
|
||||||
|
`$json = `$payload | ConvertTo-Json -Compress
|
||||||
|
|
||||||
|
`$encoding = New-Object System.Text.UTF8Encoding(`$false)
|
||||||
|
`$client = New-Object System.IO.Pipes.NamedPipeClientStream -ArgumentList @(
|
||||||
|
'.',
|
||||||
|
`$PipeName,
|
||||||
|
[System.IO.Pipes.PipeDirection]::InOut,
|
||||||
|
[System.IO.Pipes.PipeOptions]::None,
|
||||||
|
[System.Security.Principal.TokenImpersonationLevel]::Impersonation
|
||||||
|
)
|
||||||
|
|
||||||
|
try {
|
||||||
|
`$client.Connect(10000)
|
||||||
|
`$reader = New-Object System.IO.StreamReader(`$client, `$encoding)
|
||||||
|
`$writer = New-Object System.IO.StreamWriter(`$client, `$encoding)
|
||||||
|
`$writer.AutoFlush = `$true
|
||||||
|
`$writer.WriteLine(`$json)
|
||||||
|
|
||||||
|
`$readTask = `$reader.ReadLineAsync()
|
||||||
|
if (-not `$readTask.Wait(15000)) {
|
||||||
|
throw 'Zeitüberschreitung beim Warten auf Antwort des Softwarekatalog-Dienstes.'
|
||||||
|
}
|
||||||
|
`$line = `$readTask.Result
|
||||||
|
if ([string]::IsNullOrWhiteSpace(`$line)) {
|
||||||
|
throw 'Der Softwarekatalog-Dienst hat keine Antwort gesendet.'
|
||||||
|
}
|
||||||
|
|
||||||
|
`$response = `$line | ConvertFrom-Json
|
||||||
|
if (-not `$response.Success) {
|
||||||
|
throw ([string]`$response.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
return `$response
|
||||||
|
}
|
||||||
|
catch [System.TimeoutException] {
|
||||||
|
throw 'Der Softwarekatalog-Dienst ist nicht erreichbar oder startet noch. Bitte versuchen Sie es erneut.'
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
`$client.Dispose()
|
||||||
|
}
|
||||||
|
}.ToString())
|
||||||
|
|
||||||
|
`$job.AsyncResult = `$powershell.BeginInvoke()
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
`$timer.Dispose()
|
||||||
|
`$powershell.Dispose()
|
||||||
|
`$runspace.Dispose()
|
||||||
|
throw
|
||||||
|
}
|
||||||
|
|
||||||
|
`$script:RunspaceJobs = @(`$script:RunspaceJobs + `$job)
|
||||||
|
`$jobRef = `$job
|
||||||
|
`$timer.Add_Tick({
|
||||||
|
if (`$null -eq `$jobRef.AsyncResult -or -not `$jobRef.AsyncResult.IsCompleted) { return }
|
||||||
|
|
||||||
|
`$jobRef.Timer.Stop()
|
||||||
|
`$completion = [pscustomobject]@{
|
||||||
|
Context = `$jobRef.Context
|
||||||
|
Response = `$null
|
||||||
|
ErrorMessage = `$null
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
`$result = @(`$jobRef.PowerShell.EndInvoke(`$jobRef.AsyncResult))
|
||||||
|
if (`$jobRef.PowerShell.Streams.Error.Count -gt 0) {
|
||||||
|
`$firstError = `$jobRef.PowerShell.Streams.Error[0]
|
||||||
|
if (`$null -ne `$firstError.Exception) {
|
||||||
|
`$completion.ErrorMessage = `$firstError.Exception.Message
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
`$completion.ErrorMessage = [string]`$firstError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif (`$result.Count -gt 0) {
|
||||||
|
`$completion.Response = `$result[-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
`$completion.ErrorMessage = `$_.Exception.Message
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (-not `$script:CatalogClosing) {
|
||||||
|
& `$jobRef.OnCompleted `$completion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
try { `$status.Text = 'Fehler: ' + `$_.Exception.Message } catch { }
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
Remove-CatalogRunspaceJob -Job `$jobRef
|
||||||
|
}
|
||||||
|
}.GetNewClosure())
|
||||||
|
`$timer.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
function Start-AppRequestAsync {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory=`$true)]`$Selected,
|
||||||
|
[Parameter(Mandatory=`$true)][ValidateSet('Install','Uninstall')][string]`$Action
|
||||||
|
)
|
||||||
|
|
||||||
|
if (`$script:RequestWorkerBusy) {
|
||||||
|
`$status.Text = 'Eine Anfrage wird bereits verarbeitet.'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
`$script:RequestWorkerBusy = `$true
|
||||||
|
`$btnInstall.Enabled = `$false
|
||||||
|
`$btnUninstall.Enabled = `$false
|
||||||
|
`$btnRefresh.Enabled = `$false
|
||||||
|
|
||||||
|
`$context = [pscustomobject]@{
|
||||||
|
Action = `$Action
|
||||||
|
Alias = [string]`$Selected.Alias
|
||||||
|
DisplayName = [string]`$Selected.DisplayName
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Start-CatalogDaemonRunspaceRequest -Command `$Action -Alias `$context.Alias -Context `$context -OnCompleted ({
|
||||||
|
param(`$completion)
|
||||||
|
try {
|
||||||
|
`$script:RequestWorkerBusy = `$false
|
||||||
|
`$btnRefresh.Enabled = `$true
|
||||||
|
|
||||||
|
if (`$completion.ErrorMessage) {
|
||||||
|
`$status.Text = 'Fehler: ' + `$completion.ErrorMessage
|
||||||
|
`$script:StateRefreshPending = `$true
|
||||||
|
[System.Windows.Forms.MessageBox]::Show(
|
||||||
|
`$completion.ErrorMessage,
|
||||||
|
`$CatalogTitle,
|
||||||
|
[System.Windows.Forms.MessageBoxButtons]::OK,
|
||||||
|
[System.Windows.Forms.MessageBoxIcon]::Error
|
||||||
|
) | Out-Null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
`$result = [pscustomobject]@{
|
||||||
|
Action = `$completion.Context.Action
|
||||||
|
Alias = `$completion.Context.Alias
|
||||||
|
DisplayName = `$completion.Context.DisplayName
|
||||||
|
Response = `$completion.Response
|
||||||
|
}
|
||||||
|
if (`$result.Action -eq 'Uninstall') {
|
||||||
|
`$verb = 'Deinstallation'
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
`$verb = 'Installation'
|
||||||
|
}
|
||||||
|
if (`$result.Response.Message) {
|
||||||
|
`$status.Text = [string]`$result.Response.Message
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
`$status.Text = "`$verb eingereiht: {0}" -f `$result.DisplayName
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Windows.Forms.MessageBox]::Show(
|
||||||
|
("`$verb eingereiht:`r`n`r`n{0}`r`nAlias: {1}" -f `$result.DisplayName, `$result.Alias),
|
||||||
|
`$CatalogTitle,
|
||||||
|
[System.Windows.Forms.MessageBoxButtons]::OK,
|
||||||
|
[System.Windows.Forms.MessageBoxIcon]::Information
|
||||||
|
) | Out-Null
|
||||||
|
|
||||||
|
`$script:StateRefreshPending = `$true
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
Update-InstallButtonState
|
||||||
|
}
|
||||||
|
}.GetNewClosure())
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
`$script:RequestWorkerBusy = `$false
|
||||||
|
`$btnRefresh.Enabled = `$true
|
||||||
|
Update-InstallButtonState
|
||||||
|
throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Start-RefreshStatusAsync {
|
||||||
|
if (`$script:RequestWorkerBusy) {
|
||||||
|
`$status.Text = 'Eine Anfrage wird bereits verarbeitet.'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
`$script:RequestWorkerBusy = `$true
|
||||||
|
`$btnInstall.Enabled = `$false
|
||||||
|
`$btnUninstall.Enabled = `$false
|
||||||
|
`$btnRefresh.Enabled = `$false
|
||||||
|
`$status.Text = 'Installationsdaten-Aktualisierung wird angefordert...'
|
||||||
|
|
||||||
|
try {
|
||||||
|
Start-CatalogDaemonRunspaceRequest -Command 'RefreshStatus' -OnCompleted ({
|
||||||
|
param(`$completion)
|
||||||
|
try {
|
||||||
|
`$script:RequestWorkerBusy = `$false
|
||||||
|
`$btnRefresh.Enabled = `$true
|
||||||
|
|
||||||
|
if (`$completion.ErrorMessage) {
|
||||||
|
`$status.Text = 'Fehler: ' + `$completion.ErrorMessage
|
||||||
|
[System.Windows.Forms.MessageBox]::Show(
|
||||||
|
`$completion.ErrorMessage,
|
||||||
|
`$CatalogTitle,
|
||||||
|
[System.Windows.Forms.MessageBoxButtons]::OK,
|
||||||
|
[System.Windows.Forms.MessageBoxIcon]::Error
|
||||||
|
) | Out-Null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
`$response = `$completion.Response
|
||||||
|
if (`$response.Message) { `$status.Text = [string]`$response.Message }
|
||||||
|
`$script:StateRefreshPending = `$true
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
Update-InstallButtonState
|
||||||
|
}
|
||||||
|
}.GetNewClosure())
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
`$script:RequestWorkerBusy = `$false
|
||||||
|
`$btnRefresh.Enabled = `$true
|
||||||
|
Update-InstallButtonState
|
||||||
|
throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
`$btnInstall.Add_Click({
|
`$btnInstall.Add_Click({
|
||||||
try {
|
try {
|
||||||
@@ -1490,17 +1834,10 @@ function Load-AppList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
`$status.Text = "Installation wird eingereiht: {0}" -f `$selected.DisplayName
|
`$status.Text = "Installation wird eingereiht: {0}" -f `$selected.DisplayName
|
||||||
`$response = New-AppRequest -Alias `$selected.Alias -Action 'Install'
|
`$selectedItem.SubItems[2].Text = 'In Warteschlange'
|
||||||
`$status.Text = if (`$response.Message) { `$response.Message } else { "Installation eingereiht: {0}" -f `$selected.DisplayName }
|
`$selectedItem.ForeColor = [System.Drawing.Color]::DarkGoldenrod
|
||||||
|
Update-InstallButtonState
|
||||||
[System.Windows.Forms.MessageBox]::Show(
|
Start-AppRequestAsync -Selected `$selected -Action 'Install'
|
||||||
("Installation eingereiht:`r`n`r`n{0}`r`nAlias: {1}" -f `$selected.DisplayName, `$selected.Alias),
|
|
||||||
`$CatalogTitle,
|
|
||||||
[System.Windows.Forms.MessageBoxButtons]::OK,
|
|
||||||
[System.Windows.Forms.MessageBoxIcon]::Information
|
|
||||||
) | Out-Null
|
|
||||||
|
|
||||||
Load-AppList
|
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
`$status.Text = "Fehler: " + `$_.Exception.Message
|
`$status.Text = "Fehler: " + `$_.Exception.Message
|
||||||
@@ -1540,17 +1877,10 @@ function Load-AppList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
`$status.Text = "Deinstallation wird eingereiht: {0}" -f `$selected.DisplayName
|
`$status.Text = "Deinstallation wird eingereiht: {0}" -f `$selected.DisplayName
|
||||||
`$response = New-AppRequest -Alias `$selected.Alias -Action 'Uninstall'
|
`$selectedItem.SubItems[2].Text = 'Deinstallation in Warteschlange'
|
||||||
`$status.Text = if (`$response.Message) { `$response.Message } else { "Deinstallation eingereiht: {0}" -f `$selected.DisplayName }
|
`$selectedItem.ForeColor = [System.Drawing.Color]::DarkGoldenrod
|
||||||
|
Update-InstallButtonState
|
||||||
[System.Windows.Forms.MessageBox]::Show(
|
Start-AppRequestAsync -Selected `$selected -Action 'Uninstall'
|
||||||
("Deinstallation eingereiht:`r`n`r`n{0}`r`nAlias: {1}" -f `$selected.DisplayName, `$selected.Alias),
|
|
||||||
`$CatalogTitle,
|
|
||||||
[System.Windows.Forms.MessageBoxButtons]::OK,
|
|
||||||
[System.Windows.Forms.MessageBoxIcon]::Information
|
|
||||||
) | Out-Null
|
|
||||||
|
|
||||||
Load-AppList
|
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
`$status.Text = "Fehler: " + `$_.Exception.Message
|
`$status.Text = "Fehler: " + `$_.Exception.Message
|
||||||
@@ -1565,10 +1895,7 @@ function Load-AppList {
|
|||||||
|
|
||||||
`$btnRefresh.Add_Click({
|
`$btnRefresh.Add_Click({
|
||||||
try {
|
try {
|
||||||
`$status.Text = 'Installationsdaten werden aktualisiert...'
|
Start-RefreshStatusAsync
|
||||||
`$response = Invoke-CatalogDaemon -Command 'RefreshStatus'
|
|
||||||
Load-AppList
|
|
||||||
if (`$response.Message) { `$status.Text = `$response.Message }
|
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
`$status.Text = "Fehler: " + `$_.Exception.Message
|
`$status.Text = "Fehler: " + `$_.Exception.Message
|
||||||
@@ -1653,10 +1980,15 @@ function Load-AppList {
|
|||||||
`$stateRefreshTimer.Start()
|
`$stateRefreshTimer.Start()
|
||||||
})
|
})
|
||||||
`$form.Add_FormClosing({
|
`$form.Add_FormClosing({
|
||||||
|
`$script:CatalogClosing = `$true
|
||||||
`$stateRefreshTimer.Stop()
|
`$stateRefreshTimer.Stop()
|
||||||
`$stateRefreshTimer.Dispose()
|
`$stateRefreshTimer.Dispose()
|
||||||
if (`$script:StateWatcher) { `$script:StateWatcher.Dispose() }
|
if (`$null -ne `$script:StateWatcher) { `$script:StateWatcher.Dispose() }
|
||||||
if (`$script:SnapshotWatcher) { `$script:SnapshotWatcher.Dispose() }
|
if (`$null -ne `$script:SnapshotWatcher) { `$script:SnapshotWatcher.Dispose() }
|
||||||
|
foreach (`$job in @(`$script:RunspaceJobs)) {
|
||||||
|
Remove-CatalogRunspaceJob -Job `$job -Stop
|
||||||
|
}
|
||||||
|
`$script:RunspaceJobs = @()
|
||||||
})
|
})
|
||||||
|
|
||||||
`$list.Add_SelectedIndexChanged({ Update-InstallButtonState })
|
`$list.Add_SelectedIndexChanged({ Update-InstallButtonState })
|
||||||
@@ -2212,7 +2544,7 @@ function Invoke-CatalogDaemonCommand {
|
|||||||
{ $_ -in @('getcatalog','getstate') } {
|
{ $_ -in @('getcatalog','getstate') } {
|
||||||
$requiredQueued = Ensure-RequiredSoftwareQueued
|
$requiredQueued = Ensure-RequiredSoftwareQueued
|
||||||
if ($requiredQueued -gt 0) {
|
if ($requiredQueued -gt 0) {
|
||||||
Start-QueueWorker
|
Add-DaemonPostResponseWorker -WorkerMode ProcessQueue
|
||||||
}
|
}
|
||||||
$catalog = @(Get-AppCatalogObjects | Sort-Object DisplayName)
|
$catalog = @(Get-AppCatalogObjects | Sort-Object DisplayName)
|
||||||
$requiredAliases = @(Get-RequiredAliases)
|
$requiredAliases = @(Get-RequiredAliases)
|
||||||
@@ -2239,7 +2571,7 @@ function Invoke-CatalogDaemonCommand {
|
|||||||
|
|
||||||
'applypolicy' {
|
'applypolicy' {
|
||||||
Write-Log "Authenticated policy apply requested by user='$($ClientIdentity.Name)' sid='$($ClientIdentity.Sid)'"
|
Write-Log "Authenticated policy apply requested by user='$($ClientIdentity.Name)' sid='$($ClientIdentity.Sid)'"
|
||||||
Start-SoftwarekatalogWorker -WorkerMode ApplyPolicy
|
Add-DaemonPostResponseWorker -WorkerMode ApplyPolicy
|
||||||
return [pscustomobject]@{
|
return [pscustomobject]@{
|
||||||
Success = $true
|
Success = $true
|
||||||
Command = $command
|
Command = $command
|
||||||
@@ -2278,10 +2610,20 @@ function Invoke-CatalogDaemonCommand {
|
|||||||
Write-Log "Authenticated request: action=$actionText alias='$alias' package='$packageId' user='$($ClientIdentity.Name)' sid='$($ClientIdentity.Sid)'"
|
Write-Log "Authenticated request: action=$actionText alias='$alias' package='$packageId' user='$($ClientIdentity.Name)' sid='$($ClientIdentity.Sid)'"
|
||||||
|
|
||||||
$queueResult = Add-SoftwareRequestToQueue -Action $command -Alias $alias -RequestedBy $ClientIdentity.Name -RequestedBySid $ClientIdentity.Sid -Source User
|
$queueResult = Add-SoftwareRequestToQueue -Action $command -Alias $alias -RequestedBy $ClientIdentity.Name -RequestedBySid $ClientIdentity.Sid -Source User
|
||||||
Start-QueueWorker
|
Add-DaemonPostResponseWorker -WorkerMode ProcessQueue
|
||||||
|
|
||||||
$verb = if ($command -eq 'uninstall') { 'Deinstallation' } else { 'Installation' }
|
if ($command -eq 'uninstall') {
|
||||||
$message = if ($queueResult.Added) { "$verb eingereiht: $alias" } else { "$verb ist bereits in der Warteschlange: $alias" }
|
$verb = 'Deinstallation'
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$verb = 'Installation'
|
||||||
|
}
|
||||||
|
if ($queueResult.Added) {
|
||||||
|
$message = "$verb eingereiht: $alias"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$message = "$verb ist bereits in der Warteschlange: $alias"
|
||||||
|
}
|
||||||
return [pscustomobject]@{
|
return [pscustomobject]@{
|
||||||
Success = $true
|
Success = $true
|
||||||
Command = $command
|
Command = $command
|
||||||
@@ -2297,24 +2639,25 @@ function Invoke-CatalogDaemonCommand {
|
|||||||
|
|
||||||
{ $_ -in @('refreshstatus','getstatus') } {
|
{ $_ -in @('refreshstatus','getstatus') } {
|
||||||
Write-Log "Authenticated status refresh requested by user='$($ClientIdentity.Name)' sid='$($ClientIdentity.Sid)'"
|
Write-Log "Authenticated status refresh requested by user='$($ClientIdentity.Name)' sid='$($ClientIdentity.Sid)'"
|
||||||
$wingetPath = Ensure-WingetAvailable
|
$started = $false
|
||||||
if (-not $wingetPath) {
|
if (Test-WingetLockAvailable) {
|
||||||
throw 'winget is unavailable.'
|
Add-DaemonPostResponseWorker -WorkerMode ProcessQueue
|
||||||
|
$started = $true
|
||||||
}
|
}
|
||||||
|
if ($started) {
|
||||||
$result = Invoke-WithWingetLock -TimeoutSeconds 2 -ScriptBlock {
|
$message = 'Installationsdaten-Aktualisierung gestartet.'
|
||||||
$snapshotUpdated = Update-InstalledPackagesSnapshot -WingetPath $wingetPath
|
}
|
||||||
[pscustomobject]@{ SnapshotUpdated = [bool]$snapshotUpdated }
|
else {
|
||||||
|
$message = 'Installationsdaten-Aktualisierung läuft bereits.'
|
||||||
}
|
}
|
||||||
$result = @($result)[-1]
|
|
||||||
|
|
||||||
return [pscustomobject]@{
|
return [pscustomobject]@{
|
||||||
Success = [bool]$result.SnapshotUpdated
|
Success = $true
|
||||||
Command = $command
|
Command = $command
|
||||||
RequestedBy = $ClientIdentity.Name
|
RequestedBy = $ClientIdentity.Name
|
||||||
RequestedBySid = $ClientIdentity.Sid
|
RequestedBySid = $ClientIdentity.Sid
|
||||||
SnapshotUpdated = [bool]$result.SnapshotUpdated
|
SnapshotQueued = $started
|
||||||
Message = 'Installationsdaten aktualisiert.'
|
Message = $message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2340,6 +2683,7 @@ function Start-CatalogDaemon {
|
|||||||
while ($true) {
|
while ($true) {
|
||||||
$pipe = $null
|
$pipe = $null
|
||||||
try {
|
try {
|
||||||
|
$script:DaemonPostResponseWorkers = @()
|
||||||
$pipe = New-CatalogPipeServer
|
$pipe = New-CatalogPipeServer
|
||||||
$pipe.WaitForConnection()
|
$pipe.WaitForConnection()
|
||||||
|
|
||||||
@@ -2351,7 +2695,11 @@ function Start-CatalogDaemon {
|
|||||||
|
|
||||||
$response = $null
|
$response = $null
|
||||||
try {
|
try {
|
||||||
$line = $reader.ReadLine()
|
$readTask = $reader.ReadLineAsync()
|
||||||
|
if (-not $readTask.Wait(30000)) {
|
||||||
|
throw 'Timed out waiting for named pipe request.'
|
||||||
|
}
|
||||||
|
$line = $readTask.Result
|
||||||
if ([string]::IsNullOrWhiteSpace($line)) {
|
if ([string]::IsNullOrWhiteSpace($line)) {
|
||||||
throw 'Empty request.'
|
throw 'Empty request.'
|
||||||
}
|
}
|
||||||
@@ -2370,6 +2718,7 @@ function Start-CatalogDaemon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$writer.WriteLine(($response | ConvertTo-Json -Compress -Depth 6))
|
$writer.WriteLine(($response | ConvertTo-Json -Compress -Depth 6))
|
||||||
|
Invoke-DaemonPostResponseWorkers
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
Write-Log "Named pipe daemon error: $($_.Exception.Message)" 'ERROR'
|
Write-Log "Named pipe daemon error: $($_.Exception.Message)" 'ERROR'
|
||||||
|
|||||||
Reference in New Issue
Block a user