PowerShell + FTP in EXE
Hallo Admins!
folgende Batch-Datei verrichtet bislang absolut brav ihren Dienst, indem sie eine bestimmte Datei von einem ftp-Server holt, ich sie in NP++ bearbeiten kann und sie anschließend wieder hochgeladen wird. Vor dem Upload wird das Datum der letzten Änderung der index.htm noch aktualisiert, die ein iframe mit der per d3src eingebundenen csv-Datei umrahmt. Die pause dienen dazu eventuelle ftp-Probleme manuell abzufangen.
Die in der Batch aufgerufene *.ftp-Datei für den Downoad hat folgenden Inhalt, der Upload läuft entsprechend.
JETZT SOLL DARAUS EINE EXE-DATEI WERDEN.
Das Update-Tool soll auch Kollegen zur Verfügung gestellt werden, die nicht unbedingt die ftp-Credentials wissen sollen. Meine Idee war, das ganze mit dem Batch to Exe Converter 2.4.2 von www.f2ko.de in eine EXE zu konvertieren. Leider ist der Versuch (auch mit anderen bat2exe-Tools) fehlgeschlagen, weil entweder ftp oder die ps-Befehle nicht verarbeitet werden. Ergebnis: Die EXE taucht zwar gleich drei Mal im Taskmanager auf, lässt sich aber nur per Neustart (vielleicht auch per Taskill) abschießen.
Wie müsste das ganze in PowerShell aussehen, das ich dann mit einem ps1 to exe-Converter umwandeln kann?
Lieben Dank allerseits!
spinnifex
folgende Batch-Datei verrichtet bislang absolut brav ihren Dienst, indem sie eine bestimmte Datei von einem ftp-Server holt, ich sie in NP++ bearbeiten kann und sie anschließend wieder hochgeladen wird. Vor dem Upload wird das Datum der letzten Änderung der index.htm noch aktualisiert, die ein iframe mit der per d3src eingebundenen csv-Datei umrahmt. Die pause dienen dazu eventuelle ftp-Probleme manuell abzufangen.
ftp -s:updt_gms_dl.ftp
pause
"C:\Program Files (x86)\Notepad++\notepad++.exe" "data.csv"
powershell -Executionpolicy ByPass -Command "(Get-Item 'index.htm').LastWriteTime = (Get-Date)"
ftp -s:updt_gms_ul.ftp
pause
del data.csv
del index.htm
open ftp.beispiel.de
XXXXXXX-ftp
PWxxxXXX999!
cd webseiten
cd project0816
get index.htm
cd data
get data.csv
bye
JETZT SOLL DARAUS EINE EXE-DATEI WERDEN.
Das Update-Tool soll auch Kollegen zur Verfügung gestellt werden, die nicht unbedingt die ftp-Credentials wissen sollen. Meine Idee war, das ganze mit dem Batch to Exe Converter 2.4.2 von www.f2ko.de in eine EXE zu konvertieren. Leider ist der Versuch (auch mit anderen bat2exe-Tools) fehlgeschlagen, weil entweder ftp oder die ps-Befehle nicht verarbeitet werden. Ergebnis: Die EXE taucht zwar gleich drei Mal im Taskmanager auf, lässt sich aber nur per Neustart (vielleicht auch per Taskill) abschießen.
Wie müsste das ganze in PowerShell aussehen, das ich dann mit einem ps1 to exe-Converter umwandeln kann?
Lieben Dank allerseits!
spinnifex
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 298396
Url: https://administrator.de/contentid/298396
Ausgedruckt am: 22.11.2024 um 05:11 Uhr
13 Kommentare
Neuester Kommentar
Die Datei mit den Credentials hast Du ja auch dann, wenn Du die Batch konvertierst.
Vielleicht könnte man da ja mit Java glücklich werden: http://www.torsten-horn.de/techdocs/java-ftp.htm
Auf jeden Fall würde ich das Kennwort zumindest rudimentär "verschlüsseln". Ich mache das i.d.R. so, dass ich es wenigstens einmal mit meinem Geburtsdatum o.Ä. XOR-verknüpfe um wenigstens die "Zufallsfunde" abzudecken.
Vielleicht könnte man da ja mit Java glücklich werden: http://www.torsten-horn.de/techdocs/java-ftp.htm
Auf jeden Fall würde ich das Kennwort zumindest rudimentär "verschlüsseln". Ich mache das i.d.R. so, dass ich es wenigstens einmal mit meinem Geburtsdatum o.Ä. XOR-verknüpfe um wenigstens die "Zufallsfunde" abzudecken.
Hallo spinnefix.
Sorry, wenn das Off-Topic klingt, aber
Grüße
rubberman
EDIT Meine eigenen Erfahrungen:
"To Exe Converter" ...
Sorry, wenn das Off-Topic klingt, aber
JETZT SOLL DARAUS EINE EXE-DATEI WERDEN.
... bitte gar nicht erst drüber nachdenken. Der ganze Kram wird in Plaintext irgendwo in das temp Verzeichnis entpackt und ausgeführt. NULL Schutz! Vergiss diesen ...2exe Mist ganz schnell und auch sonst gehören Anmeldedaten nie hart in einen Programmcode.Grüße
rubberman
EDIT Meine eigenen Erfahrungen:
"To Exe Converter" ...
Eigentlich mit jeder beliebigen Programmiersprache deiner Wahl. Java war ja nur ein Beispiel.
Und - wie gesagt - eine Übersetzung .bat nach .ps1 wäre Dir keine Hilfe, da die Zugangsdaten in einer separaten Datei stehen. Diese Datei ist kein Bestandteil deiner "Programmierung", sondern lediglich eine Steuerdatei für den FTP-Client von Windows.
Die Kollegen werden also weiterhin "an deinem Schreibtisch warten müssen". Hoffentlich hast Du nie Urlaub
Und - wie gesagt - eine Übersetzung .bat nach .ps1 wäre Dir keine Hilfe, da die Zugangsdaten in einer separaten Datei stehen. Diese Datei ist kein Bestandteil deiner "Programmierung", sondern lediglich eine Steuerdatei für den FTP-Client von Windows.
Die Kollegen werden also weiterhin "an deinem Schreibtisch warten müssen". Hoffentlich hast Du nie Urlaub
Zumal bei FTP die Daten sowieso ungeschützt in den Äther hinausposaunt werden :-P
Gruß fk
Gruß fk
Dann bau dir halt direkt mit AutoIt,VB.Net, c# eine Exe... Oder benutze für jeden User explizite FTP-Credentials welche nur Lese-/Schreibrechte auf die jeweilige Datei auf dem FTP haben.
Hallo spinnifex,
FTP-Down- und Upload nativ mit Powershell, kein Problem.
Du nutzt wirklich noch Plain-FTP ohne SSL ?? Dir sollte man mal kräftig mit CAT-9 den Hintern versohlen
Grüße Uwe
p.s. Powershell kann auch Verschlüsseln. Hier zwei Methoden zum Ver- und Entschlüsseln mit zusätzlichem Salt und Key.
FTP-Down- und Upload nativ mit Powershell, kein Problem.
Du nutzt wirklich noch Plain-FTP ohne SSL ?? Dir sollte man mal kräftig mit CAT-9 den Hintern versohlen
function Upload-File([string]$path,[string]$url,$username,$password){
try{
$request = [System.Net.FtpWebRequest]::Create($url)
$request.Method = [System.Net.WebRequestMethods+FTP]::UploadFile
$request.Credentials = New-Object System.Net.NetworkCredential($username,$password)
[byte[]] $bytes = [System.IO.File]::ReadAllBytes($path)
[System.IO.Stream]$stream = $request.GetRequestStream();
$stream.Write($bytes,0,$bytes.Length)
$stream.Close(); $stream.Dispose()
$response = [System.Net.FtpWebResponse]$request.GetResponse()
$result = $response.StatusDescription
$response.Close()
return $result
}catch{
throw $_.Exception.Message
return $false
}
}
function Download-File([string]$url,[string]$path,$username,$password){
try{
$request = [System.Net.FtpWebRequest]::Create($url)
$request.Method = [System.Net.WebRequestMethods+FTP]::DownloadFile
$request.Credentials = New-Object System.Net.NetworkCredential($username,$password)
$response = [System.Net.FtpWebResponse]$request.GetResponse()
[System.IO.Stream]$stream = $response.GetResponseStream()
[System.IO.FileStream]$outstream = New-Object System.IO.FileStream ($path,[System.IO.FileMode]::Create)
$stream.CopyTo($outstream)
$outstream.Close();$stream.Close();$response.Close()
$stream.Dispose();$outstream.Dispose();$response.Dispose()
return $true
}catch{
throw $_.Exception.Message
}
}
# Variablen ------------------------
$username = 'FTPUSER'
$password = 'PASSWORD'
$remotefile = 'ftp://ftp.beispiel.de/data.csv'
$localfile = "$env:TEMP\data.csv"
# ----------------------------------------
# Download file from FTP
Download-File -url $remotefile -path $localfile -username $username -password $password
# Start Editing file
Start-Process $localfile -Wait
# Upload file to FTP
Upload-File -path $localfile -url $remotefile -username $username -password $password
# remove local downloaded file
remove-item $localfile -Force
p.s. Powershell kann auch Verschlüsseln. Hier zwei Methoden zum Ver- und Entschlüsseln mit zusätzlichem Salt und Key.
function Encrypt-String($plaintext,$password,$salt='jj3h4h5+tbbj2j281273#+', $init='j3j35&#*23kkk35!'){
$p = new-Object System.Security.Cryptography.AesManaged
$p.Key = (new-Object Security.Cryptography.PasswordDeriveBytes ([Text.Encoding]::UTF8.GetBytes($password)), ([Text.Encoding]::UTF8.GetBytes($salt)), "SHA1", 5).GetBytes(32) #256/8
$p.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15]
$encryptor = $p.CreateEncryptor()
$msEncrypt = New-Object IO.MemoryStream
$csEncrypt = New-Object Security.Cryptography.CryptoStream $msEncrypt,$encryptor,"Write"
$swEncrypt = New-Object IO.StreamWriter $csEncrypt
$swEncrypt.Write($plaintext)
$swEncrypt.Close();$csEncrypt.Close();$msEncrypt.Close()
$p.Clear()
[byte[]]$result = $msEncrypt.toArray()
return [Convert]::ToBase64String($result)
}
function Decrypt-String($string,$password,$salt='jj3h4h5+tbbj2j281273#+', $init='j3j35&#*23kkk35!'){
$p = new-Object System.Security.Cryptography.AesManaged
$p.Key = (new-Object Security.Cryptography.PasswordDeriveBytes ([Text.Encoding]::UTF8.GetBytes($password)), ([Text.Encoding]::UTF8.GetBytes($salt)), "SHA1", 5).GetBytes(32) #256/8
$p.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15]
$decryptor = $p.CreateDecryptor()
$msDecrypt = New-Object IO.MemoryStream @(,([Convert]::FromBase64String($string)))
$csDecrypt = New-Object Security.Cryptography.CryptoStream $msDecrypt,$decryptor,"Read"
$srDecrypt = New-Object IO.StreamReader $csDecrypt
[string]$result = $srDecrypt.ReadtoEnd()
$srDecrypt.Close();$csDecrypt.Close();$msDecrypt.Close()
$p.Clear()
return $result
}
Hallo,
ich habe mir das ganze auch mal angesehen und wollte das mit dem FTP Download jetzt mal ausprobieren
aber leider bekomme ich den Download nicht hin. Die List-FTP Files von colinardo funktioniert wunderbar
Diese Auflistung an Dateien wollte ich nun mit dem Downloadscript herunterladen
Aber bekomme am Ende nur einen Error:
Kann es sein das man damit mit einen gesamten Ordnerinhalt herunterladen kann?
BlueEyePhoenix
ich habe mir das ganze auch mal angesehen und wollte das mit dem FTP Download jetzt mal ausprobieren
aber leider bekomme ich den Download nicht hin. Die List-FTP Files von colinardo funktioniert wunderbar
function List-FTPFiles([string]$url,$username,$password){
try{
$request = [System.Net.FtpWebRequest]::Create($url)
$request.Method = [System.Net.WebRequestMethods+FTP]::ListDirectory
$request.Credentials = New-Object System.Net.NetworkCredential($username,$password)
$response = [System.Net.FtpWebResponse]$request.GetResponse()
[System.IO.Stream]$stream = $response.GetResponseStream()
$reader = new-object System.IO.StreamReader($stream)
$list = $reader.ReadToEnd() -split "[\r\n]+" | ?{$_ -ne ''}
$stream.Close();$response.Close();$reader.Close()
$stream.Dispose();$response.Dispose();$reader.Dispose()
return $list
}catch{
throw $_.Exception.Message
}
}
List-FTPFiles -url 'meinFTP' -username 'meinUser' -password 'meinpw'
Diese Auflistung an Dateien wollte ich nun mit dem Downloadscript herunterladen
function Download-File([string]$url,[string]$path,$username,$password){
try{
$request = [System.Net.FtpWebRequest]::Create($url)
$request.Method = [System.Net.WebRequestMethods+FTP]::DownloadFile
$request.Credentials = New-Object System.Net.NetworkCredential($username,$password)
$response = [System.Net.FtpWebResponse]$request.GetResponse()
[System.IO.Stream]$stream = $response.GetResponseStream()
[System.IO.FileStream]$outstream = New-Object System.IO.FileStream ($path,[System.IO.FileMode]::Create)
$stream.CopyTo($outstream)
$outstream.Close();$stream.Close();$response.Close()
$stream.Dispose();$outstream.Dispose();$response.Dispose()
return $true
}catch{
throw $_.Exception.Message
}
}
# Variablen ------------------------
$username = 'meinUser'
$password = 'meinpw'
$remotefile = 'ftp://meinFTP/*.txt'
$localfile = "C:\meinOrdner\"
# ----------------------------------------
# Download file from FTP
Download-File -url $remotefile -path $localfile -username $username -password $password
Aber bekomme am Ende nur einen Error:
Kann es sein das man damit mit einen gesamten Ordnerinhalt herunterladen kann?
BlueEyePhoenix
Servus.
Ich würde dir aber dringend raten das gleich mit WinSCP zu machen, das ist erstens schneller weil hier nicht für jeden Download eine Session mit Authentifizierung aufgemacht werden muss und zweitens noch wichtiger, es unterstützt das auch verschlüsselte Verbindungen!
Ein Beispiel wie du WinSCP mit Powershell nutzt findest du hier (ist für SSH, aber WinSCP kannst du einfach per Protocol Angabe auf FTP FTPS & Co umstellen): Script um Dateien zu verschieben und mail zu generieren
Hier ein kleines Beispiel für das WinSCP Module und ein ganz einfacher Transfer von Remote nach Lokal
So, damit solltest du nun gründlich versorgt sein .
Grüße Uwe
Zitat von @BlueEyePhoenix:
Kann es sein das man damit mit keinen gesamten Ordnerinhalt herunterladen kann?
Nein, die Funktion ist auf eine einzelne Datei ausgelegt, wenn du damit eine Liste von Dateien herunterladen willst musst du über eine Foreach Schleife über die Liste itterieren und die Download-Funktion mehrfach aufrufenKann es sein das man damit mit keinen gesamten Ordnerinhalt herunterladen kann?
function Download-File([string]$url,[string]$path,$username,$password){
try{
$request = [System.Net.FtpWebRequest]::Create($url)
$request.Method = [System.Net.WebRequestMethods+FTP]::DownloadFile
$request.Credentials = New-Object System.Net.NetworkCredential($username,$password)
$response = [System.Net.FtpWebResponse]$request.GetResponse()
[System.IO.Stream]$stream = $response.GetResponseStream()
[System.IO.FileStream]$outstream = New-Object System.IO.FileStream ($path,[System.IO.FileMode]::Create)
$stream.CopyTo($outstream)
$outstream.Close();$stream.Close();$response.Close()
$stream.Dispose();$outstream.Dispose();$response.Dispose()
return $true
}catch{
throw $_.Exception.Message
}
}
function List-FTPFiles([string]$url,$username,$password){
$request = [System.Net.FtpWebRequest]::Create($url)
$request.Method = [System.Net.WebRequestMethods+FTP]::ListDirectory
$request.Credentials = New-Object System.Net.NetworkCredential($username,$password)
$response = [System.Net.FtpWebResponse]$request.GetResponse()
[System.IO.Stream]$stream = $response.GetResponseStream()
$reader = new-object System.IO.StreamReader($stream)
$list = $reader.ReadToEnd() -split "[\r\n]+" | ?{$_ -ne ''}
$stream.Close();$response.Close();$reader.Close()
$stream.Dispose();$response.Dispose();$reader.Dispose()
return $list
}
$username = 'USER'
$password = 'PASS'
$remotepath = 'ftp://domain.tld/ordner'
$filefilter = '*.txt'
$localpath = 'D:\Ziel'
List-FTPFiles -url "$remotepath/$filefilter" -username $username -password $password | %{
Download-File -url "$remotepath/$_" -path "$localpath/$_" -username $username -password $password
}
Ich würde dir aber dringend raten das gleich mit WinSCP zu machen, das ist erstens schneller weil hier nicht für jeden Download eine Session mit Authentifizierung aufgemacht werden muss und zweitens noch wichtiger, es unterstützt das auch verschlüsselte Verbindungen!
Ein Beispiel wie du WinSCP mit Powershell nutzt findest du hier (ist für SSH, aber WinSCP kannst du einfach per Protocol Angabe auf FTP FTPS & Co umstellen): Script um Dateien zu verschieben und mail zu generieren
Hier ein kleines Beispiel für das WinSCP Module und ein ganz einfacher Transfer von Remote nach Lokal
# remote directory for files
$REMOTE_DIR = '/remote/folder/path'
# local directory for files
$LOCAL_DIR = 'D:\ziel'
# only transfer files matching filter
$FILEFILTER = '*.txt'
# FTP Hostname
$FTP_HOST = 'ftp.domain.tld'
# FTP Port
$FTP_PORT = 21
# FTP Username
$USERNAME = 'USER'
# FTP Password
$PASSWORD = 'PASS'
# ----------------------------------------
# install WinSCP module if needed
$modulename = 'WinSCP'
if(!(Get-Module -ListAvailable -Name $modulename)){
write-host "Module '$modulename' not found, trying to install module ... " -F Yellow -NoNewline
start powershell -Verb runas -ArgumentList "-EP Bypass -NoP -C Install-Module WinSCP -Force" -wait
if(!(Get-Module -ListAvailable -Name $modulename)){
write-host "install failed, please try to install manualy. Exit." -F Red
sleep 2
exit 1
}else{
write-host "Successfully installed." -F Green
}
}
# connection options
$params = @{
Hostname = $FTP_HOST
Credential = new-Object PSCredential($USERNAME,(ConvertTo-SecureString $PASSWORD -AsPlainText -Force))
Protocol = 'ftp'
FtpMode = 'Passive'
PortNumber = $FTP_PORT
}
$session = $null
try{
# create session
$session = New-WinSCPSession -SessionOption (New-WinSCPSessionOption @params)
# define transport options
$transoptions = New-WinSCPTransferOption -TransferMode Binary
# download files
$transfer = $session.GetFilesToDirectory($REMOTE_DIR,$LOCAL_DIR,$FILEFILTER,$false,$transoptions)
# check transfer result
if ($transfer.Transfers.Count){
write-host "Transfered files:" -F Green
$transfer.Transfers | ft FileName,Destination -AutoSize
# list errors if any
if(!$transfer.IsSuccess){
write-host "Transfers with Errors:" -F Yellow
$transfer.Failures | ft -AutoSize
}
}else{
write-host "No matching files found." -F Yellow
}
write-host "Done." -F Green
}catch{
write-error -Message $_.Exception.Message
}finally{
# cleanup
$session.Close()
$session.Dispose()
}
So, damit solltest du nun gründlich versorgt sein .
Grüße Uwe