5

I've been doing my best to get more familiar with PowerShell as a way to automate many of our regular tasks in an effort to eliminate human error. I support a web based application, and my current goal is to create a script to migrate the application from one server to another. So far I've gotten the script to install the application on the new server, copy the configuration files from the old server, and backup all the files prior to making any additional changes. The last thing I need to do is search through the configuration directory and all sub folders to replace all instances of the hostname, the IP address, and the directory location (in the event the drive letter changes on the new server) There is a folder called X:\Website\Tools\Database\Upgrade that contains a folder for every version that the customer has ever been on, and within that folder is the database upgrade script. I do not have permission to change anything in this folder, and frankly don't really care to change anything within X:\Website\tools.

I have written this portion of the script as follows:

#Replace all instances of hostname, IP address, and drive letter
$path = "\\$newip\$newdriveletter$\Website"
$exclude = @("$path\tools\*")
$files = get-childitem $path\*.* -recurse -exclude $exclude 
$files | %{
    (gc $_) -replace $oldhost, $newhost -replace $oldip, $newip -replace 
"${olddriveletter}:\Website", "${newDriveLetter}:\Website" | set-content 
$_.fullname
}

When I do this, it replaces everything I'm wanting it to replace, but it's still throwing the following error:

gc : Access to the path 
'\\10.5.17.60\E$\Website\Tools\Database\Upgrade\6.2.0' is denied.
At C:\Folder\Powershell\Migrate.ps1:72 char:6
+     (gc $_) -replace $oldhost, $newhost -replace $oldip, $newip -repl ...
+      ~~~~~
     + CategoryInfo          : PermissionDenied: 
(\\10.5.17.60\E$...e\Upgrade\6.2.0:String) [Get-Content], 
UnauthorizedAccessException
    + FullyQualifiedErrorId : 

I've also read that the -exclude parameter is pretty much broken in PowerShell and doesn't work well for excluding folders. The suggestion was to format it like so:

#Replace all instances of hostname, IP address, and drive letter
$path = "\\$newip\$newdriveletter$\Website"
$files = get-childitem $path\*.* -recurse | select-object -expandproperty 
fullname | where-object{$_ -notlike "\\tools\\"}
$files | %{
(gc $_) -replace $oldhost, $newhost -replace $oldip, $newip -replace "${olddriveletter}:\Website", "${newDriveLetter}:\Website" | set-content $_.fullname
}

Unfortunately, when I run this, I get the error:

Set-Content : Cannot bind argument to parameter 'Path' because it is null.
At C:\Folder\Powershell\Migrate.ps1:72 char:151
+ ... \WebAccess", "${newDriveLetter}:\Website" | set-content $_.fullname

So basically I've achieved the end goal, but I'd really like to do this without any errors popping up. If people start running this and see red they're likely to freak out. So I'm thinking there has to be a way to exclude even looking into these folders. Possibly an If statement, but I'm not quite sure how to format that. Any suggestions?

Christopher Cass
  • 817
  • 4
  • 19
  • 31

2 Answers2

4

If you just run

get-childitem $path\*.* -recurse -exclude $exclude 

you should see that it's still returning the folder you are trying to exclude. This is because get-childitem -exclude doesn't work on containers.

Instead try

$files = get-childitem $path\*.* -recurse | where-object{$_.fullname -notlike $exclude}
Ricc Babbitt
  • 355
  • 1
  • 7
  • gc : Access to the path '\\10.5.17.60\E$\Backups\Website Backups\Website 6.3.1' is denied. At C:\Backups\Powershell\Migrate.ps1:72 char:6 + (gc $_) -replace $oldhost, $newhost -replace $oldip, $newip -repl ... + ~~~~~ + CategoryInfo : PermissionDenied: (\\10.5.17.60\E$...Website 6.3.1:String) [Get-Content], UnauthorizedAccessException + FullyQualifiedErrorId : GetContentReaderUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetContentCommand – Christopher Cass May 02 '17 at 13:38
  • That's the error I'm seeing now... My $path variable is to \\10.5.17.60\E\Website. Any idea why it's trying to hit a folder that's not in that directory? – Christopher Cass May 02 '17 at 13:40
  • there was supposed to be a "\" in there.. had a little trouble getting it to show up I'm assuming $newip = '10.5.17.60' and $newdriveletter = 'E' – Ricc Babbitt May 02 '17 at 18:15
  • It seems to work without the \ and breaks with the \. Only issue is without the \ it seems to be trying to hit a folder that's not in the path. Path is \\10.5.17.60\E$\Website. Any idea why it's trying to hit \\10.5.17.60\Backups...? That's not in the $path... – Christopher Cass May 02 '17 at 18:43
  • what are all you're variables set to? did you change any of the code in your original question? I understand it previously was doing what you wanted - only that it was hitting the \tools directory and giving you the error, correct? Is that still the case with your original code? – Ricc Babbitt May 02 '17 at 19:14
  • Nothing has changed in the original code outside of replacing the line you suggested changing. and again, I've got the current code with $path*.* as the exclusions seemed to work that way, but not with $path\*.*. $oldhost = "OLDHOSTNAME" $newhost = "NEWHOSTNAME" $oldip = "10.5.17.135" $newip = "10.5.17.60" $olddriveletter = "C" $newdriveletter = "E" – Christopher Cass May 02 '17 at 19:55
  • And it is still doing what I want. Original errors are gone, now just showing error trying to hit folder outside of path. – Christopher Cass May 02 '17 at 19:56
  • with $path*.* but not with $path*.* ? – Ricc Babbitt May 02 '17 at 21:46
  • sorry, I missed the \ that time... it works with $path*.* but not $path\*.* (there is a slash in the second one... same problem as you, it's not showing up...) – Christopher Cass May 02 '17 at 21:49
  • I just edited it to include only .xml and .config files and it appears to be working without issue now. Thanks for the help! – Christopher Cass May 02 '17 at 22:55
  • still testing.. but one thing i had to do was (gc $_.fullname) or it was trying to look using the current path. – Ricc Babbitt May 02 '17 at 23:51
0

Not sure if there's a difference in PS version (I'm using 4) .. but there were a few tweaks i had to do to get it to work. This is how i did my test...

$oldhost = "RBABBITT1"
$oldip = "192.168.1.21"
$olddriveletter = "C"

$newhost = "RBABBITT2"
$newip = "192.168.1.22"
$newdriveletter = "D"


$path = "\\$newip\$newdriveletter$\test1"
$exclude = "$path\tools\*"
$files = get-childitem $path -Recurse | where-object{$_.fullname -notlike $exclude -and $_.PSIsContainer -eq $false}
$files | %{
    (gc $_.FullName) -replace $oldhost, $newhost -replace $oldip, $newip -replace [regex]::Escape("${olddriveletter}:\Website"), "${newDriveLetter}:\Website" | set-content $_.fullname
}
Ricc Babbitt
  • 355
  • 1
  • 7