使用 MemoryStream、WinSCP 和 PowerShell 在远程目录上创建文件

问题描述 投票:0回答:1

我在 WinSCP 网站上读到,您可以使用方法

Session.PutFile
在远程 FTP 服务器上创建文件,并使用
MemoryStream
在远程目录上创建对象。

显示的语法似乎缺少一些东西
https://winscp.net/eng/docs/library_session_putfile

它提到创建

MemoryStream
,然后传递远程目录路径和文件名的参数。

我在我创建的名为

SFTPCreatetrigger
的函数中使用它,因为名称表明重点是当每个文件上传到另一个文件时,使用它在单独的目录上创建具有相同名称的等效触发器文件。

但是我不断收到错误 New-Object:

无法将“System.Object[]”转换为参数“ComObject”所需的类型“System.String”。不支持指定的方法。

Error sys object vs sys string

## ---------------------------------------------------------
## 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
}

上面是函数,下面是我要执行的

## 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}
    }
}

我的所有变量(

$ftpserver
$ftpusername
$ftptriggerdirectory
等)都设置为正确的值。似乎只是在呼唤

New-Object System.IO.MemoryStream
单独创建一个新的
MemoryStream
对象

CanRead      : True
CanSeek      : True
CanWrite     : True
Capacity     : 0
Length       : 0
Position     : 0
CanTimeout   : False
ReadTimeout  : 
WriteTimeout : 

但是我无法为其分配我想要的名称(这实际上是最后一个经历 foreach 循环的

$file

我已经阅读了

MemoryStream
使用并发现您需要引用
byte
数组?然而,我只是希望它在远程目录上创建一个对象,如我在 Martin Prikryl 本人找到的示例中所述。

powershell memorystream winscp winscp-net
1个回答
1
投票

如果您的目标是创建一个 empty 文件(从新的空

MemoryStream
),那么问题是使用三个参数调用
Session.PutFile
的语法不正确。应该是:

$session.PutFile(
    (New-Object System.IO.MemoryStream),      # stream
    ($FtpTriggerDirectory + $file.fullname),  # remoteFilePath
    $transferOptions)                         # options 

$FtpTriggerDirectory + $file.fullname
两边的括号是多余的)


另请注意,

Session.PutFile
不会返回任何内容。因此,所有分配
$transferResult
并使用它的代码都会失败。

© www.soinside.com 2019 - 2024. All rights reserved.