Li no site do WINSCP que você pode criar um arquivo no servidor FTP remoto usando o método Session.PutFile e usando um memorystream para criar o objeto no diretório remoto.
No entanto, a sintaxe exibida parece estar faltando alguma coisa.
https://winscp.net/eng/docs/library_session_putfile
Ele menciona a criação do memorystream e, em seguida, a passagem de um argumento para o caminho do diretório remoto e o nome do arquivo.
Estou usando-o dentro de uma função que criei chamada SFTPCreatetrigger. Como o nome indica, o objetivo é usá-lo para criar um arquivo de gatilho equivalente com o mesmo nome em um diretório separado, à medida que cada arquivo é carregado para outro.
NO ENTANTO, continuo recebendo o erro New-Object: Não é possível converter 'System.Object[]' para o tipo 'System.String' requerido pelo parâmetro 'ComObject'. O método especificado não é suportado.
## ---------------------------------------------------------
## Function to Create file on Remote Directory
## ---------------------------------------------------------
Function SftpCreateTriggerFile
{
param
(
[string]$FtpServer,
[string]$FtpTriggerDirectory,
[string]$FtpUsername,
[string]$FtpPassword,
[string]$FtpSshHostKeyFingerprint
)
[hashtable]$Return = @{}
## Get initial time
$dt = Get-Date
$StartTime = Get-Date $dt -f "MMddyy HH:mm:ss"
$StartTimeUtc = $dt.ToUniversalTime().ToString("MMddyy HH:mm:ss")
## Load WinSCP .NET assembly
[Reflection.Assembly]::LoadFrom("C:\Program Files (x86)\WinSCP\WinSCPnet.dll") | Out-Null
## Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.Protocol = [WinSCP.Protocol]::Sftp
$sessionOptions.HostName = $FtpServer
$sessionOptions.UserName = $FtpUsername
$sessionOptions.Password = $FtpPassword
$sessionOptions.PortNumber = 22
$sessionOptions.SshHostKeyFingerprint = $FtpSshHostKeyFingerprint
$session = New-Object WinSCP.Session
try
{
# Connect
$session.Open($sessionOptions)
# Upload files
$transferOptions = New-Object WinSCP.TransferOptions
$transferOptions.TransferMode = [WinSCP.TransferMode]::Automatic
$transferOptions.FilePermissions = $null
$transferOptions.PreserveTimestamp = $false
$transferOptions.ResumeSupport.State = [WinSCP.TransferResumeSupportState]::Off
$transferResult = $session.PutFile((New-Object System.IO.MemoryStream, ($FtpTriggerDirectory + $file.fullname)), $transferOptions)
# Throw on any error
$transferResult.Check()
if ($transferResult.Transfers.Count -gt 0)
{
$Return.IsSuccess = $true
$Return.StandardOutput = "Success"
}
else
{
$Return.IsSuccess = $false
$Return.StandardOutput = "Issue occurred creating trigger file on remote directory $FtpTriggerDirectory. No file created."
}
## Calculate time elapsed
$ExecTime = [math]::Round(([datetime]::Now - ([datetime]::ParseExact($StartTime,'MMddyy HH:mm:ss',$null))).TotalSeconds)
}
catch [Exception]
{
$Return.IsSuccess = $false
$Return.StandardOutput = $_.Exception.Message
## Calculate time elapsed
$ExecTime = [math]::Round(([datetime]::Now - ([datetime]::ParseExact($StartTime,'MMddyy HH:mm:ss',$null))).TotalSeconds)
}
finally
{
$Return.StartTime = $StartTime
$Return.StartTimeUtc = $StartTimeUtc
$Return.ExecTime = $ExecTime
## Disconnect and cleanup
$session.Dispose()
}
Return $Return
}
Acima está a função e abaixo está o que estou tentando executar
## Set up wildcards to download files
$arrFiles = @(Get-ChildItem $LocalDirectory -Filter "*.txt")
foreach ($file in $arrFiles)
{
$arrReturnResults = SftpUploadWithWildcards -FtpServer $FtpServer -ftpdirectory $FtpDirectory -FtpUsername $FtpUsername -FtpPassword $FtpPassword -FtpSshHostKeyFingerprint $FtpSshHostKeyFingerprint -LocalDirectory $LocalDirectory -FileNameWildcards $file.Name
$ProcessName = "Upload($FtpServer):FromDir($LocalDirectory):Files("+$file.Name+")"
If ($arrReturnResults.IsSuccess)
{$arrResults += New-Object Psobject -property @{Time = $arrReturnResults.StartTime; Task = $ProcessName; Status = "Success"; Details = ""; ExecTime = $arrReturnResults.ExecTime; TimeUtc = $arrReturnResults.StartTimeUtc}
## File Archive
# Move-Item ($LocalDirectory+$file.Name) ($LocalDirectory+"Archive") -Force -ErrorAction Stop
## Create 0 byte file with the same name to the trigger folder on remote server
$arrReturnResults = SftpCreateTriggerFile -FtpServer $FtpServer -ftpTriggerdirectory $FtpTriggerDirectory -FtpUsername $FtpUsername -FtpPassword $FtpPassword -FtpSshHostKeyFingerprint $FtpSshHostKeyFingerprint
$ProcessName = "Upload($FtpServer):FromDir($LocalDirectory):TriggerFiles("+$file.Name+")"
If ($arrReturnResults.IsSuccess)
{$arrResults += New-Object Psobject -property @{Time = $arrReturnResults.StartTime; Task = $ProcessName; Status = "Success"; Details = ""; ExecTime = $arrReturnResults.ExecTime; TimeUtc = $arrReturnResults.StartTimeUtc}
}
Else
{$arrResults += New-Object Psobject -property @{Time = $arrReturnResults.StartTime; Task = $ProcessName; Status = "Failed"; Details = $arrReturnResults.StandardOutput; ExecTime = $arrReturnResults.ExecTime; TimeUtc = $arrReturnResults.StartTimeUtc}}
}
Else
{$arrResults += New-Object Psobject -property @{Time = $arrReturnResults.StartTime; Task = $ProcessName; Status = "Failed"; Details = $arrReturnResults.StandardOutput; ExecTime = $arrReturnResults.ExecTime; TimeUtc = $arrReturnResults.StartTimeUtc}}
}
Todas as minhas variáveis ($ftpserver, $ftpusername, $ftptriggerdirectory etc) estão definidas com valores corretos. Parece que está chamando
New-Object System.IO.MemoryStream sozinho funciona para criar um novo objeto Memorystream
CanRead: Verdadeiro CanSeek: Verdadeiro CanWrite: Verdadeiro Capacidade: 0 Comprimento: 0 Posição: 0 CanTimeout: Falso ReadTimeout: WriteTimeout:
No entanto, não posso atribuir o nome que desejo a ele (que efetivamente é o último $file a passar pelo loop foreach)
Eu li sobre o uso do MemoryStream e vi que você precisa referenciar um array 'byte'? No entanto, eu só quero que ele crie um objeto no diretório remoto, conforme declarado nos exemplos que encontrei pelo próprio Martin Prikryl.
Se seu objetivo era criar um arquivo vazio (a partir de um novo vazio
MemoryStream
), então o problema é a sintaxe incorreta para chamarSession.PutFile
com três argumentos. Deveria ser:(Os colchetes ao redor
$FtpTriggerDirectory + $file.fullname
são redundantes)Observe também que
Session.PutFile
não retorna nada. Então todo o seu código, que atribui$transferResult
e trabalha com ele, falhará.