So I've got a UNC path like so:
\\server\folder
I want to get just the path to server, eg \\server.
Split-Path "\\server\folder" -Parent returns "". Anything I try which deals with the root, fails.
For example, Get-Item "\\server" fails too.
How can I safely get the path of \\server from \\server\\folder in PowerShell?
By using the System.Uri class and querying its host property:
$uri = new-object System.Uri("\\server\folder")
$uri.host # add "\\" in front to get exactly what you asked
Note: For a UNC path, the root directory is the servername plus the share name part.
An example using regular expressions:
'\\server\share' -replace '(?<!\\)\\\w+'
$fullpath = "\\server\folder"
$parentpath = "\\" + [string]::join("\",$fullpath.Split("\")[2])
$parentpath
\\server
Related
I would like to build the powershell script to find a string in a configuration file, and use the path found after the match to copy this particular folder to a specified location. After all the folders I need are copied, I want to zip the folder.
The config file is an xml and the specific lines where I want to find the path are like these:
<add key="TlgxDir" value="C:\myapplication\Tlgx" />
example of the config file: https://mega.nz/file/wfRQBLzD#S6DeYTSvDLeilG0Hl0fLwlO4rREhGQaj6G05dhbNchI
So for example my search value in the file "config.xml" is "TlgxDir". I want to copy the folder in the specified path behind it "c:\myapplication\tlgx" to a specified folder (e.g.C:\temp\backup). After I did this procedure for multiple folders I want to zip the destination folder (backup.zip)
I already tried some things but I'm not very familiar with PowerShell...
Thanks in advance to anyone who can help me with this question :)
Just use the PowerShell xml parser:
$xml = [xml](Get-Content .\ui00.exe.config)
$xml.configuration.appSettings.add.where{ $_.key -eq 'TlgxDir' }.Value
C:\myapplication\Tlgx
Ok you can do something like this:
#set target location
$targetPath = 'C:\temp\backup'
#Load xml - replace [path] with the path to the xml document
$xml = New-Object -TypeName xml
$xml.load([path])
#Find node by using xpath and store path
$node = $xml.SelectSingleNode("//add[#key='TlgxDir']")
$sourceDirectory = $node.value
#Copy data
copy-item -Path $sourceDirectory -Destination $targetPath -Recurse -Force -Confirm:$false
#Zip Target
Compress-Archive -Path $targetPath -DestinationPath C:\temp\backup.Zip -Force -Confirm:$false
I am limited to PuTTY and WinSCP only.
I am trying to download log directories with log files. For example, I want to grab all log_files 6 days old or newer. log_dir2 and log_dir3 including the folders match the criteria, while log_dir1 and its files does not.
DIR/log_dir1/log_files % older than 6 days
DIR/log_dir2/log_files % meets criteria
DIR/log_dir3/log_files % meets criteria
My problem is that while the log_files of log_dir1 are not downloaded, the syntax I am currently using downloads the log_dir1 folder. Normally, not a big deal, but we are talking hundreds of log_dir folders (all empty as the files are older than 6 days). For reasons beyond my control, I cannot move or archive these old log directories with their log files.
My question is simply, how do I change my syntax to ignore folders that are older than 6 days as well as files.
get -filemask="*>6D" /DIR/* C:\temp
I have tried several different combinations of parameters and I have read the support page about Directory Masks and Path Masks. I cannot get any of them working (version issue?). Can anyone explain their syntax better than the help page. I will update tomorrow with the current version of WinSCP that I am using.
Time constraint in WinSCP file mask cannot be used for directories.
But you can prevent WinSCP from creating the empty folders. Use -rawtransfersettings switch with ExcludeEmptyDirectories setting.
get -rawtransfersettings ExcludeEmptyDirectories=1 -filemask="*>6D" /DIR/* C:\temp
This is the original answer, before WinSCP supported ExcludeEmptyDirectories. It might still be useful as a basis for implementations that have even more specific constraints.
You can implement this custom logic easily in PowerShell script with a use of WinSCP .NET assembly:
# Load WinSCP .NET assembly
Add-Type -Path "WinSCPnet.dll"
# Set up session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property #{
Protocol = [WinSCP.Protocol]::Sftp
HostName = "example.com"
UserName = "username"
Password = "password"
SshHostKeyFingerprint = "..."
}
$remotePath = "/remote/path"
$localPath = "C:\local\path"
$limit = (Get-Date).AddDays(-6)
$session = New-Object WinSCP.Session
# Connect
$session.Open($sessionOptions)
# Enumerate files to download
$fileInfos =
$session.EnumerateRemoteFiles(
$remotePath, $Null, [WinSCP.EnumerationOptions]::AllDirectories) |
Where-Object { $_.LastWriteTime -gt $limit }
foreach ($fileInfo in $fileInfos)
{
$localFilePath =
[WinSCP.RemotePath]::TranslateRemotePathToLocal(
$fileInfo.FullName, $remotePath, $localPath)
# If the corresponding local folder does not exist yet, create it
$localFileDir = Split-Path -Parent $localFilePath
if (!(Test-Path -Path $localFileDir))
{
Write-Host "Creating local directory $localFileDir..."
New-Item $localFileDir -ItemType directory | Out-Null
}
Write-Host "Downloading file $($fileInfo.FullName)..."
# Download file
$sourcePath = [WinSCP.RemotePath]::EscapeFileMask($fileInfo.FullName)
$transferResult = $session.GetFiles($sourcePath, $localFilePath)
# Did the download succeeded?
if (!$transferResult.IsSuccess)
{
# Print error (but continue with other files)
Write-Host ("Error downloading file ${remoteFilePath}: " +
$transferResult.Failures[0].Message)
}
}
$session.Dispose()
Write-Host "Done."
Run the script (download.ps1) like:
powershell.exe -ExecutionPolicy Unrestricted -File download.ps1
I am using PowerShell v3.0 and the IIS Administration Cmdlets to add and remove websites from my IIS 7 instance. I use Import-Module WebAdministration to make sure the IIS: drive is available, and I am able to use Remove-Item to delete files via the IIS: drive. For some reason though when I use the following code Split-Path always returns an empty string, even though the Remove-Item works fine.
$iisPath = Join-Path "IIS:\Sites" $fullPath
Remove-Item -Path $iisPath
$parent = Split-Path -Path $iisPath -Parent
Even if I comment out the Remove-Item line, Split-Path still returns an empty string. The $iisPath value would look something like this:
IIS:\Sites\Application Services\2.5.12\OurProductServicesDirectory
So I would expect $parent to contain:
IIS:\Sites\Application Services\2.5.12
But $parent is always empty. I have also tried creating the $iisPath using $iisPath = "IIS:\Sites\$fullPath", rather than Join-Path, but still get the same result.
Any ideas why Split-Path doesn't seem to work when using the IIS: drive, or how to fix it?
===UPDATE===
So I created a tiny sample script to see if I could reproduce the problem. Here it is:
$Block = {
Import-Module WebAdministration
$path = "IIS:\Sites\Application Services\2.5.12\OurProductServicesDirectory\"
Test-Path -Path $path
$parent = Split-Path -Path $path -Parent
Write-Host Parent is $parent
}
$Session = New-PSSession -ComputerName "Our.WebServer.local"
Invoke-Command -Session $Session -ScriptBlock $Block
Using this script $parent does get a value, but the text written to the console is:
True
Parent is IIS:Sites\Application Services
when I expect it to be:
True
Parent is IIS:\Sites\Application Services\2.5.12
So in my simple sample script I do get a value back, but it's the wrong value; it returns the grandparent directory instead of the parent directory, and it removes the backslash from after IIS:.
I'm not sure why I get different results in this sample script then in my main script, but both results appear to be wrong. Any suggestions are appreciated.
So because the IIS: qualifier is made valid by importing the WebAdministration module, I'm going to assume that Split-Path was simply never designed to work with the IIS: qualifier, and that is why it doesn't handle it properly.
The work around I found was simply to just exclude IIS:\Sites\ from my path when using Split-Path. So my original example would change to:
Remove-Item -Path "IIS:\Sites\$fullPath"
$parent = Split-Path -Path $fullPath -Parent
So basically I just leave IIS:\Sites\ off of all my paths, and then explicitly add it when needed, such as when calling Remove-Item, Test-Path, Get-ChildItems, etc. It's not the greatest solution, but it works.
I would like to issue a powershell command to return me the connection string (specifically I am looking for the db name value) for all the web sites on a web server...
So I would like to see something like
site1 dbname=Northwind
site2 dbname=Fitch
site3 dbname=DemoDB
I have tried using the IIS Powershell snap-in... I thought I was close with this:
PS C:\Windows\system32> Get-WebApplication | Get-WebConfiguration -filter /connectionStrings/*
but... after looking at the results... my answer doesn't appear to be in there
I am very new to powershell - so excuse my ignornance and inexperience
Any help appreciated!
thanks!
Hopefully, this will get you started. This just assumes there will be a web.config file at the physical path of the web application's physical path. It does not recurse to find other web.config files in the web application. It also assumes your connection strings are in the connectionStrings configuration element.
Import-Module WebAdministration
Get-WebApplication | `
ForEach-Object {
$webConfigFile = [xml](Get-Content "$($_.PhysicalPath)\Web.config")
Write-Host "Web Application: $($_.path)"
foreach($connString in $webConfigFile.configuration.connectionStrings.add)
{
Write-Host "Connection String $($connString.name): $($connString.connectionString)"
$dbRegex = "((Initial\sCatalog)|((Database)))\s*=(?<ic>[a-z\s0-9]+?);"
$found = $connString.connectionString -match $dbRegex
if ($found)
{
Write-Host "Database: $($Matches["ic"])"
}
}
Write-Host " "
}
This post may give you an idea to start with. Basically load in the web.config file as an XML file and then just find the node where the connection string is.
Do something like $myFile = ([xml] Get-Content web.config). You can then pipe that to Get-Member ( $myFile | Get-Member -MemberType Property) to start working your way into the file to see what node has it. I'm not at a computer where I can show you some screenshots to explain it more, but you can check this chapter out from PowerShell.com "Master PowerShell" e-book that explains working with XML very well.
I can query the AD and find all the IIS sites and their virtual directories, now I need to be able to update those home directories and save the changes.
After I fetch the directory entry I can display the site path using $site.Path, however setting it doesn't seem to have any effect. It never changes the actual stored path.
I have tried $site.Path = <new path> and $site.Put( "Path", <new path> ) but neither have these seem to be affecting the stored path.
$site = $iis.psbase.children |
where {$_.keyType -eq "iiswebserver"} |
where {$_.psbase.properties.servercomment -eq $siteConfig.name };
$s = [ADSI]($site.psbase.path + "/ROOT");
$s.Path
# $s.Path = $siteConfig.path
# $s.Put("Path", $siteConfig.path )
$s.psbase.CommitChanges()
Import-Module WebAdministration
Set-ItemProperty 'IIS:\Sites\Default Web Site\' -name physicalPath -value $siteConfig.path
http://technet.microsoft.com/en-us/library/ee909471(WS.10).aspx
Ok, I tried this and it seems to work:
$s.psbase.properties.path[0] = $siteConfig.path
$s.psbase.CommitChanges()
Is there a better cleaner way of handling this?