Function
ConvertTo-WebUriPaths
{
Param
(
[
Parameter
(
Mandatory
=
$true
)]
[string]
$Url
)
$paths
= @{
Ssl =
$null
;
SiteName = "
";
AppNames = @();
AppName = "";
};
$uri = New-Object System.Uri $Url;
$paths = New-PsType "
UriPaths
"
Add-PsTypeField $paths "
Ssl
" ($uri.Scheme -eq "
https
")
Add-PsTypeField $paths "
SiteName
" $uri.Host
Add-PsTypeField $paths "
AppNames
" $uri.LocalPath.Split("
/
", [StringSplitOptions]::RemoveEmptyEntries)
Add-PsTypeField $paths "
AppName
" $uri.LocalPath
# remove trailing slash, if exists
if($paths.AppName) {
$appNameLen = $paths.AppName.Length;
if($paths.AppName[$appNameLen - 1] -eq "
/
") {
$paths.AppName = $paths.AppName.Substring(0, $appNameLen - 1);
}
}
return $paths;
}
<#
.SYNOPSIS
Takes a UriPaths object (from ConvertTo-UriPaths) and turns it into
and IIS:\Sites\XXXX string value.
.PARAMETER UriPaths
The UriPaths object from ConvertTo-WebUriPaths
.EXAMPLE
$iisPath = ConvertTo-WebIISPath $uriPaths
.LINK
ConvertTo-WebUriPaths
#>
Function ConvertTo-WebIISPath {
Param (
[Parameter(Mandatory = $true)]
[PSObject] $UriPaths
)
$iisPath = "
IIS:\Sites\
" + $UriPaths.SiteName;
$UriPaths.AppNames |% { $iisPath += "
\
" + $_ }; # alternateively, AppName could also be used
return $iisPath;
}
<#
.SYNOPSIS
Using the given url to search the current server for the longest parent website/webapp path that matches the url.
It will only return the parent website/app information. if the root website is given, then $null will be returned.
The webapp's information from the IIS:\Sites protocol is returned.
.PARAMETER Url
The url to search on
.EXAMPLE
#>
Function Get-WebParentAppByUrl {
Param (
[Parameter(Mandatory = $true)]
[string] $Url
)
$uriPaths = ConvertTo-WebUriPaths -Url $Url
$currentPath = "
IIS:\Sites\{0}
" -f $uriPaths.SiteName
if((Test-Path $currentPath) -eq $false) { return $null }
if($uriPaths.AppName -eq "" -or $uriPaths.AppName -eq "
/
") { return $null}
$webApp = Get-Item $currentPath
if($uriPaths.AppNames -is [Array]) {
for($i = 0; $i -lt $uriPaths.AppNames.Count - 1; $i++) {
$currentPath += "
\{0}
" -f $uriPaths.AppNames[$i]
if(Test-Path $currentPath) { $webApp = Get-Item $currentPath }
}
}
return $webApp
}
<#
.SYNOPSIS
Get virtual directory information from a site/app. If the given Url is a site/app, this will
search for all virtual directories at the same level as the given the path. If not a site/app,
this will search for a virtual directory under the parent site/app.
.PARAMETER Url
The url to search at.
.EXAMPLE
#>
Function Get-WebVirtualDirectoryWrapper {
[OutputType([Microsoft.IIs.PowerShell.Framework.ConfigurationElement])]
Param (
[Parameter(Mandatory = $true)]
[string] $Url
)
$uriPaths = ConvertTo-WebUriPaths -Url $Url
# check if the url is a site/app
$iisPath = ConvertTo-WebIISPath -UriPaths $uriPaths
if(-not (Test-Path $iisPath)) {
Write-Warning "
IIS
$env:COMPUTERNAME
- No path could be found
for
'$Url'
. No virtual directories could be looked up.
"
return $null
}
$node = Get-Item $iisPath
if(@("
Application
", "
Site
") -contains $node.ElementTagName) {
# search for virtual directories below this level
$vdirs = Get-WebVirtualDirectory -Site $uriPaths.SiteName -Application $uriPaths.AppName
} else {
# search the parent app for the given virtual directory name
$parentApp = Get-WebParentAppByUrl $Url
$vdir = $uriPaths.AppName.Substring($parentApp.path.Length)
$appPath = $parentApp.path
if(-not $appPath) { $appPath = "
/
" }
$vdirs = Get-WebVirtualDirectory -Site $uripaths.SiteName -Application $appPath -Name $vdir
}
return $vdirs
}
<#
.SYNOPSIS
Set a virtual directory for a site/app. This will set the physical path for the given Url.
.PARAMETER Url
The url to turn into a virtual directory.
.PARAMETER PhysicalPath
The physical path on the server to attach to the virtual path.
.PARAMETER Force
Overwrites the current physical path if already set.
.EXAMPLE
# Create a new virtual directory
$vdir = New-WebVirtualDirectoryWrapper `
-PhysicalPath "
D:\AllContent\Data\admissions.{env}.sa.ucsb.edu
"
-ServerName "
SA89
"
#>
Function New-WebVirtualDirectoryWrapper {
[OutputType([Microsoft.IIs.PowerShell.Framework.ConfigurationElement])]
Param (
[Parameter(Mandatory = $true)]
[string] $Url,
[Parameter(Mandatory = $true)]
[string] $PhysicalPath,
[switch] $Force
)
$uriPaths = ConvertTo-WebUriPaths -Url $Url
# parse the name of the virtual directory from the given url
if($uriPaths.AppName -eq "" -or $uriPaths.AppName -eq "
/
") {
throw "
IIS
$env:COMPUTERNAME
- No virtual path could be found
in
url
'$Url'
. A subpath needs to be defined within the url.
"
}
$parentApp = Get-WebParentAppByUrl -Url $Url
if($parentApp -eq $null) {
throw "
IIS
$env:COMPUTERNAME
- No parent application could be found
for
url
'$Url'
. No virtual directory could be added.
"
}
$appPath = $parentApp.path
if(-not $appPath) { $appPath = "
/
" }
$vdirPath = $uriPaths.AppName.Substring($appPath.Length)
# if the vdirPath is multiple levels deep, check that the root path exists
if($vdirPath.Split("
/
", [StringSplitOptions]::RemoveEmptyEntries).Count -gt 1) {
$i = $vdirPath.LastIndexOf("
/
")
$rootSubLevel = $vdirPath.Substring(0,$i).Replace("
/
","
\
")
$iisPath = "
IIS:\Sites\{0}\{1}
" -f $uriPaths.SiteName, $rootSubLevel
if((Test-Path $iisPath) -eq $false) {
throw "
IIS
$env:COMPUTERNAME
- Part of the sub path
for
'$Url'
could not be found. Please ensure the full base path exists
in
IIS.
"
}
}
Write-Warning "
IIS
$env:COMPUTERNAME
- Creating a virtual directory
for
$Url
to
$PhysicalPath
.
"
if($Force) {
if($appPath -eq "
/
") { # it adds an extra / if you set the applicationName to '/'
$vdir = New-WebVirtualDirectory -Site $uriPaths.SiteName -Name $vdirPath -PhysicalPath $PhysicalPath -Force
} else {
$vdir = New-WebVirtualDirectory -Site $uriPaths.SiteName -Application $appPath -Name $vdirPath -PhysicalPath $PhysicalPath -Force
}
} else {
if($appPath -eq "
/
") { # it adds an extra / if you set the applicationName to '/'
$vdir = New-WebVirtualDirectory -Site $uriPaths.SiteName -Name $vdirPath -PhysicalPath $PhysicalPath
} else {
$vdir = New-WebVirtualDirectory -Site $uriPaths.SiteName -Application $appPath -Name $vdirPath -PhysicalPath $PhysicalPath
}
}
Write-Host "
IIS
$env:COMPUTERNAME
- Created a virtual directory
for
$Url
to
$PhysicalPath
.
"
return $vdir
}
<#
.SYNOPSIS
Removes a virtual directory from a site/app. It will only remove the virtual directory if the Url
given matches up with a virtual directory.
.PARAMETER Url
The url to search at.
.EXAMPLE
#>
Function Remove-WebVirtualDirectoryWrapper {
Param (
[Parameter(Mandatory = $true)]
[string] $Url
)
$uriPaths = ConvertTo-WebUriPaths -Url $Url
# parse the name of the virtual directory from the given url
if($uriPaths.AppName -eq "" -or $uriPaths.AppName -eq "
/
") {
throw "
IIS
$env:COMPUTERNAME
- No virtual path could be found
in
url
'$Url'
. A subpath needs to be defined within the url.
"
}
$parentApp = Get-WebParentAppByUrl -Url $Url
if($parentApp -eq $null) {
throw "
IIS
$env:COMPUTERNAME
- No parent application could be found
for
url
'$Url'
. No virtual directory could be added.
"
}
# ensure the path is a virtual directory
$iisPath = ConvertTo-WebIISPath -UriPaths $uriPaths
if(-not (Test-Path $iisPath)) {
throw "
IIS
$env:COMPUTERNAME
- No path
for
$Url
could be found
in
IIS.
"
}
$node = Get-Item $iisPath
if($node.ElementTagName -ne "
VirtualDirectory
") {
switch($node.GetType().FullName) {
"
System.IO.FileInfo
" { $type = "
File
" }
"
System.IO.DirectoryInfo
" { $type = "
Directory
" }
"
Microsoft.IIs.PowerShell.Framework.ConfigurationElement
" { $type = $node.ElementTagName }
}
throw "
IIS
$env:COMPUTERNAME
- The url
'$Url'
doesn
't match with a Virtual Directory. It is a $type."
}
$vdirPath = $uriPaths.AppName.Substring($parentApp.path.Length)
# check if the virtual path has files or folders beneath it. An error will occur if there are.
$iisVPath = ConvertTo-WebIISPath -UriPaths $uriPaths
$childItems = Get-ChildItem $iisVPath
if($childItems) {
Write-Warning ("IIS $env:COMPUTERNAME - The virtual path at '
$Url
' has items beneth it. Due to a bug in " + `
" WebAdministration\Remove-WebVirtualDirectory this would force a windows pop-up dialog to get approval." + `
" To get around this, a temporary folder will be created and the current virtual directory will" + `
" be repointed to the new (empty) location before removal. After removal of the virtual directory" + `
" the temporary folder will also be removed. The domain account this process runs under will need" + `
" permissions to the temporary folder location to create and remove it.")
$guid = [Guid]::NewGuid()
$PhysicalPath = (Get-WebVirtualDirectoryWrapper -Url $Url).PhysicalPath
$tempPath = Join-Path $PhysicalPath $guid
Write-Warning "IIS $env:COMPUTERNAME - Creating temp directory '
$tempDir
' in order to remove a virtual directory."
$tempDir = New-Item $tempPath -ItemType Directory
Write-Host "IIS $env:COMPUTERNAME - Created temp directory '
$tempDir
' in order to remove a virtual directory."
$void = New-WebVirtualDirectoryWrapper -Url $Url -PhysicalPath $tempPath -Force
}
$appPath = $parentApp.path
if(-not $appPath) { $appPath = "/" }
Write-Warning "IIS $env:COMPUTERNAME - Removing a virtual directory '
$vdirPath
' for '
$Url
'."
Remove-WebVirtualDirectory -Site $uriPaths.SiteName -Application $appPath -Name $vdirPath
Write-Host "IIS $env:COMPUTERNAME - Removed a virtual directory '
$vdirPath
' for '
$Url
'."
if($tempDir) {
Write-Warning "IIS $env:COMPUTERNAME - Removing temp directory '
$tempDir
' in order to remove a virtual directory."
$void = Remove-Item $tempDir
Write-Host "IIS $env:COMPUTERNAME - Removed temp directory '
$tempDir
'
in
order to remove a virtual directory."
}
}