Come evitare che l’attività FTP SSIS fallisca quando non ci sono file da scaricare?

Sto utilizzando SQL Server 2005 e sto creando attività ftp all’interno di SSIS.

A volte ci saranno file su ftp over, a volte no. Se non ci sono file, non voglio che l’attività e il pacchetto falliscano. Ho cambiato la freccia passando dall’attività ftp alla successiva a “completamento”, quindi il pacchetto viene eseguito. Ho cambiato il numero consentito di errori a 4 (perché ci sono 4 task ftp, e una qualsiasi delle 4 directory può o non può avere file).

Ma quando eseguo il pacchetto da un lavoro in agent, contrassegna il lavoro come non funzionante. Dato che questo verrà eseguito ogni 15 minuti, non voglio un mucchio di x rossi nella mia cronologia del lavoro, il che ci indurrà a non vedere un problema quando si verifica realmente.

Come imposto le proprietà nell’attività ftp in modo che non trovando i file su ftp non sia un errore? L’operazione che sto usando è “Invia file”.

Ecco alcune ulteriori informazioni: i file si trovano su un server a cui non ho accesso tramite FTP eccetto ftp. E, non conosco i nomi dei file prima del tempo. L’utente può chiamarli come vogliono. Quindi non posso controllare file specifici, né, penso, posso controllare affatto. Tranne attraverso l’utilizzo della connessione ftp e attività basate su quella connessione. I file sono su un server remoto e voglio copiarli sul mio server, per ottenerli da quel server remoto.

Posso shellare un ftp a livello di comando in un’attività di script. Forse è quello che devo usare al posto di un task ftp. (Sono passato a utilizzare la riga di comando ftp, con un file di parametri, chiamato da un’attività di script .Non ci sono errori quando non ci sono file da ottenere. Penso che questa soluzione funzionerà per me. parametro di file in modo dinamico, il che significa che non ho bisogno di avere informazioni di connessione nel file di testo normale, ma piuttosto può essere memorizzato nel mio file di configurazione, che si trova in una posizione più sicura.)

Capisco che tu abbia trovato una risposta alla tua domanda. Questo è per gli altri utenti che potrebbero imbattersi in questa domanda. Ecco un modo ansible per raggiungere questo objective. Script Task può essere utilizzata per trovare l’elenco di file presenti in un percorso di cartella FTP per un determinato motivo (ad esempio *.txt ). L’esempio seguente mostra come questo può essere fatto.

Procedura dettagliata:

  1. Nel pacchetto SSIS, crea una FTP Connection denominata FTP e crea anche 5 variabili come mostrato nell’immagine 1 . RemotePath variabile contiene il percorso della cartella FTP; LocalPath contiene la cartella in cui verranno caricati i file; FilePattern contiene il modello di file per trovare l’elenco di file da scaricare dal server FTP; FileName verrà popolato dal Foreach loop container ma per evitare l’errore di tempo di progettazione DelayValidation FTP, può essere popolato con / o la proprietà DelayValidation sull’attività FTP può essere impostata su True .

  2. Nel pacchetto SSIS, inserire un’attività Script Task , il Foreach Loop container e l’ FTP Task nel Foreach Loop container come mostrato nelle schermate # 2 .

  3. Sostituire il metodo Main() all’interno Script Task con il codice nella sezione Codice attività Script . Script Attività popolerà la variabile ListOfFiles con la raccolta di file corrispondenti a un determinato modello. Questo esempio utilizzerà per prima cosa il modello * .txt, che non produce risultati e successivamente il modello * .xls che corrisponderà a pochi file sul server FTP.

  4. Configura il Foreach Loop container come mostrato negli screenshot # 3 e # 4 . Questa attività eseguirà il ciclo attraverso la variabile ** ListOfFiles *. Se non ci sono file, l’attività FTP all’interno del contenitore del ciclo non verrà eseguita. Se ci sono file, l’attività FTP all’interno del contenitore loop verrà eseguita per l’attività per il numero di file trovati sul server FTP.

  5. Configura l’ FTP Task come mostrato negli screenshot # 5 e # 6 .

  6. La schermata # 7 mostra l’esempio dell’esecuzione del pacchetto quando non vengono trovati file corrispondenti per il modello *.txt .

  7. Schermata n. 8 mostra il contenuto della cartella C:\temp\ prima dell’esecuzione del pacchetto.

  8. La schermata n. 9 mostra l’esempio dell’esecuzione del pacchetto quando vengono trovati i file corrispondenti per il modello *.xls .

  9. Schermata n. 10 mostra il contenuto del percorso remoto FTP /Practice/Directory_New .

  10. Screenshot # 11 mostra il contenuto della cartella C:\temp\ dopo l’ esecuzione del pacchetto.

  11. La schermata # 12 mostra l’errore del pacchetto se fornito con percorso remoto errato.

  12. La schermata # 13 mostra il messaggio di errore relativo al fallimento del pacchetto.

Spero possa aiutare.

Script Task Code:

Codice C # che può essere utilizzato in SSIS 2008 and above .

Includi l’istruzione using using System.Text.RegularExpressions;

 public void Main() { Variables varCollection = null; ConnectionManager ftpManager = null; FtpClientConnection ftpConnection = null; string[] fileNames = null; string[] folderNames = null; System.Collections.ArrayList listOfFiles = null; string remotePath = string.Empty; string filePattern = string.Empty; Regex regexp; int counter; Dts.VariableDispenser.LockForWrite("User::RemotePath"); Dts.VariableDispenser.LockForWrite("User::FilePattern"); Dts.VariableDispenser.LockForWrite("User::ListOfFiles"); Dts.VariableDispenser.GetVariables(ref varCollection); try { remotePath = varCollection["User::RemotePath"].Value.ToString(); filePattern = varCollection["User::FilePattern"].Value.ToString(); ftpManager = Dts.Connections["FTP"]; ftpConnection = new FtpClientConnection(ftpManager.AcquireConnection(null)); ftpConnection.Connect(); ftpConnection.SetWorkingDirectory(remotePath); ftpConnection.GetListing(out folderNames, out fileNames); ftpConnection.Close(); listOfFiles = new System.Collections.ArrayList(); if (fileNames != null) { regexp = new Regex("^" + filePattern + "$"); for (counter = 0; counter <= fileNames.GetUpperBound(0); counter++) { if (regexp.IsMatch(fileNames[counter])) { listOfFiles.Add(remotePath + fileNames[counter]); } } } varCollection["User::ListOfFiles"].Value = listOfFiles; } catch (Exception ex) { Dts.Events.FireError(-1, string.Empty, ex.ToString(), string.Empty, 0); Dts.TaskResult = (int) ScriptResults.Failure; } finally { varCollection.Unlock(); ftpConnection = null; ftpManager = null; } Dts.TaskResult = (int)ScriptResults.Success; } 

Codice VB che può essere utilizzato in SSIS 2005 and above .

Includere l'istruzione Imports Importa System.Text.RegularExpressions

 Public Sub Main() Dim varCollection As Variables = Nothing Dim ftpManager As ConnectionManager = Nothing Dim ftpConnection As FtpClientConnection = Nothing Dim fileNames() As String = Nothing Dim folderNames() As String = Nothing Dim listOfFiles As Collections.ArrayList Dim remotePath As String = String.Empty Dim filePattern As String = String.Empty Dim regexp As Regex Dim counter As Integer Dts.VariableDispenser.LockForRead("User::RemotePath") Dts.VariableDispenser.LockForRead("User::FilePattern") Dts.VariableDispenser.LockForWrite("User::ListOfFiles") Dts.VariableDispenser.GetVariables(varCollection) Try remotePath = varCollection("User::RemotePath").Value.ToString() filePattern = varCollection("User::FilePattern").Value.ToString() ftpManager = Dts.Connections("FTP") ftpConnection = New FtpClientConnection(ftpManager.AcquireConnection(Nothing)) ftpConnection.Connect() ftpConnection.SetWorkingDirectory(remotePath) ftpConnection.GetListing(folderNames, fileNames) ftpConnection.Close() listOfFiles = New Collections.ArrayList() If fileNames IsNot Nothing Then regexp = New Regex("^" & filePattern & "$") For counter = 0 To fileNames.GetUpperBound(0) If regexp.IsMatch(fileNames(counter)) Then listOfFiles.Add(remotePath & fileNames(counter)) End If Next counter End If varCollection("User::ListOfFiles").Value = listOfFiles Dts.TaskResult = ScriptResults.Success Catch ex As Exception Dts.Events.FireError(-1, String.Empty, ex.ToString(), String.Empty, 0) Dts.TaskResult = ScriptResults.Failure Finally varCollection.Unlock() ftpConnection = Nothing ftpManager = Nothing End Try Dts.TaskResult = ScriptResults.Success End Sub 

Screenshot 1:

1

Screenshot 2:

2

Screenshot # 3:

3

Screenshot # 4:

4

Screenshot # 5:

5

Screenshot n. 6:

6

Screenshot # 7:

7

Screenshot # 8:

8

Screenshot n. 9:

9

Screenshot n. 10:

10

Screenshot n. 11:

11

Screenshot # 12:

12

Screenshot # 13:

13

Controllare questo collegamento che descrive l’errore di attività con garbo nel pacchetto SSIS.

Ho avuto quasi lo stesso problema, ma con il recupero dei file. Volevo che il pacchetto NON fallisse quando non sono stati trovati file sul server FTP. Il collegamento sopra riportato blocca l’errore e fa fallire il pacchetto; qualcosa che avresti pensato FailPackageOnError = false avrebbe dovuto fare? :-S

Spero che questo lo risolva anche per te!

Ho appena avuto questo problema, dopo aver letto alcune delle risposte qui, nulla ha risolto il mio problema e le soluzioni qui sembrano pazze in termini di complessità.

Il mio task FTP non funzionava poiché non permettevo di sovrascrivere i file, diciamo che il lavoro è stato avviato due volte di seguito, il primo passaggio andrà bene, perché alcuni file vengono trasferiti ma non riusciranno se esiste già un file locale.

La mia soluzione era semplice:

  1. Attività clic destro – Proprietà
  2. Imposta ForceExecutionResult = “Success”

(Non posso accettare la mia risposta, ma questa è stata la soluzione che ha funzionato per me).

Potrebbe non essere la soluzione migliore, ma funziona.

Io uso un compito di script e ho un sacco di variabili per le informazioni di connessione ftp e le directory di origine e destinazione. (Perché, cambieremo il server su cui viene eseguito, e sarà più facile cambiarlo in un pacchetto di configurazione.)

Creo un file di testo al volo e scrivo i comandi ftp su di esso:

  Dim ftpStream As StreamWriter = ftpFile.CreateText() ftpStream.WriteLine(ftpUser) ftpStream.WriteLine(ftpPassword) ftpStream.WriteLine("prompt off") ftpStream.WriteLine("binary") ftpStream.WriteLine("cd " & ftpDestDir) ftpStream.WriteLine("mput " & ftpSourceDir) ftpStream.WriteLine("quit 130") ftpStream.Close() 

Quindi, dopo aver dato il tempo necessario per chiudere veramente, avvio un processo per eseguire il comando ftp:

  ftpParameters = "-s:" & ftpParameterLoc & ftpParameterFile & " " & ftpServer proc = System.Diagnostics.Process.Start("ftp", ftpParameters) 

Quindi, dopo aver dato un po ‘più di tempo per l’esecuzione del processo ftp, cancello il file ftp temporaneo (che contiene le informazioni di connessione!).

Se i file non esistono nella directory di origine (la variabile ha la \ unità \ dir \ *. * Mapping), allora non ci sono errori. Se si verificano altri errori, l’attività non riesce ancora, come dovrebbe.

Sono nuovo di SSIS, e questo potrebbe essere un gioco da ragazzi. Ma funziona per ora. Credo di aver chiesto il modo migliore, e certamente non dirò che è così.

Come ho sottolineato, non ho modo di sapere quale sia il nome dei file, o anche se ci sono dei file lì. Se sono lì, voglio averli.

Non ho una risposta pacchettizzata per te, ma dal momento che nessun altro ha pubblicato qualcosa ancora …

Dovresti essere in grado di impostare una variabile in un’attività di script ActiveX e quindi usarla per decidere se l’attività FTP deve essere eseguita o meno. C’è un esempio qui che funziona con percorsi locali. Spero che tu possa adattare il concetto (o se ansible, mappare l’unità FTP e farlo in questo modo).

1) Impostare la proprietà Task FTP ForceExecutionResult = Success

2) Aggiungi questo codice al gestore di eventi Task OnError FTP.

  public void Main() { // TODO: Add your code here int errorCode = (int)Dts.Variables["System::ErrorCode"].Value; if (errorCode.ToString().Equals("-1073573501")) { Dts.Variables["System::Propagate"].Value = false; } else { Dts.Variables["System::Propagate"].Value = true; } Dts.TaskResult = (int)ScriptResults.Success; } 

Inseriscilo in un container ForEach, che esegue l’iterazione dei file da caricare. Nessun file, nessun FTP, nessun errore.

È ansible redirect in caso di errore, a un’altra attività che non fa nulla, cioè uno script che restituisce solo true.

Per fare ciò, aggiungi la nuova attività di script, evidenzia l’attività FTP, apparirà un secondo connettore verde, trascinalo nell’attività di script, quindi fai doppio clic. Seleziona Fallimento sul menu a discesa Valore. Ovviamente, dovrai gestire i guasti reali in questa attività di script per visualizzare ancora correttamente nella cronologia del lavoro.

Aha, OK – Grazie per i chiarimenti. Poiché l’attività FTP non può restituire una cartella che elenca non sarà ansible utilizzare ForEach come inizialmente detto – Funziona solo se carichi la quantità X di file su una fonte remota.

Per scaricare la quantità X di file, puoi andare in due modi, oppure puoi farlo interamente in .Net in un’attività di script, oppure puoi compilare un ArrayList con i nomi dei file da un’attività di script .Net, quindi ForEach su ArrayList , passando il nome del file a una variabile e scaricando il nome di tale variabile in un’attività FTP standard.

Esempio di codice adatto: http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=2472491&SiteID=1

Quindi, in quanto sopra, otterresti FileNames () e compilerai ArrayList, quindi assegnerai ArrayList a una variabile di tipo Object in Dts.Variables, quindi ForEach su quella variabile Object (ArrayList) usando codice come: http : //www.sqlservercentral.com/articles/SSIS/64014/

È ansible utilizzare l’attività FTP SSIS libera da eaSkills. Non genera un errore se il file oi file non esistono, supporta i caratteri jolly e ti dà la possibilità di scaricare ed eliminare se hai bisogno di farlo.

Ecco il link alla pagina delle caratteristiche: http://www.easkills.com/ssis/ftptask

Questa è un’altra soluzione che funziona per me, usando cose integrate e quindi senza riscrivere manualmente la logica FTP:

1) Crea una variabile nel tuo pacchetto chiamato FTP_Error

2) Fare clic su Attività FTP, quindi fare clic sulla scheda “Gestori eventi”

3) Fare clic all’interno della pagina per creare un gestore di eventi per “Attività FTP / OnError” – questo si triggers ogni volta che si verificano problemi con l’FTP

4) Dalla casella degli strumenti trascinare in un elemento Script Task e fare doppio clic per aprirlo

5) Nel primo pop-up, ReadOnlyVariables – aggiungi System :: ErrorCode, System :: ErrorDescription

6) Nel primo pop-up, ReadWriteVariables – aggiungi la tua variabile User :: FTP_Error

7) Modifica script

8) Nello script imposta la tua variabile FTP_Error per contenere le variabili ReadOnly che abbiamo sopra:

 Dts.Variables["FTP_Error"].Value = "ErrorCode:" + Dts.Variables["ErrorCode"].Value.ToString() + ", ErrorDescription=" + Dts.Variables["ErrorDescription"].Value.ToString(); 

9) Salva e chiudi script

10) Premi “OK” per l’attività di script

11) Torna alla scheda “Flusso di controllo”

12) Dall’attività FTP, OnError passa a una nuova attività Script e la modifica

13) ReadOnlyVariables: Utente :: FTP_Error di prima

14) Ora, quando non ci sono file trovati sull’FTP, il codice di errore è -1073573501 (è ansible trovare l’elenco di riferimento del codice di errore qui: http://msdn.microsoft.com/en-us/library/ms345164.aspx )

15) Nella tua sceneggiatura, inserisci la logica per fare ciò che vuoi: se trovi un codice “nessun file trovato”, allora potresti dire che l’attività è andata a buon fine. In caso contrario, l’attività non è riuscita. E il tuo stream normale può gestirlo come desideri:

 if (Dts.Variables["FTP_Error"].Value.ToString().Contains("-1073573501")) { // file not found - not a problem Dts.TaskResult = (int)ScriptResults.Success; } else { // some other error - raise alarm! Dts.TaskResult = (int)ScriptResults.Failure; } 

E da lì il tuo stream Riuscito / Fallito farà quello che vuoi fare con esso.

Un’alternativa è utilizzare questo Enumeratore file FTP inserisci la descrizione dell'immagine qui