How to log "new pnp devices" events to console on Windows? - powershell

I want to write something like nestat (that log new tcp connections to console) but for pnp devices with powershell.
Is there an API method "to subscribe to some kind of events bus" specific to PnP and get "connected" and "disconnected" events?
Or only one way to achive this is looping with Get-PnpDevice and "manually" seacrh for the differences?

You can use WMI events to do this. For example, here is one way to do it (seems over-complicated, so maybe someone can improve on it):
$addIdentifier = "WMI.PnpAddEvent"
$removeIdentifier = "WMI.PnpRemoveEvent"
$addAction = { $pnpEntity = $EventArgs.NewEvent.TargetInstance; Write-Host "`nPNPEvent: Plugged In`nCaption: $($pnpEntity.Caption)`nPNPDeviceID: $($pnpEntity.PNPDeviceID)`n" }
$addQuery = "SELECT * FROM __instancecreationevent WITHIN 5 WHERE targetinstance isa 'Win32_PnPEntity'"
$removeAction = { $pnpEntity = $EventArgs.NewEvent.TargetInstance; Write-Host "`nPNPEvent: Unplugged`nCaption: $($pnpEntity.Caption)`nPNPDeviceID: $($pnpEntity.PNPDeviceID)`n" }
$removeQuery = "SELECT * FROM __instancedeletionevent WITHIN 5 WHERE targetinstance isa 'Win32_PnPEntity'"
$addEventArgs = #{
Query = $addQuery
SourceIdentifier = $addIdentifier
SupportEvent = $true
Action = $addAction
}
$removeEventArgs = #{
Query = $removeQuery
SourceIdentifier = $removeIdentifier
SupportEvent = $true
Action = $removeAction
}
Register-WmiEvent #addEventArgs
Register-WmiEvent #removeEventArgs
Now, when you add/remove a device, you'll get output like this in the console:
PNPEvent: Unplugged
Caption: Apple iPhone
PNPDeviceID: USB\VID_05AC&PID_12A8&MI_00\E&2491F388&0&0000
PNPEvent: Plugged In
Caption: Apple iPhone
PNPDeviceID: USB\VID_05AC&PID_12A8&MI_00\E&2491F388&0&0000
A couple of things to keep in mind:
The event registrations last for the current session only
You need to run this from an elevated prompt
As mentioned, the registrations should be cancelled when your session ends, but if you want to do it manually, you can do it like this:
$addIdentifier, $removeIdentifier | ForEach-Object { Unregister-Event -Force -SourceIdentifier $_ }

Related

Grab context of a PowerShell Browser window to auto populate fields (using Selenium or something similar)

Is it possible to use some method to capture and control a powershell browser window that is generated from a 3rd party cmdlet? So that I can programmatically fill in the user and password and click submit?
$migrationAccountCreds = [Ordered]#{
'migration0#x.com' = 'xx';
'migration1#x.com' = 'xx';
'migration2#x.com' = 'xx';
'migration3#x.com' = 'xx';
'migration4#x.com' = 'xx';
'migration5#x.com' = 'xx';
'migration6#x.com' = 'xx';
'migration7#x.com' = 'xx';
'migration8#x.com' = 'xx';
'migration9#x.com' = 'xx'
}
$boxAccounts = #()
foreach ($creds in $migrationAccountCreds.GetEnumerator()) {
$box = Connect-box -email $creds.Key -admin
$boxAccounts += $box
}
the line $box = Connect-box -email $creds.Key -admin does not allow me to pass in the password. So it pops to open a browser login for me to do manually. Since I have the passwords, and this is to be run on a task, I would like to programmatically enter in the usernames and passwords of the user that is being iterated through.
Is it possible?
logically thinking, I was wondering if I could spin up another thread that does something like Get-Process looking for a browser window that is open and if the URL equals what I am looking for, then fill it in and close the thread.

New-OktaApp in OktaAPI Module will not error out but only seems to freeze

I am attempting to use New-OktaApp to make a new okta application. It runs without errors, however once it runs powershell fails to run any further and must be forced closed.
Has anyone experienced this before?
If you have used this in the past can you show me an example of how would got it to run and produce an app?
Import-Module "pathtomodule\OktaAPI"
Connect-Okta "MyAPIToken" "MyOrg"
New-OktaApp #{
name = "name";
label = "label";
}
There are many examples in the GH site, for example
https://github.com/gabrielsroka/OktaAPI.psm1/blob/master/CallOktaAPI.ps1#L12-L33
function Add-SwaApp() {
$user = Get-OktaUser "me"
# see https://developer.okta.com/docs/api/resources/apps#add-custom-swa-application
$app = #{
label = "AAA Test App"
settings = #{
signOn = #{loginUrl = "https://aaatest.oktapreview.com"}
}
signOnMode = "AUTO_LOGIN"
visibility = #{autoSubmitToolbar = $false}
}
$app = New-OktaApp $app
# see https://developer.okta.com/docs/api/resources/apps#assign-user-to-application-for-sso
$appuser = #{id = $user.id; scope = "USER"}
Add-OktaAppUser $app.id $appuser
}

Is it possible to pull multiple SNMP values from try..catch statements?

Is there a way to pull multiple SNMP values and update them as new values in PowerShell?
I have two different OIDs that I'm pulling from my UPS and I want those integer values saved to a database table.
This is my code
$UPS_Temp_oid = '1.3.6.1.4.1.318.1.1.10.2.3.2.1.4.1'
$Battery_Load_oid = '.1.3.6.1.4.1.318.1.1.1.4.2.3.0'
$sql = "SELECT temp, batteryload, upsid, ups_ip FROM ups WHERE ups_ip IS NOT NULL"
$cmd = New-Object System.Data.SqlClient.SqlCommand($sql, $conn)
$rows = $cmd.ExecuteReader()
while ($rows.Read()) {
$ups_id = $rows["upsid"]
$ups_ip = $rows["ups_ip"].trim()
$ups_temp = $rows["temp"]
$battery_load = $rows["batteryload"]
Write-Output $ups_id, $ups_ip, $ups_temp, $battery_load
# Ping UPS
$ping = New-Object System.Net.NetworkInformation.Ping
$ping_reply = $ping.Send($ups_mgmt_ip) | select status
# If success go call func SNMP
if ($ping_reply.status -eq "Success") {
try {
$frm_snmp = Invoke-SNMPget $ups_ip $UPS_Temp_oid "community"
} catch {
Write-Host "$ups_mgmt_ip SNMP Get error: $_"
return null
}
would I have to create another try..catch for the battery_load_oid or would I just simply do something like that?
Invoke-SNMPget ups_ip $ups_temp_oid, $nattery_load_oid "community"

WMI Permanent Events

I try to set wmi permanent events base on specifics events coming from network card on a Windows 7 SP1.
I use this code:
#Creating a new event filter
$instanceFilter = ([wmiclass]"\\.\root\subscription:__EventFilter").CreateInstance()
$instanceFilter.QueryLanguage = "WQL"
$instanceFilter.Query = "Select * From __InstanceCreationEvent Where TargetInstance ISA 'Win32_NTLogEvent' AND TargetInstance.LogFile='System' AND TargetInstance.SourceName LIKE '%e1_express%' AND (TargetInstance.EventCode=27 OR TargetInstance.EventCode=32 OR TargetInstance.EventCode=33 OR TargetInstance.EventCode=36)"
$instanceFilter.Name = "LAN_Watcher_Filter"
$instanceFilter.EventNamespace = 'root\cimv2'
$result = $instanceFilter.Put()
$newFilter = $result.Path
#Creating a new event consumer
$instanceConsumer = ([wmiclass]"\\.\root\subscription:CommandLineEventConsumer").CreateInstance()
$instanceConsumer.Name ='LAN_Watcher_Consumer'
$instanceConsumer.ExecutablePath="C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
$instanceConsumer.CommandLineTemplate="-file C:\Windows\System32\Switch_LAN_TEST.ps1"
$result = $instanceConsumer.Put()
$newConsumer = $result.Path
#Bind filter and consumer
$instanceBinding = ([wmiclass]"\\.\root\subscription:__FilterToConsumerBinding").CreateInstance()
$instanceBinding.Filter = $newFilter
$instanceBinding.Consumer = $newConsumer
$result = $instanceBinding.Put()
$newBinding = $result.Path
##Removing WMI Subscriptions using [wmi] and Delete() Method
#([wmi]$newFilter).Delete()
#([wmi]$newConsumer).Delete()
#([wmi]$newBinding).Delete()
I can turn off the powershell session, script will be launch but if I reboot the computer, the permanent event exist again but the script doesn't work.
Any idea ?
Thanks.

Powershell - Inexplicable timeout for HttpRequests

I have a powershell script that monitors several pages on a handful of servers. It gives the HTTP status code from each to determine the server's health.
This has been working perfectly for a number of weeks but today, without making any changes to the script, I started receiving timeout errors ("The operation has timed out"). A telnet on port 80 to the server let me through instantly and I could connect happily via every other mechanism I could think of.
Finally I updated the script by changing the timeout period from 1000ms to 2000ms and the script worked again, instantly. And it still worked after I changed it back to 1000ms.
This is the second time something like this has happened with the same resolution. What is happening and how can I avoid it?
This script may help, it may be a bit overkill for your situation.
function HTTP-Get() {
param
(
[string] $target
)
try
{
$webRequest = [System.Net.WebRequest]::Create($target)
$webRequest.Method = "GET"
[System.Net.WebResponse] $resp = $webRequest.GetResponse();
$rs = $resp.GetResponseStream();
[System.IO.StreamReader] $sr = New-Object System.IO.StreamReader -argumentList $rs;
[string] $results = $sr.ReadToEnd();
}
catch [System.Net.WebException]
{
Write-Warning $_
if ($_.response)
{
$_.response.Close();
}
}
finally
{
if ($sr)
{
$sr.close();
$sr.dispose();
}
if ($resp)
{
$resp.close();
}
}
return $results;
}
As I mentioned in the comments: I had this issue with powershell and none of the .NET http tricks worked (httprequest, webclient). The site I used worked fine with postman and other http helpers.
It seemed like the issue is related to the .NET version, sp, etc. I changed my code to use COM instead of .NET and now it works fine.
......
$HTTPREQUEST_SETCREDENTIALS_FOR_SERVER = 0
$Http = new-object -com "WinHttp.WinHttpRequest.5.1"
$Http.open("GET", "http://....", $false)
$Http.SetCredentials($userName, $password, $HttpREQUEST_SETCREDENTIALS_FOR_SERVER)
$Http.send()
$status = [int]$Http.Status
$responseText = $Http.responseText
.....
I hope it helps :)