I'm trying to populate an employee ID column in a CSV file by querying Active Directory against another column in the CSV file called "OwnerEmail" (Which is the user principal name). The problem is users in the owneremail column do not all belong to the same domain. How can I query 2 domains at one time?
Table for reference
Employee ID
OwnerEmail
DeptNumber
Costs
test#mail.com
0894
4654.45
test2#mail.com
3453
4994.15
This is what I have tried so far. The script isn't working and there are no error messages. Any Ideas
$Domains='us.domain.corp', 'uk.domain.corp'
$CSVImport |Select-Object #{
Name = "employeeID"
Expression = {
foreach($user in $CSVImport)
{
foreach($Domain in $Domains){
$user= (Get-ADUser -Filter "UserPrincipalName -eq '$($_.OwnerEmail)'" -Server $Domain -Properties 'SamAccountName').SamAccountName
}
}
}}, * |Select-Object employeeID, DepartmentNumber, OwnerEmail, #{Name="Costs"; Expression={"$ $($_.Cost)"}} | Export-Csv "$Env:temp/$OutputFile" -NoTypeInformation
How can I query 2 domains at one time?
There is no need to do this, you can query both at once with multithreading but seems like an overkill. What I would recommend is to query all users at once per Domain, the code below may seem awfully complicated but should be pretty efficient. See the inline comments for details.
# Import the Csv
$CSVImport = Import-Csv path\to\thecsv.csv
# Create a LDAP Filter to query all users at once
# This filter would look like this for example:
# (|(userPrincipalName=test#mail.com)(userPrincipalName=test2#mail.com))
$filter = "(|"
foreach($email in $CSVImport.OwnerEmail) {
if(-not [string]::IsNullOrWhiteSpace($email)) {
$filter += "(userPrincipalName=$email)"
}
}
$filter += ")"
# For each Domain, use the same filter and get all existing users
'us.domain.corp', 'uk.domain.corp' | ForEach-Object { $map = #{} } {
foreach($user in Get-ADUser -LDAPFilter $filter -Server $_) {
# and store them in a hashtable where
# the Keys are their `UserPrincipalName`
# and the Values are the attribute of interest (`SamAccountName`)
$map[$user.UserPrincipalName] = $user.SamAccountName
}
}
# Now we can simply use a calculated property with `Select-Object`
$CSVImport | Select-Object #{N='EmployeeID'; E={ $map[$_.OwnerEmail] }}, * |
Export-Csv "$Env:temp/$OutputFile" -NoTypeInformation
Related
I am new to Powershell. I am actually getting the details of the azure data factory linked services but after get I need to use contains to check if the element exists. In python I would just check if string in a list but powershell not quite sure. Please check the code below.
$output = Get-AzDataFactoryV2LinkedService -ResourceGroupName $ResourceGroupName -DataFactoryName "xxxxxxxx" | Format-List
The output of the below is :
sample output given below
LinkedServiceName : abcdef
ResourceGroupName : ghijk
DataFactoryName : lmnopq
Properties : Microsoft.Azure.Management.DataFactory.Models.AzureDatabricksLinkedService
So now I try to do this:
if ($output.Properties -contains "Microsoft.Azure.Management.DataFactory.Models.AzureDatabricksLinkedService") {
Write-Output "test output"
}
But $output.Properties gives us the properties of that json.
I need to check if "Microsoft.Azure.Management.DataFactory.Models.AzureDatabricksLinkedService" exists in output variable and perform the required operations. Please help me on this.
The -contains operator requires a collection and an element. Here's a basic example of its proper use:
$collection = #(1,2,3,4)
$element1 = 5
$element2 = 3
if ($collection -contains $element1) {'yes'} else {'no'}
if ($collection -contains $element2) {'yes'} else {'no'}
What you've done is ask PowerShell to look in an object that isn't a collection for an element of type [string] and value equal to the name of that same object.
What you need to do is inspect this object:
$output.Properties | format-list *
Then once you figure out what needs to be present inside of it, create a new condition.
$output.Properties.something -eq 'some string value'
...assuming that your value is a string, for example.
I would recommend watching some beginner tutorials.
I need to be able to compare 2 rows of IP Subnets and tell if there is overlap.
For example:
In Row 1 I have a /24 and I need to check if this /24 is existing in Row 2 (either via the /24 or via the supernet /21 for instance)
so:
ROW 1: 192.168.2.0/24
ROW 2: 192.168.0.0/21
Result -> Row 1 exists in Row 2
I am not sure how to do this in Excel
Anybody any idea?
If you want to do it in powershell, you may use this script:
Clear-Host
#Import csv file with IPs (Delimiter ";")
$rowlist = Import-Csv -Path "C:\rows_directory\rowlist.csv" -Delimiter ";"
$row1 = $rowlist | Select-Object -ExpandProperty "row1"
$row2 = $rowlist | Select-Object -ExpandProperty "row2"
foreach($string in $row1) {
if($string -in $row2) {
Write-Output "ROW1: $string exist in ROW2"
}
}
I filled file with:
And result was:
ROW1: 123 exist in ROW2
For this I would create a function to find the base address (as UInt32 type) of the IP address in the concerned Subnet:
Function Get-IPBase($Address) {
$IP, $SubNet = $Address.Split('/', 2)
$Bytes = ([IPAddress]$IP).GetAddressBytes()
if ([BitConverter]::IsLittleEndian) { [Array]::Reverse($Bytes) }
[BitConverter]::ToUInt32($bytes, 0) -BAnd -BNot ([UInt32][Math]::Pow(2, $SubNet) - 1)
}
Example of what the function returns:
Get-IPBase 192.168.2.0/24
3221225472
Get-IPBase 192.168.0.0/24
3221225472
Than, do a self-join, using this Join-Object script/Join-Object Module (see also: In Powershell, what's the best way to join two tables into one?):
Import-CSV .\My.csv |Join -On { Get-IPBase $_.Row1 } -Eq { Get-IPBase $_.Row2 }
Please add more details to your question (as what you tried yourself and a sample list. See also: How to Ask) if you like a more in dept explanation or have problems to implement this.
I have a script that fetch user's manager info from a text file containing its respective groups and I want to put the results in an excel spreadsheet.
Also, I'd like to add a custom variable to the Select-Objects command so it shows up as another column in excel with each user's respective group
Here is what I have so far:
$Properties = #( 'Title', 'Department', 'Manager' )
[string[]]$arrayFromFile = Get-Content -Path 'C:\sslvpn-active.txt'
foreach($group in $arrayFromFile){
$searchb = "CN="+"$group"+",OU=SSLVPN,OU=UserGroupsRAS,DC=xi,DC=xxxinc,DC=net"
Get-ADGroupMember $searchb |
Get-ADUser -Properties $Properties |
Where-Object{ $_.Enabled } |
Select-Object Name, Title, Department,
#{Name = "ManagerName"; Expression = { (Get-ADUser $_.Manager).Name }},
#{Name = "ManagerMail"; Expression = { (Get-ADUser $_.Manager -Properties mail).Mail }}
}
The results are currently
SSLVPN-ABC
----------------------
Name : Joe Smith
Title : IT Engineer 2
Department : IT Support
ManagerName : Billy George
ManagerMail : Billy.George#xxx.com
Name : Matt Damon
Title : IT Engineer 3
Department : IT Support
ManagerName : Billy George
ManagerMail : Billy.George#xxx.com
SSLVPN-XYZ
----------------------
Name : Jen Loo
Title : Product Designer 3
Department : Product Design
ManagerName : Ben Smit
ManagerMail : Ben.Smit#xxx.com
...
I would like this result in excel format and also add a custom column called "Group" and have the group name (ex. SSLVPN-ABC) for each row. So the columns would be Group, Name, Title Department, ManagerName, ManagerMail and for the first group, the result cells will all be "SSLVPN-ABC".
Thanks
Change the select Statement like below.
Select-Object #{Name = "Group"; Expression = { $Group }},
Name, Title, Department,
#{Name = "ManagerName"; Expression = { (Get-ADUser $_.Manager).Name }},
#{Name = "ManagerMail"; Expression = { (Get-ADUser $_.Manager -Properties mail).Mail }}
Here you're just adding another calculated property that will reference the $Group iteration variable. Note the properties are listed in the order you asked for them.
If by some chance the $Group variable doesn't hold the name you can use (Get-ADGroup $searchb).Name in the expression.
Export to Csv as normal, I believe you already resolved that part...
I'm trying to get metric from Azure to Zabbix.
The issue is that Metric for VM consists of 2 words:Percentage CPU, and Zabbix doesn't allow item keys to consists of 2 words. I also tried Percentage%20CPU but getting errors in Zabbix, and I created Zabbix key percentage_cpu.
So I decided prior sending data from Zabbix to Azure to "translate" percentage_cpu to Percentage%20CPU. This works great if only that key is present, but issue starts when I add another key (in this example SQL metric).
For SQL metric all values are in one word - no need to change anything, but then metric for VM is also assigned to SQL. I'm trying to avoid writing separate file for every service
$host_items = Get-ZabbixHostItems -url $zabbix_url -auth $zabbix_auth -
zabbix_host $host_name
foreach ($host_item in $host_items)
{
#$host_item_details = select-string -InputObject $host_item.key_ -Pattern '^(azure\.sql)\.(.*)\.(.*)\[\"(.*)\"\]$';
$host_item_details = select-string -InputObject $host_item.key_ -Pattern '^(azure\.\w{2,})\.(.*)\.(.*)\[\"(.*)\"\,(.*)]$';
#$host_item_details = select-string -InputObject $host_item.key_ -Pattern '^(azure)\.(.*)\.(.*)\.(.*)\[\"(.*)\"\,(.*)]$';
$host_item_provider = $host_item_details.Matches.groups[1];
$host_item_metric = $host_item_details.Matches.groups[2];
$host_item_timegrain = $host_item_details.Matches.groups[3];
$host_item_resource = $host_item_details.Matches.groups[4];
$host_item_suffix = $host_item_details.Matches.groups[5];
if ($host_item_metric='percentage_cpu')
{$host_item_metric='Percentage%20CPU'}
else
{ $host_item_metric = $host_item_details.Matches.groups[2];}
#}
$uri = "https://management.azure.com{0}/providers/microsoft.insights/metrics?api-version={1}&interval={2}×pan={3}&metric={4}" -f `
$host_item_resource, `
"2017-05-01-preview", `
$host_item_timegrain.ToString().ToUpper(), `
$($(get-date).ToUniversalTime().addminutes(-15).tostring("yyyy-MM-ddTHH:mm:ssZ") + "/" + $(get-date).ToUniversalTime().addminutes(-2).tostring("yyyy-MM-ddTHH:mm:ssZ")), `
$host_item_metric;
write-host $uri;
}
output of hostitems_
azure.sql.dtu_consumption_percent.pt1m["/subscriptions/111-222/resourceGroups/rg/providers/Microsoft.Sql/servers/mojsql/databases/test",common]
azure.vm.percentage_cpu.pt1m["/subscriptions/111-222/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/test",common]
When I ran code above I'm getting these URI's
https://management.azure.com/subscriptions/111-222/resourceGroups/rg/providers/Microsoft.Sql/servers/mojsql/databases/test/providers/microsoft.insights/m
etrics?api-version=2017-05-01-preview&interval=PT1M×pan=2018-08-11T07:38:05Z/2018-08-11T07:51:05Z&metric=Percentage%20CPU
https://management.azure.com/subscriptions/111-222/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/test/providers/microsoft.insights/metric
s?api-version=2017-05-01-preview&interval=PT1M×pan=2018-08-11T07:38:05Z/2018-08-11T07:51:05Z&metric=Percentage%20CPU
For first link (SQL) metric should be dtu_consumption but I'm getting same metric for both links
Second attempt:
if ($host_item_metric -eq 'percentage_cpu')
{$host_item_metric='Percentage%20CPU';}
else
{ $host_item_metric = $host_item_details.Matches.groups[2];}
write-host $host_item_metric
}
output: (original values)
dtu_consumption_percent
percentage_cpu
had to use -like
if ($host_item_metric -like 'percentage_cpu')
{$host_item_metric='Percentage%20CPU';}
else
{ $host_item_metric = $host_item_details.Matches.groups[2]}
For Powershell 2.0:
I have a hash table with several strings as keys. Unlike #{}.containskey, is it possible to find a key (e.g., "examplekey") using wildcards (e.g., "*xampl*")?
I managed to accomplish what I wanted making a list of the keys and using Where-Object as a filter. But is there a simpler way to do it? I think this method is specially bad when I'm adding new keys, because I need to recreate the list everytime.
Use .Keys property and -like or -notlike operators that return an array of keys (or a single key):
if ($hash.keys -notlike '*xampl*') {
$hash.example = 1
}
Store the keys in an array for multiple checks:
$keys = $hash.keys
if ($keys -notlike '*xampl*') {
$hash.example = 1
}
if ($keys -notlike '*foo*') {
$hash.example = 1
}
Chain the comparisons:
if ($hash.keys -notlike '*xampl*' -notlike '*123*') {
$hash.example = 1
}
Or use regexp in case there are lots of keys and you want to perform lots of checks:
if ($hash.keys -join "`n" -match '(?mi)xampl|foo|bar|^herp\d+|\wDerp$|^and$|\bso\b|on') {
echo 'Already present'
} else {
$hash.foo123 = 'bar'
# ......
}
(?mi) means multiline case-insensitive mode: each key is tested individually.