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

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"

Related

autocomplete in datagridviewcell

I have a datagridview control and would like in one of the cells to make use of autocomplete.
I tried using the editcontrolshowing event but cant really get it to work.
$DGVtimeAttendance_EditingControlShowing = [System.Windows.Forms.DataGridViewEditingControlShowingEventHandler]{
$queryGetaLLuSERS = "SELECT CONCAT(firstname,' ',lastname) AS Employee
FROM tbl_user"
$queryGetaLLuSERS = sql_query -Query $queryGetaLLuSERS
$getheaderText = $DGVtimeAttendance.Columns[1].HeaderText
if ($getheaderText -eq 'Employee')
{
#$getvalueChanged = $this.Rows[$_.RowIndex].Cells[$_.ColumnIndex].value
#Write-Host $getvalueChanged
$autotext = New-Object System.Windows.Forms.DataGridViewTextBoxEditingControl
$autotext.AutoCompleteMode = 'Suggest'
$autotext.AutoCompleteSource = 'CustomSource'
$autotext.AutoCompleteCustomSource.AddRange($queryGetaLLuSERS.employee)
$DGVtimeAttendance.Controls.add($autotext)
#$_.Control.autocompleteMode = 'Suggest'
Write-Host $_
}}
with the help from santiagos post
i changed the if statement to
if ($getheaderText -eq 'Employee')
{
$this.EditingControl.AutoCompleteMode = [System.Windows.Forms.AutoCompleteMode]::Suggest
$this.EditingControl.AutoCompleteSource = [System.Windows.Forms.AutoCompleteSource]::CustomSource
$this.EditingControl.AutoCompleteCustomSource.AddRange(($queryGetaLLuSERS.employee)) #= [System.Windows.Forms.AutoCompleteSource]::CustomSource
}
and worked like a charm
thx everyone and especially santiago

How to identify the default audio device in Powershell?

I am looking for a solution to get the default audio device via Powershell.
In best case, it could work via embedded C#-code to directly use IMMDeviceEnumerator::GetDefaultAudioEndpoint (see here IMMDeviceEnumertor).
But if it is easier to get this via RegKeys, then this is also OK.
I have seen a couple of code-snippets reading the keys from HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render or \Capture, but I still struggle to identify the DEFAULT device.
It seems, when I do modify the order of devices, then I can simply search for active devices (DeviceState=1) and then sort by the values "Level:0", "Level:1" and "Level:2", but the level-values are not available on a system, where the user has not modied the order manually. What is the sort-criteria in such case?
This is the code-snippet to solve it via RegKeys, but as mentioned - not working for all situations:
$regAudio = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio"
$nameId = "{b3f8fa53-0004-438e-9003-51a46e139bfc},6"
$classId = "{a45c254e-df1c-4efd-8020-67d146a850e0},2"
$driverDetails = "{83da6326-97a6-4088-9453-a1923f573b29},3"
function get-DefaultDevice($type) {
$activeDevices = foreach($key in Get-ChildItem "$regAudio\$type\") {
foreach($item in Get-ItemProperty $key.PsPath) {
if ($item.DeviceState -eq $activeState) {$item}
}
}
$defaultDevice = $activeDevices | Sort-Object -Property "Level:0","Level:1","Level:2" | select -last 1
$details = Get-ItemProperty "$($defaultDevice.PSPath)\Properties"
$name = "$($details.$classId) ($($details.$nameId))"
return #{
name = $name
driver = $details.$driverDetails
}
}
$OsRender = get-DefaultDevice "Render"
$OsCapture = get-DefaultDevice "Capture"
Is there any way to get this info "in a smart way" (without any external DLLs, of course)?
Finally I figured it out and I am happy to share the working code-snippet:
cls
Add-Type #'
[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDevice {
int a(); int o();
int GetId([MarshalAs(UnmanagedType.LPWStr)] out string id);
}
[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDeviceEnumerator {
int f();
int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint);
}
[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject { }
public static string GetDefault (int direction) {
var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
IMMDevice dev = null;
Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(direction, 1, out dev));
string id = null;
Marshal.ThrowExceptionForHR(dev.GetId(out id));
return id;
}
'# -name audio -Namespace system
function getFriendlyName($id) {
$reg = "HKLM:\SYSTEM\CurrentControlSet\Enum\SWD\MMDEVAPI\$id"
return (get-ItemProperty $reg).FriendlyName
}
$id0 = [audio]::GetDefault(0)
$id1 = [audio]::GetDefault(1)
write-host "Default Speaker: $(getFriendlyName $id0)"
write-host "Default Micro : $(getFriendlyName $id1)"
and in case you need a language-neutral international name of each device MMDEVICE-id and (optional) its driver then use this function:
# https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/shared/devpkey.h
# https://github.com/EddieRingle/portaudio/blob/master/src/hostapi/wasapi/mingw-include/mmdeviceapi.h
$regId = "{b3f8fa53-0004-438e-9003-51a46e139bfc},2"
$regName = "{b3f8fa53-0004-438e-9003-51a46e139bfc},6"
$regFormFactor = "{1da5d803-d492-4edd-8c23-e0c0ffee7f0e},0"
# https://learn.microsoft.com/en-us/windows/win32/api/mmdeviceapi/ne-mmdeviceapi-endpointformfactor
$formFactor = #(
"RemoteNetworkDevice",
"Speakers",
"LineLevel",
"Headphones",
"Microphone",
"Headset",
"Handset",
"UnknownDigitalPassthrough",
"SPDIF",
"DigitalAudioDisplayDevice",
"UnknownFormFactor"
)
function getInternationalNameAndDriver($id) {
$guid = $id.Substring(17)
$subKey = #("Render","Capture")[[int]::Parse($id[5])]
$reg = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\$subKey\$guid\Properties"
$details = get-ItemProperty $reg -ea 0
if ($details) {
$id = $details.$regId.subString(4)
$name = $details.$regName
$form = $formFactor[$details.$regFormFactor]
$hardware = get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Enum\$id"
$regDrv = $hardware.Driver
$driver = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Class\$regDrv"
$drvName = $driver.DriverDesc
$drvVersion = $driver.DriverVersion
}
return "$form ($name), driver: $drvName $drvVersion"
}
this gives you an output like this:
Default Speaker: Speakers (Realtek Audio), driver: Realtek Audio 6.0.1.6127
Default Micro : Microphone (Logitech BRIO), driver: USB Audio Device 10.0.22000.653

Tidying up a powershell script

So I need help tidying up a script that I have. The purpose of this script is to make 18 different sql files based on the data below 18 different column headers. What my script does now is make 1 sql file based on which column I choose to input via "Read-Host". This is my current script
function get-header
{Read-Host "Type the Column header betwen B-Z for which sql files needs to be created"
}
function get-column
{
Read-Host "Type the Column number"
}
do
{
$val = get-header
}
while(!($val))
do
{$col = get-column
}
while(!($col))
switch ($val)
{
"B"{$column = "1"}
"C"{$column = "2"}
"D"{$column = "3"}
"E"{$column = "4"}
"F"{$column = "5"}
"G"{$column = "6"}
"H"{$column = "7"}
"I"{$column = "8"}
"J"{$column = "9"}
"K"{$column = "10"}
"L"{$column = "11"}
"M"{$column = "12"}
"N"{$column = "13"}
"O"{$column = "14"}
"P"{$column = "15"}
"Q"{$column = "16"}
"R"{$column = "17"}
"S"{$column = "18"}
"T"{$column = "19"}
"U"{$column = "20"}
"V"{$column = "21"}
"W"{$column = "22"}
"X"{$column = "23"}
"Y"{$column = "24"}
"Z"{$column = "25"}
default { $column = 'Unknown' }
}
if ($column -eq 'Unknown')
{
Write-Warning "Not a valid input"
return
}
$csv = Import-Csv "Indices Updates - September 2018.csv" -Header 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
$date = (Get-Date -Format "MM/dd/yyyy").Replace("-","/")
$sql = #("INSERT INTO benchmark_values(created_at,benchmark_id,date,amount,created_by_username)
foreach($data in $csv)
{
$secondcolumn = [int]$column + 1
$sql += "('$date',$col,'$($data.1)',$($data.$secondcolumn),'BPylla'),"
}
$sql | Out-File "sqldata.sql"
Now I want to get rid of read-host entirely because I dont want to input any values. I also will give an example of what the csv file looks like and what the sql file should look like.
So the goal is to produce different sql files from each column of information using the the sql format posted. I already have the template for that in my script now, I just need the script to create all the sql files based on headers and still input the data below the headers in the new sql files. Any help would be greatly appreciated! Thanks!

Is it possible to update a row in MS Access from PowerShell?

I have the following PowerShell code which adds a new line of data into a MS Access database (based on user input) and works perfectly.
if ($NewAccounts ="Y") {
$cursor = 3
$lock = 3
$Ado = New-Object -ComObject ADODB.Connection
$recordset = New-Object -ComObject ADODB.Recordset
$Ado.Open("Provider = Microsoft.ACE.OLEDB.12.0;Data Source=$Source")
$query = "Select * from [Sheet1]"
$recordset.Open($query, $ado, $cursor, $lock)
$recordset.AddNew()
$recordset.Fields.Item("Account") = $AccName
$recordset.Fields.Item("Serial") = $CGBSerial
$recordset.Fields.Item("SAExpiry") = $SAEDate.ToString("dd/MM/yyyy")
$recordset.Fields.Item("SAValidatedPerson") = $SAPerson
$recordset.Fields.Item("DataCollection") = $DCRun
$recordset.Fields.Item("DataCollectionDate") = $DCRunDate
$recordset.Fields.Item("DataCollectionPerson") = $DCPerson
$recordset.Fields.Item("Version") = $Version
$recordset.Fields.Item("VersionDateValidated") = Get-Date -Format d
$recordset.Fields.Item("VersionValidatedPerson") = $logontrim
$recordset.Update()
$recordset.Close()
$ado.Close()
}
However, I cannot seem to update a row in the database that already exists. Is it possible to update a row, rather than creating an entirely new row?
$recordset.AddNew() appends a new empty record to the recordset. To update an existing record you need to navigate to the record you want to modify first, and then change the values of that record.
$recordset.Open($query, $ado, $cursor, $lock)
while ($recordset.Fields.Item('Account').Value -ne $AccName) {
$recordset.MoveNext()
}
$recordset.Fields.Item('Serial') = $CGBSerial
...
$recordset.Update()
$recordset.Close()
However, you can't use MoveNext() with a static cursor, so you need to change the cursor type to adOpenForwardOnly ($cursor = 0).
Alternatively you could use a prepared statement:
$cn = New-Object -ComObject 'ADODB.Connection'
$cn.ConnectionString = "..."
$cn.Open()
$cmd = New-Object -ComObject 'ADODB.Command'
$cmd.CommandText = 'UPDATE [Sheet1] SET Serial=?, SAExpiry=?, ... WHERE Account=?'
$cmd.Parameters.Append($cmd.CreateParameter('#p1', 200, 1, 50, $CGBSerial))
$cmd.Parameters.Append($cmd.CreateParameter('#p2', 7, 1, $null, $SAEDate))
...
$cmd.Execute()
$cn.Close()

How To Execute MS Access Query with OLEDB.12

I am looking for the syntax for executing MS Access named query using Microsoft.ACE.OLEDB.12.0 command object.
I see lots of examples using tables but non for queries yet. Swapping out the table name for the query name seems not to work. i.e. select * from 'myquery'
Here is my code snippet:
$OleDbConn = New-Object "System.Data.OleDb.OleDbConnection";
$OleDbCmd = New-Object "System.Data.OleDb.OleDbCommand";
$OleDbAdapter = New-Object "System.Data.OleDb.OleDbDataAdapter";
$DataTable = New-Object "System.Data.DataTable";
$OleDbConn.Open();
$OleDbCmd.Connection = $OleDbConn;
$OleDbCmd.CommandText = "'myQuery'"; # name query in MS Access db
$OleDbCmd.CommandType = [System.Data.CommandType]::StoredProcedure;
$OleDbAdapter.SelectCommand = $OleDbCmd;
$RowsReturned = $OleDbAdapter.Fill($DataTable);
Write-Host $RowsReturned;
Error: Exception calling "Fill" with "1" argument(s): "The Microsoft Access database engine cannot find the input table or query ''Lab Manual''. Make sure it exists and that its name is spelled correctly."
The trick was to append the command 'Execute' before the query name and use square brackets around the query name.
$OleDbConn = New-Object "System.Data.OleDb.OleDbConnection";
$OleDbCmd = New-Object "System.Data.OleDb.OleDbCommand";
$OleDbAdapter = New-Object "System.Data.OleDb.OleDbDataAdapter";
$DataTable = New-Object "System.Data.DataTable";
$OleDbConn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\temp\labmanual.mdb;";
$OleDbCmd.Connection = $OleDbConn;
$OleDbCmd.CommandText = "Execute [myQuery]";
$OleDbAdapter.SelectCommand = $OleDbCmd;
$OleDbConn.Open();
$RowsReturned = $OleDbAdapter.Fill($DataTable);
Write-Host $RowsReturned;
$OleDbConn.Close();