Coding

[PowerShell] Making good use of AD Computer object ManagedBy field

If you put the assignee of the computer in the computer object’s ManagedBy field, you will be able to search for it based on the username of the assignee with the following script

$username = Read-Host 'Please enter Username'
$userDistinguishedName = Get-ADUser -Filter "SamAccountName -eq '$username'"|Select-Object -ExcludeProperty DistinguishedName
Get-ADComputer -Filter "ManagedBy -eq '$($userDistinguishedName)'" -Properties IPv4Address,OperatingSystem,OperatingSystemServicePack,OperatingSystemHotfix,Description|Select-Object Name,IPv4Address,OperatingSystem,OperatingSystemServicePack,OperatingSystemHotfix,Description|ft -AutoSize
Advertisements

[PowerShell] Getting a list of users that has full-access rights to a mailbox

Below is the PowerShell Cmdlet that lets you get a list of members that has FullAccess right to a mailbox.

Get-MailboxPermission -Identity mailbox|select Identity, User,AccessRights|where{$_.AccessRights -match "FullAccess"}

To have the result on your clipboard, add |clip to the end of the command as below

Get-MailboxPermission -Identity mailbox|select Identity, User,AccessRights|where{$_.AccessRights -match "FullAccess"}|clip

[POWERSHELL] CHECK QUEST KACE ONE AGENT SERVICE FOR MULTIPLE COMPUTER (VERSION #4)

Here is the #4 version, changes as below:

  • Limit concurrent running background job with $maxConcurrentJobs to 50
  • use Start-Job to check online status as well as check service

 

#The OU to search
 $SearchBase = "OU=COMPUTER,OU=World_First,DC=domain,DC=local"

#Search result of computers (Windows only)
$Computers = Get-ADComputer -Filter {OperatingSystem -Like "Windows*"} -SearchBase $SearchBase -SearchScope Subtree -ErrorAction Stop -ErrorVariable NoComputers|sort Name
if($noComputers){
 Write-Warning -Message "Unable to get computer from AD"
 Exit
}

$ServiceStatusFile = "ServiceStatus.csv"
$OfflineFile = "Offline.csv"
$noServiceFile = "noService.csv"
$maxConcurrentJobs = 50 #Max. number of simultaneously running jobs

#Array for online computers
$onlineComputers = @()
#Array for offline computers
$offlineComputers = @()

$ping={

function ping{
 param (
 [parameter(Mandatory=$true,ValueFromPipeline=$true)]
 [string]$client
 )
 
 
 #win32_PingStatus variables
 $timeout= 1500
 $filter='Address="{0}" and Timeout={1}' -f $client, $timeout
 
 
 
 
 return Get-WmiObject Win32_PingStatus -Filter $filter
 
 
 
 }

}




$func={

function checkService{

param (
 [parameter(Mandatory=$true,ValueFromPipeline=$true)]
 [string]$client
 )
 
 try{

$serviceStatus=get-service -DisplayName "Quest KACE One Agent" -ComputerName $client -ErrorAction SilentlyContinue -ErrorVariable ServiceNotAvailable|select-object MachineName,DisplayName,Status
 
 if($serviceStatus){
 $output = $serviceStatus
 return $serviceStatus
 }

else{
 
 write-warning -Message "$client,$ServiceNotAvailable"
 $output = $client +"," + $ServiceNotAvailable
 return $output
 }
 
 }
 
 Catch [System.Management.Automation.CmdletInvocationException]{
 
 write-warning -Message "$client,$ServiceNotAvailable"
 $output = $client +"," + $ServiceNotAvailable.Message
 return $output
 }
 
 Catch{
 $ErrorMessage = $_.Exception.Message
 $FailedItem = $_.Exception.ItemName
 }
 
 } 
} 
 
#Ping all computers
foreach($computer in $computers) {
 $client = $computer.Name 
 Write-Progress -Activity "Checking computer availablilty....." -status "Ping $client" -percentComplete ($computers.IndexOf($computer) / $Computers.count*100)
 if ((Get-Job -State 'Running').Count -lt $maxConcurrentJobs) {
 Start-Job -ScriptBlock {ping $args[0]} -ArgumentList @($client) -Name "$client" -InitializationScript $ping
 }else{
 Start-Sleep -Seconds 3
 Start-Job -ScriptBlock {ping $args[0]} -ArgumentList @($client) -Name "$client" -InitializationScript $ping
 }
}

#Wait for job to complete
Get-Job|Wait-Job

#Get result of ping
foreach($computer in $computers) {
 
 $client = $computer.Name
 Write-Progress -Activity "Retrieving results of availability....." -status "Ping result for $client" -percentComplete ($computers.IndexOf($computer) / $Computers.count*100)
 $pingStatus=Receive-Job -Name $client
 #Removes the ping job when result is retrieved
 Remove-Job -Name $client

#If PC is online
 if($pingStatus.StatusCode -eq '0'){
 
 $onlineComputers= $onlineComputers+($computer)
 #Create a checkService job for online PC
 if ((Get-Job -State 'Running').Count -lt $maxConcurrentJobs) {
 Start-Job -ScriptBlock {checkService $args[0]} -ArgumentList @($computer.Name) -Name "$client" -InitializationScript $func 
 }
 else{
 Start-Sleep -Seconds 5
 Start-Job -ScriptBlock {checkService $args[0]} -ArgumentList @($computer.Name) -Name "$client" -InitializationScript $func 
 }
 }
 else{
 $offlineComputers= $offlineComputers+($computer)
 Write-Warning -Message "$client is offline"
 
 $client|Out-File -FilePath $OfflineFile -Append
 
 }
}

#Wait for job to complete
Get-Job|Wait-Job

#Get result from checkService
foreach($onlinecomputer in $onlineComputers) {
 $result=receive-job -Name $onlineComputer.Name -Keep
 
 Write-Progress -Activity "Retrieving results of availability....." -status "Service result for $onlineComputer.Name" -percentComplete ($onlineComputers.IndexOf($onlinecomputer) / $onlineComputers.count*100)
 #Contains MachineName, service available
 if([bool]($result.PSobject.Properties.name -match "MachineName")){
 
 
 $result|select-object MachineName,DisplayName,Status |export-csv -Path $ServiceStatusFile -NoTypeInformation -Append
 
 }
 
 else{
 
 $result|Out-File -FilePath $noServiceFile -Append
 
 }

}
#Remove all completed job
Remove-Job -State Completed

Import-Csv $ServiceStatusFile|ft -AutoSize

[POWERSHELL] CHECK QUEST KACE ONE AGENT SERVICE FOR MULTIPLE COMPUTER (VERSION #3)

Here is the #3 version, changes as below:

  • use of Win32_PingStatus for a ping timeout of 1500ms because Test-Connection defaults to 4 seconds and there is no option to change that.
  • Added error handling with try/catch
  • use Start-Job to start checking for service status once found PC is online.

 

#The OU to search
 $SearchBase = "OU=COMPUTER,OU=World_First,DC=domain,DC=local"

#output files
 $ServiceStatusFile = "ServiceStatus.csv"
 $OfflineFile = "Offline.csv"
 $noServiceFile = "noService.csv"

#Search result of computers (Windows only)
 $Computers = Get-ADComputer -Filter {OperatingSystem -Like "Windows*"} -SearchBase $SearchBase -SearchScope Subtree|sort Name

#Array for online computers
 $onlineComputers = @()

#Array for offline computers
 $offlineComputers = @()

$func={

function checkService{

param (
 [parameter(Mandatory=$true,ValueFromPipeline=$true)]
 [string]$client
 )

try{

$serviceStatus=get-service -DisplayName "Quest KACE One Agent" -ComputerName $client -ErrorAction SilentlyContinue -ErrorVariable ServiceNotAvailable|select-object MachineName,DisplayName,Status

if($serviceStatus){
 return $serviceStatus
 }

else{

write-warning -Message "$client,$ServiceNotAvailable"
 $output = $client +"," + $ServiceNotAvailable
 return $output
 }

}
 Catch [System.Management.Automation.CmdletInvocationException]{

write-warning -Message "$client,$ServiceNotAvailable"
 $output = $client +"," + $ServiceNotAvailable.Message
 return $output

}

Catch{
 $ErrorMessage = $_.Exception.Message
 $FailedItem = $_.Exception.ItemName

}

}
 }




#Check if computers are online
 foreach($computer in $computers) {

$client = $computer.Name
 #win32_PingStatus variables
 $filter='Address="{0}" and Timeout={1}' -f $client, $timeout
 $timeout= 1500
 Write-Progress -Activity "Checking computer availablilty....." -status "Ping computer $client" -percentComplete ($computers.IndexOf($computer) / $Computers.count*100)

if((Get-WmiObject Win32_PingStatus -Filter $filter).StatusCode -eq '0'){
 Start-Job -ScriptBlock {checkService $args[0]} -ArgumentList @($client) -Name "$client" -InitializationScript $func
 $onlineComputers= $onlineComputers+($computer)

}
 else{

$offlineComputers= $offlineComputers+($computer)
 Write-Warning -Message "$client is offline"

$client|Out-File -FilePath $OfflineFile -Append
 }

}







Get-Job|Wait-Job

foreach($onlineComputer in $onlineComputers){




$result=receive-job -Name $onlineComputer.Name -Keep

#Contains MachineName, service available
 if([bool]($result.PSobject.Properties.name -match "MachineName")){
 $result|select-object MachineName,DisplayName,Status|export-csv -Path $ServiceStatusFile -NoTypeInformation -Append

}

else{

$result|Out-File -FilePath $noServiceFile -Append

}

}

Remove-Job -State Completed

import-csv -Path ServiceStatus.csv

[POWERSHELL] CHECK QUEST KACE ONE AGENT SERVICE FOR MULTIPLE COMPUTER (VERSION #2)

Here is the version #2 where the source of computer is retrieve from the AD by searching on specific OU defined on $SearchBase. The search will be recursive and include only Windows machine with a progress bar.

Once the search is completed, it will start checking the availablity of the machine with test-connection. It will then check the service status of the online PC.

Once done, the result will be saved to 3 files.

  1. ServiceStatus.csv = Machine that had successfully return the service status
  2. Offline.csv = Offline machine
  3. noService.csv = Machine that have issue with getting the service status

 

#The OU to search
$SearchBase = "OU=COMPUTER,DC=domain,DC=local"

$ServiceStatusFile = "ServiceStatus.csv"
$OfflineFile = "Offline.csv"
$noServiceFile = "noService.csv"

#Search result of computers (Windows only)
$Computers = Get-ADComputer -Filter {OperatingSystem -Like "Windows*"} -SearchBase $SearchBase -SearchScope Subtree -ErrorAction Stop -ErrorVariable NoComputers|sort Name
if($noComputers){
 Write-Warning -Message "Unable to get computer from AD"
 Exit
}

#Service to check
$Service = "Quest KACE One Agent"

#Array for offline computers
$offlineComputers = @()

#Array for online computers
$onlineComputers = @()

##Array for computers without service
$noServiceComputers = @()

#Check if computers are online
foreach($computer in $computers) {
 
 $client = $computer.Name

if (Test-Connection -Computername $client -BufferSize 16 -Count 1 -Quiet){

Write-Progress -Activity "Checking computer availablilty....." -status "Ping computer $client" -percentComplete ($computers.IndexOf($computer) / $Computers.count*100)
 $onlineComputers= $onlineComputers+($computer)


 }
 else{
 
 $offlineComputers= $offlineComputers+($computer)
 Write-Warning -Message "$client is offline"
 
 $client|Out-File -FilePath $OfflineFile -Append
 }

}

#Check if service is available on online computers
foreach($onlineComputer in $onlineComputers){
 $client = $onlineComputer.Name
 Write-Progress -Activity "Checking service availablilty....." -status "Check service on computer $client" -percentComplete ($onlineComputers.IndexOf($onlineComputer) / $onlineComputers.count*100)
 $Servicestatus = get-service -DisplayName $Service -ComputerName $client -ErrorAction SilentlyContinue -ErrorVariable ServiceNotAvailable|select-object MachineName,DisplayName,Status|export-csv -Path $ServiceStatusFile -NoTypeInformation -Append
 if($ServiceNotAvailable){
 Write-Warning -Message "$client : $ServiceNotAvailable"
 #Write-Warning -Message "$client does not have Quest Kace One Agent"
 $noServiceComputers = $noServiceComputers+($computer)
 $client|Out-File -FilePath $noServiceFile -Append
 }
 
 }

import-csv -Path ServiceStatus.csv

[PowerShell] Check Quest Kace One Agent Service for multiple computer (Version #1)

computers.txt being a list of computers, the script will check for the service status of the computers.

$Computers = get-content computers.txt
$Service = "Quest KACE One Agent"

foreach ($computer in $computers) {
 $Servicestatus = get-service -DisplayName $Service -ComputerName $computer
 $Servicestatus | select-object DisplayName,Status,MachineName

}

 

[PowerShell]Get all distribution list and members from AD with PowerShell

The following script will create a csv file for every distribution list with the members listed:

$allDL=get-adgroup -filter 'GroupCategory -eq "Distribution"' | sort name|select SamAccountName

foreach($dl in $allDL){

$filename=($dl.SamAccountName).ToString()
Get-ADGroupMember -identity $dl.SamAccountName|select-object name,SamAccountName,distinguishedName,objectClass|Export-Csv -Path $filename".csv" -NoTypeInformation

}

List Security group members with a autocomplete form

 

#http://social.technet.microsoft.com/wiki/contents/articles/28824.how-to-add-a-graphical-user-interface-to-your-powershell-functions-using-the-net-systemwindowsform-class.aspx
#https://community.spiceworks.com/topic/255740-powershell-script-to-show-all-groups-in-ad
#https://www.petri.com/powershell-problem-solver-exporting-active-directory-groups-csv
get-adgroup -filter 'GroupCategory -eq "Security"'  | sort name | select Name|Export-Csv -Path $env:temp\ADGroup.txt -NoTypeInformation
(Get-Content $env:temp\ADGroup.txt) -replace '"''' | Set-Content $env:temp\ADGroup.txt
Import-Module activedirectory
#import Presentation framework for error message pop-up
Add-Type -AssemblyName PresentationCore,PresentationFramework
Function getADMember($groupName)
{
    try
    {
        Get-ADGroupMember $groupName -Recursive|select-object name,SamAccountName,distinguishedName,objectClass|Export-Csv -Path $env:temp\$groupName.csv -NoTypeInformation
        #|Export-Csv -Path $env:temp\$groupName.csv -NoTypeInformation
        #Out-GridView -PassThru|
        invoke-item -Path $env:temp\$groupName.csv
    }
    catch
    {
        $ButtonType = [System.Windows.MessageBoxButton]::OK
        $MessageIcon = [System.Windows.MessageBoxImage]::Error
        $MessageBody = $($_.Exception.Message)
        $MessageTitle "Error"
        $Result = [System.Windows.MessageBox]::Show($MessageBody,$MessageTitle,$ButtonType,$MessageIcon)
    }
    finally
    {
        
    }
}
#region Boring beginning stuff
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
#endregion
  
#region begin to draw forms
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "Get AD Group Member"
$Form.Size = New-Object System.Drawing.Size(300,170)
$Form.StartPosition = "CenterScreen"
$Form.KeyPreview = $True
$Form.MaximumSize = $Form.Size
$Form.MinimumSize = $Form.Size
  
$label = New-Object System.Windows.Forms.label
$label.Location = New-Object System.Drawing.Size(5,5)
$label.Size = New-Object System.Drawing.Size(240,30)
$label.Text = "Type any group name"
$Form.Controls.Add($label)
$textbox = New-Object System.Windows.Forms.TextBox
$textbox.Location = New-Object System.Drawing.Size(5,40)
$textbox.Size = New-Object System.Drawing.Size(165,25)
#$textbox.Text = "Select source PC:"
$Form.Controls.Add($textbox)
  
$search_group =
{
#region Actual Code
  
$statusBar1.Text = "Searching..."
$DLName $textbox.Text
  
getADMember($DLName)
  
$statusBar1.Text = "Searching Complete"
#endregion
}
  
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(180,38)
$OKButton.Size = New-Object System.Drawing.Size(50,23)
$OKButton.Text = "OK"
$OKButton.Add_Click($search_group)
$Form.Controls.Add($OKButton)
  
$result_label = New-Object System.Windows.Forms.label
$result_label.Location = New-Object System.Drawing.Size(5,65)
$result_label.Size = New-Object System.Drawing.Size(240,30)
$result_label.Text = ""
$Form.Controls.Add($result_label)
  
$statusBar1 = New-Object System.Windows.Forms.StatusBar
$statusBar1.Name = "statusBar1"
$statusBar1.Text = "Ready..."
$form.Controls.Add($statusBar1)
  
$Form.Add_KeyDown({if ($_.KeyCode -eq "Enter"){& $search_group}})
$Form.Add_KeyDown({if ($_.KeyCode -eq "Escape")
{$Form.Close()}})
#endregion begin to draw forms
#Autocomplete region begins here
$textbox.AutoCompleteSource = 'CustomSource'
$textbox.AutoCompleteMode='SuggestAppend'
$textbox.AutoCompleteCustomSource=$autocomplete
#Importing from a file
Get-content -Path $env:temp\ADGroup.txt | % {$textbox.AutoCompleteCustomSource.AddRange($_) }
#Autocomplete region ends here
  
#Show form
$Form.Topmost = $True
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()