PowerShell Split-Path does not work properly with IIS: drive qualifier - iis

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.

Related

unable to append data to sharepoint file via Azure Automation

Ok I have asked a question like this but now I am trying to perform the task via Azure Automation. I can connect to the SharePoint site via Azure Automation (powershell). with the correct credentials. I can download the file and append data to it. But I can when I try and upload the file back to SharePoint it adds the contents 3 times and then Azure Automation suspends the Runbook after 3 times.
It does run perfect if I upload this file as a different file name.
$siteurl="https://abc.sharepoint.com/sites/xxx/teamsites/os"
$credSP = Get-AutomationPSCredential -Name 'test'
$fileFolder = "$Env:temp"
Connect-PnPOnline -Url $siteurl -Credentials $credSP
Get-PnPFile -Url "/sites/xxx/teamsites/os/Directory and Operating
Systems/test.csv" -Path $fileFolder -Filename test.csv -AsFile -Force
$test = "31-07-2019 -11:35"
Add-Content -Path $fileFolder\test.csv $test
Add-PnPFile -Path $fileFolder\test.csv -Approve -Folder "Directory and
Operating Systems" #-ErrorAction Ignore
Here are the results
test test
31-07-2019 -11:35
31-07-2019 -11:35
31-07-2019 -11:35
As you can see it added $test 3 times. But I dont have this issue if I upload it as a new file name.
Ok after a while I have fix the issue.
After the add-pnpfile ...... you pipe it to | out-null
Thats it. the sript stops after it uploads ,
happy days

Running Powershell Script from Task Scheduler when User is Logged Off [duplicate]

This question already has an answer here:
Task Scheduler doesn't execute batch file properly
(1 answer)
Closed 6 years ago.
I have a powershell script that I'm intending to run from a remote server. The purpose of the script is to do the following:
Copy an Excel file from a mapped drive to the remote server
Open the Excel file and run a macro that
The macro copies an Access table that's on the remote server and pastes it into the Excel file, then does some manipulation of the data
Saves the Excel file, closes it, and then copies it back to the mapped drive
Right now, I'm testing it on my local machine, so it's copying the Excel file from the mapped drive to my C drive, then grabbing the Access table from a location on my local machine. It runs perfectly when I run it from Powershell. Here is the code:
# collect excel process ids before and after new excel background process is
# started
$priorExcelProcesses = Get-Process -name "*Excel*" | % { $_.Id }
$Excel = New-Object -ComObject Excel.Application
$postExcelProcesses = Get-Process -name "*Excel*" | % { $_.Id }
#run program
$folderPath = "my folder goes here"
$filePath = "my folder gooes here\filename.xlsm"
$tempPath = "C:\Users\Public"
$tempFile = "C:\Users\Public\filename.xlsm"
#copy file from I drive to remote desktop
Copy-Item -Path $filePath -Destination $tempPath
#create Excel variables
$excel = new-object -comobject excel.application
$excel.visible = $False
$excelFiles = Get-ChildItem -Path $tempPath -Include *.xls, *xlsm -Recurse
#open excel application and run routine
Foreach($file in $excelFiles)
{
$workbook = $excel.workbooks.open($tempFile)
$worksheet = $workbook.worksheets.item(1)
$excel.Run("getAccessData")
$workbook.save()
$workbook.close()
}
#copy file from remote desktop back onto I drive
Copy-Item -Path $tempFile -Destination $folderPath
# try to gently quit
$Excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)
# otherwise allow stop-process to clean up
$postExcelProcesses | ? { $priorExcelProcesses -eq $null -or $priorExcelProcesses -notcontains $_ } | % { Stop-Process -Id $_ }
I need to have the script run once per day in the middle of the night, so I have been working on making it a scheduled task. I first set up the 'Action' with the following information:
Program/Script:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Add arguments (optional):
-NoProfile -ExecutionPolicy Bypass -file "C:\Users\nelsonth\emsUpdateDesktop.ps1"
Now, if I run this task while the security option is set to "Run only when user is logged on" and the "Hidden" checkbox selected, then the task runs perfectly.
Since this is going to be running from a remote desktop in the middle of the night, I need the script to run while I am logged off. But when I selected "Run whether user is logged on or not" and "Run with highest privileges" the script no longer runs.
I need this to work so can anyone help me troubleshoot this?
When run as "Run whether user is logged on or not", your PowerShell Script will most likely have to manually Map the drives or access the file via UNC path.
Try adding something like the following to the top of your script, checking for the drive letter, then mapping it if not found:
if (-Not (Test-Path 'X:\')) {New-PSDrive -Name "X" -PSProvider FileSystem -Root "\\MyServer\MyShare"}

Get dbname from multiple web.config files with powershell

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.

IIS: how to undeploy/delete/remove a webapp from command line?

Suppose there's a webapp deployed on local IIS server. When I need to remove/undeploy it, I can go to IIS Manager, right-click on the app, and then select "Delete application and content" - et voila. But, I need to do the same from the command line - how? It can be assumed that the name of the application is known.
Maybe this can be done via MSDeploy somehow?
If you just want to remove the application from the Web Site in IIS without physically deleting the files (like msdeploy does) or if you don't have the WebDeploy-extension installed, you can use the following command:
C:\Windows\System32\inetsrv\appcmd.exe delete app "Default Web Site/MyAppName"
This is what did it:
"C:\Program Files\IIS\Microsoft Web Deploy\msdeploy" -verb:delete -dest:apphostconfig="Default Web Site/<webapp_name>"
I know the question says "command line", but you can use PowerShell and the IIS Administration Cmdlets to do this task. I provide all of the functions and explain the process of how to automate this on my blog. Also, you can easily swap out the IIS Administration Cmdlet calls with calls to msdeploy, appcmd, IIsVdir.vbs, etc.
For your specific question, this PowerShell code should do the trick:
$block = {
Import-Module WebAdministration
$website = "YourWebsiteName"
$applicationName = "PathUnderWebsite\ToYourApplication"
$fullPath = Join-Path $website $applicationName
Write-Host "Checking if we need to remove '$fullPath'..."
if (Get-WebApplication -Site "$website" -Name "$applicationName")
{
Write-Host "Removing '$fullPath'..."
Remove-WebApplication -Site "$website" -Name "$applicationName"
}
Write-Host "Deleting the directory '$fullPath'..."
Remove-Item -Path "IIS:\Sites\$fullPath" -Recurse -Force
}
$session = New-PSSession -ComputerName "Your.WebServer.HostName"
Invoke-Command -Session $session -ScriptBlock $block
Remove-PSSession -Session $session
iisweb /delete WebSite [/s Computer [/u [Domain ]User /p Password ]]

Change IIS Site Home Directory w/ Powershell

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?

Resources