User PowerShell to get IIS Recycling Time For Remote Server - powershell

I'm trying to create a script to audit the IIS recycling times on a number of remote servers. The script I'm attempting is:
$scriptBlock = {
import-module webadministration
Get-itemproperty -Path IIS:\AppPools\WebPage -Name recycling.periodicRestart.schedule.collection}
invoke-command -computername HOSTNAME -ScriptBlock $scriptBlock
Unfortunately, this is returning absolutely nothing. Any idea what I might be doing wrong?

You are not doing anything wrong, assuming you want to query the "DefaultAppPool," what you are doing will return empty if there is no value in the collection:
Get-ItemProperty -Path IIS:\AppPools\DefaultAppPool -Name recycling.periodicRestart.schedule.collection
Set it with:
Set-ItemProperty -Path IIS:\AppPools\DefaultAppPool -Name recycling.periodicRestart.schedule -Value #{value = '03:00:00'}
And then try to get it, you will see the value.

Related

PowerShell - Invoke Command on Remote Machines/Computers

There's plenty of forums/material regarding the subject line, but cannot seem to get an answer for my problem.
I'm trying to execute a script from the main server (SRV01) that will clean the temp folders on the secondary servers (SRV02, SRV03).
Here is the script:
#Set the machines on the network to run the script on
$VDST = #("SRV02", "SRV03")
#Folder locations to clean out
$TempFolder = #("C:\Windows\Temp\*", "C:\Documents and Settings\*\Local Settings\temp\*")
#This function actually performs the clean up operation
Function executeCleanUp
{
$TempFolder = $args[0]
$machineNames = $args[2]
ForEach($machine in $machineNames){
Get-PSSession -ComputerName $machine | Format-Table -Property ComputerName, InstanceID
Write-Host 'Starting Clean Up...'
#Loop through the sub folders in the registry location
ForEach($folderLocation in $TempFolder)
{
$StrInput = 'Remove-Item -Path ' + $folderLocation + ' -Force -Recurse -ErrorAction SilentlyContinue'
$action = New-ScheduledTaskAction -Execute 'PowerShell.exe' -Argument $StrInput
Register-ScheduledTask -Action $action -TaskName "CleanUp"
Start-ScheduledTask -TaskName "CleanUp"
Unregister-ScheduledTask -TaskName "CleanUp" -Confirm:$false -ErrorAction SilentlyContinue
}
}
#Execute Script on specified machines - provided in array above
Invoke-Command -ComputerName $VDST -ScriptBlock ${function:executeCleanUp} -ArgumentList $TempFolder, $VDST
After running the above, I get the error:
A specified logon session does not exist
So, I came across a forum where it was suggested to do the following:
#Remote Server (VDI)
Enable-WSManCredSSP -Role server
#Expected Output
#This computer is configured to receive credentials from a remote client computer.
#Local Machine
Enable-WSManCredSSP -Role Client -DelegatedCredentials 'SRV01'
#Expected Output
#The machine is configured to allow delegating fresh credentials to the following target(s): wsman/SRV01.
#Local Machine
#Open gpedit.msc
#Browse to Computer Configuration > Administrative Templates > System > Credentials Delegation.
#Double-click "Allow delegating fresh credentials with NTLM-only Server Authentication"
#Enable the setting
#Add the build server to the server list as WSMAN/BuildServerName.
#Example Execution:
#Invoke-Command -ComputerName <REMOTE_COMPUTER_NAME> -Authentication CredSSP -Credential <USERNAME> -ScriptBlock { #code}
I've done all this, but now I get the error:
A computer policy does not allow the delegation of the user
credentials to the target computer
Also, I am assuming the line
WSMAN/BuildServerName
should be written
WSMAN/SRV02
The 2 hop authentication issue came up because you are trying to list remote sessions with in your remote session
Get-PSSession -ComputerName $machine | Format-Table -Property ComputerName, InstanceID
If you just want to clear some files on the remote servers the code below should work with no need for CredSPP.
Setting -ErrorAction SilentlyContinue will make trouble shooting difficult, It's easier to check if the file exists before you try to delete it.
$TempFolder = $args[0]
$ComputerArray = "SRV02","SRV03"
$ScriptBlock =
{
foreach ($Folder in $TempFolders)
{
if (Test-Path -Path $TempFolder)
{
Remove-Item -Path $Folder -force
}
}
}
Invoke-Command -ComputerName $ComputerArray -ScriptBlock $ScriptBlock -ArgumentList $TempFolder
Wrong answer:
Your issue is two hop authentication.
You can't nest remote sessions with default windows settings.
While this would not be considered to be best practice, you can enable CredSSP to bypass the problem.
https://learn.microsoft.com/en-us/windows/win32/secauthn/credential-security-support-provider
https://learn.microsoft.com/en-us/powershell/module/microsoft.wsman.management/enable-wsmancredssp?view=powershell-7
Could you either log on to SVR01 to run the script or run the script against the target machines from your own computer?

Powershell Remote file copy is not working

I am trying to copy files remotely on several IIS servers from one source server.
sourcepath is a UNC path like \\server\c$\path\ and destinationpath is a local folder c:\data\destination\
The strange thing is when I run this on the local server this will work perfectly.
$cmd = $sqlConnection.CreateCommand()
$cmd.CommandText ="SELECT * from infrastructure"
$Serverinfo = $cmd.ExecuteReader()
try
{
while ($Serverinfo.Read())
{
$servername = $Serverinfo.GetValue(1)
$location = $Serverinfo.GetValue(2)
#Invoke-Command -ComputerName $servername { new-item -Path $Using:destinationpath -name $Using:versionnumber -Itemtype directory }
Invoke-Command -ComputerName $servername { Copy-Item -Path $Using:sourcepath -destination $Using:destinationpath }
#Invoke-Command -ComputerName $servername {Import-Module WebAdministration ; New-WebApplication -force -Site "Default Web Site" -Name $Using:versionnumber -PhysicalPath $Using:destinationpath$Using:versionnumber }
}
}
What you have posted is incomplete without a catch block and source and destination path defined as others said.
But what I can see here as a possible cause even if you mention all above three constrains.
You will face issues with credential delegation . You are remoting to one server using PSRP and copying one file to that machine and you are taking your source file from a UNC path which requires some authentication.
I could give you two better alternatives, of course 1st once could be the proper solution.
If you are in PS 5.o or later, you can use -ToSession parameter of Copy-Item cmdlet.
$Session = New-PSSession -ComputerName $ServerName
Copy-Item -SourcePath \\\Server\c$\path -Destination c:\data\Destination-ToSession $Session
For more info Get-Help Copy-Item
Edit:
The second one:
Copy-Item -Path <Sourcepath> -DestinationPath \\destinataionserver\c$\folder
from source to the destination by accessing the shared folder of the destination system.

Run Registry File Remotely with PowerShell

I'm using the following script to run test.reg on multiple remote systems:
$computers = Get-Content computers.txt
Invoke-Command -ComputerName $computers -ScriptBlock {
regedit /i /s "\\SERVER\C$\RegistryFiles\test.reg"
}
The script doesn't error, but the registry entry doesn't import on any of the systems.
I know test.reg file is a valid registry file because I copied it over, ran it manually, and the registry key imports. I also made sure PowerShell Remoting is enabled on the remote computers.
Any ideas why the registry key isn't importing?
I found the best way not to mess with issues related to server authentication and cut down on complexity just to pass Reg file as parameter to function.
$regFile = #"
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters]
"MaxUserPort"=dword:00005000
"TcpTimedWaitDelay"=dword:0000001e
"#
Invoke-Command -ComputerName computerName -ScriptBlock {param($regFile) $regFile | out-file $env:temp\a.reg;
reg.exe import $env:temp\a.reg } -ArgumentList $regFile
I posted on some PowerShell forums and finally got this working.
I had to 1) move the $newfile variable inside the loop and 2) comment out the $ in the path stored in the $newfile variable.
For reference, the final script looks like this if anyone wants to use it:
$servers = Get-Content servers.txt
$HostedRegFile = "C:\Scripts\RegistryFiles\test.reg"
foreach ($server in $servers)
{
$newfile = "\\$server\c`$\Downloads\RegistryFiles\test.reg"
New-Item -ErrorAction SilentlyContinue -ItemType directory -Path \\$server\C$\Downloads\RegistryFiles
Copy-Item $HostedRegFile -Destination $newfile
Invoke-Command -ComputerName $server -ScriptBlock {
Start-Process -filepath "C:\windows\regedit.exe" -argumentlist "/s C:\Downloads\RegistryFiles\test.reg"
}
}

Automate process of Disk Cleanup cleanmgr.exe without user intervention

I am developing a powershell script file which shall execute some disk cleanup without user intervention. The user shall not be able to configure anything.
When I run cleanmgr.exe /d c: sageset:1 a popup window appears to select files/folders to be cleaned(cleanup options).
This will create a registry entry containing the settings with the cleanup options and after this, you can run cleanmgr.exe /sagerun:1 which will actually execute the cleanup.
Is there a way to specify the cleanup options directly with powerhell/command line(without the need to manually select things to be deleted)?
The following Powershell script automates CleanMgr.exe. In this case, it removes temporary files and runs the Update Cleanup extension to purge superseded Service Pack Backup files (Windows 10 now does this automatically via a scheduled task). To automate other extensions, create a "StateFlags0001" property in the corresponding Registry key, as done in the New-ItemProperty lines. You will find the Registry key names in the "VolumeCaches" branch.
As far as being silent, this script attempts to start CleanMgr.exe in a hidden window. However, at some point CleanMgr spawns new processes which are visible and must be waited on separately.
Write-Host 'Clearing CleanMgr.exe automation settings.'
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\*' -Name StateFlags0001 -ErrorAction SilentlyContinue | Remove-ItemProperty -Name StateFlags0001 -ErrorAction SilentlyContinue
Write-Host 'Enabling Update Cleanup. This is done automatically in Windows 10 via a scheduled task.'
New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Update Cleanup' -Name StateFlags0001 -Value 2 -PropertyType DWord
Write-Host 'Enabling Temporary Files Cleanup.'
New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Temporary Files' -Name StateFlags0001 -Value 2 -PropertyType DWord
Write-Host 'Starting CleanMgr.exe...'
Start-Process -FilePath CleanMgr.exe -ArgumentList '/sagerun:1' -WindowStyle Hidden -Wait
Write-Host 'Waiting for CleanMgr and DismHost processes. Second wait neccesary as CleanMgr.exe spins off separate processes.'
Get-Process -Name cleanmgr,dismhost -ErrorAction SilentlyContinue | Wait-Process
$UpdateCleanupSuccessful = $false
if (Test-Path $env:SystemRoot\Logs\CBS\DeepClean.log) {
$UpdateCleanupSuccessful = Select-String -Path $env:SystemRoot\Logs\CBS\DeepClean.log -Pattern 'Total size of superseded packages:' -Quiet
}
if ($UpdateCleanupSuccessful) {
Write-Host 'Rebooting to complete CleanMgr.exe Update Cleanup....'
SHUTDOWN.EXE /r /f /t 0 /c 'Rebooting to complete CleanMgr.exe Update Cleanup....'
}
The PowerShell logic provided below is dynamic and ready for use or automation with the sageset options all being selected and no user interaction being required. This was inspired by multiple answers and comments from this post.
Note: I've adjusted for my needs and used successfully without any issues on multiple remote and local Windows 10 systems in particular.
Run on Local System
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\*' | % {
New-ItemProperty -Path $_.PSPath -Name StateFlags0001 -Value 2 -PropertyType DWord -Force
};
Start-Process -FilePath CleanMgr.exe -ArgumentList '/sagerun:1' ##-WindowStyle Hidden
Run on Remote System
$cred = Get-Credential "domain\administrator";
Invoke-Command -ComputerName "computer004" {
Process {
Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\*' | % {
New-ItemProperty -Path $_.PSPath -Name StateFlags0001 -Value 2 -PropertyType DWord -Force
};
Start-Process -FilePath CleanMgr.exe -ArgumentList '/sagerun:1' -WindowStyle Hidden
}
} -AsJob -Credential $cred
Supporting Resources
cleanmgr
Invoke-Command
-AsJob
Run the command as a background job on a remote computer.
Use this parameter to run commands that take an extensive time to complete.
Get-Credential
Automate process of Disk Cleanup cleanmgr.exe without user intervention
Creating a Disk Cleanup Handler
You can use cleanmgr /verylowdisk to silently automate all the cleanup steps.
The only solution I found is to manually set the registry values like this:
...
#Set StateFlags0012 setting for each item in Windows 8.1 disk cleanup utility
if (-not (get-itemproperty -path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Active Setup Temp Folders' -name StateFlags0012 -ErrorAction SilentlyContinue)) {
set-itemproperty -path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Active Setup Temp Folders' -name StateFlags0012 -type DWORD -Value 2
set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\BranchCache' -name StateFlags0012 -type DWORD -Value 2
set-itemproperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Downloaded Program Files' -name StateFlags0012 -type DWORD -Value 2
...
see full example
I ran into the same issue. Researching the possible ways, I have found the following:
http://stealthpuppy.com/cleaning-up-and-reducing-the-size-of-your-master-image/
It shows how to create the sageset registry settings via cmd. You can then use the sagerun:# cmd. I have not tried it via script yet, but have validated that it works...
This script will get all the Volume Caches from the Registry, enable them to be cleaned and run the CLEANMGR.EXE for all caches.
$VolumeCachesRegDir = "hklm:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches"
$CacheDirItemNames = Get-ItemProperty "$VolumeCachesRegDir\*" | select -ExpandProperty PSChildName
$CacheDirItemNames |
%{
$exists = Get-ItemProperty -Path "$VolumeCachesRegDir\$_" -Name "StateFlags6553" -ErrorAction SilentlyContinue
If (($exists -ne $null) -and ($exists.Length -ne 0))
{
Set-ItemProperty -Path "$VolumeCachesRegDir\$_" -Name StateFlags6553 -Value 2
}
else
{
New-ItemProperty -Path "$VolumeCachesRegDir\$_" -Name StateFlags6553 -Value 0 -PropertyType DWord
}
}
Start-Sleep -Seconds 3
Write-Host 'Running CleanMgr.exe...'
Start-Process -FilePath CleanMgr.exe -ArgumentList '/sagerun:65535' -WindowStyle Hidden -PassThru
cls
Running CleanMgr.exe in a powershell script or by itself seems to work fine as long as you run it locally with an account that has local admin rights. But try running it remotely via any remote management tool or remote scripting command (Invoke-Command) and it does not run. You might see the process running on the remote system but it doesn't seem to cleanup anything and the process never ends. I would be interested if anyone has been able to get cleanmgr.exe to run remotely without any user interaction. E.G. ConfigMgr Right Click Tools, ConfigMgr App or PKG, Task Scheduler.

Get IIS Bindings from many webservers using powershell remoting, invoke command and module webadministration

Right now I made a small script to see my actual webbindings on a server.
Import-Module WebAdministration;
$today = Get-Date -format M.d.yyyy
$machine = hostname
function IISRport
{
Get-ChildItem -path IIS:\Sites | out-file "\\server01\d$\_utils\PowerShell Scripts\IISexport\IISExport$machine$today.txt"
}
IISReport
This wil outfile my IIS bindings to txt which works brilliant.
I now need to invoke that command to several other servers and save the output file on one server. since the machine name will be diffrent I expect as many outputs as servers.
I tried for example the following :
icm -comp server02 {get-childitem -path IIS:\Sites}
But than the imported Module webadministration is not working, since I only loaded on one server. So I tried to load that remotely using :
icm -comp server02 {import-module webadministration}
without success.
How to achieve that?
This will get the data from all machines defined in $machines and output to \\server01\d$_utils\PowerShell Scripts\IISexport\.
$today = Get-Date -format M.d.yyyy
$machines = #("server01","server02")
foreach($machine in $machines) {
icm -comp $machine { param($machine,$today)
import-module webadministration;
Get-ChildItem -path IIS:\Sites |
out-file "\\server01\d$\_utils\PowerShell Scripts\IISexport\IISExport$machine$today.txt"
} -ArgumentList $machine,$today
}
You can of course change the output path( and import list of machines from a file,AD or some other source).