my question seems to be basic, but so far i have spent several hours already trying to figure it out. Basically the goal is to search for the transport rule that block members of a DL (Distribution List) from sending external email. then display the members of that DL too.
What the below code does is that it can display the Transport rule and the DL value in "FromMemberOf" but it doesn't display the members of it. If for example I ran just $dl_info.FromMemberOf it does show the DL groups so Im sure that is being picked up (see attached screenshots) thus I tried to use it as my array when I use the foreach-objct . ALso I noticed that its being called RawIdentity which i didnt define. ANy thoughts?
param(
[parameter(Mandatory=$true)]
[string]$sid = "SID",
[parameter(Mandatory=$true)]
[string[]]$ExchGuid = "ruleid"
)
$dl_info = #()
foreach ($rule in $ExchGuid){
$dl_info += Get-TransportRule | where {$_.guid -eq $rule} | select Priority, name, RejectMessageEnhancedStatusCode, ExceptIfFromMemberOf, FromMemberOf, #{n="DL_Block_Members";e={$dl_info.FromMemberof | ForEach-Object (Get-DistributionGroupMember $_ -ResultSize unlimited | select name)}}
}
$dl_info
I was able to resolve it by using Pscustomobject. It could display the DL member but I have to work on the script to be able to search the account membership. THats for another day
param(
[parameter(Mandatory=$true)][string]$sid = "sid",
[parameter(Mandatory=$true)][string[]]$ExchGuid = "ruleid"
)
$TRule_Info = #()
$DL_Info = #()
foreach ($rule in $ExchGuid){
$TRule_Info = Get-TransportRule | where guid -EQ $rule
foreach ($group in $TRule_Info){
$ht = [pscustomobject]#{
SID = $sid
RuleName = $TRule_Info.Name
DL_Group_Exemption = $TRule_Info.ExceptIfFromMemberOf
DL_BlockGroup_Members = $TRule_Info.FromMemberOf
}
$DL_Info += $ht
}
}
$DL_Info
Related
I have to list full subgroup dependency of specific group - filter -> only subgroups which contain at least 1 user.
I have tried this approach:
dsquery group -samid <specific_group> | dsget group -members -expand | dsquery * -filter "(&(objectclass=group))"
This is an adapted version of my answer here to omit groups without any user object.
Unfortunately, using Get-ADGroupMember together with switch -Recursive will not return members that are groups.
As the docs state:
If the Recursive parameter is specified, the cmdlet gets all members
in the hierarchy of the group that do not contain child objects.
To get an array of nested group objects within a certain parent group, you will need a recursive function like below:
function Get-NestedADGroup {
Param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, Position = 0)]
[ValidateNotNullOrEmpty()]
[Alias ('Identity')]
[string]$Group,
# the other parameters are optional
[string]$Server = $null,
[string]$SearchBase = $null,
[ValidateSet('Base', 'OneLevel', 'Subtree')]
[string]$SearchScope = 'Subtree'
)
$params = #{
Identity = $Group
SearchScope = $SearchScope
Properties = 'Members'
ErrorAction = 'SilentlyContinue'
}
if (![string]::IsNullOrWhiteSpace($Server)) { $params['Server'] = $Server }
if (![string]::IsNullOrWhiteSpace($SearchBase)) { $params['SearchBase'] = $SearchBase }
$adGroup = Get-ADGroup #params
if ($adGroup) {
if (-not $script:groupsHash.ContainsKey($Group)) {
# output this group object only if it has at least one user object
if (#($adGroup.Members | Where-Object {$_.objectClass -eq 'user'}).Count -gt 0) {
$adGroup
}
# avoid circular group references
$script:groupsHash[$Group] = $true
# and recurse to get the nested groups
foreach ($group in ($adGroup.Members | Where-Object {$_.objectClass -eq 'group'})) {
Get-NestedADGroup -Group $group.DistinguishedName -Server $Server -SearchBase $SearchBase
}
}
}
else {
Write-Warning "Group '$($Group)' could not be found.."
}
}
# create a Hashtable to avoid circular nested groups
$groupsHash = #{}
# call the function
$result = Get-NestedADGroup -Group 'SpecificGroup'
# output just the names if you like
$result.Name
# save to CSV
$result | Export-Csv -Path 'X:\Somewhere\SubgroupsWithAtLeastOneUser.csv' -NoTypeInformation
Here is an easy alternative leveraging Active Directory filtering capabilities. See inline comments to understand the logic.
Do note, this answer requires the ActiveDirectory Module available.
# Get the DN of the parent group (this is the initial group)
$parent = (Get-ADGroup parentGroup).distinguishedName
$param = #{
LDAPFilter = "(memberof:1.2.840.113556.1.4.1941:=$parent)"
Properties = "member"
}
# Find, recursively, all child groups Members Of this parent group
# and filter
Get-ADGroup #param | Where-Object {
# For each member of this child group,
# check if this member is an object of the Class `user`,
# if it is, we already can break the pipeline and return
# this child group, since we already know it has
# at least 1 user member
$_.member | Get-ADObject | Where-Object ObjectClass -EQ user |
Select-Object -First 1
}
Using winget,
winget list command displays the list of the applications currently installed in my computer, but it doesn't display the applications in alphabetical order of application name just like in the control panel,
Is there a way to display the installed applications in alphabetical order of application name using winget?
Note: The two images are from different machines.
Thanks.
As Demetrius mentioned in his comment, there isn't an ability to sort built into the client currently. However, in your screenshot I see you are using PowerShell. You can use PowerShell variables and commands to effectively sort the output. By chaining a few commands together, it is possible to re-create the table. This seemed to work for me -
$a=winget list;$a|select -First 3;$a|select -Skip 3|Sort-Object|select -First 9
I was trying to see if there was a parameter/option to accompany the winget command, and really wanted to just comment on the answer by Trenly; I had been using a similar piped command (just shorter), so he should still get the credit!
However, apparently, I must have a certain reputation score to even comment on his (or any other) answer... Yet, I can provide an answer without any rating whatsoever; go figure. So, the shorter version, similar to his answer, but without the unnecessary nested piping:
winget list|Sort-Object
You can check for ConvertFrom-FixedColumnTable function at here to convert the result of winget list to a table.
I created a function winget_list_OrderBy in order to make it simple:
function winget_list_OrderBy {
<#
.EXAMPLE
winget_list_OrderBy
.EXAMPLE
winget_list_OrderBy -OrderBy 'Name' -Arguments "--id=Git.Git"
#>
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline)]
[string[]]
$OrderBy = 'Name', # $OrderBy can be equal to 'Name'/'Id'/'Version'/'Source' (and 'Available' if exist).
[Parameter(ValueFromPipeline)]
[string[]]
$Arguments = ''
)
# Backup the original [Console]::OutputEncoding
$encoding = [Console]::OutputEncoding
# Make PowerShell interpret winget.exe's output as UTF-8
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
(winget list $Arguments) -match '^(\p{L}|-)' | # filter out progress-display lines
ConvertFrom-FixedColumnTable | # parse output into objects
Sort-Object $OrderBy | # sort by the ID property (column)
Format-Table # display the objects in tabular format
# Restore the original [Console]::OutputEncoding afterwards
[Console]::OutputEncoding = $encoding
}
Usage is simple: winget_list_OrderBy -OrderBy $OrderBy -Arguments $Arguments or winget_list_OrderBy.
thoughts on this? It may need a little clean up, but I just converted the results to an object Array.
$apps = #("Microsoft Visual Studio Code", "Microsoft Visual Studio Code Insiders", "Visual Studio Community 2022")
$global:foundapps = [System.Collections.Generic.List[object]]::new()
foreach ($app in $apps) {
$Applist = winget search $app
$header = $Applist[1]
$nameposition = $header.indexof('Name')
$idPosition = $header.indexof('Id')
$versionPosition = $header.indexof('Version')
$sourceposition = $header.indexof('Source')
$name = $header.substring($nameposition, $idPosition).replace(' ', '')
$id = $header.substring($idPosition, ($versionPosition - $idPosition)).replace(' ', '')
$iVersiond = $header.substring($versionPosition, ($sourceposition - $versionPosition)).replace(' ', '')
$source = $header.substring($sourceposition, ($header.length - $sourceposition)).replace(' ', '')
$appstoadd = $Applist | select-object -skip 3
foreach ($AppToAdd in $appstoadd) {
$foundapps.Add([PSCustomObject] #{
"Name" = $AppToAdd.substring($nameposition, $idPosition).replace(' ', '')
"Version" = $AppToAdd.substring($versionPosition, ($sourceposition - $versionPosition)).replace(' ', '')
"ID" = $AppToAdd.substring($idPosition, ($versionPosition - $idPosition)).replace(' ', '')
"Source" = $AppToAdd.substring($sourceposition, ($header.length - $sourceposition)).replace(' ', '')
})
}
}
$foundapps |fl
I am using PowerShell to build some scripts in an Active Directory enviroment and am currently struggling to find a way to count objects. My base search is:
$DClist = (Get-ADForest).Domains | % { Get-ADDomainController –Filter * -Server $_ } | Select Site, Name, Domain
And it generates the following output:
Site Name Domain
---- ---- ------
Site-A DC-123 acme.local
Site-A DC-ABC acme.local
Site-B DC-XYZ domain.local
Site-C DC-YPT domain.local
Now I would like to count the number of objects in the column 'Name' and display something like this:
Site Count_of_Name
---- ----
Site-A 2
Site-B 1
Site-C 1
I have already tried a lot of things and the closest I got so far was using:
$DcList | Group-Object Site
But unfortunately it is not the right way to go as it only counts the number of 'Site' and "ignores" the rest. Also tried this, but it did not work as I expect either:
$DcList | Group-Object Site, Name
Please help me figure out the logic of this.
********************** UPDATE **********************
I have finally been able to come to this, but I cannot figure out a way to count the objects from 'Site' column:
$DClist | Group-Object -Property Site | ForEach-Object -Process {
[PSCustomObject]#{
Site = $_.Name
DCs = ($_.Group.Site)
}
}
Please help me out. I feel I'm so close to a solution now. :)
you are REALLY close, and the answer is about what you would expect :)
when doing group you automatically get a count property. just use this.
$DClist = (Get-ADForest).Domains | % { Get-ADDomainController –Filter * -Server $_ } | Select Site, Name, Domain
$dclist|Group-Object site|ForEach-Object{
[PSCustomObject]#{
site = $_.name
DCs = $_.group
count = $_.count
}
}
edit:
you could also do this that could be even faster if propegating through many objects. when doing select you can add a custom query and a label for that query.
#{name='fieldname';expression={$_.reference.to.object}} or #{n='field';e={$_.expression}} if you want to shorten it.
$dclist|Group-Object site|ForEach-Object{
$_|select #{n='site';e={$_.name}},count,#{n='DCs';e={$_.group}}
}
I don't exactly understand what you really want, but if it is some kind of tree, this will show it:
ForEach($Site in ($dclist | Group-Object site))
{
$Site.Count.ToString() + " " + $Site.Name
ForEach($Server in $Site.Group)
{
" + " + $Server.Name
}
}
Output:
2 Site-A
+ DC-123
+ DC-ABC
1 Site-B
+ DC-XYZ
1 Site-C
+ DC-YPT
I want to change the loop PowerShell content from the CSV file automatically, is there someone know how to achieve the goal?
I want to run the loop PowerShell as below,I export the AD Group Members UPN with CSV file like One#contoso.com. I want to change the Userlist with the UPN automatically because there have more than 1000 members in the group and I have to change the upn from one#contoso.com to 'one#contoso.com',it’s easy to make a miss, is there has a smart way can achieve the goal,thanks.
Export-ADGroupmember UPN:
Get-ADGroupmember -identity adgroup | % { get-aduser $_.samaccountname | select userprincipalname } | export-csv upn.csv -notypeinformation
Loop PowerShell:
Loop PowerShell:
$UserList = #(
'One#contoso.com'
'Two#contoso.com'
'Three#contoso.com'
'Four#contoso.com'
'Five#contoso.com'
)
foreach ($UL_Item in $UserList)
{
$ARAGU_Params = #{
TenantName = "contoso"
HostPoolName = "contosoHostPool"
AppGroupName = "Desktop Application Group"
UserPrincipalName = $UL_Item
}
Add-RdsAppGroupUser #ARAGU_Params
}
You cant change content in your $UserList .More precisely, it is possible but affect the performance since You will need to read from the file and break it into segments. The best way is to download all users at once.You can do it like this:
$UserList=Get-ADGroupmember -identity adgroup | % { get-aduser $_.samaccountname | select userprincipalname }
foreach ($UL_Item in $UserList)
{
$ARAGU_Params = #{
TenantName = "contoso"
HostPoolName = "contosoHostPool"
AppGroupName = "Desktop Application Group"
UserPrincipalName = $UL_Item.userprincipalname
}
Add-RdsAppGroupUser #ARAGU_Params
}
Ok so we have a manual process that runs through PL/SQL Developer to run a query and then export to csv.
I am trying to automate that process using powershell since we are working in a windows environment.
I have created two files that seems to be exact duplicates from the automated and manual process but they don't work the same so I assume I am missing some hidden characters but I can't find them or figure out how to remove them.
The most obvious example of them working differently is opening them in excel. The manual file opens in excel automatically putting each column in it's own seperate column. The automated file instead puts everything into one column.
Can anybody shed some light? I am hoping that by resolving this or at least getting some info will help with the bigger problem of it not processing correctly.
Thanks.
ex one column
"rownum","year","month","batch","facility","transfer_facility","trans_dt","meter","ticket","trans_product","trans","shipper","customer","supplier","broker","origin","destination","quantity"
ex seperate column
"","ROWNUM","RPT_YR","RPT_MO","BATCH_NBR","FACILITY_CD","TRANSFER_FACILITY_CD","TRANS_DT","METER_NBR","TKT_NBR","TRANS_PRODUCT_CD","TRANS_CD","SHIPPER_CD","CUSTOMER_NBR","SUPPLIER_NBR","BROKER_CD","ORIGIN_CD","DESTINATION_CD","NET_QTY"
$connectionstring = "Data Source=database;User Id=user;Password=password"
$connection = New-Object System.Data.OracleClient.OracleConnection($connectionstring)
$command = New-Object System.Data.OracleClient.OracleCommand($query, $connection)
$connection.Open()
Write-Host -ForegroundColor Black " Opening Oracle Connection"
Start-Sleep -Seconds 2
#Getting data from oracle
Write-Host
Write-Host -ForegroundColor Black "Getting data from Oracle"
$Oracle_data=$command.ExecuteReader()
Start-Sleep -Seconds 2
if ($Oracle_data.read()){
Write-Host -ForegroundColor Green "Connection Success"
while ($Oracle_data.read()) {
#Variables for recordset
$rownum = $Oracle_data.GetDecimal(0)
$rpt_yr = $Oracle_data.GetDecimal(1)
$rpt_mo = $Oracle_data.GetDecimal(2)
$batch_nbr = $Oracle_data.GetString(3)
$facility_cd = $Oracle_data.GetString(4)
$transfer_facility_cd = $Oracle_data.GetString(5)
$trans_dt = $Oracle_data.GetDateTime(6)
$meter_nbr = $Oracle_data.GetString(7)
$tkt_nbr = $Oracle_data.GetString(8)
$trans_product_cd = $Oracle_data.GetString(9)
$trans_cd = $Oracle_data.GetString(10)
$shipper_cd = $Oracle_data.GetString(11)
$customer_nbr = $Oracle_data.GetString(12)
$supplier_nbr = $Oracle_data.GetString(13)
$broker_cd = $Oracle_data.GetString(14)
$origin_cd = $Oracle_data.GetString(15)
$destination_cd = $Oracle_data.GetString(16)
$net_qty = $Oracle_data.GetDecimal(17)
#Define new file
$filename = "Pipeline" #Get-Date -UFormat "%b%Y"
$filename = $filename + ".csv"
$fileLocation = $newdir + "\" + $filename
$fileExists = Test-Path $fileLocation
#Create object to hold record
$obj = new-object psobject -prop #{
rownum = $rownum
year = $rpt_yr
month = $rpt_mo
batch = $batch_nbr
facility = $facility_cd
transfer_facility = $transfer_facility_cd
trans_dt = $trans_dt
meter = $meter_nbr
ticket = $tkt_nbr
trans_product = $trans_product_cd
trans = $trans_cd
shipper = $shipper_cd
customer = $customer_nbr
supplier = $supplier_nbr
broker = $broker_cd
origin = $origin_cd
destination = $destination_cd
quantity = $net_qty
}
$records += $obj
}
}else {
Write-Host -ForegroundColor Red " Connection Failed"
}
#Write records to file with headers
$records | Select-Object rownum,year,month,batch,facility,transfer_facility,trans_dt,meter,ticket,trans_product,trans,shipper,customer,supplier,broker,origin,destination,quantity |
ConvertTo-Csv |
Select -Skip 1|
Out-File $fileLocation
Why are you skipping the first row(usually the headers)? Also, try using Export-CSV instead:
#Write records to file with headers
$records | Select-Object rownum, year, month, batch, facility, transfer_facility, trans_dt, meter, ticket, trans_product, trans, shipper, customer, supplier, broker, origin, destination, quantity |
Export-Csv $fileLocation -NoTypeInformation