Good day all, I'm trying to write a script that will check if a User is valid and export the results to a .csv file. I'm using the "for each" and erroraction -silentlycontinue cmdlet to check a list of Users from a .csv file and then verify on the Microsoft Teams admin center if that is a Valid User.
The problem I'm having is if I add the "$errorActionpreference" cmdlet which suppresses errors (or Users Not Found on Screen) the results in the CSV File are empty, If I remove the $errorAction cmdlet (hashed out in the script below), then it works fine by exporting the valid Users BUT it spits out a lot of errors on the screen.
The scripts just need to suppress error messages for invalid Users, Move to the next User in the csv file, and finally export the results of the valid Users to another csv file.
$path = Read-Host -Prompt "`nEnter the path of .csv file:"
if (Test-Path -Path $path) { break }
Write-Host "Wrong file or path specified. Please enter the correct
path to file!" -ForegroundColor Red
Write-Host "File has been located in the path specified!" -
ForegroundColor Green
$CsvFilePath = Import-CSV -Path $path
# $ErrorActionPreference = "silentlycontinue"
$results = foreach ($Users in $CsvFilePath) {
$User = $Users.UserPrincipalName
Get-CsOnlineUser $User | Select-Object UserPri*, LineURI,
TeamsUpgradeE*,IsSipEnabled, Enterprise*,
#{l="AssignedPlan";e={$_.AssignedPlan
- join "; "}}, #{l="FeatureTypes";e={$_.FeatureTypes -join ";
"}}
}
# $ErrorActionPreference = "silentlycontinue
#Export Results: Prompt for Path, If file does not exist, create it!#
$resultspathfilelocation = Read-Host -Prompt "`nEnter file path
to export results of
the Post Checks: "
$FileName = "$resultspathfilelocation"
if(Get-Item -Path $FileName -ErrorAction Ignore){
Write-Host "File found in directory specified!"
}
else{
New-Item -Verbose $FileName -ItemType File
}
$results | Export-Csv $resultspathfilelocation
Instead of trying to ignore the errors, why not just handle them properly?
$Results = foreach ($Users in $CsvFilePath) {
Try {
$User = $Users.UserPrincipalName
$ThisUser = Get-CsOnlineUser $User -ErrorAction Stop
# Output as custom object
[pscustomobject]#{UPN = $User
TeamsUpgradeEffectiveMode = $ThisUser.TeamsUpgradeEffectiveMode
IsSipEnabled = $ThisUser.IsSipEnabled
AssignedPlan = ($ThisUser.AssignedPlan -join "; ")
FeatureTypes = ($ThisUser.FeatureTypes -join "; ")
Error = ''}
}
Catch {
# User not found or error, output object with blank fields except for error
[pscustomobject]#{UPN = $User
TeamsUpgradeEffectiveMode = ''
IsSipEnabled = ''
AssignedPlan = ''
FeatureTypes = ''
Error = $_.Exception.Message}
}
}
Continuing from my previous question:
I have Powershell script that exports Mailboxes Size Results to CSV file.
The Results contain "Total Size" column that display results, and follow by Name.
However, i want the exported CSV file to filter and display only "greater then" 25GB Results, from high to low.
Like that:
Now, there is the traditional way to use excel to filter to Numbers in the CSV results- after the powershell export.
But, i want to have it in the CSV file, so i do not have to do it over and over again.
Here's the script:
Param
(
[Parameter(Mandatory = $false)]
[switch]$MFA,
[switch]$SharedMBOnly,
[switch]$UserMBOnly,
[string]$MBNamesFile,
[string]$UserName,
[string]$Password
)
Function Get_MailboxSize
{
$Stats=Get-MailboxStatistics -Identity $UPN
$IsArchieved=$Stats.IsArchiveMailbox
$ItemCount=$Stats.ItemCount
$TotalItemSize=$Stats.TotalItemSize
$TotalItemSizeinBytes= $TotalItemSize –replace “(.*\()|,| [a-z]*\)”, “”
$TotalSize=$stats.TotalItemSize.value -replace "\(.*",""
$DeletedItemCount=$Stats.DeletedItemCount
$TotalDeletedItemSize=$Stats.TotalDeletedItemSize
#Export result to csv
$Result=#{'Display Name'=$DisplayName;'User Principal Name'=$upn;'Mailbox Type'=$MailboxType;'Primary SMTP Address'=$PrimarySMTPAddress;'IsArchieved'=$IsArchieved;'Item Count'=$ItemCount;'Total Size'=$TotalSize;'Total Size (Bytes)'=$TotalItemSizeinBytes;'Deleted Item Count'=$DeletedItemCount;'Deleted Item Size'=$TotalDeletedItemSize;'Issue Warning Quota'=$IssueWarningQuota;'Prohibit Send Quota'=$ProhibitSendQuota;'Prohibit send Receive Quota'=$ProhibitSendReceiveQuota}
$Results= New-Object PSObject -Property $Result
$Results | Select-Object 'Display Name','User Principal Name','Mailbox Type','Primary SMTP Address','Item Count',#{Name = 'Total Size'; Expression = {($_."Total Size").Split(" ")[0]}},#{Name = 'Unit'; Expression = {($_."Total Size").Split(" ")[1]}},'Total Size (Bytes)','IsArchieved','Deleted Item Count','Deleted Item Size','Issue Warning Quota','Prohibit Send Quota','Prohibit Send Receive Quota' | Export-Csv -Path $ExportCSV -Notype -Append
}
Function main()
{
#Check for EXO v2 module inatallation
$Module = Get-Module ExchangeOnlineManagement -ListAvailable
if($Module.count -eq 0)
{
Write-Host Exchange Online PowerShell V2 module is not available -ForegroundColor yellow
$Confirm= Read-Host Are you sure you want to install module? [Y] Yes [N] No
if($Confirm -match "[yY]")
{
Write-host "Installing Exchange Online PowerShell module"
Install-Module ExchangeOnlineManagement -Repository PSGallery -AllowClobber -Force
}
else
{
Write-Host EXO V2 module is required to connect Exchange Online.Please install module using Install-Module ExchangeOnlineManagement cmdlet.
Exit
}
}
#Connect Exchange Online with MFA
if($MFA.IsPresent)
{
Connect-ExchangeOnline
}
#Authentication using non-MFA
else
{
#Storing credential in script for scheduling purpose/ Passing credential as parameter
if(($UserName -ne "") -and ($Password -ne ""))
{
$SecuredPassword = ConvertTo-SecureString -AsPlainText $Password -Force
$Credential = New-Object System.Management.Automation.PSCredential $UserName,$SecuredPassword
}
else
{
$Credential=Get-Credential -Credential $null
}
Connect-ExchangeOnline -Credential $Credential
}
#Output file declaration
$ExportCSV=".\MailboxSizeReport_$((Get-Date -format yyyy-MMM-dd-ddd` hh-mm` tt).ToString()).csv"
$Result=""
$Results=#()
$MBCount=0
$PrintedMBCount=0
Write-Host Generating mailbox size report...
#Check for input file
if([string]$MBNamesFile -ne "")
{
#We have an input file, read it into memory
$Mailboxes=#()
$Mailboxes=Import-Csv -Header "MBIdentity" $MBNamesFile
foreach($item in $Mailboxes)
{
$MBDetails=Get-Mailbox -Identity $item.MBIdentity
$UPN=$MBDetails.UserPrincipalName
$MailboxType=$MBDetails.RecipientTypeDetails
$DisplayName=$MBDetails.DisplayName
$PrimarySMTPAddress=$MBDetails.PrimarySMTPAddress
$IssueWarningQuota=$MBDetails.IssueWarningQuota -replace "\(.*",""
$ProhibitSendQuota=$MBDetails.ProhibitSendQuota -replace "\(.*",""
$ProhibitSendReceiveQuota=$MBDetails.ProhibitSendReceiveQuota -replace "\(.*",""
$MBCount++
Write-Progress -Activity "`n Processed mailbox count: $MBCount "`n" Currently Processing: $DisplayName"
Get_MailboxSize
$PrintedMBCount++
}
}
#Get all mailboxes from Office 365
else
{
Get-Mailbox -ResultSize Unlimited | foreach {
$UPN=$_.UserPrincipalName
$Mailboxtype=$_.RecipientTypeDetails
$DisplayName=$_.DisplayName
$PrimarySMTPAddress=$_.PrimarySMTPAddress
$IssueWarningQuota=$_.IssueWarningQuota -replace "\(.*",""
$ProhibitSendQuota=$_.ProhibitSendQuota -replace "\(.*",""
$ProhibitSendReceiveQuota=$_.ProhibitSendReceiveQuota -replace "\(.*",""
$MBCount++
Write-Progress -Activity "`n Processed mailbox count: $MBCount "`n" Currently Processing: $DisplayName"
if($SharedMBOnly.IsPresent -and ($Mailboxtype -ne "SharedMailbox"))
{
return
}
if($UserMBOnly.IsPresent -and ($MailboxType -ne "UserMailbox"))
{
return
}
Get_MailboxSize
$PrintedMBCount++
}
}
#Open output file after execution
If($PrintedMBCount -eq 0)
{
Write-Host No mailbox found
}
else
{
Write-Host `nThe output file contains $PrintedMBCount mailboxes.
if((Test-Path -Path $ExportCSV) -eq "True")
{
Write-Host `nThe Output file available in $ExportCSV -ForegroundColor Green
$Prompt = New-Object -ComObject wscript.shell
$UserInput = $Prompt.popup("Do you want to open output file?",`
0,"Open Output File",4)
If ($UserInput -eq 6)
{
Invoke-Item "$ExportCSV"
}
}
}
#Disconnect Exchange Online session
Disconnect-ExchangeOnline -Confirm:$false | Out-Null
}
. main
How can i achieve that?
It's a bit of an unfortunate scenario, but if you're outputting the results to the file on each iteration, you have 2 options:
At the end of the script, read the output file, filter the >25gb mailboxes, sort the objects, then output again
Instead of writing the user mailbox to the file each user, save to a
variable instead. At the end, filter, sort, then export to file
Without going too far into the code...
Option 1
Might be simplest, as you're working off two input sizes already. After you've retrieved all mailboxes and gotten all statistics, read the exported csv file and filter + sort the data. Then, export the info back to the file, overwriting. Something like
$tempImport = Import-CSV $exportCSV | Where-Object {($_.'Total Size' -ge 25) -and ($_.Unit -eq "GB")} | Sort-Object 'Total Size' -descending
$tempImport | Export-CSV $exportCSV -noTypeInformation
PowerShell may not like overwriting a file read-in on the same command, hence the saving as a temp variable.
Option 2
Create a live variable storing all mailbox data, and write the information at the end of the script instead of opening the file to append data each iteration. Then, at the end of the script, filter and sort before exporting.
$global:largeMailboxes = #() # definition to allow reading through all functions
Then, instead of exporting to CSV each time, add the result to the above variable
$tvar = $null
$tvar = $Results | Select-Object 'Display Name','User Principal Name','Mailbox Type','Primary SMTP Address','Item Count',#{Name = 'Total Size'; Expression = {($_."Total Size").Split(" ")[0]}},#{Name = 'Unit'; Expression = {($_."Total Size").Split(" ")[1]}},'Total Size (Bytes)','IsArchieved','Deleted Item Count','Deleted Item Size','Issue Warning Quota','Prohibit Send Quota','Prohibit Send Receive Quota'
$global:largeMailboxes += $tvar
#
# Alternatively, only add the mailbox if it's larger than 25GB, to avoid adding objects you don't care about
if ($TotalItemSizeinBytes -ge 26843545600) # This is 25 GB, better to make a variable called $minSize or such to store this in, in case you want to change it later.
{
# Above code to add to global variable
}
Once all mailboxes have been added, sort the object
$global:largeMailboxes = $global:largeMailboxes | Sort-Object 'Total Size' -descending
Then export as needed
$global:largeMailboxes | Export-CSV $exportCSV -NoTypeInformation
I have the following code where I look up a users SID and if its not found I set an output value to the SID not being found. I output the entire results to a csv file using a psobject.
Whats happening is that I find an invalid sid and instead of stopping processing the user after doing the following:
$objPrintdata.User_SID_Status ="Invalid SID", it continues to process the same sid and goes to the $regPrinterDetails.GetSubKeyNames() |ForEach-Object line where it fails and writes another line with the same SID but with the correct error of registry cant be opened and 2003 cant be found. How can I get out of the loop for the user where I haven't found a SID?
Get-Content "P:\PowerShell\jv\servers.txt" | ForEach-Object{
#Write-Host $_
$intNumberofServers++
$strServer =$_
#setting the psobject server value
#$strserver
$objPrintdata.Server = $strServer
$blnHasOldQueues = $false
#Setting server value
$strComputer = $strServer.server
$PingResult = Test-Connection -ComputerName $strServer -Count 1 -Quiet
If($PingResult){
#Outputting server status
$objPrintdata.ServerStatus = "Workstation is UP"
try{
If($strHklm = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine',$strServer )){
#executes when it can open HKLM
$objPrintdata.RegistryStatus = "Was able to open the registry"
#set the path of the registry
$PrinterRegKey = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Providers\\Client Side Rendering Print Provider'
$regPrinterRef = $strHklm.OpenSubKey($PrinterRegKey)
#debug
#$regPrinterRef
}
#setting this to output to csv
# $resultsarray =#()
#$strPrinters = $regPrinterRef.GetSubKeyNames()
#check if regprinterref is not null
if($regPrinterRef){
#executes when there are keys
#region Loop thru all child keys. These contain the calculable UNC paths to 2003
$regPrinterRef.GetSubKeyNames() | ForEach-Object{
#debug
# $_
#concatinating to get to the connections key
$strPrinterpath =$PrinterRegKey+"\\"+ $_ + "\\Printers\\Connections"
#$strPrinterPath
if ($strPrinterpath -notlike "*servers*"){
#this value is the sid
# $_ will give us the sids. Here I am storing the SIDs into strUserSID to use later on
$strUserSID = $_
#debug
$strUserSID
# The logic below will convert SID to username
#pass the SID to the secrity principal SID being struserSID
#$objSID = New-Object System.Security.Principal.SecurityIdentifier("$strUserSID")
#using a try catch to filter out deleted SIDs, otherwise powershell will throw an error saying it is null
Try{
$objSID=get-aduser -filter {sid -eq $strUserSID}
if($objSID-eq $null)
{
#does a test AD lookup to see if the user still exists baseed on their sid. Returns the user object if it exists & null if not
$objPrintdata.User_SID_Status ="Invalid SID"
$objPrintdata.User = "Invalid SID"
$objPrintdata.Does_it_Have_2003_Queues ="Invalid SID"
$objPrintdata.UNC_2003_Queues = "Invalid SID"
$objPrintdata | Export-Csv P:\powershell\jv\results.csv -NoTypeInformation -Append
}
else
{
#executes when the sid is still valid. Displays a subset of the user object properties
$strUser= $objSID.SamAccountName
$objPrintdata.User_SID_Status ="Valid SID"
}
}
Catch{
#$strUserID = $objSID.Value
Write-Host "Lost connection to AD"
#exit
}
#$strUser
$regPrinterDetails = $Strhklm.OpenSubKey($strPrinterPath)
#debug
#$strPrinterPath
#$regPrinterDetails
$regPrinterDetails.GetSubKeyNames() |ForEach-Object{
#looping through each key at the connections level to search for the 2003 print server names
if($_ -like "*sabppprt2*"){
$objPrintdata.Does_it_Have_2003_Queues = "Yes"
#this value is the printer if it exists
# $_ will give us the printers. Here I am storing the printers into strUserPrinters to user later on
$strUserPrinters = $_
#$strUserPrinters
$blnHasOldQueues = $true
#The code below is to build the printer UNC to make it more legible
$intPrinterLength= $strUserPrinters.Length
$strPrintServer= $strUserPrinters.Substring(2,10)
#Doing the -13 because we have to limit the length of the substring statement to the length minus the starting poistion of the substring
$strPrinterShareName =$strUserPrinters.Substring(13,$intPrinterLength-13)
$strPrintUNC = "\\"+$strPrintServer+"\"+$strPrinterShareName
$objPrintdata.UNC_2003_Queues = $strPrintUNC
$objPrintdata.User = $strUser
# Write-Host $strServer $blnHasOldQueues $strUser $strPrintUNC
$objPrintdata | Export-Csv P:\powershell\jv\results.csv -NoTypeInformation -Append
}
# Write-Host $strServer $blnHasOldQueues $strUserSID $strUserPrinters
}
}
else
{
#Write-host "No 2003 Queues Detected"
#Write-host "no 2003 Queues detected" $strUserSID,$strUser,$strPrintUNC
$objPrintdata.User = $strUser
$objPrintdata.Does_it_Have_2003_Queues = "No 2003 Queues Detected for this user or vsabppprt* queue"
$objPrintdata.UNC_2003_Queues = "No 2003 Queues Detected for this user or vsabppprt* queue"
$objPrintdata | Export-Csv P:\powershell\jv\results.csv -NoTypeInformation -Append
}
}
#endregion
}
}
catch{
Write-Host "Can Not access this machines registry: " $strServer
$objPrintdata.RegistryStatus = "Can not open the registry"
$objPrintdata.User_SID_Status = "Can not open the registry"
$objPrintdata.User = "Can not open the registry"
$objPrintdata.UNC_2003_Queues = "Could not open the registry"
$objPrintdata.Does_it_Have_2003_Queues = "Could not open the registry"
$objPrintdata | Export-Csv P:\powershell\jv\results.csv -NoTypeInformation -Append
}
} #if ends here
else{
#executes when the machine is unpingable
Write-Host "This machine is currently not on the network: " $strServer
$objPrintdata.ServerStatus = "Workstation is Down"
$objPrintdata.RegistryStatus = "Workstation is Down"
$objPrintdata.User_SID_Status = "Workstation is Down"
$objPrintdata.User = "Workstation is Down"
$objPrintdata.UNC_2003_Queues = "Workstation is Down"
$objPrintdata.Does_it_Have_2003_Queues = "Workstation is Down"
$objPrintdata | Export-Csv P:\powershell\jv\results.csv -NoTypeInformation -Append
}
#Doesn't the Else need to be here
}
$intNumberofServers
if I understand correctly you want to stop processing the current child key if you have found an invalid SID. If so just add a return statement after the following line:
$objPrintdata | Export-Csv P:\powershell\jv\results.csv -NoTypeInformation -Append
I have written a script which checks a service status, tests two paths and also tests a registry value. Currently I am getting output on the power shell console (that could be because I am using write-output command).
Is there any way to write the single one page output to a file?
I am struggling to find a way to out-file entire output to a file.
Below is the script.
$testpath = Test-Path "C:\test"
$testpath2 = test-path "C:\test"
$mcshieldk = Get-Service -Name mcshield | select Name
$internet = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\internet explorer").MkEnabled $hostname = hostname Write-Host "hostname of comuter is" $hostname if (Test-Path $Machinetype)
{}
else { Write-Host "internet is" $internet }
if ($testpath -eq $true -and $testpath2 -eq $true)
{ Write-Host "test and test1 folder exists" -ForegroundColor Green }
else{ Write-Host "folder does not exists" -ForegroundColor Red } if($mcshield.Name -eq "mcshield") { Write-Host "mcshield service exists" }
else { Write-Host "mcshield does not exists" }
Below is the console output
hostname of comuter is Server1
internet is Yes
test and test1 folder exists
mcshield does not exists
Swap out your Write-Host cmdlets or add in another line with the following:
"Your output text $YourVariable" | Out-File -FilePath "C:\Log.txt" -Append -Encoding utf8
This will append a string to the end of the log file C:\Log.txt. Note, missing the -Append parameter will cause the file to be overwritten.
You can also use the follow to give the same affect:
"Your output text $YourVariable" >> "C:\Log.txt"
But be carefully not to mix the two methods as you might get encoding errors in the text file. If you wish to overwrite the file with the second method use > instead of >>.
I'm making a script to add some user from a csv to my AD and it doesn't work for some reason that i can't find out ^^'.
I'm using the file ADlog to see where my code goes or not and it goes in the "else (Woot?)" so maybe it can't access to my AD thx to a mistake in my code or ... dunno
#connection to the Active Directory
$objOU=[ADSI]"LDAP://localhost:389/DC=maho,DC=lan"
if($objOU.Children -ne $null) {
# import data from the csv file
$dataSource=import-csv ("\user.csv")
ForEach($dataRecord in $dataSource) {
$ou=$dataRecord.service
#checking the existance of the UO
if(($objOU.Children | where {$_.Path -match "OU=$ou"}) -eq $null){
#if it doesn't, we creat it
$objOU = $objOU.create("organizationalUnit", "ou="+$ou)
$objOU.SetInfo()
"UO not there" | Add-Content C:\ADlog.txt
}
else {
#if it does exist we point on it to creat the new user
$objOU = $objOU.Children.Find("OU=$ou")
"WOOT ?" | Add-Content C:\ADlog.txt
}
$SamAccountName=$dataRecord.login
$GivenName=$dataRecord.fname
$sn=$dataRecord.lname
$cn=$GivenName + " " + $sn
$displayName=$cn
$description=$dataRecord.description
$UserPrincipalname=$SamAccountName +"#"+$DNS_DomainName
#we create the obj user in the AD
$objUser=$objOU.Create("User","CN="+$cn)
$objUser.Put("SamAccountName",$SamAccountName)
$objUser.Put("UserPrincipalName",$UserPrincipalName)
$objUser.Put("DisplayName",$Displayname)
$objUser.Put("Description",$description)
$objUser.Put("GivenName",$GivenName)
$objUser.Put("sn",$sn)
$objUser.SetInfo()
#$objUser.setPassword("")
#empty to make the user choise his own passwd
#we activate the account
$objUser.psbase.InvokeSet("AccountDisabled",$false)
$objUser.SetInfo()
#we check that the acc is created
if(($objOU.Children | where {$_.Path -match "CN=$cn"}) -ne $null) {
"User : "+$UserPrincipalName+" Ok" | Add-Content C:\ADlog.txt
}
$objOU=[ADSI]"LDAP://localhost:389/DC=maho,DC=lan"
}
Write-Host "Sucess!"
#Delete the reg key
Remove-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run"-Name "Unattend*"
}
else {
"Failure" | Add-Content C:\ADlog.txt
}
Check out This Scripting Guy article, pretty straight forward
http://blogs.technet.com/b/heyscriptingguy/archive/2011/12/22/use-powershell-to-read-a-csv-file-and-create-active-directory-user-accounts.aspx