Connect-SPOService Only When Necessary - powershell

I'm writing an administrative script for my SharePoint Online instance, and I'm trying to figure out how to prevent unnecessary connections to the SPO Service.
For example, I have 5 functions that each executive an administrative function. Each one obviously requires that I have successfully connected to the SPO Service before the rest can be run.
If I open the script with the intention of running more than one of the functions, I don't want to have to connect more than once.
Is there a way for me to check whether the connection is already established before I connect again?
Example Code:
function Admin-Function_A{
Write-Host "Connecting to SharePoint Online" -ForegroundColor White
try {
Connect-Function
Write-Host "Successfully connected to SharePoint Online." -ForegroundColor Green
} catch {
Write-Host "Connection to SharePoint Online failed." -ForegroundColor Red
}
}
function Connect-Function{
# Import the module
Import-Module Microsoft.Online.SharePoint.Powershell -DisableNameChecking
# Load credential
$credential = Get-Credential -Message "Enter admin account password" -UserName $adminUsername
Connect-SPOService -Url $adminUrl -Credential $credential
}

From the little i saw about SPOService connections, once you open it, it stays connected until you close it, using Disconnect-SPOService or when the session is closed.
You could add all your functions to the same script and call the Connect-Function before doing your work.
Did i understood it correctly?
Anything let me know

This is all in theory as I do not have access to SPO
function Test-SPOConnected {
[CmdletBinding()]
param()
Write-Verbose 'Testing Connection to SharePoint Online'
try {
# Choose a command that you know should return something if you are connected,
# preferably only a small amount of objects, or error otherwise
# Based off documentation I've choosen Get-SPOSite
# however there could be a better option
$results = Get-SPOSite -ErrorAction Stop
If ($results) {
Write-Verbose 'Successfully connected to SharePoint Online.'
$true
}
else {
Write-Warning 'Nothing returned. Not connected to SharePoint Online.'
$false
}
}
catch {
Write-Warning 'Connection to SharePoint Online failed.'
$false
}
}
Then in other code/functions you can check connection by using an if statement
if (!Test-SPOConnected) {
Connect-Function
}
# do SPO stuff

Related

How to correctly know a mailbox exists in exchange online or not using PowerShell

I have created a powershell script to connects to exchange online. The way it works is that, the script accepts a commandline argument as input(userprincipalname of a user), retrieves all mailboxes in exchange online then it checks if the user issued userprincipalname matches mailbox in exchange online. If the mailbox does not exist, i'm writing host, "mailbox does not exist", if the mailbox exists, i'm writing host "mailbox exists."
Problem
The problem is the scripts returns both if and else statement bodies. I expect to see if statement body returned only if the mailbox exists and else statement body returned only if the mailbox does not exist.
What I'm i doing wrong.
Below is the script.
param($m)
# Add your Global admin plain password here
$password_ = "mysecurepassword"
$password = ConvertTo-SecureString $password_ -AsPlainText -Force
# Add your global administrator login email here.
$upn = "bernardmwanza#bernardcomms.onmicrosoft.com"
# Automated login to azure ad
$AppCredential = New-Object System.Management.Automation.PSCredential($upn, $password)
Connect-ExchangeOnline -Credential $AppCredential
# Retrieving all mailboxes in exchange online
$usermbxs = (Get-EXOMailbox).UserPrincipalName
foreach($usermbx in $usermbxs){
# Check if the user given mailbox exists in exchangeonline
if($m -match $usermbx){
write-host $m "Mailbox does exists"
}else{
write-host "The mailbox does not exist"
}
}
The output i get when i pass upn of a user who has mailbox in exchange online
The output i get when i pass upn of a user who does not exist in exchange online
What am I doing wrong?
Ignoring the "put your global admin password in this script" requirement (you should be using modern authentication instead for better security - upgrade your PowerShell module for ExchangeOnline), your script is comparing each mailbox against the $m passed one at a time. Presuming your tenant has 6 accounts, it is checking each UserPrincipalName at a time, and advising if that UPN matches the $m param.
$usermbxs = (Get-EXOMailbox).UserPrincipalName
foreach($usermbx in $usermbxs){
# Check if the user given mailbox exists in exchangeonline
if($m -match $usermbx){
write-host $m "Mailbox does exists"
}else{
write-host "The mailbox does not exist"
}
}
You can simplify your code by removing the "foreach" check, and comparing using the -contains operator, which checks for the existence of a value in an collection, which would be the $usermbxs array. -contains is case insensitive - if (for whatever reason) you need case sensitive checking, use -ccontains.
$usermbxs = (Get-EXOMailbox).UserPrincipalName
if ($usermbxs -contains $m) {
Write-Host "$m mailbox exists"
}
else {
Write-Host "$m mailbox does not exist"
}

PowerShell - Connect and disconnect from SPO

The script connects to SPO and read from excel. At the end I close the local excel instance and disconnect from SPO. Usually I am running the script so this is really necessary to do it every run? connect ad disconnect. Maybe there is another way to do it? ask if there is a valid active connection?
I saw that if the credentials are wrong for example the script is still reading from the sheet maybe from the memory, how can I protect from this scenario?
#Connecting to SharePoint Online site
Write-host "Connecting to SharePoint Online"
Connect-PnPOnline -Url $SharePointSiteURL # -Credentials $PSCredentials
$ExcelObject = New-Object -ComObject Excel.Application
$ExcelWorkBook = $ExcelObject.Workbooks.Open($SharePointSiteURL)
$ExcelWorkSheet = $ExcelWorkBook.Sheets.Item("VIP List")
function QuitExcel {
# when done, quit Excel and remove the used COM objects from memory (important)
$ExcelWorkBook.Close()
$ExcelObject.Quit()
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($ExcelWorkSheet)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($ExcelWorkBook)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($ExcelObject)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
Disconnect-PnPOnline

Upload file to Sharepoint Online (Microsoft 365) using Powershell (Option 2 - Using Microsoft.SharePoint.PowerShell)

I'm trying to upload a file into a Sharepoint Online (M365) library subfolder, but it keeps giving me errors. I have tried many scripts. This post is about using Microsoft.SharePoint.PowerShell (I have posted questions about other scripts hoping someone can help me with any of them)
This is the code:ยด
if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null)
{
Write-Host "Adding PSSnapin"
Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}
$url="https://mydomanin.sharepoint.com/sites/mySite/"
Write-Host "Connecting to URL..."
$web=Get-SPWeb -Identity $url
if($web)
{
try
{
$list = $web.Lists.TryGetList("myLibrary/subfolder")
$files = Get-Item -Path "C:\MyFolder\myFile.csv" -Force
foreach ($file in $files)
{
$stream = $file.OpenRead()
$done= $list.RootFolder.Files.Add($file.Name, $stream, $true)
Write-Host $done.Name "Uploaded into the Site" -BackgroundColor Green
}
}
catch
{
$ErrorMessage = $_.Exception.Message
Write-Host $ErrorMessage
}
}
else
{
Write-Host "Site Doesn't exist"
}
$list.Update()
It fails from the beginning:
Add-PSSnapin : No snap-ins have been registered for Windows PowerShell version 5
I Have tried to use Install-Module:
Install-Module "Microsoft.Sharepoint.Powershell"
But it fails fo find it:
PackageManagement\Install-Package : No match was found for the specified search criteria and module name 'Microsoft.Sharepoint.Powershell'
I suppose the script will also require for credentials. If you can help me with this, I would be grateful, too
Thanks
Microsoft.Sharepoint.Powershell is for server side scripting only. It depends on a local farm on the same computer.
You should take a look at PnP PowerShell module which wraps client side APIs (CSOM).
That said, you have to understand the differences beetween SSOM (server side object model) and CSOM (client side object model). Two points in particular:
SSOM can do anything on a farm / CSOM only provide a subset of APIs, especially regarding administrative operations
CSOM is mainly a wrapper of HTTP requests. It works in a fashion where you first declare what you need, and then load it. PnP Powershell wraps a part of this complexity, but you shoud really read some docs about the CSOM behavior.
You should ends with something similar to
Import-Module PnP.Powershell
Connect-PnPOnline https://yourtenant.sharepoint.com/sites/yoursite -Interactive
Add-PnPFile c:\myfolder\myfiles.csv -Folder "YourLibrary"
Ref: Add-PnPFile

Basic Loop Help - Powershell

Complete Powershell Noobie here.
I have a .bat file that I would like to convert to Powershell.
Basically when run; it asks the user to enter their Active Directory credentials. Once validated; it starts a RSAT tool (example: dhcpmgmt.msc) as the elevated domain user.
However, if credentials are incorrect (if %ERRORLEVEL% EQU 5); it does a GOTO an echo "Incorrect username and password" and then loops back requesting the user to enter their credentials again.
When I use:
do
{
Start-Process -FilePath C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Credential (Get-Credential "$env:USERDNSDOMAIN\") -ArgumentList "C:\Windows\System32\dhcpmgmt.msc"
} until ($response -eq $null)
It works. But if I enter an incorrect password; the window closes.
I would like a notification information the user that the Username/Password is incorrect and then re-direct them to enter their credentials again. This would loop until either the user enters the correct credentials or simple clicks the cancel button.
Any help/guidance is highly appreciated. Thanks a bunch in advance!
You can run this in the while loop to keep asking for credentials until they are valid.
Take credentials
Run powershell with new creds
If fails, ask for new credentials. Break out of the loop if no.
while ($true)
{
$userCreds = Get-Credential "$env:USERDNSDOMAIN\"
try {
Start-Process powershell -Credential $userCreds -ArgumentList "C:\Windows\System32\dhcpmgmt.msc" -ErrorAction Stop
break
}
catch {
Write-Output "Invalid Credentials"
Write-Output "Enter new credentials?"
if ((Read-Host) -ne "Yes") { break }
}
}
This should do the needful.
Loop to Get and Check Credential
Try-Catch Credential Check
Raise Messagebox on Failed Credential
Exit script on Cancel.
$Credential=$null
while ($Credential -eq $null) {
$Credential = Get-Credential -Username "$env:USERDNSDOMAIN\" -message "Enter Admin Password"
try {
Start-Process -FilePath cmd.exe /c -Credential $Credential
}
catch {
$Credential=$null
IF (
$([System.Windows.MessageBox]::Show('Invalid UN/PW! ?','Credential Error','OKCancel','Error')
) -eq "Cancel") { EXIT}
}
}
### Your code to launch RSAT tools here:
We use a while loop.
While the credentials are NULL we p, getting the credentials, storing it as a secure string in a variable, then do a try-catch on the test of running a process, if that will try to get the credentials again, and we store the credentials in a variable as a secure string.
Initially, credentials are NULL so we ask for them.
Then we use Try to test the credentials by initiating a process as them.
If that fails we Catchit and 1st set credentials to NULL again, then we Raise a Windows Message Box to the user letting them know the credentials failed and checking if they would like to try again (OK) or Cancel.
If they respond with Cancel, there is no point in continuing the script so we just exit.
Otherwise, we just go ahead with our loop as planned

Using PowerShell to test an FTP connection

I have a PowerShell script that performs checks on some servers, for example Test-Connection for PING.
I wish to check one of the servers that has an FTP server by performing an "FTP Open" command. I don't need to log in or upload/download any files, just need to know if the FTP server responds or not.
Most of my research on the internet points to setting up credentials and importing proprietary modules to connect, perhaps uploading or downloading files, but I just need a simple method to open the connection and tell me either true or false if there is a responding server.
The server I am running this script from should have minimal software installed, but if it needs anything, preferably Microsoft and from their website.
Test-NetConnection is native Powershell and can be used to test simple connectivity on FTP Port 21:
Test-NetConnection -ComputerName ftp.contoso.com -Port 21
There's nothing like FTP command "open".
But maybe you mean to just test that the server listens on FTP port 21:
try
{
$client = New-Object System.Net.Sockets.TcpClient("ftp.example.com", 21)
$client.Close()
Write-Host "Connectivity OK."
}
catch
{
Write-Host "Connection failed: $($_.Exception.Message)"
}
If you want to test that the FTP server is behaving, without actually logging in, use FtpWebRequest with wrong credentials and check that you get back an appropriate error message.
try
{
$ftprequest = [System.Net.FtpWebRequest]::Create("ftp://ftp.example.com")
$ftprequest.Credentials = New-Object System.Net.NetworkCredential("wrong", "wrong")
$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::PrintWorkingDirectory
$ftprequest.GetResponse()
Write-Host "Unexpected success, but OK."
}
catch
{
if (($_.Exception.InnerException -ne $Null) -and
($_.Exception.InnerException.Response -ne $Null) -and
($_.Exception.InnerException.Response.StatusCode -eq
[System.Net.FtpStatusCode]::NotLoggedIn))
{
Write-Host "Connectivity OK."
}
else
{
Write-Host "Unexpected error: $($_.Exception.Message)"
}
}