PSLockScreenSlideShow.psm1
$Script:ModuleName = (Get-Item -Path $PSCommandPath).BaseName <# .SYNOPSIS Get PSLockScreenSlideShow images from path .DESCRIPTION Get PSLockScreenSlideShow images from path and return a list of objects with Path, Time, Unit properties. The result can directly be piped to Start-PSLockScreenSlideShow (e.g. see PSLockScreenSlideShow.ps1) .PARAMETER Path Specifiy the path where to load the LockScreen images from Defaults to C:\ProgramData\PSLockScreenSlideShow Files are NOT loaded recursively, but sorted by name to force a consistent order .PARAMETER Time The time each slideshow image will be shown if no time can be extracted from filename by parameter TimeRegEx Defaults to "5s" .PARAMETER TimeRegEx Defaults to "^.*\W(?<Time>\d{1,})(?<Unit>ms|s)$" which means: ^ start of line (line=file.Basename) .* 0 to n any characters \W one any non digit or letter (means special character) (?<Time>\d{1,}) one or more digits (this pattern must be named 'Time' to be used internally to fill the result objects property "Time") (?<Unit>ms|s) 'ms' or 's', unit of the afore mentioned Time (this pattern must be named 'Unit' to be used internally to fill the result objects property "Unit") $ end of line (line= file.Basename) .INPUTS None. Right now you cannot pipe objects to Get-PSLockScreenSlideShow .OUTPUTS a list of PSCustomObjects [PSCustomObject]@{ Path = ... Time = ... Unit = ... } .EXAMPLE Get-PSLockScreenSlideShow Path Time Unit ---- ---- ---- C:\ProgramData\PSLockScreenSlideShow\00-Show.jpg 5 s C:\ProgramData\PSLockScreenSlideShow\01-Show-5s.jpg 5 s C:\ProgramData\PSLockScreenSlideShow\02-Show-10s.jpg 10 s C:\ProgramData\PSLockScreenSlideShow\03-Show-5000ms.jpg 5000 ms assumed C:\ProgramData\PSLockScreenSlideShow contains the following files 00-Show.jpg 01-Show-5s.jpg 02-Show-10s.jpg 03-Show-5000ms.jpg #> function Get-PSLockScreenSlideShow { [CmdletBinding()] Param ( [Parameter()][string]$Path = "$([System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::CommonApplicationData))\$($Script:ModuleName)", [Parameter()][string]$Time = "5s", [Parameter()][string]$TimeRegEx = "^.*\W(?<Time>\d{1,})(?<Unit>ms|s)$" ) Begin { $Default = Get-PSLockScreenSlideShowTime $Time } Process { Get-ChildItem -Path $Path | Sort-Object -Property FullName | ForEach-Object { $Result = [PSCustomObject]@{ Path = $_.FullName Time = $Default.Time Unit = $Default.Unit } if($TimeRegEx) { if($_.BaseName -match $TimeRegEx) { if($Matches.Time) { $Result.Time = [Convert]::ToInt32($Matches.Time) } if($Matches.Unit) { $Result.Unit = $Matches.Unit } } } $Result } } } function Get-PSLockScreenSlideShowTime($Time) { if($Time -match "^(\d{1,})(ms|s)$") { [PSCustomObject]@{ Time = [Convert]::ToInt32($Matches[1]) Unit = $Matches[2] } } else { [PSCustomObject]@{ Time = 5 Unit = "s" } } } function Wait-PSLockScreenSlideShow { [CmdletBinding()] Param ( [Parameter(ValueFromPipelineByPropertyName)]$Time, [Parameter(ValueFromPipelineByPropertyName)]$Unit ) Process { $Sleep = @{ @{ "s" = "Seconds" "ms" = "Milliseconds" "Seconds" = "Seconds" "Milliseconds" = "Milliseconds" }[$Unit] = $Time } Start-Sleep @Sleep } } <# .SYNOPSIS Set LockScreen image .DESCRIPTION Set LockScreen image .PARAMETER Path Specifiy the image filename to set as LockScreen image .INPUTS Image filename that should be set as LockScreen image .OUTPUTS None. .EXAMPLE "C:\ProgramData\PSLockScreenSlideShow\00-Show.jpg" | Set-PSLockScreenSlideShowImage Set "C:\ProgramData\PSLockScreenSlideShow\00-Show.jpg" via pipeline as the actual LockScreen image .EXAMPLE Set-PSLockScreenSlideShowImage "C:\ProgramData\PSLockScreenSlideShow\00-Show.jpg" Set "C:\ProgramData\PSLockScreenSlideShow\00-Show.jpg" via parameter as the actual LockScreen image #> function Set-PSLockScreenSlideShowImage { [CmdletBinding()] Param ( [Parameter(ValueFromPipelineByPropertyName,ValueFromPipeline)][string]$Path ) Begin { [void]([Windows.Storage.StorageFile,Windows.Storage,ContentType=WindowsRuntime]) [void]([Windows.System.UserProfile.LockScreen,Windows.System.UserProfile,ContentType=WindowsRuntime]) Add-Type -AssemblyName System.Runtime.WindowsRuntime $asTaskGeneric = ([System.WindowsRuntimeSystemExtensions].GetMethods() | ? { $_.Name -eq 'AsTask' -and $_.GetParameters().Count -eq 1 -and $_.GetParameters()[0].ParameterType.Name -eq 'IAsyncOperation`1' })[0] function Await($WinRtTask, $ResultType) { $asTask = $asTaskGeneric.MakeGenericMethod($ResultType) $netTask = $asTask.Invoke($null, @($WinRtTask)) $netTask.Wait(-1) | Out-Null $netTask.Result } function AwaitAction($WinRtAction) { $asTask = ([System.WindowsRuntimeSystemExtensions].GetMethods() | ? { $_.Name -eq 'AsTask' -and $_.GetParameters().Count -eq 1 -and !$_.IsGenericMethod })[0] $netTask = $asTask.Invoke($null, @($WinRtAction)) $netTask.Wait(-1) | Out-Null } } Process { $image = Await ([Windows.Storage.StorageFile]::GetFileFromPathAsync($Path)) ([Windows.Storage.StorageFile]) AwaitAction ([Windows.System.UserProfile.LockScreen]::SetImageFileAsync($image)) } } function Start-PSLockScreenSlideShow { [CmdletBinding()] Param ( [Parameter(ValueFromPipelineByPropertyName,ValueFromPipeline)][string[]]$Path, [Parameter(ValueFromPipelineByPropertyName)] [int] $Time, [Parameter(ValueFromPipelineByPropertyName)] [string] $Unit, [Parameter()] [switch] $Forever ) Begin { $Slides = [System.Collections.Generic.List[object]]::new() } Process { foreach($p in $Path) { $Slides.Add([PSCustomObject]@{ Path = $p Time = $Time Unit = $Unit }) Set-PSLockScreenSlideShowImage -Path $p Wait-PSLockScreenSlideShow -Time $Time -Unit $Unit } } End { if($Forever) { $Slides | ForEach-Object { Set-PSLockScreenSlideShowImage -Path $_.Path Wait-PSLockScreenSlideShow -Time $_.Time -Unit $_.Unit } } } } function Register-PSLockScreenSlideShowScheduledTask { [CmdletBinding()] Param ( [Parameter()][string]$Path, [Parameter()][string]$Time, [Parameter()][string]$TimeRegEx ) Unregister-PSLockScreenSlideShowScheduledTask @( @{ TaskPath = "\$($Script:ModuleName)\" TaskName = "Lock" Principal = New-ScheduledTaskPrincipal -GroupId "S-1-5-32-545" # VORDEFINIERT\Benutzer = Builtin\Users Trigger = . { $class = Get-CimClass MSFT_TaskSessionStateChangeTrigger Root/Microsoft/Windows/TaskScheduler $instance = $class | New-CimInstance -ClientOnly $instance.Enabled = $true $instance.StateChange = 7 # Lock $instance } Action = . { $ActionExe = (([System.Environment]::GetCommandLineArgs() | Select-Object -First 1) -replace "_ISE", "") $ActionArgs = . { "-ExecutionPolicy Bypass -WindowStyle Hidden -File ""$([System.IO.Path]::ChangeExtension($PSCommandPath, ".ps1"))""" foreach($key in $PSBoundParameters.Keys) { "-$($key) $($PSBoundParameters[$key])" } } New-ScheduledTaskAction -Execute $ActionExe -Argument ($ActionArgs -join ' ') } Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -MultipleInstances IgnoreNew -ExecutionTimeLimit "00:00:00" } @{ TaskPath = "\$($Script:ModuleName)\" TaskName = "Unlock" Principal = New-ScheduledTaskPrincipal -GroupId "S-1-5-32-545" # VORDEFINIERT\Benutzer = Builtin\Users Trigger = . { $class = Get-CimClass MSFT_TaskSessionStateChangeTrigger Root/Microsoft/Windows/TaskScheduler $instance = $class | New-CimInstance -ClientOnly $instance.Enabled = $true $instance.StateChange = 8 # Unlock $instance } Action = . { $ActionExe = (([System.Environment]::GetCommandLineArgs() | Select-Object -First 1) -replace "_ISE", "") $ActionArgs = . { "-ExecutionPolicy Bypass -WindowStyle Hidden -Command ""Stop-ScheduledTask -TaskPath '\$($Script:ModuleName)\' -TaskName 'Lock' -ErrorAction SilentlyContinue""" } New-ScheduledTaskAction -Execute $ActionExe -Argument ($ActionArgs -join ' ') } Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -MultipleInstances IgnoreNew -ExecutionTimeLimit "00:00:00" } ) | ForEach-Object { Register-ScheduledTask @_ -ErrorAction SilentlyContinue } } function Unregister-PSLockScreenSlideShowScheduledTask { Unregister-ScheduledTask -TaskPath "\$($Script:ModuleName)\" -TaskName "Lock" -Confirm:$false -ErrorAction SilentlyContinue Unregister-ScheduledTask -TaskPath "\$($Script:ModuleName)\" -TaskName "Unlock" -Confirm:$false -ErrorAction SilentlyContinue try { $taskScheduler = New-Object -ComObject Schedule.Service $taskScheduler.Connect() $taskScheduler.GetFolder("\").DeleteFolder($Script:ModuleName, $null) } catch { } } |