Powershell Script Truncated Result - powershell

I have the following script,
$filteracl = {$_.IdentityReference -match "User" -and ($_.FileSystemRights -band 131241 -or $_.FileSystemRights -band 278)}
$objects = Get-ChildItem "C:\" -Recurse -Force
foreach ($i in $objects)
{
$i.GetAccessControl().Access | Where $filteracl | Select `
#{n="Path";e={$i.fullname}},
#{n="User";e={$_.IdentityReference}},
#{n="Permission";e={$_.FileSystemRights}}
}
However, the output from the path is being truncated. I have no idea how to solve this.

Try Format-Table -Wrap like:
$filteracl = {$_.IdentityReference -match "User" -and ($_.FileSystemRights -band 131241 -or $_.FileSystemRights -band 278)}
$objects = Get-ChildItem "C:\" -Recurse -Force
foreach ($i in $objects)
{
$i.GetAccessControl().Access | Where $filteracl | Select `
#{n="Path";e={$i.fullname}},
#{n="User";e={$_.IdentityReference}},
#{n="Permission";e={$_.FileSystemRights}} |
Format-Table -Wrap
}
Since the whole statement is in a loop and Format-Table displays headers, so you'll see multiple headers. To get rid of that you can edit your script to store the output in an Array and then finally display when the loop is complete. Something like:
$filteracl = {$_.IdentityReference -match "User" -and ($_.FileSystemRights -band 131241 -or $_.FileSystemRights -band 278)}
$objects = Get-ChildItem "C:\" -Recurse -Force
$OutputView = #()
foreach ($i in $objects)
{
$s = $i.GetAccessControl().Access | Where $filteracl
$output = New-Object PSObject
$output | Add-Member -MemberType NoteProperty -Name "Path" -Value $i.fullname
$output | Add-Member -MemberType NoteProperty -Name "User" -Value $s.IdentityReference
$output | Add-Member -MemberType NoteProperty -Name "Permission" -Value $s.FileSystemRights
$OutputView += $output
}
$global:outputView |
Select-Object Path,User,Permission

Related

Powershell - Export-CSV outside loop only last line is printed/exported

Is it possible to adjust this code to export all lines outside foreach loop:
This works fine (inside loop):
$vms = Get-VM | Where { $_.State –eq ‘Running’ } | Select-Object -ExpandProperty Name
foreach($vm in $vms) {
# Get network interface details
$out = Get-VMNetworkAdapter -vmname $vm | select VMName, MacAddress, IPAddresses
$vm_name = $out.VMName | Get-Unique
$ip = ($out.IPAddresses | ForEach-Object {
$_ | ? {$_ -notmatch ':'}
}) -join " "
# If more than 1 MAC , put it in same row separated by space (00:15:5D:58:12:5E 00:15:5D:58:12:5F )
$mac = ($out.MacAddress | ForEach-Object {
$_.Insert(2,":").Insert(5,":").Insert(8,":").Insert(11,":").Insert(14,":")
}) -join ' '
$results = #()
$comp = Get-WmiObject Win32_ComputerSystem | Select-Object -ExpandProperty name
$obj = New-Object -TypeName psobject
$obj | Add-Member -MemberType NoteProperty -Name "VM NAME" -Value $vm_name
$obj | Add-Member -MemberType NoteProperty -Name "IP ADDRESS" -Value $ip
$obj | Add-Member -MemberType NoteProperty -Name "MAC ADDRESS" -Value $mac
$obj | Add-Member -MemberType NoteProperty -Name "HYPER-V HOST" -Value $comp
$results += $obj
Write-Output $results
$results| Export-Csv -Path "c:\1.csv" -NoTypeInformation -append
}
However, when i move $results| Export-Csv -Path "c:\1.csv" -NoTypeInformation -append outside loop,
only one (last) line is saved to CSV
Inside loop, $results variable contains all lines, when i move this variable outside loop write-host $results only one (last) line is printed
For what it's worth, your code can be condensed quite a bit. Many of your steps are not necessary:
$results = Get-VM | Where State –eq Running | Get-VMNetworkAdapter | ForEach-Object {
[pscustomobject]#{
'VM NAME' = $_.VMName
'IP ADDRESS' = ($_.IPAddresses -notmatch ':') -join ' '
'MAC ADDRESS' = ($_.MacAddress -replace '(..)(..)(..)(..)(..)','$1:$2:$3:$4:$5:') -join ' '
'HYPER-V HOST' = $env:COMPUTERNAME
}
}
$results | Export-Csv -Path "c:\1.csv" -NoTypeInformation
Notes:
You can pipe the VMs that Get-VM returns directly into Get-VMNetworkAdapter
If you filter on a single property you don't need a script block for Where-Object. Where State -eq Running is a bit easier to write and read than Where { $_.State -eq 'Running' }.
$_.IPAddresses -notmatch ':' Operators like -notmatch work on arrays. 'a','b','0','c' -notmatch '\d' will return 'a','b','c'.
The same goes for -replace. 'a0','b1','c2' -replace '\d','' will return return 'a','b','c'. No foreach loops necessary at all.
$env:COMPUTERNAME should be faster than using WMI to get the computer name
Any object you create in a script block (like the ForEach-Object {...} script block) that you do not assign to a variable will be in the script block's output. This is why $results = ... | ForEach-Object {...} works. There is no need to explicitly create arrays with #() and add values to them.
Casting a hash table to [pscustomobject] is much easier than using Add-Member.
Figured it out:
moved $results variable outside loop (make it "global")
$vms = Get-VM | Where { $_.State –eq ‘Running’ } | Select-Object -ExpandProperty Name
$results = #()
foreach($vm in $vms) {
# Get network interface details
$out = Get-VMNetworkAdapter -vmname $vm | select VMName, MacAddress, IPAddresses
# Remove duplicate VM names
$vm_name = $out.VMName | Get-Unique
# In case more than 1 IP, put it in same row separated by space (192.168.1.1, 192.168.1.2)
$ip = ($out.IPAddresses | ForEach-Object {
$_ | ? {$_ -notmatch ':'}
}) -join " "
# If more than 1 MAC , put it in same row separated by space (00:15:5D:58:12:5E 00:15:5D:58:12:5F )
$mac = ($out.MacAddress | ForEach-Object {
$_.Insert(2,":").Insert(5,":").Insert(8,":").Insert(11,":").Insert(14,":")
}) -join ' '
$comp = Get-WmiObject Win32_ComputerSystem | Select-Object -ExpandProperty name
$obj = New-Object -TypeName psobject
$obj | Add-Member -MemberType NoteProperty -Name "VM NAME" -Value $vm_name
$obj | Add-Member -MemberType NoteProperty -Name "IP ADDRESS" -Value $ip
$obj | Add-Member -MemberType NoteProperty -Name "MAC ADDRESS" -Value $mac
$obj | Add-Member -MemberType NoteProperty -Name "HYPER-V HOST" -Value $comp
$results += $obj
}
$results| Export-Csv -Path "c:\1.csv" -NoTypeInformation

exchange powershell list sendas, send on behalf of, AND fullaccess for a given mailbox

For a given mailbox, I want to list of any users who have any of the following permissions:
send as
send on behalf of
full access
I haven't been able to find a simple way to get all 3 at once, so I have been going at it on a per permission basis...
get-exolmailbox -identity "example#example.com" | get-exolmailboxpermission | where { ($_.AccessRights -eq "FullAccess") -and ($_.IsInherited -eq $false) -and -not ($_.User -like "NT AUTHORITY\SELF") }
get-exolmailbox -Identity "example#example.com" | Get-ADPermission | ? { ($_.ExtendedRights -like "*send*") -or ($_.ExtendedRights -like "*full*") -and -not ($_.User -like "*\self*") } | FT -auto User,ExtendedRights
get-exolmailbox -identity "example#example.com" | fl displayname, grantsendonbehalfto
Is there was a more elegant way to get that same info before I put some time into figuring out how to format the results the way I want?
I would prefer to end up with an excel file that lists each user by display name and which permissions they have to the mailbox.
Something like this should do what you want, it creates a custom object and assigns the info from your commands to its properties.
$emailaddress = "user1#example.com","user2#example.com"
$MailboxPermissions = #()
foreach ($email in $emailaddress)
{
$exolmailbox = get-exolmailbox -identity $email
$FullAccess = $exolmailbox | where { ($_.AccessRights -eq "FullAccess") -and ($_.IsInherited -eq $false) -and -not ($_.User -like "NT AUTHORITY\SELF") }
$SendAs = $exolmailbox | Get-ADPermission | ? { ($_.ExtendedRights -like "*send*") -or ($_.ExtendedRights -like "*full*") -and -not ($_.User -like "*\self*") }
$MailboxInfo = New-Object System.Object
$MailboxInfo | Add-Member -type NoteProperty -name DisplayName -value $exolmailbox.displayname
$MailboxInfo | Add-Member -type NoteProperty -name FullAccess -value $FullAccess
$MailboxInfo | Add-Member -type NoteProperty -name SendAsUser -value $SendAs.User
$MailboxInfo | Add-Member -type NoteProperty -name SendAsExtendedRights -value $SendAs.ExtendedRights
$MailboxInfo | Add-Member -type NoteProperty -name GrantSendOnBehalfTo -value $exolmailbox.grantsendonbehalfto
$MailboxPermissions += $MailboxInfo
}
$MailboxPermissions
Note: I can't test this as I can't find anything online that references get-exolmailbox, and I've only ever seen/used get-mailbox before.

Converting from bytes to GB or MB returns nothing

I got this code, which returns number of bytes:
$size = Get-ChildItem $userAccount.homeDirectory -Recurse | Measure-Object -Property Length -Sum
This works fine, but is not very user friendly, so I want to convert to megabytes or gigabytes.
After googling and looking at examples, I've tried this:
$size = "{0:N2}" -f ((Get-ChildItem $userAccount.homeDirectory -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB)
However, PowerShell returns nothing.
Any idea why?
Edit: Posting complete code.
Function:
Function Get-ADHomeDirectorySize
{
Param
(
[Parameter(ValueFromPipeline=$true,Mandatory=$true)]
[Microsoft.ActiveDirectory.Management.ADUser]$User
)
Begin
{
$HomeD = #()
$size = $nul
}
Process
{
ForEach($userAccount in $User)
{
$userAccount = Get-ADUser $userAccount -properties homeDirectory
$size = "{0:N2}" -f ((Get-ChildItem $userAccount.homeDirectory -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB)
If($userAccount.homeDirectory -eq $nul)
{
Write-Host "`nERROR -- User: $userAccount has no Home Directory`n" -foregroundcolor red
Return
}
$obj = New-Object System.Object
$obj | add-member -type NoteProperty -name User -value $userAccount.Name
$obj | add-member -type NoteProperty -name HomeDirectory -value $userAccount.homeDirectory
$obj | add-member -type NoteProperty -name HomeDirectorySize -value $size.sum
$HomeD += $obj
}
}
End
{
$HomeD
}
}
Script to generate report based on an input list of user IDs:
Get-Content brukerlistetest.txt | Foreach-Object {Get-ADUser $_ -properties homeDirectory | ? {$_.homeDirectory -ne $nul} | Get-ADHomeDirectorySize | sort HomeDirectorySize | Format-Table -HideTableHeaders | out-file output.txt -width 120 -append}
You can perform math operations on your first example:
$size = (Get-ChildItem $userAccount.homeDirectory -Recurse | Measure-Object -Property Length -Sum) / 1MB # or / 1GB
PowerShell has constants that define bytes.
If you want it to be a string, you can use a string subexpression:
$size = "$((GCI $userAccount.homeDirectory -Recurse | Measure Length -Sum) / 1MB)MB"

Include if/else logic

Hello I am trying to if/else and write two separate files, if PST exists then do the following. Export-Csv -NoTypeInformation C:\$UserName-$ComputerName-OpenPSTs-$Date.csv
Else Export-Csv -NoTypeInformation C:\$UserName-$ComputerName-NOPSTs-$Date.csv
Could anyone please suggest.
$Date = Get-Date -format d-M-yyyy
$UserName = $env:USERNAME
$ComputerName = $env:COMPUTERNAME
$Outlook = New-Object -comObject Outlook.Application
$object = $Outlook.Session.Stores | Where {$_.FilePath -like "*.PST"} | Select `
#{Expression={$_.DisplayName}; Label="PST Name in Outlook"},`
#{Expression={$_.FilePath}; Label="PST Location/FileName"},`
#{Expression={$_.IsOpen}; Label="PST Open in Outlook"},`
#{Expression={(Get-Item $_.FilePath).Length / 1KB}; Label="PST File Size (KB)"}
$object | Add-Member -MemberType NoteProperty -Name 'ComputerName' -Value $ComputerName
$object | Add-Member -MemberType NoteProperty -Name 'UserName' -Value $UserName
$object | Export-Csv -NoTypeInformation C:\$UserName-$ComputerName-OpenPSTs-$Date.csv
Start-Sleep 5
Get-Process | Where {$_.Name -like "Outlook*"} | Stop-Process
You could replace the Where-Object filter with a ForEach-Object loop and a nested conditional:
$Outlook.Session.Stores | % {
if ($_.FilePath -like '*.pst') {
$_ | select ... | Export-Csv 'OpenPST.csv' -NoType -Append
} else {
$_ | select ... | Export-Csv 'NoPST.csv' -NoType -Append
}
}
That might not perform too well, though, because it repeatedly appends to the output files. It might be better to just run 2 pipelines with complementary filters:
$stores = $Outlook.Session.Stores
$stores | ? { $_.FilePath -like '*.pst' } | select ... |
Export-Csv 'OpenPST.csv' -NoType
$stores | ? { $_.FilePath -notlike '*.pst' } | select ... |
Export-Csv 'NoPST.csv' -NoType

Disabled ActiveDirectory Users from specific date with exclude list

i wrote a script that gonna disabled old users...
and i need to do an exclude list to it...
the exclude list should be .csv, with 3 columns "Name","SamaccountName","Reason"...
i'm kind of stuck with the exclude list filtering...
i tried to do -notmatch and -notcontains and nothing worked for me...
i even try to do a foreach with if but the same...
Function Get-ADLockOldUsers {
param ()
begin{
[datetime]$myDate = '01/01/1601 02:00:00'
$colObj = #()
$AllUsers = (Get-ADUser -Filter * -Properties lastLogonTimestamp | ? {$_.Enabled} | Select-Object Name,SamAccountName,#{N="LastLogon";E={[datetime]::FromFileTime($_.lastLogonTimestamp)}})
$AllUsers = $AllUsers | ? {(Get-Date).AddDays(-30) -gt $_.LastLogon -and -not ($_.LastLogon -eq $myDate)}
}
process {
$AllUsers | % {
$obj = New-Object psobject
$obj | Add-Member noteproperty 'Name' $_.Name -Force
$obj | Add-Member noteproperty 'SamAccountName' $_.SamAccountName -Force
$obj | Add-Member noteproperty 'LastLogon' $_.LastLogon -Force
$obj | Add-Member noteproperty 'NeedDisabled' $true -Force
$colObj += $obj
}
}
end { return $colObj }
}
Function Set-ADLockUser {
param()
begin{
if (Test-Path '.\excludeusers.csv') {
$excludeUsers = Import-Csv '.\excludeusers.csv'
$DUser = #()
$colUsers = Get-ADLockOldUsers
$colUsers | ? {$_.SamAccountName -notcontains $excludeUsers} | % {Set-ADUser -Identity $_.SamAccountName -Enabled $false -WhatIf }
}
else { Write-Output "Error! excludeusers.csv cannot be found, stop script"; break }
}
process {
}
end{}
}
Set-ADLockUser
A string value can never contain an array, so
$_.SamAccountName -notcontains $excludeUsers
will always evaluate to $true. You need to reverse the check and make the reference an array of strings (the CSV import produces an array of custom objects). Selecting only the field SamaccountName from the imported CSV and switching the arguments should do what you want:
$excludeUsers = Import-Csv '.\excludeusers.csv' | % { $_.SamaccountName }
...
$colUsers | ? { $excludeUsers -notcontains $_.SamAccountName } | ...
As a side note, you could simplify the the code for finding obsolete accounts like this:
$myDate = Get-Date '01/01/1601 02:00:00'
$limit = (Get-Date).AddDays(-30)
$colObj = Get-ADUser -Filter * -Properties * `
| ? { $_.Enabled } `
| select Name,SamAccountName,#{n="NeedDisabled";e={$true}},
#{n="LastLogon";e={[datetime]::FromFileTime($_.lastLogonTimestamp)}} `
| ? { $limit -gt $_.LastLogon -and $_.LastLogon -ne $myDate }
This is the final solution...
<#
.Synopsis
Get All Users in the Domain and check the last logon Date
.Example
Set-ADLockUser -ReportOnly:$true
Get all users that didn't logon for a 30 days and write a report to the current directory
.Example
Set-ADLockUser -ReportOnly:$false
Get all users that didn't logon for a 30 days and disabled them
.Description
Get All Users in the Domain and check the last logon Date, and exclude some users from a list .\excludeusers.csv
.Parameter ReportOnly
Specifies if the script is in reportmode or active mode if ReportOnly=$false all the relevant users will lock
.Outputs
PSObject[]
.Notes
Name: Set-ADLockUser
Author: Ohad Halali
Date: 14.07.2013
.Link
#>
Function Get-ADLockOldUsers {
param ()
begin{
[datetime]$myDate = '01/01/1601 02:00:00'
$colObj = #()
$AllUsers = (Get-ADUser -Filter * -Properties lastLogonTimestamp | ? {$_.Enabled} | `
Select Name,SamAccountName,#{N="LastLogon";E={[datetime]::FromFileTime($_.lastLogonTimestamp)}}) | `
? {(Get-Date).AddDays(-30) -gt $_.LastLogon -and -not ($_.LastLogon -eq $myDate)}
}
process {
$AllUsers | % {
$obj = New-Object psobject
$obj | Add-Member noteproperty 'Name' $_.Name -Force
$obj | Add-Member noteproperty 'SamAccountName' $_.SamAccountName -Force
$obj | Add-Member noteproperty 'LastLogon' $_.LastLogon -Force
$obj | Add-Member noteproperty 'NeedDisabled' $true -Force
$colObj += $obj
}
}
end { return $colObj }
}
Function Set-ADLockUser {
param([bool]$ReportOnly=$true)
begin{
if (Test-Path '.\excludeusers.csv') {
$excludeUsers = Import-Csv '.\excludeusers.csv'
$colUsers = Get-ADLockOldUsers | ? {$excludeUsers.SamAccountName -notcontains $_.SamAccountName}
if ($ReportOnly) {
$colUsers | Export-Csv '.\Report.csv' -NoClobber -NoTypeInformation -Encoding ASCII -Force
}
else {
$colUsers.SamAccountName | Set-ADUser -SamAccountName $_ -Enabled:$False -Replace #{info="Disabled after no login for 30 days (Script)"} -WhatIf
}
}
else { Write-Output "Error! excludeusers.csv cannot be found, stop script"; break }
}
process {}
end{}
}
Set-ADLockUser