Handling PSSessions in PS script - powershell

So my issue is that this script will run fine the first time but if I try running it again, the PSSessions are still active despite the
Get-PSSession | Remove-PSSession
lines. I've tried other methods like calling the computernames or instanceIDs but still won't close them. I'm not sure why the sessions aren't closing but it's the last thing that is keeping this script from working correctly.
Also this is made from the Microsoft article here: https://support.microsoft.com/en-us/help/2956029/migrationpermanentexception-cannot-find-a-recipient-that-has-mailbox-g
#Exchange session for EOL
function EOLExchange-Session {
Write-Host "Importing Exchange Scripting Module.....please wait a few seconds"
Write-Host "NOTE: Login with your username#aklsj.com credentials for Office 365" -ForegroundColor red -BackgroundColor white
pause
$counter = 0
while ($counter -lt 3) {
try {
$EOLPSSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell-liveid?DelegatedOrg=yalldontneedtoknow.com -Authentication Basic -AllowRedirection -Credential $UserCredential -ea stop
write-host "success"
$counter = 10
}
catch {
write-host "failed"
$counter++
if ($counter -ge 3) {
print "Too many attempts"
exit
}
}
}
Import-PSSession $EOLPSSession -AllowClobber -DisableNameChecking -CommandName Get-Mailbox, Set-Mailbox
$SessionID = $EOLPSSession.InstanceId
Write-Host "-------------Instance ID = " $PSSession.InstanceId
Write-Host "-------------Exchange-Session ID = " $SessionID
$SessionID
}
#Exchange session for On-Prem
function OPExchange-Session {
add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction Stop
#Write-Host "Importing Exchange Scripting Module.....please wait a few seconds"
#Connect to Exchange using Remote Shell <-- allows Exchange commands in this script
$OPPSSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://mindyabusiness.com/PowerShell/ -Authentication Kerberos -AllowRedirection
Import-PSSession $OPPSSession -AllowClobber -DisableNameChecking -CommandName Get-RemoteMailbox, Set-RemoteMailbox
$SessionID = $OPPSSession.InstanceId
#Write-Host "-------------Instance ID = "$PSSession.InstanceId
#Write-Host "-------------Exchange-Session ID = "$SessionID
$SessionID
}
Function End-Script($SessionID, $f_runtype) {
Write-Host "Log File: $LogFile"
Write-Host ""
if ($SessionID -ne $null) {
$s = Get-PSSession -InstanceId $SessionID
Remove-PSSession -Session $s
}
if((Get-Content $LogFile) -eq $Null) {
Remove-Item $LogFile
} else {
#Set Log File to Read Only
Set-ItemProperty -Path $LogFile -Name IsReadOnly -Value $true
}
Write-Host "Script Complete" -ForegroundColor Gray
Read-Host "Press enter to close the script"
exit
}
Function SyncADConnect {
$s = New-PSSession -computerName server
Invoke-Command -Session $s -Scriptblock {Start-ADSyncSyncCycle -PolicyType Delta}
Remove-PSSession $s
End-Script
}
#Removes any PSSessions before running
Get-PSSession | Remove-PSSession
#Find current path script is executing from
$ScriptPath = $PSScriptRoot = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition
$ScriptPath = $ScriptPath + "\"
#Setup Log File
$LogPath = $ScriptPath + "Logs\"
$LogFilename = "SetExchangeGUID_$((Get-Date).ToString('yyyy-MM-dd_hh-mm-ss')).log"
$LogFile = $LogPath + $LogFilename
New-Item -Path "$LogFile" -ItemType File
Write-Host "Checking Domain Admin Permissions...."
$CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$WindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($CurrentUser)
#Make sure user is a domain admin
if(!($WindowsPrincipal.IsInRole("Domain Admins")))
{
Write-Host "You must be logged in as a Domain Admin to run this script" -ForegroundColor Red
End-Script
} else {
Write-Host "Domain Admin permissions detected, please wait....."
}
$today = Get-Date -Format yyyy-MM-dd_hh-mm-ss
$msg = "Run on " + $today + ". Run by " + $env:username
$msg | out-file $LogFile -Append
#Clear-Host
$CloudMailbox = Read-Host "Enter the identity of the cloud mailbox"
Write-Host "Connecting to EOL"
EOLExchange-Session
$SessionID = $EOLPSSession.InstanceId
Write-Host $SessionID
#Fetches EOL ExchangeGUID and trims to just the GUID
$TempCloudGUID = Get-Mailbox $CloudMailbox | Format-List ExchangeGUID | Out-String
$CloudGUID = $TempOnPremGUID.Substring(19).Trim()
#Clear-Host
Write-Host "The EOL GUID is $CloudGUID"
pause
Write-Host "Connecting to On-Prem"
OPExchange-Session
#Fetches ExchangeGUID and trims to just the GUID
$TempOnPremGUID = Get-RemoteMailbox $CloudMailbox | Format-List ExchangeGUID | Out-String
$OnPremGUID = $TempOnPremGUID.Substring(19).Trim()
#Checks if GUID is all zeros
#$ZeroGUID = "00000000-0000-0000-0000-000000000000"
#if ($OnPremGUID -eq $ZeroGUID) {
#Write-Host "The value isn't stamped on the on-premises remote mailbox. Ending script"
#End-Script
#} else {
#Write-Host $CloudMailbox "On-prem GUID is" $OnPremGUID
#}
#Clear-Host
Write-Host "EOL GUID is $CloudGUID"
Write-Host "On-prem GUID is $OnPremGUID"
if ($CloudGUID -eq $OnPremGUID) {
Write-Host "Exchange GUIDs already match, ending script."
End-Script
} else {
$confirmation = Read-Host "The GUIDs are different, would you like to set the EOL GUID to be the same as On-Prem?"
if ($confirmation -eq 'y') {
Set-RemoteMailbox $CloudMailbox -ExchangeGUID $CloudGUID
$msg = "$CloudMailbox has been changed to use $CloudGUID in EOL and On-Prem"
$msg | out-file $LogFile -Append
Write-Host "GUID for $CloudMailbox has been set. Syncing ADSyncClcye and ending script"
Get-PSSession | Remove-PSSession
SyncADConnect
}
else {End-Script}
}

No reason to do this from scratch. There are already tools/addons to do this for you.
See these:
Connect to all Office 365 Services PowerShell (Supports MFA too)
Using our All-in-One PowerShell script, you can connect to all Office
365 Services using a single cmdlet. It supports both MFA and non-MFA
account -Exchange Online -Azure AD -SharePoint Online -Skype for
Business Online -Security & Compliance Center -Teams
https://gallery.technet.microsoft.com/PowerShell-Script-to-4081ec0f/file/225256/1/ConnectO365Services.ps1
https://blog.rmilne.ca/2015/02/02/using-exchange-powershell-remoting-with-integrated-scripting-environmentise
https://jaapwesselius.com/2013/07/21/ise-remote-powershell-and-exchange-2013
Adding Exchange Shell items to PowerShell ISE
# in the Microsoft.PowerShellISE_profile.ps1 file, add the following contents:
$psISE.CurrentPowerShellTab.AddOnsMenu.SubMenus.Add(
"Connect to Exchange # Contoso", {
$ExSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri 'http://exserver.contoso.com/PowerShell/' -Authentication Kerberos
Import-PSSession $ExSession
},
"Control+Alt+1"
)
$psISE.CurrentPowerShellTab.AddOnsMenu.SubMenus.Add(
"Connect to Exchange On-Premise", {
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
. $env:ExchangeInstallPath\bin\RemoteExchange.ps1
Connect-ExchangeServer –auto
},
"Control+Alt+2"
)
$psISE.CurrentPowerShellTab.AddOnsMenu.SubMenus.Add(
"Connect to Exchange Online", {
$o365Cred = Get-Credential
$o365Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri 'https://ps.outlook.com/powershell/' -Credential $o365Cred -Authentication Basic -AllowRedirection
Import-PSSession $o365Session
},
"Control+Alt+3"
)
As for this...
Get-PSSession | Remove-PSSession
... though it should work, I've often had this be a bit quirky, with forcing a loop.
Get-PSSession | ForEach {Remove-PSSession -Id $PSItem.Id}

Related

how can i add credentials in New-PSSession? everytime i face the login-prompt (powershell)

im trying to schedule a powershellscript which changes the calender permissions of users within the group "kalender_rechten" to limited details. however im facing the login prompt on new-pssesion. how can i add the $credObject into New-PSSession, without the loginprompt?
#Start transcript
Start-Transcript -Path C:\temp\Set-DefCalPermissions.log -Append
#get credentials to authenticate
$username = "test.onmicrosoft.com"
$pwdTxt = Get-Content "C:\test\test\pw.txt"
$securePwd = $pwdTxt | ConvertTo-SecureString
$credObject = New-Object System.Management.Automation.PSCredential -ArgumentList
$username, $securePwd
#authenticate admin office365
get-credential $credObject
#create session Office365
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri
https://outlook.office365.com/powershell-liveid/ -Credential $credObject -Authentication
Basic –AllowRedirection
$credObject
#import Office365/exchange commands to PowerShell console
Import-PSSession $Session
# Get all user mailboxes
$Users = Get-DistributionGroupMember -Identity "Kalender_rechten"
# Permissions
$Permission = "LimitedDetails"
# Calendar name languages
$FolderCalendars = #("Agenda", "Calendar", "Calendrier", "Kalender")
# Loop through each user
foreach ($User in $Users) {
# Get calendar in every user mailbox
$Calendars = (Get-MailboxFolderStatistics $User.Identity -FolderScope Calendar)
# Loop through each user calendar
foreach ($Calendar in $Calendars) {
$CalendarName = $Kalender_rechten
# Check if calendar exist
if ($FolderCalendars -Contains $CalendarName) {
$Cal = $User.Identity.ToString() + ":\$CalendarName"
$CurrentMailFolderPermission = Get-MailboxFolderPermission -Identity $Cal - User Default
# Set calendar permission / Remove -WhatIf parameter after testing
Set-MailboxFolderPermission -Identity $Cal -User Default -AccessRights
$Permission -WarningAction:SilentlyContinue -WhatIf
# Write output
if ($CurrentMailFolderPermission.AccessRights -eq "$Permission") {
Write-Host $User.Identity already has the permission
$CurrentMailFolderPermission.AccessRights -ForegroundColor Yellow
}
else {
Write-Host $User.Identity added permissions $Permission -ForegroundColor Green
}
}
}
}
Stop-Transcript

Connect-MsolService - providing credentials without exposing password in script

I wish to run the below PowerShell script as a scheduled task to pull provisioning logs from Azure AD. However, I do not wish to embed the password. I appreciate this is not a problem specific to PowerShell or Microsoft Online. What technique can I use to not have the password stored as clear text? Thanks
Script credits go to: Pawel Janowicz
$AzureUsername = 'log.reader#tenant.net'
$Password = "xxxxxx"
$SecureString = ConvertTo-SecureString -AsPlainText $Password -Force
$SecuredCreds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AzureUsername,$SecureString
$OutputCSV = "$Env:USERPROFILE\desktop\DirSyncProvisioningErrors_$(Get-Date -Format "yyyyMMdd").csv"
###### Connecting ############################################################################################################
Try{
[void] (Connect-MsolService -Credential $SecuredCreds)
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $SecuredCreds -Authentication Basic -AllowRedirection
[void] (Import-PSSession $Session -DisableNameChecking)
}
Catch{
$_.Exception.Message
Read-Host 'Press enter to close the window'
Remove-PSSession $Session
Exit
}
###### Getting errors ########################################################################################################
If(Get-MsolHasObjectsWithDirSyncProvisioningErrors){
Try{
$Errors = Get-MsolDirSyncProvisioningError -All | select DisplayName,ObjectID,ObjectType,ProvisioningErrors
$Results = Foreach ($i in $Errors){
$AllErrors = $i.ProvisioningErrors
$AllErrors | %{
$ErrorItem = $_
Get-AzureADObjectByObjectId -ObjectIds $i.objectid | Foreach{
New-Object PSObject -Property ([ordered]#{
'Displayname' = $i.displayname
'ObjectType' = $i.ObjectType
'Attribute' = $ErrorItem.propertyname
'Conflicting value' = $ErrorItem.propertyvalue
})
}
}
}
}
Catch{
$_.Exception.Message
Read-Host 'Press enter to close the window'
Remove-PSSession $Session
Exit
}
}
###### Results ###############################################################################################################
If($Results){
$Results | Format-Table -AutoSize
#Exporting CSV
$Results | Export-CSV $OutputCSV -NoTypeInformation -Force
}
Remove-PSSession $Session
Thank You Theo for providing your suggestion as a comment. Making this as answer to help other community member.
I have executed the command and getting a display to enter the password rather than it was manually provided in script itself.
$SecuredCreds = Get-Credential -UserName 'log.reader#tenant.net' -Message "Please enter credentials"
$OutputCSV = "$Env:USERPROFILE\desktop\DirSyncProvisioningErrors_$(Get-Date -Format "yyyyMMdd").csv"
###### Connecting ############################################################################################################
Try{
[void] (Connect-MsolService -Credential $SecuredCreds)
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $SecuredCreds -Authentication Basic -AllowRedirection
[void] (Import-PSSession $Session -DisableNameChecking)
}
Catch{
$_.Exception.Message
Read-Host 'Press enter to close the window'
Remove-PSSession $Session
Exit
}
###### Getting errors ########################################################################################################
If(Get-MsolHasObjectsWithDirSyncProvisioningErrors){
Try{
$Errors = Get-MsolDirSyncProvisioningError -All | select DisplayName,ObjectID,ObjectType,ProvisioningErrors
$Results = Foreach ($i in $Errors){
$AllErrors = $i.ProvisioningErrors
$AllErrors | %{
$ErrorItem = $_
Get-AzureADObjectByObjectId -ObjectIds $i.objectid | Foreach{
New-Object PSObject -Property ([ordered]#{
'Displayname' = $i.displayname
'ObjectType' = $i.ObjectType
'Attribute' = $ErrorItem.propertyname
'Conflicting value' = $ErrorItem.propertyvalue
})
}
}
}
}
Catch{
$_.Exception.Message
Read-Host 'Press enter to close the window'
Remove-PSSession $Session
Exit
}
}
###### Results ###############################################################################################################
If($Results){
$Results | Format-Table -AutoSize
#Exporting CSV
$Results | Export-CSV $OutputCSV -NoTypeInformation -Force
}
Remove-PSSession $Session

Read and write from a remote PC to a shared network with powershell

I am trying to read a file from a remote machine, and then what I read, write it in a shared folder in network. This is my code.
Write-Host "Remote copy a file"
$username = 'Usuario'
$password = 'Password'
$myfile = [System.IO.File]::ReadAllBytes("C:\user.txt") ;
$Escribir={[System.IO.File]::WriteAllBytes("\\192.x.x.x\foreach\54.txt", $args)} ;
$pw = ConvertTo-SecureString $password -AsPlainText -Force
$cred = New-Object Management.Automation.PSCredential ($username, $pw)
$servers = Get-Content C:\Users\Agent\Desktop\pcs
foreach($server in $servers) {
$s = New-PSSession -computerName $server -credential $cred
Write-Host "PC name: $server ..." -ForegroundColor GREEN -Background BLACK
$Job = Invoke-Command -Session $s -ArgumentList $myfile -ScriptBlock $Escribir -AsJob
$Null = Wait-Job -Job $Job
Write-Host "Completed"
Remove-PSSession -Session $s
}
When I run the .ps1 file, I get the following error.

Run Remote Command via Powershell

I'm trying to invoke discrete CLI commands on a series of remote systems via a script, and I can't get any PowerShell commands to accept them. Rather than try to explain the specifics of the issue, I'll provide some pseudocode of what I'm trying to do below.
Please note that this is just a simple example. Using the stop-service command is not an option. These are explicit commands used via CLI with via the Splunk program that I need to run in this order.
In short, I just can not figure out how to tell PowerShell to run a CLI command verbatim on a remote machine.
foreach ($server in $list)
cd C:\Program Files\SplunkUniversalForwarder\bin
splunk stop
splunk clone-prep-clear-config
splunk start
Bunch of ways you can do this. Using WMI c/o Powershell:
Starting,Stopping and Restarting Remote Services with PowerShell
You can also use Windows remoting, but I'd start here.
You could try...
Foreach($server in $list)
{
Invoke-command -computername $server -scripblock {
$splunkpath = 'c:\program files\splunkuniversalforwarder\bin\splunk.exe'
Start-process -filepath $splunkpath -argumentlist 'stop' -wait -nonewwindow
Start-process -filepath $splunkpath -argumentlist 'clone-prep-clear-config' -wait -nonewwindow
Start-process -filepath $splunkpath -argumentlist 'start' -wait -nonewwindow
}
}
Note: you may need to remove the -wait and/or -nonewwindow from the commands depending on how your process behaves.
There are also output redirection parameters checkout the docs below for more.
Invoke-command
Start-process
I literally just did this this morning. This is the main part I came up with.
foreach($server in $servers){
Write-Host "From " -nonewline; Write-Host "$server" -ForegroundColor Yellow
Invoke-Command -ComputerName $server -ScriptBlock { C:\SplunkUniversalForwarder\bin\splunk.exe stop } -Credential $cred
Invoke-Command -ComputerName $server -ScriptBlock { C:\SplunkUniversalForwarder\bin\splunk.exe clone-prep-clear-config } -Credential $cred
Invoke-Command -ComputerName $server -ScriptBlock { C:\SplunkUniversalForwarder\bin\splunk.exe start } -Credential $cred
}
my full code is below:
#Author: Christopher Boillot
#Clear config of Splunk Forwarder
[CmdletBinding()]
Param ([Parameter(Mandatory=$False,Position=0)]
[String[]]$servers = (Get-Content C:\ClearConfig.txt))
Set-Location $PSScriptRoot
#User login
$User = "user.txt"
$FileExists = Test-Path $User
If ($FileExists -eq $False) {
Write-Host "Enter your user name. This will be saved as $User"
read-host | out-file $User
}
$Pass = "securepass.txt"
$FileExists = Test-Path $Pass
If ($FileExists -eq $False) {
Write-Host "Enter your password. This will be saved as an encrypted sting as $Pass"
read-host -assecurestring | convertfrom-securestring | out-file $Pass
}
$username = cat $User
$password = cat $Pass | convertto-securestring
$cred = new-object -typename System.Management.Automation.PSCredential `
-argumentlist $username, $password
#go through each server in list
foreach($server in $servers){
Write-Host "From " -nonewline; Write-Host "$server" -ForegroundColor Yellow
Invoke-Command -ComputerName $server -ScriptBlock { C:\SplunkUniversalForwarder\bin\splunk.exe stop } -Credential $cred
Invoke-Command -ComputerName $server -ScriptBlock { C:\SplunkUniversalForwarder\bin\splunk.exe clone-prep-clear-config } -Credential $cred
Invoke-Command -ComputerName $server -ScriptBlock { C:\SplunkUniversalForwarder\bin\splunk.exe start } -Credential $cred
}

PowerShell coding in O365

I have a question regarding sample code. I am running some scripts in O365, "Running script" as below. I want to do when a PSSession enters a "Broken" state, it will pause the script, and remove broken session (Remove-PSSession ) and re-connecting PSSession (following "Re-connecting code" as below), then restart the script. I tried to write this but but I am no familiar with coding.... Can anyone help?.....
(Server 2008 R2 SP1/PowerShell)
Any help would be appriciated.
Running Script-----
Import-Csv D:\work\users.csv | ForEach {
Grant-CsConferencingPolicy $_.UserPrincipalName -PolicyName BposSAllModalityNoFT}
Import-Csv D:\work\users.csv | ForEach {
Grant-CsExternalAccessPolicy $_.UserPrincipalName -PolicyName FederationOnly}
Re-connecting code-------
$sfboSession = New-CsOnlineSession -Credential $credential
Import-Pssession $sfboSession -AllowClobber
`Import-csv D:\IDMaster\Tools\SkypeTool\users.txt | foreach {
Do {
Grant-CsConferencingPolicy $_.UserPrincipalName -PolicyName BposSAllModalityNoFT
if ($? -ne "True")
{
get-pssession | remove-pssession
$sfboSession = New-CsOnlineSession -credential $credential
Import-PSSession $sfboSession -AllowClobber }
} # End of 'Do'
Until ($? -eq "True")
Write-Host $_.UserPrincipalName "BposSAllModalityNoFT"
Do {
Grant-CsExternalAccessPolicy $_.UserPrincipalName -PolicyName FederationAndPICDefault
if ($? -ne "True")
{
get-pssession | remove-pssession
$sfboSession = New-CsOnlineSession -credential $credential
Import-PSSession $sfboSession -AllowClobber }
} # End of 'Do'
Until ($? -eq "True")
Write-Host $_.UserPrincipalName "FederationAndPICDefault"
$string = $_.UserPrincipalName + " " + "BposSAllModalityNoFT" + " " + "FederationAndPICDefault"
Write-Output $string | Out-file D:\IDMaster\Tools\SkypeTool\Modify_Log.csv -Append -Encoding default
}`