Powershell - Change variables based on CSV file - variables

I'm attempting to use a CSV file for automatic computer naming with powershell. Our Computer names carry general model numbers which tell me the actual type of computer. For instance, Model # 2537CU1 is a Lenovo T410. I want to pull the model number and change the variable to T410.
I can already get the model number with a get-wmiobject call to the computersystem class, but to create a variable with the "type" data, like T410 I'm having to use a bunch of If, and elseif statements. This is due to the sheer number or models/types we support. My goal is to have a CSV to edit instead of the script itself. I just want the corresponding Model to get the right variable for the "type" of machine.
So here's where my head is so far and I know I'm way off:
$model = Get-WmiObject -Class Win32_ComputerSystem | select -ExpandProperty Model
$modelCSV = "0"
$typeCSV = "0"
Import-Csv -Path "C:\TechDiv\ComputerModel_Type.csv" |
ForEach-Object {
$modelCSV += $_.Model
$typeCSV += $_.Type
}
if ($modelCSV -like $model)
{
$model = $typeCSV
}
Where my CSV looks like this:
Model, Type
0401B7U, A70Z
0401R6U, A70Z
1165A3U, A70Z
25521H8, 0E31
2552Ck1, 0E31
7360, 0M58
7483, 0M58
7630, 0M58
Ultimately my computer naming script will concatenate the model and serial number for easy collections and updates. Example with model/serial name (0's pad the left serial to fill 10 spaces): T410000R84D06Z

Here is how I would do it:
$model = Get-WmiObject -Class Win32_ComputerSystem | select -ExpandProperty Model
$modelCSV = "0"
$typeCSV = "0"
$modelList = Import-Csv -Path "C:\TechDiv\ComputerModel_Type.csv" |
$modelName = $modelList | Where-Object{$_.Model -eq $model}

I'd load that CSV into a hash table:
$ModelHash = #{}
Import-Csv -Path "C:\TechDiv\ComputerModel_Type.csv" |
ForEach-Object { $ModelHash[$_.Model = $_.Type }
$model = Get-WmiObject -Class Win32_ComputerSystem | select -ExpandProperty Model
$Type = $ModelHash[$Model]

Related

Data inserting to ODBC destination with powershell

I need to load data table to ODBC driver connection with powershell.
With OLEDB and SQL server we can use Bulk Copy and insert data quickly.
Is there such posibility with ODBC ?
I'm using powershell because it shoud have the best support for these kind of opperations,
but my current code doesn't utillise an of the dlls.
So my code firstly needs to create an insert statements with two for loops and iterate on every row and hold it in its memory,
and then to construct INSERT INTO with 1000 rows, and then repeat same thing.
Am i doomed to something like this ?
$Datatable = New-Object System.Data.DataTable
$tabledump= $src_cmd.ExecuteReader()
$Datatable.Load($tabledump)
foreach ($item in $Datatable.Rows) {
$f +=1
for ($i = 0; $i -lt $item.ItemArray.Length; $i++) {
$items = $item[$i] -replace "'" , "''"
$val +="'"+ $items + "',"
}
$vals += $val
if ($f % 1000 -eq 0 -or $f -eq $row_cnt) {
$values = [system.String]::Join(" ", $vals)
$values = $values.TrimEnd(",")
$cols = [system.String]::Join(",", $columns)
$postgresCommand = "Insert Into $dst_schema.$dst_table ($cols) values $values"
$dest_cmd_.CommandText = $postgresCommand
$dest_cmd_.ExecuteNonQuery()
Bad code i admit, any advice on code compositions are welcomed.
You can use Get-ODBCDSN command to retrieve the values of the ODBC connections and use it with a query
$conn.ConnectionString= "DSN=$dsn;"
$cmd = new-object System.Data.Odbc.OdbcCommand($query,$conn)
$conn.open()
$cmd.ExecuteNonQuery()
$conn.close()
https://www.andersrodland.com/working-with-odbc-connections-in-powershell/
But the ODBC provider doesnt do bulk copy
https://learn.microsoft.com/en-us/sql/relational-databases/native-client-odbc-bulk-copy-operations/performing-bulk-copy-operations-odbc?view=sql-server-ver15
I know this post is not new, but i've been fiddeling around looking for a solution and also found nothing, however this post gave me a couple of insights.
First: There is no such thing as 'Bad Code'. If it works is not bad, heck even if it didn't worked, but helped with something..
Alright, what i did is not the best solution, but i'm trying to import Active Directory data on PostgreSQL, so...
I noticed that you're trying with pgsql as well, so you can use the COPY statement.
https://www.postgresql.org/docs/9.2/sql-copy.html
https://www.postgresqltutorial.com/import-csv-file-into-posgresql-table/
In my case i used it with a csv file:
*Assuming you have installed pgsql ODBC driver
$DBConn = New-Object System.Data.Odbc.OdbcConnection
$DBConnectionString = "Driver={PostgreSQL UNICODE(x64)};Server=$ServerInstance;Port=$Port;Database=$Database;Uid=$Username;Pwd=$(ConvertFrom-SecureString -SecureString $Password);"
$DBConn.ConnectionString = $DBConnectionString
try
{
$ADFObject = #()
$ADComputers = Get-ADComputer -Filter * -SearchBase "OU=Some,OU=OrgU,OU=On,DC=Domain,DC=com" -Properties Description,DistinguishedName,Enabled,LastLogonTimestamp,modifyTimestamp,Name,ObjectGUID | Select-Object Description,DistinguishedName,Enabled,LastLogonTimestamp,modifyTimestamp,Name,ObjectGUID
foreach ($ADComputer in $ADComputers) {
switch ($ADComputer.Enabled) {
$true {
$ADEnabled = 1
}
$false {
$ADEnabled = 0
}
}
$ADFObject += [PSCustomObject] #{
ADName = $ADComputer.Name
ADInsert_Time = Get-Date
ADEnabled = $ADEnabled
ADDistinguishedName = $ADComputer.DistinguishedName
ADObjectGUID = $ADComputer.ObjectGUID
ADLastLogonTimestamp = [datetime]::FromFileTime($ADComputer.LastLogonTimestamp)
ADModifyTimestamp = $ADComputer.modifyTimestamp
ADDescription = $ADComputer.Description
}
}
$ADFObject | Export-Csv $Env:TEMP\TempPsAd.csv -Delimiter ',' -NoTypeInformation
docker cp $Env:TEMP\TempPsAd.csv postgres_docker:/media/TempPsAd.csv
$DBConn.Open()
$DBCmd = $DBConn.CreateCommand()
$DBCmd.CommandText = #"
COPY AD_Devices (ADName,ADInsert_Time,ADEnabled,ADDistinguishedName,ADObjectGUID,ADLastLogonTimestamp,ADModifyTimestamp,ADDescription)
FROM '/media/TempPsAd.csv'
DELIMITER ','
CSV HEADER
"#
$DBCmd.ExecuteReader()
$DBConn.Close()
docker exec postgres_docker rm -rf /media/TempPsAd.csv
Remove-Item $Env:TEMP\TempPsAd.csv -Force
}
catch
{
Write-Error "$($_.Exception.Message)"
continue
}
Hope it helps!
Cheers!

Powershell if then

I'm having an issue with the if then.
$result = getMachineInfo $rlprddeploy $mdt
"-MachineID- -LastContactAt- -LastIP- -Deployment Receiver Version-"
$machine = $result.MachineID
$result | % { '{0,-10} {1,23} {2,16} {3,20}' -f $_.MachineID, $_.LastContactAt, $_.LastIP, $_.DeploymentReceiverVersion }
#$result | ft -auto
if $_.DeploymentReceiverVersion is less than 5.46.54 then I'm going to send a file to do an update. If the version is 5.55 then nothing needs to be done.
I've been banging my head against this for a week now and I can't figure it out. Every $_.blahblah is information pulled from an SQL table on a server.
We've been sending out updates manually and I'd like to stop that.
PowerShell's If statement can be written just like any C like language:
if ($true) {Write-Host "True Yo" }
That said, you haven't posted exactly what your issues is, so this somewhat generic:
Creating a custom object:
$dep = New-Object psobject -Property #{DeploymentReceiverVersion = "5.000.11"; AppName = "OxenTails" }
Comparing this is going to pose a potential problem:
$dep.DeploymentReceiverVersion.GetType()
The version is a string, so the comparison is comparing strings:
$dep.DeploymentReceiverVersion -lt "5.000.12"
gives an expected result, but
$dep.DeploymentReceiverVersion -lt "5.000.101"
does not.
This however could work to compare each set of numbers:
$parts = $dep.DeploymentReceiverVersion.Split('.')
if ([int]$parts[0] -lt 6 -and [int]$parts[1] -lt 001 -and [int]$parts[2] -lt 101) {
#Do Stuff!
}
Additionally, as pointed out by #TheMadTechnician there is the System.Version type [Version]
It can be used with one of the overload methods:
[Version]::new(parts[0],parts[1], parts[2]) -lt [Version]::new(5,46,54)
Which is marginally more readable.

Variable stored Object Property name used to reference said Object Property name

In Powershell can one reference a Object's property through the contents of a variable? To allow changing of variable contents to change logic, instead of changing the logic directory. See the below for a working example using the $CorAorMTime variable, where this functionality would be handy:
$DirectoryIterationDepth = 1
$CorAorMTime = "creationtime"
$FilesDatedAfter = -7
$Path = #()
foreach($Level in 1..($DirectoryIterationDepth+1))
{
$Path += $PathToTargetDir + ("\*" * $Level)
}
get-childitem $Path -force | where-object {$_.$CorAorMTime -gt ((get-date).adddays($FilesDatedAfter))}

How to match SQL results with AD results and the other way around

I have to write a script that will query AD for users from a specific department that I will prompt user to input initially and then to output the software that is installed on the all machines that a specific user from the chosen department. I want to be able to see all the software from all the machine(s) that specific is logging on.
Presently I am using the following parts:
1) A query in AD to get the users from a specific department:
Import-Module ActiveDirectory
$Dept = Read-Host "Enter the desired department"
$strFilter = "(&(objectCategory=User)(Department=*$Dept*))"
$colResults = Get-ADUser -LDAPFilter $strFilter |
Select-Object -Expand DistinguishedName
2) I am also using a script from the person before me, that performs a query in SQL combined with LanDesk. See below:
$SQLServerLANDESK = "usernam\password"
$SqlConnectionLANDESK = New-Object System.Data.SqlClient.SqlConnection
$global:dt = new-object System.Data.DataTable
$LONA = ""
$o = 0
function doit() {
$SqlConnectionLANDESK.ConnectionString = "Server=$SQLServerLANDESK; Database= $SQLDBNameLANDESK;uid=useraidi; pwd=parola"
$SqlConnectionLANDESK.Open()
$QueryLANDesk = #"
SELECT DISTINCT A0.DISPLAYNAME, A0.LOGINNAME,A0.PRIMARYOWNER,A0.TYPE, A1.OSTYPE, A2.SUITENAME, A2.PUBLISHER, A2.VERSION
FROM Computer A0 (nolock) LEFT OUTER JOIN Operating_System A1 (nolock) ON A0.Computer_Idn = A1.Computer_Idn LEFT OUTER JOIN AppSoftwareSuites A2 (nolock) ON A0.Computer_Idn = A2.Computer_Idn
WHERE A0.DEVICENAME like '%D02DI0907061%'
or A0.DEVICENAME like '%D02DI0929860%'
"#
$CommandLANDesk = new-object System.Data.SqlClient.SqlDataAdapter ($QueryLANDesk, $SqlConnectionLANDESK)
$CommandLANDesk.fill($dt) | out-null
$dtrc = $dt.Rows.Count
Write-Host "($i) Searching all cores ($dtrc machines)..."
$SqlConnectionLANDESK.Close()
}
foreach ($i in 1..10)
{if ($i -eq 6) {continue}
$SQLDBNameLANDESK = "database"
$SQLServerLANDESK = "username\parola"
doit
}
Write-Host
$dt.select("displayname like '%$LONA%'") | export-csv H:\TEST\add-remove_TEST_LOGINNAME.csv # | foreach { $o++ }
# "$o machines found."
I want to be able to basically connect the result search from point 1 and match it with the "PRIMARYOWNER" which is in DistinguishedName format and to store those in a table back in SQL. How do I do that?

powershell v2 - how to get process ID

I have an Application, that runs multiple instances of itself. e.g
AppName.exe instance1
AppName.exe instance2
AppName.exe instance3
Using Powershell v2 I am trying to create a simple script that given an array of AppNames and instances, it loops through them, checks if they are running, and then shuts them down.
I figured the best way to do this would be check for each instance, if found capture it's processID, and pass that to the stop-process cmdlet.
BUT, I can't figure out how to get the process id.
So far I have:
$appName = "AppName.exe"
$instance = "instance1"
$filter = "name like '%"+$appName+"%'"
$result = Get-WmiObject win32_process -Filter $filter
foreach($process in $result )
{
$desc = $process.Description
$commArr = $process.CommandLine -split"( )"
$inst = $commArr[2]
$procID = "GET PROCESS ID HERE"
if($inst -eq $instance)
{
Stop-Process $procID
}
}
Can anyone tell me where to get the process ID from please?
you can use the get-process cmdlet instead of using wmi :
$procid=get-process appname |select -expand id
$procid=(get-process appname).id
When using Get-WmiObject win32_process ..., the objects returned have an attribute named ProcessId.
So, in the question, where you have:
$procID = "GET PROCESS ID HERE"
use:
$procID = $process.ProcessId
You could also use that in the $filter assignment, e.g.
$filter = "ProcessId=1234"