Using PowerShell to test an FTP connection - powershell

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)"
}
}

Related

How can I check internet connection with PowerShell

I have a PowerShell script that need to check if there is internet connectivity before running the rest of the script. For the example using Test-Connection
if (Test-Connection example.com) {
Write-Host "Connection available"
# do-other things
} else {
Write-Host "No internet connection"
Exit
}
The problem with this approach is if there is no connection it gives this error message:
Testing connection to computer 'example.com' failed: Cannot resolve the | target name. and then the actual message follows No internet connection but the idea was to have it move to the else clause not giving that error message when there no connection.
For example when there is no internet connection the error message No internet connection is printed, that's it, nothing else. How can I achieve this.
Test-Connection doesn't seem to have something that we can catch with try-catch, but there is a -Quiet parameter that may do what you want. It translates the output to a simple boolean.
Testing without and with an internet connection:
Per #mukunda's answer, Test-Connection has a -Quiet switch that ignores errors and returns a boolean result - see the documentation for Test-Connection for the details.
Note there's some perhaps unexpected behaviour if you're testing multiple sites in a single call:
If any ping to a given target succeeds, $True is returned
In other words, even if some sites fail you'd still get $true returned.
Note that in general you can also suppress errors in cmdlets with -ErrorAction "SilentlyContinue", and check the return value after:
$result = Test-Connection -Ping "www.example.org" -ErrorAction "SilentlyContinue";
if ($null -eq $result)
{
Write-Host "No internet connection"
Exit
}
else
{
Write-Host "Connection available"
# do-other things
}

Connect-SPOService Only When Necessary

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

Service cannot be started due to the following error: Cannot open service on computer '.'

I'm trying to Start a service using Powershell and using the code below
function CheckServiceStatus {
param($winupdate)
$getservice = Get-Service -Name $winupdate
if($getservice.Status -ne $running){
stop-service $winupdate
Start-Service $winupdate
Write-output "Starting" $winupdate "service"|out-file "C:\Users\Mani\Desktop\abc.txt"
Add-Content C:\Users\Mani\Desktop\abc.txt $getservice.Status
}
}
Read-Host -Prompt "Press Enter to exit"
#Variables
$winupdate = 'vsoagent.192.Shalem'
$running = 'Running'
CheckServiceStatus $winupdate
I got the following error:
Service 'ABC' cannot be stopped due to the following error: Cannot
open ABC service on computer '.'
I found some link here on our forum but couldn't resolve. Please suggest
If you want to start/stop/etc services, you need elevated privileges (run as Admin). You can still get information about the service, but that's it. If you want to include a more verbose error, include this:
$isadmin = [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")
if($isadmin){
Write-Error "You need elevated privileges to run this script"
exit(1)
}
...
Rest of your code
Or even better, if you're running Powershell 4.0 or higher (You can get it by checking $PSVersionTable), you can include
#Requires -RunAsAdministrator
At the top of your file, and you won't be able to run it without admin privilages.
I had this issue while running the command on PowerShell ISE. All I did was start the PowerShell ISE as an administrator.
Look into Event Viewer and find more details. In my case, I have found relevant info in Administrative Events, then Service Control Manager. The error was related to insufficient privileges given for the account. The service was creating a new file and this task failed. Of course, your error's details are probabably different, but that is the tip.

Read encrypted connection string in Machine.config from Powershell

Is it possible to read the encrypted connection string in Machine.config from Powershell script?
Due to security reason, we are trying to move the hardcoded connection string from PowerShell script to Machine.config
Update: Powershell script is supposed to read the connection string from Machine.config (Encrypted through aspnet_regiis) and connect to the DB.
I'm not sure where PowerShell figures into your question. If you use a built-in command like aspnet_regiis.exe to encrypt a configuration section, then your IIS site is unaware that the section is encrypted.
I'm not sure how putting something in machine.config is going to make an app more secure since anything that reads it transparently would work for any app on that machine.
The way .net configs work is you have an some.exe and it has a some.exe.config file. When you deploy some.exe you can (should?) include a step to encrypt sensitive sections. The app would still just read the data, unaware that it's been encrypted.
But again that is the app, not powershell that's reading the encrypted value.
Here's a section of a script I use that encrypts/decrypts sections. Use carefully since data encrypted can only be decrypted on the same machine (and likely the same OS). YMMV
$appConfig = "your.exe"
$sectionName = "appSettings"
$dataProtectionProvider = "DataProtectionConfigurationProvider"
if (-not (Test-Path $path) ) { throw "Unable to find $($appConfig) $($path)" }
$configuration = [System.Configuration.ConfigurationManager]::OpenExeConfiguration($path)
$section = $configuration.GetSection($sectionName)
if (-not $section.SectionInformation.IsProtected) {
$section.SectionInformation.ProtectSection($dataProtectionProvider)
$section.SectionInformation.ForceSave = $true
$configuration.Save([System.Configuration.ConfigurationSaveMode]::Full)
Write-Information -Message "$($sectionName) in $($appConfig) has been protected from casual users"
}
else {
Write-Information -Message "$($sectionName) in $($appConfig) is already protected"
$section.SectionInformation.UnprotectSection()
$section.SectionInformation.ForceSave = $true
$configuration.Save([System.Configuration.ConfigurationSaveMode]::Full)
Write-Information -Message "$($sectionName) in $($appConfig) protection removed"
}
This is a snippet of a full script to encrypt/decrypt config sections.
The previous answer was largely correct, I did have to make a couple minor changes to get it working on my system with respects to the 'path' and 'appConfig' variables. For this script to work I am placing the powershell script in the same folder as the exe and config file I'm working with.
#This script will encrypt/decrypt the section specified in the sectionName variable of a .net configuration file
#using the DataProtectionConfigurationProvider method of encryption/decryption.
#Place this file in the same folder as the executable/config file and run it, be sure to update the 'appConfig'
#and 'sectionName' variables accordingly.
$path = Get-Location
$appConfig = "ServionDataRecovery.exe"
$sectionName = "connectionStrings"
$dataProtectionProvider = "DataProtectionConfigurationProvider"
if (-not (Test-Path $appConfig) ) { throw "Unable to find $($appConfig) $($path)" }
$configuration = [System.Configuration.ConfigurationManager]::OpenExeConfiguration("$path\$appConfig")
$section = $configuration.GetSection($sectionName)
if (-not $section.SectionInformation.IsProtected) {
$section.SectionInformation.ProtectSection($dataProtectionProvider)
$section.SectionInformation.ForceSave = $true
$configuration.Save([System.Configuration.ConfigurationSaveMode]::Full)
Write-Host "$($sectionName) in $($appConfig) has been protected from casual users"
}
else {
Write-Host "$($sectionName) in $($appConfig) is already protected"
$section.SectionInformation.UnprotectSection()
$section.SectionInformation.ForceSave = $true
$configuration.Save([System.Configuration.ConfigurationSaveMode]::Full)
Write-Host "$($sectionName) in $($appConfig) protection removed"
}

Trying to create process on remote PC from network share

I have this Powershell:
Try
{
#Start the installer remotely
$process = ([WMICLASS]"\\$comp\ROOT\CIMV2:Win32_Process").Create($InstallString)
if ( $process.ReturnValue -eq 0 )
{
$logstr = $comp + ": spawned process " + $process.ProcessId
Write-Host -ForegroundColor GREEN $logstr
}
else
{
Write-Host -ForegroundColor RED "${comp}: failed to create process ${InstallString}"
Continue
}
}
Catch
{
Write-Host -ForegroundColor RED "${comp}: error: $_.Exception.Message"
Continue
}
Where $comp is a valid PC name and InstallString is \\SERVERNAME\ShareFolder\setup.exe.
Within that ShareFolder is an installer and its files. I expect I can run the setup like this to remote install, but it is not working. It's falling into the else:
COMPUTERNAME: failed to create process \\SERVERNAME\ShareFolder\setup.exe
What am I missing? I can access this path outside Powershell.
This works on a local path. Do I need some special syntax in Powershell to point to this share?
This code works if the exe (well, a different installer) is located on COMPUTERNAME and the code is still executed remotely.
It could be a permission problem. According to this link: Creating Processes Remotely
A process created remotely can run under any account if the account has the Execute Method and Remote Enable permissions for root\cimv2. The Execute Method and Remote Enable permissions are set in WMI Control in the Control Panel.