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.
Related
I have a snippet that works fine. It registers an objectevent as follows (snippet):
Register-ObjectEvent $Watcher -EventName Created -SourceIdentifier FileCreated -Action {
It works fine, but I can't seem to get the script to fully stop and unregister. When I use "normal" methods to stop code (listed below), when I rerun the code (via F5) I get error:
Register-ObjectEvent : Cannot subscribe to the specified event. A subscriber with the source identifier 'FileCreated' already exists.
The only way I can unregister it (so far) is to terminate the powershell.exe process, which also kills the powershell run time within VSCode (throwing errors, forcing a manual restart).
I start the code by hitting F5
To stop the code, I have tried:
Shift-F5
Ctrl-C (in the powershell terminal area)
Nothing works except as described above.
What am I missing?
For debugging purposes only, where you often force-stop your script, there are 2 options. Either run the unregister-Event line manually so the event is unregistered or do add something like that near the top f your script. (at least before the Register-ObjectEvent )
Unregister-Event -SourceIdentifier FileCreated -EA 0
-EA 0 is the same as -ErrorAction SilentlyContinue and will prevent the script from throwing an error when you are on a new session and the event was never registered yet.
Note: This should not be in your production script and is only meant as a debugging help. (If you want to keep it on hand, I'd say comment it out at least on the prod. version of the script)
Your production version of the script should implement Unregister-Event properly though, something more akin to:
$FileWatcherReg = #{
InputObject = $Watcher
EventName = 'Created'
SourceIdentifier = 'FileCreated'
MessageData = #{WatchQueue = $WatchQueue; Timer = $WatchTimer }
Action = {
if ($null -ne $event) {
Write-Host "Path: $($Event.SourceArgs.FullPath) - ($($Event.Timegenerated))"
}
}
}
Register-ObjectEvent #FileWatcherReg
while ($true) {
Start-Sleep -Milliseconds 100
# Logic to exit the loop at some point.
}
# Exit script logic ...
Unregister-Event -SourceIdentifier FileCreated
Similar to Sage's example above, is this larger example. It structures the event clearly, and shows how by keeping the script running, you can then cancel the script, which will trigger the cleanup block.
So there is something to be said for this approach. (However, I continue to see the whole Register-ObjectEvent as kind of a TSR... your code stays resident... forever... waiting for the relevant event....)
The example:
https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/using-filesystemwatcher-correctly-part-2#
We have a data dump come from an external entity on a daily basis. Once we receive the file, a Object Event Listener triggers, moves the file into two separate locations (one live, one backup) and then calls a MS SQL stored procedure to import the file into the database.
The process and my script seem to function perfectly fine. The file moves, and the SQL is executed. However, every morning when I check to see if it triggered, nothing triggered. I check for event-subscribers by calling Get-EventSubscriber and there are no listeners registered. Once I register the listeners and move the file into the input location, everything runs fine.
I understand that the Event Subscriptions do not persist through reboots, but how long do they stay open? is it possible that something is closing them? or do they time out?
$watchFolder = "\\server\c$\path\to\inbound\"
$filter = "*.txt"
$fsw = New-Object IO.FileSystemWatcher $watchFolder, $filter -Property #{
IncludeSubdirectories = $false
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileMonitor -Action {
$filePath = $Event.SourceEventArgs.FullPath
$fileName = $Event.SourceEventArgs.Name
Write-Host "Source File: $fileName"
$success = copyFile($fileName, $filePath) #custom function to copy file to multiple destinations
if ($success) {
Write-Host "Starting SQL_JOB_NAME Job"
Set-Location SQLSERVER:\SQL\server\DEFAULT\Databases\msdb\
$execute_import = "EXEC dbo.sp_start_job N'SQL_JOB_NAME';"
Invoke-Sqlcmd -SuppressProviderContextWarning -Query $execute_import
} else {
Write-Host "Something failed along the way: `r`n"
}
}
As silly as it seems, I learned here that calling Register-ObjectEvent if the PowerShell process is closed, the ObjectEvent is also unregistered.
Because the nature of the project required us to have an always-on file listener, we decided that Powershell was not the correct implementation for us.
Instead we implemented a Windows service using the .NET libraries, which are the same used here in PowerShell.
Thanks to PetSerAl for his prompt answer.
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
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)
I was trying to execute powershell in parallel mode. I was advised to create an event which will trigger whenever there is a change in folder.
For ex: If a folder name called "test1" is created in a particular folder then my powershell script test1.ps1 should be triggered.
I was trying to get example for this with Register-Objevent , but i am not getting any good clue.
If you have implemented some thing like this , can you please guide me?
Updated:
When i create a file named test1.ps1 in the "D:\ParallelEvent\temp" folder, it should execute test1.ps1 powershell file. Following is the code for that
$ScriptLoc="D:\My_Scripts"
$watcher = New-Object System.IO.FileSystemWatcher -Property #{Path = 'D:\ParallelEvent\temp';Filter = '*.txt';NotifyFilter = [System.IO.NotifyFilters]'FileName,LastWrite'}
$CreatedAction =
{
$FilenamewithoutExtn=$(($event.sourceEventArgs.Name).Split('.')[0])
Start-Job $ScriptLoc\$FilenamewithoutExtn.ps1
Get-Job -State Running | Wait-Job
}
Register-ObjectEvent -InputObject $watcher -EventName Created -SourceIdentifier FileCreated -Action $CreatedAction
My test1.ps1 has following line
[system.windows.forms.messagebox]::show("Hello, Test1!")
But still it doesn't execute the test1.ps1 it seems. I did not get any messagebox. Am i missing any thing?
you are not getting messagebox because powershell jobs run as background process and does not show ui.
if you modify the test1.ps1 to a file redirection
"test " > C:\AnywhereYouWantToRedirectData\testagain.txt
you will be able to see that the test1.ps1 runs and redirected file gets created (testagain.txt).