Call multiple commands from powershell e.g psftp - powershell

I am trying to SFTP a file from powershell using psftp.exe (putty). I can run single command such as open but I need to change the default directory and then put the file. The following code takes me to psftp but ignores lines from cd .. to bye. I guess I can run a batch file which has the sftp commands but if possible I want to accomplish using powershell.
$file = "C:\Source\asdf.csv"
$user = "user"
$pass = "pass"
$hst = "host"
$path="C:\ProgramFiles\psftp.exe"
$cmd = #"
-pw $pass $user#$hst
cd ..
cd upload
put $file
bye
"#
invoke-expression "$path $cmd"

Give this a try:
$file = "C:\Source\asdf.csv"
$user = "user"
$pass = "pass"
$hst = "host"
$path="C:\ProgramFiles\psftp.exe"
$cmd = #(
"cd ..",
"cd upload",
"put $file",
"bye"
)
$cmd | & $path -pw $pass "$user#$hst"
In answer to the questions in the comment:
The first part, "$cmd |" pipes the contents of $cmd to the command that follows. Since it is an external program (as opposed to a cmdlet or function) it will send the contents of $cmd to stdin of the external program.
The "& $path" part says to treat the contents of $path as a command or program name and execute it.
The rest of the line is passed to the external program as command line arguments.

Related

Accessing a menu on a cisco system in SSH using Plink

I'm working on automating the extract of a report on a cisco system (ISE in that case), to do that i'm using poweshell and the Plink component of the PuTTy suite.
I manage to automate the connection and run simple task, but when it come to generate the report you need to go throught a menu :
SERVER/#User# application configure ise
Selection configuration option
[1]Reset M&T Session Database
[2]Rebuild M&T Unusable Indexes
[3]Purge M&T Operational Data
[4]Reset M&T Database
[5]Refresh Database Statistics
[6]Display Profiler Statistics
[7]Export Internal CA Store
[8]Import Internal CA Store
[9]Create Missing Config Indexes
[10]Create Missing M&T Indexes
[11]Enable/Disable ACS Migration
[12]Generate Daily KPM Stats
[13]Generate KPM Stats for last 8 Weeks
[14]Enable/Disable Counter Attribute Collection
[15]View Admin Users
[16]Get all Endpoints
[17]Enable/Disable Wifi Setup
[18]Reset Config Wifi Setup
[19]Establish Trust with controller
[20]Reset Context Visibility
[21]Synchronize Context Visibility With Database
[22]Generate Heap Dump
[23]Generate Thread Dump
[24]Force Backup Cancellation
[25]CleanUp ESR 5921 IOS Crash Info Files
[26]Configure TCP params
[27]Recreate undotablespace
[28]Fetch SGA/PGA Memory usage
[0]Exit
All in need to do to generate the report is typing 16 but when i try to automate this process the flow of command can't pass this menu.
Here's some of the script i tried to use :
The easiest version
$plinkPath = "C:\Program Files\PuTTY\plink.exe"
Set-Alias plink $plinkPath
$t = "SERVER"
$l = "#User"
$pw = "SoMePaSSwOrD"
echo application configure ise 0 exit | plink -ssh -pw $pw -t $t -l $l
Normal version :
$plinkPath = "C:\Program Files\PuTTY\plink.exe"
Set-Alias plink $plinkPath
$t = "SERVER"
$l = "#User"
$pw = "SoMePaSSwOrD"
plink -ssh -pw $pw -t $t -l $l "application configure ise 0 exit"
Using System.Diagnostics.Process :
$ProcessStartInfo = New-Object System.Diagnostics.ProcessStartInfo
$ProcessStartInfo.UseShellExecute = $false
$ProcessStartInfo.RedirectStandardError = $true
$ProcessStartInfo.RedirectStandardInput = $true
$ProcessStartInfo.RedirectStandardOutput = $true
$ProcessStartInfo.FileName = "C:\Program Files\PuTTY\plink.exe"
$t = "SERVER"
$l = "#User"
$pw = "SoMePaSSwOrD"
$ProcessStartInfo.Arguments = "-ssh -t $t -l $l -pw $pw"
$Process = New-Object System.Diagnostics.Process
$Process.StartInfo = $ProcessStartInfo
$Process.Start() | Out-Null
$Process.StandardInput.WriteLine("application configure ise")
#Start-Sleep -m 3000
$Process.StandardInput.WriteLine("0")
$Process.StandardInput.WriteLine("exit")
$Process.WaitForExit()
$stdoutput = $Process.StandardOutput.ReadToEnd()
$erroutput = $Process.StandardError.ReadToEnd()
Write-Host "Standard Output: $stdoutput"
Write-Host "Error Output : $erroutput"
Write-Host "exit code: " + $Process.ExitCode
But all of these method result in the same way, no crash just blocked in the menu waiting for an input.
Just some clarification :
-No i don't use the Posh-SSH module it simply doesn't work (no output, no effect ...)
-The -m (path to a .txt file with the flow of command) in the line plink -ssh -pw $pw -t $t -l $l doesn't work either (it's apparently a known issue on cisco systems)

Used PowerShell to change my RHEL root passwords via PuTTY, but I don't know what I changed my password to

Basically the title. My friend provided me a script to batch change RHEL passwords via Powershell and PuTTY, but the new password I entered doesn't work when I try to log in. I think the issue is that it doesn't escape one of the special characters that's in the new password, but I can't figure out what the new password would have been.
The "new password" I used was similar to this: a1b2c3d"4e5f6g7
I attempted to replace the secure strings for regular strings, or use telnet instead of SSH with a packet capture to determine what exactly is being sent, but none of that has worked thus far.
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
# Displays prompt
Write-Host "This will update the root password on the Linux Servers"
# Get the running directory
$rundirectory = Split-Path $MyInvocation.MyCommand.Path
#$rundirectory = Split-Path $rundirectory
# Get old root credential
$oldrootPassword = Read-Host "Enter old root password" -AsSecureString
$oldrootCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "root", $oldrootPassword
# Get new root credential
$newrootPassword = Read-Host "Enter new root password" -AsSecureString
$newrootCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "root", $newrootPassword
$newrootPassword2 = Read-Host "Retype new root password" -AsSecureString
$newrootCredential2 = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "root", $newrootPassword2
# $gc = get-content \linuxservers.txt
if ($newrootCredential.GetNetworkCredential().Password -ceq $newrootCredential2.GetNetworkCredential().Password) {
$templogfile = $rundirectory + "\Temp\log.txt"
$tempchfile = $rundirectory + "\Temp\pwd_changes.txt"
$log = $rundirectory + "\Logs\RHEL\Password_Changes_$(Get-Date -f MMddyyyy).log"
$newrootPassword = $newrootCredential.GetNetworkCredential().Password
$serverlist = $rundirectory + "\linuxservers.txt"
Get-Content $serverlist | %{
# Connects to host and stores SSH key in case it does not have one already
echo y | plink.exe -ssh -pw $oldrootCredential.GetNetworkCredential().Password root#$_ exit
# Opens a session to the server to use for disaster recovery
putty.exe -ssh -pw $oldrootCredential.GetNetworkCredential().Password root#$_
# Adds delay to complete login before password is changed
Start-Sleep -Milliseconds 900
# Command sent to host to change password that is then logged
echo y | plink.exe -ssh -v -pw $oldrootCredential.GetNetworkCredential().Password root#$_ "echo root:'$newrootPassword' | chpasswd" 2>&1 >> $templogfile
# Parses file and stores output in variable
$outpt = cat $templogfile | Select-String "Session sent command exit status"
# Adds server name and variable to changes file
echo `n $_.ToUpper() `n$outpt `n "------------------------------------" >> $tempchfile
# Removes the log file to be used again in loop
Remove-Item $templogfile
# Opens second PuTTY session to make sure password works
putty.exe -ssh -pw $newrootCredential.GetNetworkCredential().Password root#$_
}
} else {
$writehost = "ERROR: New root passwords do not match. Exiting..."
}
if ($writehost -ceq "ERROR: New root passwords do not match. Exiting...") {
Write-Host "ERROR: New root passwords do not match. Exiting..."
} else {
# Places contents of results file in variable
$pwresults = cat $tempchfile
# Adds comment at top of file and creates new results file
echo "Investigate all servers that do not have a command exit status of 0" $pwresults >> $log
# Removes the changes file
Remove-Item $tempchfile
# Opens results file for administrator to investigate
Invoke-Item $log
}
I expected the new password to be a1b2c3d"4e5f6g7; however, this does not work upon login.
Try this. Backslash the doublequote. You might have changed it to the password without the doublequote. You need some way to undo these things if they don't work.
$newrootPassword = $newrootpassword -replace '"','\"'

Start-Process cannot execute psexec.exe

I have working script that use Invoke-Expression to execute psexec in Powershell ISE
<# $password is encrypted password, need to unencrypt to pass it to psexec #>
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
$str = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
$enable_command = "D:\PSTools\PsExec.exe $comp -u Administrator -p $str -accepteula powershell.exe c:\share\ps_enable.ps1"
Invoke-Expression $enable_command
I don't want to use Invoke-Expression because it outputs data, including PLAINTEXT password onto Powershell ISE console. But this script with Start-Process doesn't work
<# $password is encrypted password, need to unencrypt to pass it to psexec #>
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
$str = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
Start-Process -FilePath D:\PSTools\PsExec.exe -ArgumentList '$comp', '-u', 'Administrator', '-p', '$str', '-accepteula', 'powershell.exe', 'c:\share\ps_enable.ps1'
How to fix?
How about just capturing the Invoke-Expression in a variable, or piping it to Out-Null?
$CmdOutput = Invoke-Expression $enable_command
or
Invoke-Expression $enable_command | Out-Null
Edit: Ok, I forgot that PSExec likes to use StdErr as a method for displaying some of it's text, and that portion would not be captured by these. What you can do is redirect StdErr to StdOut, and either pipe to Out-Null or capture it as suggested. Try this:
$CmdOutput = Invoke-Expression $enable_command 2>&1

Starting Powershell elevated from PSExec (enable-psremoting)

I'm trying to enable-psremoting with PSexec on my servers with the following command:
psexec.exe \\server cmd /c "echo . | powershell (-verb runas -argumentlist (enable-psremoting -force))"
but it doesn't work. I'm guessing I'm messing up my double quotes. Any help?
Sune:)
Thanks for commenting all! I found out how to do it, and this is the completed code:
$user = "youruser"
$p = Read-Host "Enter domain password for $adminuser"
cls
$expression1 = "enable-psremoting -force"
$commandBytes1 = [System.Text.Encoding]::Unicode.GetBytes($expression1)
$encodedCommand1 = [Convert]::ToBase64String($commandBytes1)
$expression2 = "Set-ExecutionPolicy remotesigned -Force”
$commandBytes2 = [System.Text.Encoding]::Unicode.GetBytes($expression2)
$encodedCommand2 = [Convert]::ToBase64String($commandBytes2)
$expression3 = "Restart-Service winrm”
$commandBytes3 = [System.Text.Encoding]::Unicode.GetBytes($expression3)
$encodedCommand3 = [Convert]::ToBase64String($commandBytes3)
foreach ($server in (get-content c:\temp\enablepsremotinglist.txt))
{
echo " "
echo "Running on $server"
echo "--------------------------------------- "
echo " "
psexec.exe \\$server -h -u no\$user -p $p cmd /c "echo . | powershell -EncodedCommand $encodedCommand1"
psexec.exe \\$server -h -u no\$user -p $p cmd /c "echo . | powershell -EncodedCommand $encodedCommand2"
psexec.exe \\$server -h -u no\$user -p $p cmd /c "echo . | powershell -EncodedCommand $encodedCommand3"
}
I hope this can be of help to someone else one day:)
PS: Please keep in mind that this send your adminpassword as clear text..
It looks like you are trying to invoke PowerShell to run elevated. This might not be possible to do remotely... I was able to get this to work against a machine without UAC enabled (2003 server):
$c = Get-Credential
$u = $c.UserName
$p = $c.GetNetworkCredential().Password
$path = "C:\SysinternalsSuite"
& "$path\psexec.exe" \\server -u $u -p $p powershell.exe -Command "Enable-PSRemoting -Force"
For some reason though I had to press enter a couple times on the shell for it to keep spitting out output and eventually return me to a prompt. Not sure what's up with that...
You don't need PSExec for that. Check this script by PowerShell developer Lee.
http://poshcode.org/2141

How to script FTP upload and download

I'm attempting to make a batch file to upload a file to an FTP server.
If I type it in manually it works fine, but when I run the batch file it halts after it's connected... It says:
connected to domain.com.
220 microsoft ftp server
User(domain.com:(none)):
And then nothing else. What is going on here?
Below is my batch file:
ftp www.domainhere.com
user useridhere
passwordhere
put test.txt
bye
pause
It's a reasonable idea to want to script an FTP session the way the original poster imagined, and that is the kind of thing Expect would help with. Batch files on Windows cannot do this.
But rather than doing cURL or Expect, you may find it easier to script the FTP interaction with PowerShell. It's a different model, in that you are not directly scripting the text to send to the FTP server. Instead you will use PowerShell to manipulate objects that generate the FTP dialogue for you.
Upload:
$File = "D:\Dev\somefilename.zip"
$ftp = "ftp://username:password#example.com/pub/incoming/somefilename.zip"
"ftp url: $ftp"
$webclient = New-Object System.Net.WebClient
$uri = New-Object System.Uri($ftp)
"Uploading $File..."
$webclient.UploadFile($uri, $File)
Download:
$File = "c:\store\somefilename.zip"
$ftp = "ftp://username:password#example.com/pub/outbound/somefilename.zip"
"ftp url: $ftp"
$webclient = New-Object System.Net.WebClient
$uri = New-Object System.Uri($ftp)
"Downloading $File..."
$webclient.DownloadFile($uri, $File)
You need PowerShell to do this. If you are not aware, PowerShell is a shell like cmd.exe which runs your .bat files. But PowerShell runs .ps1 files, and is quite a bit more powerful. PowerShell is a free add-on to Windows and will be built-in to future versions of Windows. Get it here.
Source: http://poshcode.org/1134
Create a command file with your commands.
I.e., file commands.txt:
open www.domainhere.com
user useridhere
passwordhere
put test.txt
bye
Then run the FTP client from the command line:
ftp -s:commands.txt
Note: This will work for the Windows FTP client.
Batch files don't work that way. They don't just "type" everything - they run system commands, in this case ftp, wait for them to return, and run the next command... so in this case, the interpreter is simply waiting for ftp to exit.
If you must use the ftp command, then prepare a script file (for example, commands.txt and run ftp -s:commands.txt.
But using cURL, or a PHP/Perl/Python/whatever script may be a better idea.
I've done this with PowerShell:
function DownloadFromFtp($destination, $ftp_uri, $user, $pass){
$dirs = GetDirecoryTree $ftp_uri $user $pass
foreach($dir in $dirs){
$path = [io.path]::Combine($destination,$dir)
if ((Test-Path $path) -eq $false) {
"Creating $path ..."
New-Item -Path $path -ItemType Directory | Out-Null
}else{
"Exists $path ..."
}
}
$files = GetFilesTree $ftp_uri $user $pass
foreach($file in $files){
$source = [io.path]::Combine($ftp_uri,$file)
$dest = [io.path]::Combine($destination,$file)
"Downloading $source ..."
Get-FTPFile $source $dest $user $pass
}
}
function UploadToFtp($artifacts, $ftp_uri, $user, $pass){
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($user,$pass)
foreach($item in Get-ChildItem -recurse $artifacts){
$relpath = [system.io.path]::GetFullPath($item.FullName).SubString([system.io.path]::GetFullPath($artifacts).Length + 1)
if ($item.Attributes -eq "Directory"){
try{
Write-Host Creating $item.Name
$makeDirectory = [System.Net.WebRequest]::Create($ftp_uri+$relpath);
$makeDirectory.Credentials = New-Object System.Net.NetworkCredential($user,$pass)
$makeDirectory.Method = [System.Net.WebRequestMethods+FTP]::MakeDirectory;
$makeDirectory.GetResponse();
}catch [Net.WebException] {
Write-Host $item.Name probably exists ...
}
continue;
}
"Uploading $item..."
$uri = New-Object System.Uri($ftp_uri+$relpath)
$webclient.UploadFile($uri, $item.FullName)
}
}
function Get-FTPFile ($Source,$Target,$UserName,$Password)
{
$ftprequest = [System.Net.FtpWebRequest]::create($Source)
$ftprequest.Credentials = New-Object System.Net.NetworkCredential($username,$password)
$ftprequest.Method = [System.Net.WebRequestMethods+Ftp]::DownloadFile
$ftprequest.UseBinary = $true
$ftprequest.KeepAlive = $false
$ftpresponse = $ftprequest.GetResponse()
$responsestream = $ftpresponse.GetResponseStream()
$targetfile = New-Object IO.FileStream ($Target,[IO.FileMode]::Create)
[byte[]]$readbuffer = New-Object byte[] 1024
do{
$readlength = $responsestream.Read($readbuffer,0,1024)
$targetfile.Write($readbuffer,0,$readlength)
}
while ($readlength -ne 0)
$targetfile.close()
}
#task ListFiles {
#
# $files = GetFilesTree 'ftp://127.0.0.1/' "web" "web"
# $files | ForEach-Object {Write-Host $_ -foregroundcolor cyan}
#}
function GetDirecoryTree($ftp, $user, $pass){
$creds = New-Object System.Net.NetworkCredential($user,$pass)
$files = New-Object "system.collections.generic.list[string]"
$folders = New-Object "system.collections.generic.queue[string]"
$folders.Enqueue($ftp)
while($folders.Count -gt 0){
$fld = $folders.Dequeue()
$newFiles = GetAllFiles $creds $fld
$dirs = GetDirectories $creds $fld
foreach ($line in $dirs){
$dir = #($newFiles | Where { $line.EndsWith($_) })[0]
[void]$newFiles.Remove($dir)
$folders.Enqueue($fld + $dir + "/")
[void]$files.Add($fld.Replace($ftp, "") + $dir + "/")
}
}
return ,$files
}
function GetFilesTree($ftp, $user, $pass){
$creds = New-Object System.Net.NetworkCredential($user,$pass)
$files = New-Object "system.collections.generic.list[string]"
$folders = New-Object "system.collections.generic.queue[string]"
$folders.Enqueue($ftp)
while($folders.Count -gt 0){
$fld = $folders.Dequeue()
$newFiles = GetAllFiles $creds $fld
$dirs = GetDirectories $creds $fld
foreach ($line in $dirs){
$dir = #($newFiles | Where { $line.EndsWith($_) })[0]
[void]$newFiles.Remove($dir)
$folders.Enqueue($fld + $dir + "/")
}
$newFiles | ForEach-Object {
$files.Add($fld.Replace($ftp, "") + $_)
}
}
return ,$files
}
function GetDirectories($creds, $fld){
$dirs = New-Object "system.collections.generic.list[string]"
$operation = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails
$reader = GetStream $creds $fld $operation
while (($line = $reader.ReadLine()) -ne $null) {
if ($line.Trim().ToLower().StartsWith("d") -or $line.Contains(" <DIR> ")) {
[void]$dirs.Add($line)
}
}
$reader.Dispose();
return ,$dirs
}
function GetAllFiles($creds, $fld){
$newFiles = New-Object "system.collections.generic.list[string]"
$operation = [System.Net.WebRequestMethods+Ftp]::ListDirectory
$reader = GetStream $creds $fld $operation
while (($line = $reader.ReadLine()) -ne $null) {
[void]$newFiles.Add($line.Trim())
}
$reader.Dispose();
return ,$newFiles
}
function GetStream($creds, $url, $meth){
$ftp = [System.Net.WebRequest]::Create($url)
$ftp.Credentials = $creds
$ftp.Method = $meth
$response = $ftp.GetResponse()
return New-Object IO.StreamReader $response.GetResponseStream()
}
Export-ModuleMember UploadToFtp, DownLoadFromFtp
You can script the ftp command with the -s:filename option. The syntax is just a list of commands to pass to the ftp shell, each terminated by a newline. This page has a nice reference to the commands that can be performed with ftp.
Upload/Download Entire Directory Structure
Using the normal ftp doesn't work very well when you need to have an entire directory tree copied to or from a FTP site. So you could use something like these to handle those situations.
These scripts work with the Windows ftp command and allows for uploading and downloading of entire directories from a single command. This makes it pretty self-reliant when using on different systems.
Basically, they map out the directory structure to be up/downloaded, dump corresponding ftp commands to a file, and then execute those commands when the mapping has finished.
ftpupload.bat
#echo off
SET FTPADDRESS=%1
SET FTPUSERNAME=%2
SET FTPPASSWORD=%3
SET LOCALDIR=%~f4
SET REMOTEDIR=%5
if "%FTPADDRESS%" == "" goto FTP_UPLOAD_USAGE
if "%FTPUSERNAME%" == "" goto FTP_UPLOAD_USAGE
if "%FTPPASSWORD%" == "" goto FTP_UPLOAD_USAGE
if "%LOCALDIR%" == "" goto FTP_UPLOAD_USAGE
if "%REMOTEDIR%" == "" goto FTP_UPLOAD_USAGE
:TEMP_NAME
set TMPFILE=%TMP%\%RANDOM%_ftpupload.tmp
if exist "%TMPFILE%" goto TEMP_NAME
SET INITIALDIR=%CD%
echo user %FTPUSERNAME% %FTPPASSWORD% > %TMPFILE%
echo bin >> %TMPFILE%
echo lcd %LOCALDIR% >> %TMPFILE%
cd %LOCALDIR%
setlocal EnableDelayedExpansion
echo mkdir !REMOTEDIR! >> !TMPFILE!
echo cd %REMOTEDIR% >> !TMPFILE!
echo mput * >> !TMPFILE!
for /d /r %%d in (*) do (
set CURRENT_DIRECTORY=%%d
set RELATIVE_DIRECTORY=!CURRENT_DIRECTORY:%LOCALDIR%=!
echo mkdir "!REMOTEDIR!/!RELATIVE_DIRECTORY:~1!" >> !TMPFILE!
echo cd "!REMOTEDIR!/!RELATIVE_DIRECTORY:~1!" >> !TMPFILE!
echo mput "!RELATIVE_DIRECTORY:~1!\*" >> !TMPFILE!
)
echo quit >> !TMPFILE!
endlocal EnableDelayedExpansion
ftp -n -i "-s:%TMPFILE%" %FTPADDRESS%
del %TMPFILE%
cd %INITIALDIR%
goto FTP_UPLOAD_EXIT
:FTP_UPLOAD_USAGE
echo Usage: ftpupload [address] [username] [password] [local directory] [remote directory]
echo.
:FTP_UPLOAD_EXIT
set INITIALDIR=
set FTPADDRESS=
set FTPUSERNAME=
set FTPPASSWORD=
set LOCALDIR=
set REMOTEDIR=
set TMPFILE=
set CURRENT_DIRECTORY=
set RELATIVE_DIRECTORY=
#echo on
ftpget.bat
#echo off
SET FTPADDRESS=%1
SET FTPUSERNAME=%2
SET FTPPASSWORD=%3
SET LOCALDIR=%~f4
SET REMOTEDIR=%5
SET REMOTEFILE=%6
if "%FTPADDRESS%" == "" goto FTP_UPLOAD_USAGE
if "%FTPUSERNAME%" == "" goto FTP_UPLOAD_USAGE
if "%FTPPASSWORD%" == "" goto FTP_UPLOAD_USAGE
if "%LOCALDIR%" == "" goto FTP_UPLOAD_USAGE
if not defined REMOTEDIR goto FTP_UPLOAD_USAGE
if not defined REMOTEFILE goto FTP_UPLOAD_USAGE
:TEMP_NAME
set TMPFILE=%TMP%\%RANDOM%_ftpupload.tmp
if exist "%TMPFILE%" goto TEMP_NAME
echo user %FTPUSERNAME% %FTPPASSWORD% > %TMPFILE%
echo bin >> %TMPFILE%
echo lcd %LOCALDIR% >> %TMPFILE%
echo cd "%REMOTEDIR%" >> %TMPFILE%
echo mget "%REMOTEFILE%" >> %TMPFILE%
echo quit >> %TMPFILE%
ftp -n -i "-s:%TMPFILE%" %FTPADDRESS%
del %TMPFILE%
goto FTP_UPLOAD_EXIT
:FTP_UPLOAD_USAGE
echo Usage: ftpget [address] [username] [password] [local directory] [remote directory] [remote file pattern]
echo.
:FTP_UPLOAD_EXIT
set FTPADDRESS=
set FTPUSERNAME=
set FTPPASSWORD=
set LOCALDIR=
set REMOTEFILE=
set REMOTEDIR=
set TMPFILE=
set CURRENT_DIRECTORY=
set RELATIVE_DIRECTORY=
#echo on
This script generates the command file then pipes the command file to the ftp program, creating a log along the way. Finally print the original bat file, the command files and the log of this session.
#echo on
#echo off > %0.ftp
::== GETmy!dir.bat
>> %0.ftp echo a00002t
>> %0.ftp echo iasdad$2
>> %0.ftp echo help
>> %0.ftp echo prompt
>> %0.ftp echo ascii
>> %0.ftp echo !dir REPORT.CP1C.ROLLEDUP.TXT
>> %0.ftp echo get REPORT.CP1C.ROLLEDUP.TXT
>> %0.ftp echo !dir REPORT.CP1C.ROLLEDUP.TXT
>> %0.ftp echo *************************************************
>> %0.ftp echo !dir CONTENT.CP1C.ROLLEDUP.TXT
>> %0.ftp echo get CONTENT.CP1C.ROLLEDUP.TXT
>> %0.ftp echo !dir CONTENT.CP1C.ROLLEDUP.TXT
>> %0.ftp echo *************************************************
>> %0.ftp echo !dir WORKLOAD.CP1c.ROLLEDUP.TXT
>> %0.ftp echo get WORKLOAD.CP1C.ROLLEDUP.TXT
>> %0.ftp echo !dir WORKLOAD.CP1C.ROLLEDUP.TXT
>> %0.ftp echo *************************************************
>> %0.ftp echo !dir REPORT.TMMC.ROLLEDUP.TXT
>> %0.ftp echo get REPORT.TMMC.ROLLEDUP.TXT
>> %0.ftp echo !dir REPORT.TMMC.ROLLEDUP.TXT
>> %0.ftp echo *************************************************
>> %0.ftp echo !dir CONTENT.TMMC.ROLLEDUP.TXT
>> %0.ftp echo get CONTENT.TMMC.ROLLEDUP.TXT
>> %0.ftp echo !dir CONTENT.TMMC.ROLLEDUP.TXT
>> %0.ftp echo **************************************************
>> %0.ftp echo !dir WORKLOAD.TMMC.ROLLEDUP.TXT
>> %0.ftp echo get WORKLOAD.TMMC.ROLLEDUP.TXT
>> %0.ftp echo !dir WORKLOAD.TMMC.ROLLEDUP.TXT
>> %0.ftp echo quit
ftp -d -v -s:%0.ftp 150.45.12.18 > %0.log
type %0.bat
type %0.ftp
type %0.log
I was having a similar issue - like the original poster, I wanted to automate a file upload, but I couldn't figure out how. Because this is on a register terminal at my family's store, I didn't want to install PowerShell (although that looks like an easy option) and I just wanted a simple .bat file to do this.
This is pretty much what grawity and another user said; I'm new to this stuff, so here's a more detailed example and explanation (thanks also to How to Automate FTP Uploads from the Windows Command Line who explains how to do it with just one .bat file).
Essentially you need two files - one .bat and one .txt. The .bat tells ftp.exe what switches to use. The .txt gives a list of commands to ftp.exe. In the text file put this:
username
password
cd whereverYouWantToPutTheFile
lcd whereverTheFileComesFrom
put C:\InventoryExport\inventory.test (or your file path)
bye
Save that wherever you want. In the BAT file put:
ftp.exe -s:C:\Windows\System32\test.txt destinationIP
pause
Obviously change the path after the -s: to wherever your text file is. Take out the pause when you're actually running it - it's just so you can see any errors. Of course, you can use "get" or any other ftp command in the .txt file to do whatever you need to do.
I'm not positive that you need the lcd command in the text file. Like I said, I'm new to using command line for this type of thing, but this is working for me.
I had this same issue, and solved it with a solution similar to what Cheeso provided.
"doesn't work, says password is srequire, tried it a couple different ways "
Yep, that's because FTP sessions via a command file don't require the username to be prefaced with the string "user". Drop that, and try it.
Or, you could be seeing this because your FTP command file is not properly encoded (that bit me, too). That's the crappy part about generating a FTP command file at runtime. PowerShell's out-file cmdlet does not have an encoding option that Windows FTP will accept (at least not one that I could find).
Regardless, as doing a WebClient.DownloadFile is the way to go.
Try manually:
$ ftp www.domainhere.com
> useridhere
> passwordhere
> put test.txt
> bye
> pause