I need to change the background image when a user has locked the system. Currently, it displays the users desktop, but it has become a security issue (not sure how, but it has).
So now - I need to change the background image to a blank (black image with legal text) whenever the user has locked their system (ctrl-alt-del lock workstation).
I have changed the registry located at
HKEY_USERS.DEFAULT\Control Panel\Desktop\Wallpaper
This works for the initial login screen, but what i am looking for is how to change the background on the lock screen.
Thank you
I was able to do wallpaper change via power shell.
(I guess it powershell 2 - "host" returns "2.0")
It might get you (or someone else) started.
(pieces found on (Hey, Scripting Guy!) etc - I never used powershell before)
Program should create object
$sysevent = [microsoft.win32.systemevents]
create function that will cahnge wallpaper
It is called on lock and on unlock - your should research how to tell a difference. I just check which BMP I have and change it to another one
Function Global:OnLock{
$wp=Get-ItemProperty -path 'HKCU:\Control Panel\Desktop\' -name wallpaper
Write-Host "Current WP:" $wp.WallPaper
if ($wp.WallPaper -eq "C:\Documents and Settings\username\Local Settings\Application Data\Microsoft\Wallpaper2.bmp")
{Set-ItemProperty -path 'HKCU:\Control Panel\Desktop\' -name wallpaper -value "C:\Documents and Settings\username\Local Settings\Application Data\Microsoft\Wallpaper1.bmp"}
else
{Set-ItemProperty -path 'HKCU:\Control Panel\Desktop\' -name wallpaper -value "C:\Documents and Settings\username\Local Settings\Application Data\Microsoft\Wallpaper2.bmp"}
rundll32.exe user32.dll, UpdatePerUserSystemParameters
}
register event
Register-ObjectEvent -InputObject $sysevent -EventName "SessionSwitch" -Action {OnLock} -SourceIdentifier "ExecuteOnLock"
Now, lock/unlock will call that function.
Of cource (?) you have to leave powershell running
For example by
powershell -NoExit -WindowStyle Hidden C:\pathToPrScript\script.ps1
Hope that helps
Related
Here is a very simple example of the problem I am experiencing:
$process = Start-Process 'C:\Program Files\Mozilla Firefox\firefox.exe' -argumentlist "-new-window https://google.com -foreground" -PassThru
Write-Host $process.Id
The firefox window will start and work as expected, it will return a process id, but when I actually check the running processes, I see no results for that PID.
I tried adding this just to see,
while (-not $process.HasExited){
Write-Host "..."
}
Write-Host $process.HasExited
And it looks like the process does run for maybe a couple milliseconds before it exits.
I'm thinking this may have something to do with how Firefox handles it's own processes. Because I tested a similar setup with some other random apps and they all worked as expected.
Any ideas on how to work around this when it comes to Firefox?
There are several challenges to overcome:
The firefox process that ends up presenting the actual browser window is different from the one that is initially launched. That is, as you've observed, the launched process spawns other processes and itself exits quickly.
As Olaf points out, modern browsers typically launch multiple non-transient processes, so the challenge is how to identify the one that represent the browser window.
Browsers may reuse existing processes, so a single process can present multiple windows / tabs, and closing one of them won't terminate the process as a whole.
If you need to ensure that a dedicated, new process is used, you have two options:
(a) Make sure that no preexisting Firefox instance is running, either by erroring out, or - if acceptable for your use case - by forcefully terminating all existing instances first (Stop-Process -Name firefox).
(b) With significantly more effort, create a dedicated, temporary Firefox profile that you can launch with the -new-instance option, which allows multiple independent Firefox instances to run concurrently and whose lifetime can be tracked separately.
The following - cumbersome - solution implements option (b):
If no firefox process is found, there is no concern about creating independent instances, and Firefox can be launched normally.
Otherwise, a temporary profile is created, and launched via the -new-instance and -profile options to ensure that a new process will be used to present the new browser window.
After launching the initial process, loop until a firefox process appears that was launched later and has a nonempty window title, which is then presumed to be the real process of interest.
You can then wait for the termination of this process to know when the dedicated browser window has been closed. If a temporary profile had to be created, it is cleaned up afterwards.
# Comment this statement out to silence the verbose messages below.
$VerbosePreference = 'Continue'
$now = Get-Date
$url = 'https://example.org' # URL to open.
# Launch a (new) Firefox instance.
if ($alreadyRunning = [bool] (Get-Process -ErrorAction Ignore firefox)) {
# Determine the path for a temporary profile with a unique name.
$tempProfilePath = Join-Path ([IO.Path]::GetTempPath()) ([datetime]::utcnow.tostring('o') -replace '\D')
Write-Verbose "Firefox is already running. Creating temp. profile $tempProfilePath..."
# Note: Creating an empty directory for the profile is seemingly enough.
$null = New-Item -Type Directory $tempProfilePath
Write-Verbose "and starting a new instance with it..."
Start-Process firefox "-new-instance -profile $tempProfilePath $url"
} else {
Write-Verbose 'Firefox isn''t running. Starting normally...'
Start-Process firefox $url
}
# Find the newly launched process that is the actual browser window.
Write-Verbose 'Waiting for a recently launched Firefox process with a nonempty window title to appear...'
while (-not (
$ps = Get-Process firefox |
Where-Object StartTime -gt $now |
Where-Object MainWindowTitle
)) {
Write-Host -NoNewLine .
Start-Sleep -MilliSeconds 500
}
Write-Host
Write-Verbose "Found. Waiting for process to exit..."
$ps.WaitForExit()
Write-Verbose 'Process has exited.'
if ($alreadyRunning) {
Write-Verbose "Cleaning up temporary profile $tempProfilePath..."
do {
# The profile dir. is typically held on to for a little while longer by associated processes that may not have terminated yet.
Start-Sleep -MilliSeconds 200
Remove-Item -ErrorAction Ignore -Literalpath $tempProfilePath -Recurse -Force
}
while (Test-Path -LiteralPath $tempProfilePath)
}
Thanks to #mklement0 work, in your case you can use the parent Process ID.
I use WMI to get the parent process, but it works for the very first launch.
$parentProcess = Start-Process 'C:\Program Files\Mozilla Firefox\firefox.exe' -argumentlist "-new-window https://google.com -foreground" -PassThru
$childProcess = get-process -id $(Get-CimInstance -Class Win32_Process -Filter "Name = 'firefox.exe'" | where {$_.ParentProcessId -eq $parentProcess.id}).ProcessId
# effectively stop the child
$childProcess | Stop-Process
I am new to powershell!
Thank you to anyone who takes the time out of their day and can kindly help me with this.
NOTES: I AM NOT AN ADMINSTRATOR AND MY POWERSHELL IS RUNNING IN CONSTRAINED MODE - IT CANNOT BE CHANGED DUE TO WORK POLICY :D
I have the following code so far:
Add-Type -AssemblyName System.Windows.Forms
$global:balloon = New-Object System.Windows.Forms.NotifyIcon
Get-Member -InputObject $Global:balloon
[void](Register-ObjectEvent -InputObject $balloon -EventName MouseDoubleClick -SourceIdentifier IconClicked -Action {
#Perform cleanup actions on balloon tip
$global:balloon.dispose()
Unregister-Event -SourceIdentifier IconClicked
Remove-Job -Name IconClicked
Remove-Variable -Name balloon -Scope Global
})
$path = (Get-Process -id $pid).Path
$balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path)
[System.Windows.Forms.ToolTipIcon] | Get-Member -Static -Type Property
$balloon.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]::Warning
$balloon.BalloonTipText = 'What do you think of this balloon tip?'
$balloon.BalloonTipTitle = "Attention $Env:USERNAME"
$balloon.Visible = $true
$balloon.ShowBalloonTip(5000)
Sadly this does not work in constrained work - I cannot use the Add-Type function. Is there a code that allows balloon type tip notifications (or anything similar - just need a pop up message) in powershell in constrained mode FOR people with no admin rights.
Error:
Cannot invoke method. Method invocation is supported only on core types in this language mode.
If this is not possible at all, no worries at all, can someone please clarify this so I can tell my network adminstrator.
One solution to this is to get your administrator to add the script as an exception to their policy. This will allow your approved script to run in Full Language mode.
The better solution is for your administrator to allow signed scripts in their policy exceptions and for you to sign your scripts by obtaining a Code Signing certificate from your local CA. On a Windows domain this takes a little setting up but once done is relatively easy to administer.
We block all unsigned scripts on our domain and Admins/Developers are given Code Signing certificates.
I am attempting to set app pools to recycle at multiple times in the day in iis 8.5, I've tried using powershell and app command and when testing on a server that has no sites/applications in the pool it seems to work perfectly, however when trying to set using either method on a server that has sites in the app pools I'm seeing strange behavior, It seems to work however in the GUI of IIS if i look at the recycling settings of the app pool it only shows one of the times specified.
Powershell script initially tried using is:
function Set-ApplicationPoolRecycleTimes {
param (
[string]$ApplicationPoolName,
[string[]]$RestartTimes
)
Import-Module WebAdministration
Write-Output "Updating recycle times for $ApplicationPoolName"
# Delete all existing recycle times
Clear-ItemProperty IIS:\AppPools\$ApplicationPoolName -Name Recycling.periodicRestart.schedule
Clear-ItemProperty IIS:\AppPools\$ApplicationPoolName -Name Recycling.periodicRestart.time
foreach ($restartTime in $RestartTimes) {
Write-Output "Adding recycle at $restartTime"
# Set the application pool to restart at the time we want
New-ItemProperty -Path "IIS:\AppPools\$ApplicationPoolName" -Name Recycling.periodicRestart.schedule -Value #{value=$restartTime}
Set-ItemProperty -Path "IIS:\AppPools\$ApplicationPoolName" -Name Recycling.periodicRestart.time -Value "00:00:00"
} # End foreach restarttime
} # End function Set-ApplicationPoolRecycleTimes
$apppoolname1 = "app pool's name"
$restartat = #("1:45", "18:45")
Set-ApplicationPoolRecycleTimes -ApplicationPoolName $apppoolname1 -RestartTimes $restartat
Again this seems to work perfectly unless there are sites in the application pool. When sites exist it seems to work except that the gui only shows one of the times set:
however querying the value show's both times:
Import-Module WebAdministration
(Get-ItemProperty ('IIS:\AppPools\app pool name') -Name Recycling.periodicRestart.schedule.collection) | select value
value
-----
18:45:00
01:45:00
also attempted using appcmd but finding the same results, works perfectly on a server with no sites in the app pool, but when run against servers with sites, missing one of the times in the gui, querying shows both times. I have turned logging on for app pool recycles to confirm it's happening at both times but wondering if I'm just overlooking something obvious.
appcmd script:
CD C:\windows\System32\inetsrv
$V1 = "app pool name"
#clears any existing schedule
cmd.exe /c appcmd.exe set apppool /apppool.name: $V1 /-recycling.periodicRestart.schedule
#setting desired recycles
cmd.exe /c appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='$v1'].recycling.periodicRestart.schedule.[value='01:45:00']" /commit:apphost
cmd.exe /c appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='$v1'].recycling.periodicRestart.schedule.[value='18:45:00']" /commit:apphost
I tried your PowerShell script with the application pool which contains a site or without site.in both the condition your posted script is working.
you could try to use the below script:
function Set-ApplicationPoolRecycleTimes {
param (
[string]$ApplicationPoolName,
[string[]]$RestartTimes
)
Import-Module WebAdministration
Write-Output "Updating recycle times for $ApplicationPoolName"
# Delete all existing recycle times
Clear-ItemProperty IIS:\AppPools\$ApplicationPoolName -Name Recycling.periodicRestart.schedule
foreach ($restartTime in $RestartTimes) {
Write-Output "Adding recycle at $restartTime"
# Set the application pool to restart at the time we want
New-ItemProperty -Path "IIS:\AppPools\$ApplicationPoolName" -Name Recycling.periodicRestart.schedule -Value #{value=$restartTime}
} # End foreach restarttime
} # End function Set-ApplicationPoolRecycleTimes
$apppoolname = "abcsite"
$restartat = #("05:55", "12:55", "17:00")
Set-ApplicationPoolRecycleTimes -ApplicationPoolName $apppoolname -RestartTimes $restartat
or
appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='test1'].recycling.periodicRestart.schedule.[value='07:00:00']" /commit:apphost
appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='test1'].recycling.periodicRestart.schedule.[value='18:25:00']" /commit:apphost
or
Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/applicationPools/add[#name='test1']/recycling/periodicRestart/schedule" -name "." -value #{value='07:00:00'}
Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.applicationHost/applicationPools/add[#name='test1']/recycling/periodicRestart/schedule" -name "." -value #{value='18:25:00'}
The above scripts are tested with the IIS 10 (Windows 10) and IIS 8.5(windows server 2012r2)
I try to bypass Windows IE setting pop up from the initial launch IE. either close the window or click ask later. Is it possible Powershell can check the window object? I tried the "New-Object" below:
New-Object -ComObject 'internetExplorer.Application'
But it doesn't seem to work that way I expected.
Thanks
For those looking for the Registry method (or Powershell), this is the script I use:
$keyPath = 'Registry::HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Internet Explorer\Main'
if (!(Test-Path $keyPath)) {
New-Item $keyPath -Force
}
Set-ItemProperty `
-Path $keyPath `
-Name "DisableFirstRunCustomize" `
-Value 1
You want to test the path exists first as using the -Force parameter on New-Item will remove any existing children of the path provided.
Is using group policy out of the question as this can easily be done through a gpo. Here is a link explaining. https://mkcheah88.blogspot.com/2014/06/microsoft-how-to-disable-internet.html
If not is it ok to change the registry key this links to with powershell prior to internet explorer opening? If so I can modify this answer to include that answer.
I'm extracting a ZIP file in PowerShell by using the DotNetZip library, and I want to display progress. I'm using the following code:
try {
$zip = [Ionic.Zip.ZipFile]::Read($ZipFileName)
Register-ObjectEvent `
-InputObject $zip `
-EventName ExtractProgress `
-SourceIdentifier ExtractProgress `
-Action {
[Console]::Beep()
Write-Host $Sender
Write-Host $SourceEventArgs
} | Out-Null
$zip.ExtractAll($Destination, 'OverwriteSilently')
}
finally {
Unregister-Event -SourceIdentifier ExtractProgress
$zip.Dispose()
}
My problem is that I don't see the events (no beep, no Write-Host) until the very end. I'm expecting to see progress events during the process.
Initially, I thought it was because Register-ObjectEvent queued the events, but the PowerShell help says that -Action is invoked immediately, without the event being queued.
If I write the equivalent code in a C# console application, then I see the progress events as each file is extracted, as expected, which means that (as far as I can tell) DotNetZip is doing the right thing. Note that the events are raised on the same thread that called ExtractAll.
What am I doing wrong?
(Windows 7 x64, PowerShell 2.0, configured to use .NET 4.0)