How to do looping FTP uploads and downloads with powershell - powershell

I have a project here that I am trying to automate. I have some load tests i need to run on a machine and during that time I need to have a constant in and out of FTP traffic. I have been trying to write a Powershell script to do it but have been coming up short. I can get the file to download every time but the upload always fails. I also need to make sure my looping mechanism is correct.
I need this to download and upload a single file until I tell it to stop. Here is the script.
$FTPServer = '172.20.2.124'
$FTPUsername = 'ftp'
$FTPPassword = 'ftpTransfers'
$FTPSecurePassword = ConvertTo-SecureString -String $FTPPassword -asPlainText -Force
$FTPCredential = New-Object System.Management.Automation.PSCredential($FTPUsername,$FTPSecurePassword)
$Path = '/'
$LocalPath = 'C:\Downloads'
#Open session
Set-FTPConnection -Credentials $FTPCredential -Server $FTPServer -Session MySession -UseBinary -KeepAlive
$Session = Get-FTPConnection -Session MySession
#download file
Get-FTPItem -Path /File1.mxf -LocalPath $LocalPath -Overwrite -Session $Session | out-null
#Upload the file
Add-FTPItem -LocalPath $LocalPath/File1.mxf -Path $Path -Overwrite -Session $Session | out-null
do {
response = Read-Host "repeat?"
}
while ($response -eq "Y")
This is the error I get whenever I try to do an upload with the script. I have tried to figure out how to close the stream but I have not had any luck.
Add-FTPItem : Exception calling "GetRequestStream" with "0"
argument(s): "Object reference not set to an instance of an object."
At C:\Powershell Scripts\FTPUploadandDownload.ps1:22 char:1
+ Add-FTPItem -LocalPath $LocalPath/File1.mxf -Path $Path -Overwrite -Session ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Add-FTPItem
Any help would be appreciated, I am fairly new to this level of powershell.

Related

Powershell v5.1 : Copy from share server to local folder on a remote PC

I have to manage around 10 PC running window 10.
I need to copy some software to those PC from share folder ( \company\folder or \MyPC\SharedFolder)
Manual remote is okay, however, doing copy item from share folder to 10 PC is take time and boring.
I found use Invoke-command and copy-item can help me to do it faster. However, I get error Access is denied
$usr = "UserName"
$pw = convertto-securestring -AsPlainText -Force -String Password
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist "$usr",$pw
For ($i=1; $i -lt 11; $i++)
{
$computerName=""
if($i -lt 10) {
$computerName="PC000$i"
} else {
$computerName="PC00$i"
}
Write-host "Copy on $computerName"
$session = New-PSSession -ComputerName "ServerA" -Credential $creds -Authentication Kerberos
Invoke-Command -Session $session -ScriptBlock { Copy-Item \\CompanyFolder\Shared\Sample.zip D:\Shared }
}
And below is error
Access is denied
+ CategoryInfo : PermissionDenied: (\\CompanyFolder\Shared\Sample.zip:String) [Copy-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.CopyItemCommand
+ PSComputerName : PC0007
Cannot find path '\\CompanyFolder\Shared\Sample.zip' because it does not exist.
+ CategoryInfo : ObjectNotFound: (\\CompanyFolder\Shared\Sample.zip:String) [Copy-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
+ PSComputerName : PC0007
I search around and find similar issues at here but it can not fix my issue. Do you have any idea?
At the end, I find the Solution, and it is workaround solutions for this problem.
Copy-Item -ToSession $session -Path \\CompanyFolder\Shared\Samples.zip -Destination D:\ -Recurse
More information can be found here

Getting below error on running PowerShell script

I am using one PowerShell script to download content (a zip file) from a website which requires credentials to get authenticated for the website. Also, have used proxy and proxy credentials since it is an authenticated proxy. I am getting an error which I have pasted below.
I have tried giving the proxy and proxy credentials but no luck.
I have bypassed the execution policy using Powershell -ExecutionPolicy Bypass.
When I try accessing the website from my browser then I am able to access the zip file.
Please find the code snippet below:
#Path to Save data
$tipath = "C:\Somepath"
$localpath = "\somefile.zip"
$timepath = "\Zip_file.txt"
$unzippath = "\Someotherpath"
$storepath = $tipath + $localpath
$remotefilepath = $tipath + $timepath
$unzipfolder = $tipath + $unzippath
# Create Folder If Not Exists #
$FolderToCreate = $tipath
if (!(Test-Path $FolderToCreate -PathType Container)) {
New-Item -ItemType Directory -Force -Path $FolderToCreate
}
#Downloading File #
$username = "username"
$password = "Password" | ConvertTo-SecureString -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($username, $password)
$secPasswd = "password123" | ConvertTo-SecureString -AsPlainText -Force
$wc = New-Object System.Net.WebClient
$wc.Credentials = New-Object System.Net.NetworkCredential("domain\user", $secPasswd)
# get remote file info
Invoke-WebRequest -Proxy "http://x.x.x.x:8080" -ProxyCredential $myCreds -Uri "https://somewebsite/checksum.txt" -OutFile $remotefilepath -Credential $cred
$remotefile = Get-Content -Path $remotefilepath
Write-Host Remote File Hash : $remotefile
# if the file exists already
if (Test-Path $storepath) {
# get local file info
$localfile = (Get-FileHash $storepath -Algorithm SHA256).Hash
Write-Host Local File Hash : $localfile
# if the remote file is newer than the local file
if ($remotefile -ne $localfile) {
Invoke-WebRequest -Proxy "http://x.x.x.x:8080" -ProxyCredential $myCreds -Uri "https://somewebsite/checksum.txt" -OutFile $remotefilepath -Credential $cred
Invoke-WebRequest -Proxy "http://x.x.x.x:8080" -ProxyCredential $myCreds -Uri "https://somewebsite/somezipfile.zip" -OutFile $storepath -Credential $cred
This code should check the hash and download directly download the zip file from the website and unzip it.
If it can download in the zip file then the later part I can troubleshoot.
PS C:\Users\Administrator\Desktop> powershell -ExecutionPolicy ByPass -File C:\Users\Administrator\Desktop\mypowershell.ps1
powershell : Invoke-WebRequest : .?? ??? ?????? ???????? ??? ????? ?????
At line:1 char:1
+ powershell -ExecutionPolicy ByPass -File C:\Users\Administrator\Desktop\mypowershell.p ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (Invoke-WebReque...??? ????? ?????:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
The site you are trying to access contains content that is prohibited.
If you believe the website you are trying to access does not contain any such
content, please click here.
Above is the error I am getting.

Unable to execute some commands in ps1 file from powershell

I have a windows service running on one of the Azure VMs.
So whenever a deployment has to be done, we copy the binaries manually. So now, I'm writing a script to do that.
Besically the binaries are in the form of a zip folder in MachineA. That zip folder is copied to MachineB (where windows service is running).After copying, the files are extracted and then zip folder is deleted. Then after the service is started.
To do this I have the below script.
#get session details
$UserName = "$IPAddress\$adminUsername"
$Password = ConvertTo-SecureString $adminPassword -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($UserName, $Password)
$s = New-PSSession -ComputerName $IPAddress -Credential $psCred
#stop the service
Invoke-Command -Session $s -ScriptBlock {Stop-Service -Name "ServiceName" -Force}
#delete existing binaries in destination machine
$tempDestPath = $destinationPath + "\*"
Invoke-Command -Session $s -ScriptBlock {param($tempDestPath)Remove-Item $tempDestPath -Recurse} -ArgumentList $tempDestPath
#copy binaries zip folder in destination machine
Copy-Item -Path $sourcePath -Destination $destinationPath -ToSession $s -Recurse
#extract zipfolder in destination machine
$zipFilePath = $destinationPath + "\" + $fileName
Invoke-Command -Session $s -ScriptBlock {param($zipFilePath,$destinationPath) Expand-Archive $zipFilePath -DestinationPath $destinationPath}-ArgumentList $zipFilePath,$destinationPath
#delete zipfolder in destination machine after extraction
Invoke-Command -Session $s -ScriptBlock {param($zipFilePath)Remove-Item –path $zipFilePath}-ArgumentList $zipFilePath
#start the service
Invoke-Command -Session $s -ScriptBlock {Start-Service -Name "ServiceName"}
This is working fine when I open Windows powershell in MachineA and execute these commands one by one.
But when I put the exact same commands in a ps1 file and execute that file, I'm getting the below error:
At C:\ScriptTest\test.ps1:13 char:95
+ ... -ScriptBlock {Start-Service -Name "ServiceName"}
+ ~~
The string is missing the terminator: ".
At C:\ScriptTest\test.ps1:11 char:42
+ Invoke-Command -Session $s -ScriptBlock {param($zipFilePath)Remov ...
+ ~
Missing closing '}' in statement block or type definition.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
Where am I missing this terminator. I'm not able to figure out. Any help is highly appreciated.
Turns out a - in one of the commands is wrong.
I have replaced this line
Invoke-Command -Session $s -ScriptBlock {param($zipFilePath)Remove-Item –path $zipFilePath}-ArgumentList $zipFilePath
with this line
Invoke-Command -Session $s -ScriptBlock {param($zipFilePath)Remove-Item -path $zipFilePath}-ArgumentList $zipFilePath
The hyphen in from of the path is slightly different.I was able to figure out from this answer

using PsFtp to upload a file to FTP Powershell

I've been wracking my brain on this issue and can't seem to fix it. I'm trying to upload a file to FTP using PSFTP.
The script I'm using:
#------------------------------------------------------
#local variables
$ftp_server = "SERVERNAME"
$ftp_path = "/FTPPATH/PATH"
$local = "C:\ftp\"
$local_in = Join-Path $local "In"
$local_out = Join-Path $local "Out"
$session = "my_ftp_session"
# set up credentials object
$username = "FFandP"
$password = Get-Content "$local_out\Credentials.txt" | ConvertTo-SecureString -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password
Set-FTPConnection -Server $ftp_server -Credentials $cred -Session $session -KeepAlive -confirm -UseBinary
Get-ChildItem -Path $local_out |
% {
$ftp_file = "$ftp_path/$($_.Name)" # determine item fullname
Add-FTPItem -Path $ftp_file -LocalPath $_.FullName -Session $session -
}
# -------------------------------------------------
And the error I receive:
Add-FTPItem : Exception calling "GetResponse" with "0" argument(s): "The remote server returned an error: (550) File
unavailable (e.g., file not found, no access)."
At line:22 char:1
+ Add-FTPItem -Path $ftp_file -LocalPath $_.FullName -Session $session
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Add-FTPItem
I've tried running the Add-FTPitem command by itself, but I get the same error.
I can upload to the FTP using FileZilla. I have also tried removing the variables and using hard-coded paths; I get the same error.
Any ideas?
The answer in #Josh's comment solved it for me. Run Add-FTPItem with the -Overwrite parameter.
Add-FTPItem -Path $remotePath -LocaPath $myPath -Overwrite
It took me a moment to figure out this problem, but here is my solution (I had the same problem).
When using Add-FTPItem the -Path parameter must not include the filename itself.
Add-FTPItem
-Path "ftp://SomeServer/SomeDir/"
-LocalPath "C:\SomeFilename.ext"
-Session $session
So in your example it should be:
Add-FTPItem -Path $ftp_path -LocalPath $_.FullName -Session $session
The filename will be added to the remote FTP path. In case you don't want to have the same name you must either rename the file locally first or remotely after.
Change block
Get-ChildItem -Path $local_out | %{ .... }
to one line
Get-ChildItem -Path $local_out | Add-FTPItem -Path $ftp_path

Powershell OnlyInJobError

Weird problem I saw today and I don't understand.
Is there a difference beetween running a script manually in the ISE or Pshell, and as a job?
If I run it manually the code doesn't throw an error - runs smoothly:
Get-ChildItem "\\SERVER\S$\ROOT\DIR" -Recurse | Where {$_.creationtime -lt (Get-Date).AddDays(-35)} | Remove-Item -Force -Include *.conf
But if I run it via Job and let the it export the $error to a txtfile this happens:
Are the rights of my running machine different to the rights of the scheduled job?
Get-ChildItem : Zugriff verweigert
In Zeile:81 Zeichen:1
+ Get-ChildItem "\\SERVER\S$\ROOT\DIR" -Recurse | Where
{$_.creati ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-ChildItem], UnauthorizedA
ccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.Pow
erShell.Commands.GetChildItemCommand
Zugriff verweigert = Access denied
Oh, totally forgot to tell about my windows rights.
Normally the Server I am connecting to is blocked for everybody - except for login with credentials ofc. But somehow my manual powershell script is able to delete and create files?
In "job-mode" it loses it's abilities.
Edit:
Same for the Test-Path commandlet. Manually it shows me true or false. Via job it throws an error.
EDIT - SAME PROBLEM COMPLETELY DIFFERENT Commandlets:
$username = "Administrator"
$password = cat C:\securestring.txt | convertto-securestring
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
New-PSDrive -Name Z -PSProvider FileSystem -Root \\Server\ROOT -Credential $cred -Persist
test-path 'Z:'
Remove-PSDrive -Name Z -PSProvider FileSystem
This works!
This does not:
$jobname = "Test5"
$JobTrigger = New-JobTrigger -Daily -At "00:18 PM"
$MyOptions = New-ScheduledJobOption -ContinueIfGoingOnBattery -HideInTaskScheduler -RunElevated
Register-ScheduledJob -name "$jobname" -scriptblock {
$username = "Administrator"
$password = cat C:\securestring.txt | convertto-securestring
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password
New-PSDrive -Name Z -PSProvider FileSystem -Root \\Server\ROOT -Credential $cred -Persist
test-path 'Z:'
Remove-PSDrive -Name Z -PSProvider FileSystem
} -trigger $JobTrigger –ScheduledJobOption $MyOptions
You probably have the job running under the SYSTEM account. Use the -Credential parameter to provide your account credentials (whatever account you're logged in with when you successfully run the command interactively).
BTW, Register-ScheduledJob uses the Task Scheduler. You can check the properties of the job in Task Scheduler to see what account it's configured to run as.
Well, it is not exactly an answere to my original question, but I was able to work around my problem by using the invoke-command and test-path from there and giving argument via the -arg.
Invoke-Command -ComputerName $FTPADRESS -ArgumentList $DIRECTORY -ScriptBlock {param ($DIR)
$check = Test-Path -Path "\\SERVER\ROOT\$DIR"
if ($check -ne $true) {New-Item -ItemType directory -Path "\\SERVER\ROOT\$DIR"}
}
Same works with the get-childitem.