Script translates local path to remote differently. Depending on how the script is initiated.

Advertisement

Stumped23
Joined:
Posts:
4

Script translates local path to remote differently. Depending on how the script is initiated.

I'm running into an issue adapting the script located below to my environment. I suspect the issue lies in the TranslateLocalPathToRemote portion of the script. The RemoteFilePath is translated differently depending on how the PowerShell script is ran.
  • Running locally on my machine, Windows 11, it returns what I expect and works fine.
  • Running it via PowerShell ISE on Server 2019, it returns what I expect and works fine.
  • Running it via PowerShell, on Server 2019 returns a different path and fails.
I've attached screenshots showing the different returned remote paths.

Is this a bug? If not, what is the best way to handle this situation?

Thanks!

# Watches a directory for new files and
# fires off the batch file to push to connection
 
$processedfiles = "D:\EDI-Upload\Files\ProcessedFiles"
$remotePath = "/XXX/Co-Packer/Orders/Source/"
$localPath = "D:\EDI-Upload\Files\Source"
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $localPath
$watcher.Filter  = "*.xlsx"
$watcher.IncludeSubdirectories = $False
$watcher.EnableRaisingEvents = $True
 
### LISTEN FOR CREATE
Register-ObjectEvent $watcher Created -SourceIdentifier FileCreated -Action { 
    try
    {
        $localFilePath = $event.SourceEventArgs.FullPath
        Write-Host "Local path: $localFilePath"
 
        $assemblyPath = "C:\Program Files (x86)\WinSCP"
        Add-Type -Path (Join-Path $assemblyPath "WinSCPnet.dll")
 
        # Setup session options
        $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
            Protocol = [WinSCP.Protocol]::ftp
            FtpSecure = [WinSCP.FtpSecure]::Implicit
            HostName = ""
            UserName = ""
            Password = ""
            TlsHostCertificateFingerprint = ""
        }
 
        $session = New-Object WinSCP.Session
 
        try
        {
            $remoteFilePath = [WinSCP.RemotePath]::TranslateLocalPathToRemote(
                    $localFilePath, $localPath, $remotePath)
 
            Write-Host "Remote path: $remoteFilePath"
 
            # Connect
            $session.Open($sessionOptions)
 
            $session.PutFiles($localFilePath, $remoteFilePath).Check()
 
            Write-Host "Upload of $localFilePath succeeded"
 
            move-item "$localfilepath" "$ProcessedFiles"
        }
        finally
        {
            # Disconnect, clean up
            $session.Dispose()
        }
 
    } #end of first try 
    catch
    {
        Write-Host "Error: $($_.Exception.Message)"
    }
} #end of action
while ($True) {sleep 5}
  • Upload-Success.png (54.69 KB, Private file)
Description: Script ran from Server 2019 machine via PowerShell ISE. Resulted in success. Script also runs successfully on Windows 11 machine.
  • Upload-Failure.png (57.02 KB, Private file)
Description: Script ran from Server 2019 machine via PowerShell. Resulted in failure.

Reply with quote

Advertisement

martin
Site Admin
martin avatar
Joined:
Posts:
41,441
Location:
Prague, Czechia

Re: Script translates local path to remote differently. Depending on how the script is initiated.

I wanted to test it, but I was not able to even load the WinSCPnet.dll in PowerShell ISE on Windows Server. I've getting "Could not load file or assembly ... Operation is not supported". I know the error, but I do not have the "Unblock" button on Windows Server.

Anyway, can you post minimal example? Or what do you get with this simple example?
Add-Type -Path ".\WinSCPnet.dll"
$localFilePath = "D:\EDI-Upload\Files\Source\test2.xlsx"
$remotePath = "/XXX/Co-Packer/Orders/Source/"
$localPath = "D:\EDI-Upload\Files\Source"
$remoteFilePath =
    [WinSCP.RemotePath]::TranslateLocalPathToRemote(
        $localFilePath, $localPath, $remotePath)
Write-Host $remoteFilePath
So far I cannot imagine that the RemotePath.TranslateLocalPathToRemote code could be returning different results on different systems. It's purely a string computation code. It does not use any system functions.

Reply with quote

Guest

I tested your minimal example on Server 2019. It returns the correct remote path:
/XXX/Co-Packer/Orders/Source/test2.xlsx
Given that result, I commented out the portion of my original script that automates the $localfilepath variable and manually specified instead.
$localFilePath = "D:\EDI-Upload\Files\Source\test2.xlsx"
# $localFilePath = $event.SourceEventArgs.FullPath
Write-Host "Local path: $localFilePath"
Even with the local file path manually specified, the remote path is still returned incorrectly.
Local path: D:\EDI-Upload\Files\Source\test2.xlsx
Remote Path: D:/EDI-Upload/Files/Source/test2.xlsx
Is there anything else you would like me to test? This has me stumped.

Reply with quote

martin
Site Admin
martin avatar

So can you post minimal example that still has the problem?
Or help me making the script run on Windows Server. What do I need to do to allow loading the WinSCP .NET assembly on PowerShell ISE on Windows Server?

Reply with quote

Stumped23
Joined:
Posts:
4

Thank you for working with me on this. I'm not the best with scripting.

I'm not sure regarding the assembly in ISE. I did not have to do anything special to get it to work on my side. Just installed WinSCP in default directory and referenced the assembly file located in C:\Program Files (x86)\WinSCP in my script.

This minimal script returns the correct remote path for me...
Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"
$localFilePath = "D:\EDI-Upload\Files\Source\test2.xlsx"
$remotePath = "/XXX/Co-Packer/Orders/Source/"
$localPath = "D:\EDI-Upload\Files\Source"
$remoteFilePath =
    [WinSCP.RemotePath]::TranslateLocalPathToRemote(
        $localFilePath, $localPath, $remotePath)
Write-Host $remoteFilePath
This script, where I manually specified the $remotepath, $localpath, AND $localfilepath variables, still returns the incorrect remote file path. I've removed the upload aspect of the script to test and just requested it write-host $remotefilepath. I'm not sure how to simplify further without entirely removing the watcher aspect.
$remotePath = "/XXX/Co-Packer/Orders/Source/"
$localPath = "D:\EDI-Upload\Files\Source"
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $localPath
$watcher.Filter  = "*.xlsx"
$watcher.IncludeSubdirectories = $False
$watcher.EnableRaisingEvents = $True
 
### LISTEN FOR CREATE
Register-ObjectEvent $watcher Created -SourceIdentifier FileCreated -Action { 
    try
    {
        $localFilePath = "D:\EDI-Upload\Files\Source\test2.xlsx"
        # $localFilePath = $event.SourceEventArgs.FullPath
        Write-Host "Local path: $localFilePath"
 
        $assemblyPath = "C:\Program Files (x86)\WinSCP"
        Add-Type -Path (Join-Path $assemblyPath "WinSCPnet.dll")
 
        # Setup session options
        $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
            Protocol = [WinSCP.Protocol]::ftp
        FtpSecure = [WinSCP.FtpSecure]::Implicit
            HostName = ""
            UserName = ""
            Password = ""
            TlsHostCertificateFingerprint = ""
        }
 
        $session = New-Object WinSCP.Session
 
        try
        {
           $remoteFilePath = [WinSCP.RemotePath]::TranslateLocalPathToRemote(
           $localFilePath, $localPath, $remotePath)
           Write-Host Remote Path: $remoteFilePath
        }
        finally
        {
            # Disconnect, clean up
            $session.Dispose()
        }
 
    } #end of first try 
    catch
    {
        Write-Host "Error: $($_.Exception.Message)"
    }
} #end of action
while ($True) {sleep 5}

Reply with quote

Advertisement

martin
Site Admin
martin avatar
Joined:
Posts:
41,441
Location:
Prague, Czechia

Ok, I've made the script working in PowerShell on Windows Server 2019.
With your exact script from the last post (I've just commented out the TlsHostCertificateFingerprint line, as that won't work), I get:
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

PS C:\Users\Administrator> cd C:\foo
PS C:\foo> powershell -file test.ps1

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
1      FileCreated                     NotStarted    False                                 ...
Local path: D:\EDI-Upload\Files\Source\test2.xlsx
Remote Path: /XXX/Co-Packer/Orders/Source/test2.xlsx
So I cannot reproduce the problem with your script.

Reply with quote

Stumped23
Joined:
Posts:
4

Does it still return the correct path if you let the watcher process build the $localfilepath variable instead of manually specifying?

According to System > About this is what I am currently running.
Edition: Windows Server 2019 Standard
Version: 1809
OS Build: 17763.4010
Not sure if build versions are playing a factor here.

Reply with quote

martin
Site Admin
martin avatar

Stumped23 wrote:

Does it still return the correct path if you let the watcher process build the $localfilepath variable instead of manually specifying?
How's that relevant? You claim the problem happens even with manually specified path.

Reply with quote

Advertisement

You can post new topics in this forum