0

The replace method worked in this code for two years, why did it stop? Am I missing an update? Did a security update kill it? I just want to know if it's me, or if by some fluke it worked to begin with.

The following is a slice of a script that uploads home directory files/folders to a secure site. It records/changes the file path in order to upload them to the appropriate location on the site, while maintaining the original file structure of the user's homedir.

#Mapped drive to overcome long file names
New-PSDrive -Name "X" -PSProvider FileSystem -Root "<server path to homedir root>"

$ADuser = Get-ADUser -Identity <username> -Server <domain> -Properties homeDirectory

#I know this looks weird. We have users who've changed their name, and their homedir folder wasn't
#renamed. Our server path up to the users original sAMAccountName is 41 characters. I've done this 
#with the username typed in directly, and $aduser.samaccountname; test how you will, it doesn't 
#matter:
$SourceFolderPath = "X:\$($ADuser.homedirectory.Substring(41))"

#I've typed this in directly, thinking that something was wrong with the property, or that it 
#wasn't stored as a normal string, but it doesn't matter:
$rootPath = $ADuser.HomeDirectory

#This is just to setup the slice of code below that's part of a larger function
$Docs = $true

Get-ChildItem $SourceFolderPath -Recurse | % {
    if ($_.PSIsContainer -eq $True) {
        #I put my breakpoint here:
        if($Docs) {
            $folderUrl = $_.FullName.Replace($rootPath,"/Documents").Replace("\","/")
        }
        elseif($Website) {
            $folderUrl = $_.FullName.Replace($SourceFolderPath,"/Website").Replace("\","/")
        }
        else {
            $folderUrl = $_.FullName.Replace($SourceFolderPath,"").Replace("\","/")
        }
        if($folderUrl) {
            #This is obviously a function that's not here, you shouldn't get here anyway, but I've 
            #commented it out.
            #Ensure-Folder -Web $web -ParentFolder $list.RootFolder -FolderUrl $folderUrl
        }  
    }
    else{
        #Alternatively, you could put a breakpoint here if you don't have/want any folders in your 
        #test. You're clearly missing the $list variable, but it doesn't matter for testing, and
        #the replace method doesn't work here either:
        if($Docs) {
            $folderRelativeUrl = $list.RootFolder.ServerRelativeUrl + $_.DirectoryName.Replace($rootPath,"/Documents").Replace("\","/") 
        }
        elseif($Website) {
            $folderRelativeUrl = $list.RootFolder.ServerRelativeUrl + $_.DirectoryName.Replace($SourceFolderPath,"/Website").Replace("\","/")
        }
        else {
            $folderRelativeUrl = $list.RootFolder.ServerRelativeUrl + $_.DirectoryName.Replace($SourceFolderPath,"").Replace("\","/")
        } 
    }
}

I should also note, that it's only the first call of replace that doesn't work. The second call that replaces "\" with "/" still works. You can remove the second call, and the first still doesn't work. I've tested the replace method on folder/file.fullname outside of this loop and it works fine. It's only in this loop that it has stopped working. I've looked at object classes (string, as expected), verified that the variables contain what they're supposed to, tested on the server and a local desktop, and it just simply doesn't work anymore. The server is using PS version 5.1.14409.1027, and my desktop is on 5.1.19041.1682.

I do have a fix in place, I just want to know why this quit working, and maybe it will get some attention to be fixed in the future if it's not just something in my environment, or if I'm using the method incorrectly.

The fix for those interested is to use the -replace operator instead:

$folderUrl = $_.FullName -replace [regex]::Escape("$rootPath"),"/Documents" -replace "\\","/"

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68
dwillits
  • 183
  • 1
  • 11
  • What this boils down to is what are some sample values of `$_.FullName` and `$rootPath` such that `$_.FullName.Replace($rootPath,"/Documents")` returns `$_.FullName`? – Lance U. Matthews Jul 29 '22 at 00:22
  • @Lance - The values are of folder paths. $_.FullName would be something like: \\server\foldershare\homedir\username\subfolder\thisfile.docx. $rootpath would be: \\server\foldershare\homedir\username. I'm not returning $_.Fullname, the result of the replace is supposed to be stored as a string into the variable(s) $folderURL, or $folderRelativeUrl, to be passed on to another function. The result should be a string value of something like: /Documents/subfolder/thisfile.docx. – dwillits Jul 29 '22 at 00:53
  • So I just created a test folder structure on my local C: drive, and it worked. That would suggest that the Replace method is having an issue with the UNC path for some reason now. It should however just see a string, so I don't know why it being a UNC path would cause issues. – dwillits Jul 29 '22 at 01:22
  • What I meant is that If `$rootPath` isn't found in `$_.FullName` then `Replace()` returns the original string, which is `$_.FullName`. Testing with `$rootPath = '\\server\foldershare\homedir\username'; [PSCustomObject] @{ FullName = '\\server\foldershare\homedir\username\subfolder\thisfile.docx' } | % { $_.FullName.Replace($rootPath,"/Documents") }` returns `/Documents\subfolder\thisfile.docx`. `$PSVersionTable.PSVersion` is the same as yours, `5.1.19041.1682`. – Lance U. Matthews Jul 29 '22 at 02:01
  • `$_.FullName` should begin with ```X:\``` since that (`$SourceFilePath`) and not a UNC path is what you passed to `Get-ChildItem`. I wouldn't expect `Replace()` to do anything unless `$rootPath` (`$ADuser.HomeDirectory`) also begins with ```X:\```, but you say it's a UNC path. – Lance U. Matthews Jul 29 '22 at 02:14
  • It would appear that X:\ is just a pointer to the root string then, as $_.FullName returns a full UNC path. When ever I check $_.FullName in my testing, it displays the UNC path. When I test with just strings, the replace method works, it only stops working when I'm looping through the objects retrieved by get-childitem, and the FullName is a UNC path (so far). With your logic, my fix shouldn't work, because the $rootpath wouldn't match any part of the FullName, but it does. I ran the full script today without error, and all I changed was using the operator instead of the method. – dwillits Jul 29 '22 at 07:14
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/246897/discussion-between-dwillits-and-lance-u-matthews). – dwillits Jul 29 '22 at 20:15

0 Answers0