A fairly Simple Script, but cannot see what is wrong here - powershell

I have written a fairly simple script, to simply retrieve users via the UserPrinsipalName. It fails with the following error:
Get-AdUser : Property: 'UserPrincipalName' not found in object of type: 'System.Management.Automation.PSCustomObject'.
At C:\Temp\changeUPN.ps1:8 char:16
+ ... serObject = Get-AdUser -Filter {UserPrincipalName -eq $Obj.UserPrinci ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-ADUser], ArgumentException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:System.ArgumentException,Microsoft.ActiveDirectory.Management.Commands.GetADUser
$Csv = Read-Host "Enter Path to the Csv file"
$sps = Import-csv -Path $Csv
Foreach ($Obj in $Sps) {
Write-Host "Splitting UPN $($Obj.UserPrincipalName) to retreive domain information" -ForegroundColor Green
$Domain = ($Obj.UserPrincipalName -split "#")[1]
Write-Host "$($Obj.UserPrincipalName) is located in $($Domain)" -ForegroundColor Green
Write-Host "Getting AD Object" -ForegroundColor Green
$UserObject = Get-AdUser -Filter {UserPrincipalName -eq "$Obj.UserPrincipalName"} -Server $Domain
If ($UserObject) {
Write-Host "UserObject $($UserObject.DistinguishedName) Retrieved" -ForegroundColor Green
Write-Host "Changing UPN" -ForegroundColor Green
$NewUpn = $Obj.UserPrincipalName -Replace ("$Domain", "Contoso.com")
Write-Host "New UserPrincipalName = $($NewUpn)" -ForegroundColor Green
$UserObject | Set-AdUser -UserPrincipalName $NewUpn
}
Else {
Write-Host "Could not retrieve $($Obj.UserPrincipalName) from $($Domain)" -ForegroundColor Yellow
}
}

Related

Argument Passed into ScriptBlock Doesn't Work on Last Iteration

I'm using the following script to run through all of the servers in a specified Active Directory OU and log out the specified user. This runs perfectly well for the first 35 servers but always errors out on the very last server it iterates through. The error is:
Program 'quser.exe' failed to run: Object reference not set to an instance of an object. At line:6 char:24
+ $result = (quser $userAccount)
+ ~~~~~~~~~~~~~~~~~~.
At \\path\to\script.ps1:79 char:5
+ invoke-command -ComputerName $server -ScriptBlock $scriptBlock -A ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (Program 'quser....~~~~~~~~~~~~~~.:String) [], RuntimeException
+ FullyQualifiedErrorId : Program 'quser.exe' failed to run: Object reference not set to an instance of an object.At line:6 char:24
+ $result = (quser $userAccount)
+ ~~~~~~~~~~~~~~~~~~.
My reading of the error is that it thinks $userAccount has no value. Is that correct and, if so, can anyone point at what I'm missing? Thank you in advance!
Write-Host " "
Write-Host "This script will log out all active sessions for the specified user. Proceed with caution." -ForegroundColor Black -BackgroundColor Yellow
Write-Host " "
$servers = [System.Collections.ArrayList]::new()
foreach ($server in (Get-ADComputer -SearchBase "OU=FictionalDepartment,DC=Company,DC=net" -Filter "OperatingSystem -like 'Windows Server*'" -Properties Name | select -ExpandProperty name))
{
$servers.add($server) | Out-Null
}
$servers.Sort()
$userAccount = Read-Host "Enter account to log out"
Write-Host " "
foreach ($server in $servers)
{
$scriptBlock = {
param($userAccount)
$ErrorActionPreference = 'Stop'
try
{
$result = (quser $userAccount)
$session = ((quser $userAccount)[1] -split "\s+")[2]
logoff $session
Write-Host " The user was logged into session #$session. They have been LOGGED OFF." -ForegroundColor Yellow
}
catch
{
if ($_.Exception.Message -match 'No user exists')
{
Write-Host " User is not logged in." -ForegroundColor Green
}
else
{
throw $_.Exception.Message
}
}
}
Write-Host "$server"
Invoke-Command -ComputerName $server -ScriptBlock $scriptBlock -ArgumentList $userAccount
$session = $null
}
Based on feedback, I modified the script so that it no longer uses Invoke-Command, but parses the active sessions by running quser <user> /SERVER:<server> as follows:
Write-Host "Will log specified user out of all servers..." -ForegroundColor Black -BackgroundColor Yellow
Write-Host " "
$servers = [System.Collections.ArrayList]::new()
foreach ($server in (Get-ADComputer -SearchBase "OU=Fictional,DC=Company,DC=net" -Filter "OperatingSystem -like 'Windows Server*'" -Properties Name | select -ExpandProperty name))
{
$servers.add($server) | Out-Null
}
$servers.Sort()
$userAccount = Read-Host "Enter account to scan for"
Write-Host ""
foreach ($server in $servers)
{
Write-Host "$server"
$ErrorActionPreference = 'Stop'
try
{
$session = ((quser $userAccount /SERVER:$server)[1] -split "\s+")[3]
logoff /SERVER:$server $session
Write-Host " The user was logged into session #$session. They have been LOGGED OFF." -ForegroundColor Yellow
}
catch
{
if ($_.Exception.Message -match 'No user exists')
{
Write-Host " User is not logged in." -ForegroundColor Green
}
}
}

Add ProxyAddresses to separate script

Goal: Append script to add three different SMTP addresses.
Script: https://thesysadminchannel.com/how-to-create-o365-mailboxes-hybrid-exchange/
Code Snippet:
Write-Host "Continuing will create the AD account and O365 Email." -ForegroundColor:Green
Write-Host
$Proceed = $null
$Proceed = Read-Host "Continue? (y/n)"
if ($Proceed -ieq 'y') {
Write-Host "Creating the O365 mailbox and AD Account."
New-RemoteMailbox -Name $fullname -FirstName $firstname -LastName $lastname -DisplayName
$fullname -SamAccountName $logonname -UserPrincipalName $logonname#$domain -PrimarySmtpAddress
$logonname#$domain -Password $password -OnPremisesOrganizationalUnit $OU -DomainController $Server
Write-Host "Done..."
Write-Host
Write-Host
Sleep 5
Write-Host "Adding Properties to the new user account."
Get-ADUser $logonname -Server $Server | Set-ADUser -Server $Server -Description $Description -
Office $Office -StreetAddress $StreetAddress -City $City -State $State -PostalCode $PostalCode -
Country $Country -Title $Title -Department $Department -Company $Company -Manager $Manager -
EmployeeID
$EmployeeID
Write-Host "Done..."
Write-Host
Write-Host
if ($MemberOf) {
Write-Host "Adding Membership Groups to the new user account."
Get-ADUser $logonname -Server $Server | Add-ADPrincipalGroupMembership -Server $Server -
MemberOf $MemberOf
Write-Host "Done..."
Write-Host
Write-Host
}
}
Get-PSSession | Remove-PSSession
What I'm trying to add are these three values:
SMTP:user#domain.com
smtp:user#domain.mail.onmicrosoft.com
smtp:user#domain.onmicrosoft.com
This is along the lines of what I've come up with:
Write-Host "Adding Properties to the new user account."
Get-ADUser $logonname -Server $Server | Set-ADUser -Server $Server -Description $Description
-Office $Office -StreetAddress $StreetAddress -City $City -State $State -PostalCode $PostalCode -
Country $Country -Title $Title -Department $Department -Company $Company -Manager $Manager -
EmployeeID $EmployeeID
Write-Host "Done..."
Write-Host
Write-Host
Write-Host “Setting up TCS E-mail Standard”
$userinfo.ProxyAddresses = "SMTP:" + ($FirstInitial.Add(1)) + ($userinfo.sn) +
"#DOMAIN.COM"
#$userinfo.ProxyAddresses += "smtp:" + ($userinfo.givenname) + "." + ($userinfo.sn) +
"#domain.mail.onmicrosoft.com"
$userinfo.ProxyAddresses += "smtp:" + ($FirstInitial.Remove(1)) + ($userinfo.sn) +
"#domain.onmicrosoft.com"
$userinfo.targetAddress = "SMTP:" + ($userinfo.sAMAccountName) +
"#domain.mail.onmicrosoft.com"
Write-Host "Done..."
Write-Host
Then I get this error:
You cannot call a method on a null-valued expression.
At C:\Users\Temp\CreateStudentEmail.ps1:233 char:21
+ ... $userinfo.ProxyAddresses = "SMTP:" + ($FirstInitial.Add(1 ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\Users\Temp\CreateStudentEmail.ps1:235 char:21
+ ... $userinfo.ProxyAddresses += "smtp:" + ($FirstInitial.Rem ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
The property 'targetAddress' cannot be found on this object. Verify that the property exists and can
be set.
At C:\Users\Temp\CreateStudentEmail.ps1:236 char:21
+ ... $userinfo.targetAddress = "SMTP:" + ($userinfo.sAMAccou ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
Just trying to find a way to incorporate the proxy address section so that I don't have to worry about extra steps.
I pulled the code from another PowerShell I used years ago, then tweaked it a bit, but it DOES actually input SMTP address fields into the AD character. It still throws errors though.
Here is what you need to do:
set-Aduser $samaccountname -Add #{ proxyAddresses = "SMTP:user#domain.com","smtp:user#domain.mail.onmicrosoft.com","smtp:user#domain.onmicrosoft.com" }

Powershell: Retrieving LogonDate in Active Directory

I've a list of computers, I'm checking if they are connected, if they aren't check with AD and "spit out" the one that aren't connecting for more than 3 months.
If it's connected then check if a services is installed.
Here's my code:
Import-Module ActiveDirectory
$datecutoff = (Get-Date).AddDays(-90)
Get-Content "C:\powershell\pc.txt" |
foreach {
if (-not (Test-Connection -comp $_ -quiet)){
Write-host "$_ is down" -ForegroundColor Red
$LastLog = Get-ADComputer -Identity $_ | Select LastLogonDate
if($LastLog -lt $datecutoff){
Write-host "$_ is offline for more than 3 months" -ForegroundColor Yellow
}
} Else {
$service = get-service -name masvc -ComputerName $_ -ErrorAction SilentlyContinue
if ($service ){
write-host "$_ Installed"
} else {
Write-host "$_ Not Installed"
}
}
}
When it finds a disconnected computer it gives me the following error:
Cannot compare "#{LastLogonDate=}" to "2020.04.16 18:49:19" because the objects are not the same type or the object "#{LastLogonDate=}" does not implement "IComparable".
At line:10 char:20
+ if($LastLog -lt $datecutoff){
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], ExtendedTypeSystemException
+ FullyQualifiedErrorId : PSObjectCompareTo
I know the error happens because my variable is saving wrong info, but I cannot find a way to only select the date in the AD.
Is there anyway to do this?
Thanks in advance.
You have a couple of issues. You'll need to request that LastLogonDate is returned with Get-ADComputer as its not by default. You'll need to use the dotted notation method of selecting property LastLogonDate from the $LastLog object so your compare works.
Import-Module ActiveDirectory
$datecutoff = (Get-Date).AddDays(-90)
Get-Content "C:\powershell\pc.txt" |
foreach {
if (-not (Test-Connection -comp $_ -Quiet)) {
Write-Host "$_ is down" -ForegroundColor Red
$LastLog = Get-ADComputer -Identity $_ -Properties LastLogonDate
if ($LastLog.LastLogonDate -lt $datecutoff) {
Write-Host "$_ is offline for more than 3 months" -ForegroundColor Yellow
}
} Else {
$service = Get-Service -Name masvc -ComputerName $_ -ErrorAction SilentlyContinue
if ($service ) {
Write-Host "$_ Installed"
} else {
Write-Host "$_ Not Installed"
}
}
}
Welcome to stackoverflow, please read https://stackoverflow.com/help/someone-answers
Side note. You can filter for aged computers like this Get-ADComputer -Filter 'LastLogonDate -lt $datecutoff'

Powershell - "Invalid assignment expression." error

I've got a couple things that i'm working on. One of them is sort of an import/export thing i found on here. but i'm getting the following error
PS C:\Users\joeblogs> C:\Users\joeblogs\Scripts\Copy user data.ps1 Invalid assignment expression. The left hand side of an assignment
operator needs to be something that can be assigned to like a variable
or a property. At C:\Users\delpillay\Documents\Scripts\Copy user
data.ps1:16 char:12
+ $username = <<<< gc env:userame
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : InvalidLeftHandSide
I don't know where to start and i'm not sure what to try...
Below is the code:
$destination = "E:\Users\%username%\Backup"
$folder = "Desktop",
#"Downloads",
"Favorites",
"My Documents",
#"Music",
#"Pictures",
#"Videos",
#"AppData\Local\Mozilla",
#"AppData\Local\Google",
#"AppData\Roaming\Mozilla"
######################################
$username = gc env:userame
$userprofile = gc env:userprofile
##$appData = gc env:localAPPDATA
###### Restore data section ######
if ([IO.Directory]::Exists($destination + "\" + $username + "\"))
{
$caption = "Choose Action";
$message = "A backup folder for $username already exists, would you like to restore the data to the local machine?";
$Yes = new-Object System.Management.Automation.Host.ChoiceDescription "&Yes","Yes";
$No = new-Object System.Management.Automation.Host.ChoiceDescription "&No","No";
$choices = [System.Management.Automation.Host.ChoiceDescription[]]($Yes,$No);
$answer = $host.ui.PromptForChoice($caption,$message,$choices,0)
if ($answer -eq 0)
{
write-host -ForegroundColor green "Restoring data to local machine for $username"
foreach ($f in $folder)
{
$currentLocalFolder = $userprofile + "\" + $f
$currentRemoteFolder = $destination + "\" + $username + "\" + $f
write-host -ForegroundColor cyan " $f..."
Copy-Item -ErrorAction silentlyContinue -recurse $currentRemoteFolder $userprofile
if ($f -eq "AppData\Local\Mozilla") { rename-item $currentLocalFolder "$currentLocalFolder.old" }
if ($f -eq "AppData\Roaming\Mozilla") { rename-item $currentLocalFolder "$currentLocalFolder.old" }
if ($f -eq "AppData\Local\Google") { rename-item $currentLocalFolder "$currentLocalFolder.old" }
}
rename-item "$destination\$username" "$destination\$username.restored"
write-host -ForegroundColor green "Restore Complete!"
}
else
{
write-host -ForegroundColor yellow "Aborting process"
exit
}
}
###### Backup Data section ########
#else
{
Write-Host -ForegroundColor green "Outlook is about to close, save any unsaved emails then press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Get-Process | Where { $_.Name -Eq "OUTLOOK" } | Kill
write-host -ForegroundColor green "Backing up data from local machine for $username"
foreach ($f in $folder)
{
$currentLocalFolder = $userprofile + "\" + $f
$currentRemoteFolder = $destination + "\" + $username + "\" + $f
$currentFolderSize = (Get-ChildItem -ErrorAction silentlyContinue $currentLocalFolder -Recurse -Force | Measure-Object -ErrorAction silentlyContinue -Property Length -Sum ).Sum / 1MB
$currentFolderSizeRounded = [System.Math]::Round($currentFolderSize)
write-host -ForegroundColor cyan " $f... ($currentFolderSizeRounded MB)"
Copy-Item -ErrorAction silentlyContinue -recurse $currentLocalFolder $currentRemoteFolder
}
$oldStylePST = [IO.Directory]::GetFiles($appData + "\Microsoft\Outlook", "*.pst")
foreach($pst in $oldStylePST)
{
if ((test-path -path ($destination + "\" + $username + "\Documents\Outlook Files\oldstyle")) -eq 0){new-item -type directory -path ($destination + "\" + $username + "\Documents\Outlook Files\oldstyle") | out-null}
write-host -ForegroundColor yellow " $pst..."
Copy-Item $pst ($destination + "\" + $username + "\Documents\Outlook Files\oldstyle")
}
write-host -ForegroundColor green "Backup complete!"
}
Few observations:
You are not commenting the Favourites and My Documents. If you want to use them then use comma separated directly.
Use this:
$destination = "E:\Users\%username%\Backup"
$folder = "Desktop","Favorites","My Documents"
#"Downloads",
#"Favorites",
#"My Documents",
#"Music",
#"Pictures",
#"Videos",
#"AppData\Local\Mozilla",
#"AppData\Local\Google",
#"AppData\Roaming\Mozilla"
You have missed the n in username:
$username = gc env:username
Donot use gc env:username. Instead directly access them like this below: Completely reframed:
$destination = "E:\Users\%username%\Backup"
$folder = "Desktop","Favorites","My Documents"
#"Downloads",
#"Favorites",
#"My Documents",
#"Music",
#"Pictures",
#"Videos",
#"AppData\Local\Mozilla",
#"AppData\Local\Google",
#"AppData\Roaming\Mozilla"
######################################
$username = $env:username
$userprofile = $env:userprofile
##$appData = gc env:localAPPDATA
These are the major things that have been fixed. Hope it helps you.

Missing Terminator and Missing Closing in PowerShell

I'm quite new to PowerShell, so apologies if this should be obvious to me.
I have the following PowerShell script;
$FieryChasm = {
Clear-Host
Write-Host "`n This script is for dropping user accounts from the Active Directory.`n`n`n It will :`n`n - Disable the AD account`n - Reset the AD password`n - Move the account to the Disabled OU`n - Set the expiry date on the account to yesterday's date`n - Remove all # groups`n- Hide the user from the email exchange`n`n`n`n Input the UserID`n"
$UserID = Read-Host -Prompt ' '
Clear-Host
$title = "`n You input '$UserID'"
$message = "`n`n Are you certain you want to process this UserID as a leaver?`n`n`n`n"
$yes = New-Object System.Management.Automation.Host.ChoiceDescription " &Yes", `
"Yes, process this userID as a leaver.`n"
$no = New-Object System.Management.Automation.Host.ChoiceDescription " &No", `
"No, take me back a step so I can input the UserID again.`n"
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$result = $host.ui.PromptForChoice($title, $message, $options, 1)
Clear-Host
switch ($result)
{
0 {
Write-Host "`n Disabling account...`n"
Disable-ADAccount -Identity $UserID
Write-Host "`n Moving to OU 'Disabled Accounts'...`n"
Move-ADObject -Identity $UserID -TargetPath "OU=Disabled Accounts,DC=my-company,DC=co,DC=uk"
Write-Host "`n Resetting password...`n"
$YouShallNotPass = (Get-Random -input "Da$her","Danc%r","Pr$ncer","V!xen","C$met","Cup!d","Donn%r","Bl!tzen") + (Get-Random -Minimum 1000 -Maximum 999999) + (Get-Random -input "Da$her","Danc%r","Pr$ncer","V!xen","C$met","Cup!d","Donn%r","Bl!tzen")
Set-ADAccountPassword -Reset -NewPassword $YouShallNotPass –Identity $UserID
Write-Host "`n Setting expiry date...`n"
$Yesterday = (Get-Date).AddDays(-1).ToString('dd/MM/yyyy')
Set-ADAccountExpiration $UserID -DateTime $Yesterday
Write-Host "`n Removing AD groups...`n"
Get-ADuser $UserID -property MemberOf | % {$_.MemberOf | Get-ADGroup | select Name | sort name} | clip
Get-ADGroup -Filter 'name -like "#*"' | Remove-ADGroup -identity $UserID
Write-Host "`n Hiding user from Exchange...`n"
Set-Mailbox -Identity DOMAIN\$UserID -HiddenFromAddressListsEnabled $true
Write-Host "`n Completed.`n`n $UserID has been processed as a leaver.`n`n`n Press any key to go back to the fiery chasm from whence you came ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}
1 {
Write-Host "`n You selected No.`n`n User was NOT set as a leaver.`n`n`n Press any key to go back to the fiery chasm from whence you came ..."
}
}
.$FieryChasm
}
and I'm getting the following errors...
At C:\Users\user\Desktop\LeaverScript.ps1:64 char:148
+ ... ce you came ..."
+ ~
The string is missing the terminator: ".
At C:\Users\user\Desktop\LeaverScript.ps1:34 char:8
+ 0 {
+ ~
Missing closing '}' in statement block.
At C:\Users\user\Desktop\LeaverScript.ps1:33 char:5
+ {
+ ~
Missing closing '}' in statement block.
At C:\Users\user\Desktop\LeaverScript.ps1:1 char:15
+ $FieryChasm = {
+ ~
Missing closing '}' in statement block.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
Could someone explain why, and give some tips on me not making the same mistake again?
Thank you.
Ah, got it!
On line 37, which was this;
Set-ADAccountPassword -Reset -NewPassword $YouShallNotPass -Identity $UserID
the dash before 'Identity' was an incorrect Unicode character. I replaced it and the errors went away :)