Output from invoke-command not returning - powershell

I have the following scriptblock:
$scriptblock = {
$regpath = "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"
$securitylayer = Get-ItemProperty -Path $regpath -Name SecurityLayer -ErrorAction SilentlyContinue
If (!($securitylayer) -or ($securitylayer.securitylayer -ne '0')) {
Write-Host -ForegroundColor Yellow "Regkey not present or value not 0. Creating/setting to 0"
#Commented out for testing purposes
#Set-ItemProperty -Path $regpath -Name SecurityLayer -Value 0
}
Else {Write-Host -ForegroundColor green "Regkey present and set to 0. Skipping."}
}
that I pass to a PSSession on a remote machine running Server 2003 SP2:
$computername = 'computer'
$pssession = New-PSSession -ComputerName $computername -Name $computername
Invoke-Command -Session $pssession -ScriptBlock {$scriptblock}
But i don't see any output.
I've also tried
write-output
but still don't see any output.
I saw another post that suggested doing the following, however nothing was returned:
$scriptblock = {
$regpath = "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"
$securitylayer = Get-ItemProperty -Path $regpath -Name SecurityLayer -ErrorAction SilentlyContinue
If (!($securitylayer) -or ($securitylayer.securitylayer -ne '0')) {
new-object pscustomobject –property #{Result = "Regkey not present or value not 0. Creating/setting to 0"}
#Commented out for testing purposes
#Set-ItemProperty -Path $regpath -Name SecurityLayer -Value 0
}
Else {new-object pscustomobject –property #{Result = "Regkey present and set to 0. Skipping."}}
}
$computername = 'computer'
$pssession = New-PSSession -ComputerName $computername -Name $computername
$results = Invoke-Command -Session $pssession -ScriptBlock {$scriptblock}
$results.result
Code runs as expected when run on machine.

You are wrapping your scriptblock in a scriptblock, so it's not actually executing the script block. Just remove the {} from around the {$scriptblock}:
Invoke-Command -Session $pssession -ScriptBlock $scriptblock

Related

Check if process is running on multiple remote computers and copy a file if process is NOT running, keep list of those which succeeded

I need to copy a file to multiple computers, but can only do so if a particular app (process) is not running.
I know I can use Invoke-Command to run a script (scriptblock) on a list of machines.
But how can I check if process is running on the machine and then only copy file if it is not running.
So that at the end of running against a load of computers I can easily see those which succeeded e.g. process was not running and file was copied
Thanks
UPDATE:
I am assuming something like this will do the first bits of what I am asking, but how to visually show or log success or failure so I know which computers have been done - doesn't need to be anything fancy, even if simply a variable that holds computername of those where process wasn't running and file was copied okay
Invoke-Command -ComputerName PC1, PC2, PC3 -ScriptBlock {
If ((Get-process -Name notepad -ea SilentlyContinue) -eq $Null){
Copy-Item -Path "\\server01\c$\test\file.txt" -Destination "C:\test\file.txt" -Force
}
}
$Procs = invoke-command -ComputerName PC1 { get-process | Select Name }
If($Procs -notmatch "Notepad"){ Copy-Item -Path "\\server01\c$\test\file.txt" -Destination "\\$PC1\c$\test\" -Force}
edited:
$computers = #("PC1","PC2","PC3")
Foreach($computer in $computers){
$Procs = invoke-command -ComputerName $computer { Get-Process Notepad -ErrorAction SilentlyContinue}
If(!$Procs){"$Computer - not running Notepad"; Copy-Item -Path "\\server01\c$\test\file.txt" -Destination "\\$computer\c$\test\" -Force}
elseif($Procs){"$Computer - is running Notepad"}
}
Edit2(for clean output):
$computers = #("PC1","PC2","PC3")
$RNote = #()
$NNote = #()
$off = #()
Foreach($computer in $computers){
$TestC = Test-Connection -ComputerName $computer -Count 1
If(!($TestC)){$off += $computer} Else{
$Procs = invoke-command -ComputerName $computer { Get-Process Notepad -ErrorAction SilentlyContinue}
If(!$Procs){$NNote +=$computer; Copy-Item -Path "\\server01\c$\test\file.txt" -Destination "\\$computer\c$\test\" -Force}
elseif($Procs){$RNote +=$computer}
}
}
$leng =[array]$RNote.count,$NNote.Count,$off.count
[int]$max = ($leng | measure -Maximum).Maximum
for($i=0; $i -lt $max;$i++){
[pscustomobject]#{
"Notepad On" = $(if ($RNote[$i]){$RNote[$i]})
"Notepad Off" = $(if ($NNote[$i]){$NNote[$i]})
"Offline " = $(if ($off[$i]){$off[$i]})
}
}
I think this is what you're looking for or at least close:
$Results = #()
$Results +=
Invoke-Command -ComputerName DellXPS137000, DellXPS8920 -ScriptBlock {
$GPArgs = #{Name = "Notepad++"
ErrorAction = "SilentlyContinue"}
If ( $Null -ne (get-process #GPArgs )) {
#Process your copy here
$Status = "Success"
}
Else {$Status = "Failed"}
$Machine =
(Get-CimInstance -ClassName 'Win32_OperatingSystem').CSName
Return ,"$Machine : $Status"
}
Value of $Results:
PS> $results
DELLXPS137000 : Success
DELLXPS8920 : Failed
HTH

Invoke-Command with remote session: Cannot validate argument on parameter

I wrote a script to restart a few ASP.NET websites on a remote server:
$computerName = #...
$password = #...
$secureStringPassword = ConvertTo-SecureString -AsPlainText -Force -String $password
$userName = #...
$credential= New-Object System.Management.Automation.PSCredential ($userName, $secureStringPassword)
$websiteNames = #..., #..., #...
Get-PSSession -ComputerName $computerName -Credential $credential | Remove-PSSession
$psSession = New-PSSession -ComputerName $computerName -Credential $credential
Invoke-Command -Session $psSession -ScriptBlock { $websiteNames | foreach{ Stop-Website -Name $_ } }
Invoke-Command -Session $psSession -ScriptBlock { $websiteNames | foreach{ Start-Website -Name $_ } }
$psSession | Remove-PSSession
For some reasons my Invoke-Command do not run properly, I have the following error message:
Cannot validate argument on parameter 'Name'. The argument is null. Provide a valid value for the argument, and then try running the command again.
When the commands are run after an Enter-PSSession it works fine within a -ScriptBlock it kinda mess up the -Name parameter, any idea how to fix that up?
The remote session cannot access the variables you have defined locally. They can be referenced with $using:variable
Invoke-Command -Session $psSession -ScriptBlock { $using:websiteNames | foreach{ Stop-Website -Name $_ } }
Invoke-Command -Session $psSession -ScriptBlock { $using:websiteNames | foreach{ Start-Website -Name $_ } }
More information in the about_remote_variables help:
get-help about_remote_variables -Full
Actually just needed to pass the arguments to the -ArgumentList of the -ScriptBlock and use $args to reference to it within the function block:
Invoke-Command -Session $psSession -ScriptBlock { $args | foreach{ Stop-Website -Name $_ } } -ArgumentList $websiteNames
Invoke-Command -Session $psSession -ScriptBlock { $args | foreach{ Start-Website -Name $_ } } -ArgumentList $websiteNames

Passing a variable inside s nested loop

I'm tying to work out how I pass a variable from an if statement into a nested if statement starting at:
If ($server -eq $env:COMPUTERNAME)
Foreach ($comp in $computer) {
$server = split-FQDN $comp -part H
$domain = Split-FQDN $comp -part D
#Set the domain based parameters
If ($domain -eq '1.fqdn.com') {
set-domparams $domain $userprompt $userpass
}
Elseif ($domain -eq '2.fqdn.com') {
set-domparams $domain $userprompt $userpass
}
Elseif ($domain -eq '3.fqdn.com') {
set-domparams $domain $userprompt $userpass
}
ElseIf ($domain -eq '4.fqdn.com') {
set-domparams $domain $userprompt $userpass
}
ElseIf ($domain -eq '5.fqdn.com') {
set-domparams $domain $userprompt $userpass
}
ElseIf ($domain -eq '6.fqdn.com') {
set-domparams $domain $userprompt $userpass
}
If ($server -eq $env:COMPUTERNAME) {
$server = $_
#clear Kerberos ticket cache
Invoke-Expression -Command:'cmd.exe /c klist purge' | Out-Null
$buildlogsuccess = check-buildlog $domain
$chocologstatus = Invoke-Command -ScriptBlock {check-choco}
$KMSvalues = Invoke-Command -ScriptBlock {get-winlicense}
$parentOU = get-ParentOU (Get-ADComputer -Server $dc -SearchBase $searchbase -Filter {name -eq $server} -Credential $fetchCreds) | select -expand parentou
$SCCMcheck = Invoke-Command -ScriptBlock {get-sccmstatus}
$scomcheck = Invoke-Command -ScriptBlock {get-scomstatus} -argumentlist $scom
$AV = Invoke-Command -ScriptBlock {get-avstatus}
$wfirewall = Invoke-Command -ScriptBlock {(get-service MpsSvc).status}
$net35 = Invoke-Command -ScriptBlock {(Get-WindowsFeature NET-Framework-Core).installed}
$admins = Invoke-Command -ScriptBlock {check-admins}
$DomainComms = Invoke-Command -ScriptBlock {get-domaininfo}
$bigfix = Invoke-Command -ScriptBlock {get-bigfix}
}
Else {
$server = $_
#clear Kerberos ticket cache
Invoke-Expression -Command:'cmd.exe /c klist purge' | Out-Null
#start running functions against target server(s) to get required info
$PSSession = New-PSSession -ComputerName $comp -Credential $fetchCreds -Name $server
$buildlogsuccess = check-buildlog $domain
$chocologstatus = Invoke-Command -Session $pssession -ScriptBlock ${function:check-choco}
$KMSvalues = Invoke-Command -Session $PSSession -ScriptBlock ${Function:get-winlicense}
$parentOU = get-ParentOU (Get-ADComputer -Server $dc -SearchBase $searchbase -Filter {name -eq $server} -Credential $fetchCreds) | select -expand parentou
$SCCMcheck = Invoke-Command -Session $PSSession -ScriptBlock ${Function:get-sccmstatus}
$scomcheck = Invoke-Command -Session $PSSession -ScriptBlock ${function:get-scomstatus} -argumentlist $scom
$AV = Invoke-Command -Session $PSSession -ScriptBlock ${Function:get-avstatus}
$wfirewall = Invoke-Command -Session $PSSession -ScriptBlock {(get-service MpsSvc).status}
$net35 = Invoke-Command -Session $PSSession -ScriptBlock {(Get-WindowsFeature NET-Framework-Core).installed}
$admins = Invoke-Command -Session $PSSession -ScriptBlock ${Function:check-admins}
$DomainComms = Invoke-Command -Session $PSSession -ScriptBlock ${Function:get-domaininfo}
$bigfix = Invoke-Command -Session $PSSession -ScriptBlock ${Function:get-bigfix}
#clean up the remote session
Remove-PSSession -Name $server
}
I already have some global variables in use that are passed by a loaded function, but I'm trying to avoid do the same for this bit of code and understand how to pass my remaining variables ($comp, $computer and $domain) correctly to the next inner loop.
I've tried getting $server to work doing the following but haven't had any success as of yet:
$server = $_
This is more code review opinion instead of an answer, but anyway.
Instead of long if...elseif constructs, why not use table driven programming? If there are lots of domains and they require different credentials, maintaining the if...elseif is tedious. Store the credentials in custom Powershell objects and those in a hashtable. Then lookup can be done with the domain name only. Like so,
# Declare a hashtable and add custom credential objects
$creds=#{}
$creds.Add('foo.fqdn', $(New-Object –TypeName PSObject –Prop #{'Domain'='foo.fqdn'; 'User'='foo.user'; 'Pass'='foo.pass'}))
$creds.Add('bar.fqdn', $(New-Object –TypeName PSObject –Prop #{'Domain'='bar.fqdn'; 'User'='bar.user'; 'Pass'='bar.pass'}))
$creds.Add('zof.fqdn', $(New-Object –TypeName PSObject –Prop #{'Domain'='zof.fqdn'; 'User'='zof.user'; 'Pass'='zof.pass'}))
# Later when credentials are needed, check if the domain is present
# and get the values from the hashtable.
if($creds.ContainsKey($domain) {
set-domparams $domain $creds[$domain].User $creds[$domain].Pass
} else {
write-warning "Domain $domain not found!"
}
I think this is a non-question as your variables are valid within the loops/statements they are created.
Foreach ($comp in $computer) {
$server = split-FQDN $comp -part H
$domain = Split-FQDN $comp -part D
if($true){
# $comp, $server and $domain are all in scope
Write-host "$comp $server $domain"
if($true){
# also true in nested if statements
Write-host "$comp $server $domain"
}
}
Else{
# $comp, $server and $domain are all in scope
Write-host "$comp $server $domain"
}
}
# outside, $comp is not available, only $computer
# $server and $domain will only contain the values from the last run of the foreach loop.

PowerShell pass a switch to a function with Invoke-Command

I'm having some difficulties passing the switch -CleanFolders to a function by using Invoke-Command. I found this, but I don't really know how to implement it as it's not targeted to a function.
Calling my function like this works fine:
Delete-OldFiles $Target $OlderThanDays $Server -CleanFolders
Invoke-Command -ComputerName "$Server" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server)
But this doesn't work at all:
Invoke-Command -ComputerName "$Server" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server, -CleanFolders)
Full script:
#__________________________________________________________________________________________________________________________________
$ImportFile = "S:\Input\Scheduled Task\Auto_Clean.csv"
$Password = cat "S:\Input\pwd.txt" | ConvertTo-SecureString -Force
$UserName = "domain\me"
#__________________________________________________________________________________________________________________________________
# Scriptblock for running the function in a job
$JobFunc = {
# Function that removes files older than x days in all subfolders
Function Delete-OldFiles {
<#
.SYNOPSIS
Script to delete files and folders older than x days
.DESCRIPTION
Remove files older than x days in all subfolders and write success and failure actions to the logfile in "\\DEUSTHEIDIT02\Log\Scheduled Task\Auto_Clean\".
By default, empty foldes will be left behind and not deleted.
.PARAMETER Target
The path that will be recusively scanned for old files
.PARAMETER OlderThanDays
Filter for age of file, entered in days. Use 0 for all files to be removed
.PARAMETER CleanFolders
If this switch is specified folders that are older than 'OlderThanDays' and are empty will be removed. Default behaviour of this script is to leave empty folders behind.
.EXAMPLE
Delete-OldFiles -Target "\\grouphc.net\bnl\DEPARTMENTS\Brussels\CBR\SHARE\Target" -OlderThanDays "10"
Delete-OldFiles "\\grouphc.net\bnl\DEPARTMENTS\Brussels\CBR\SHARE\Target" "10"
Delete-OldFiles "E:\DEPARTMENTS\CBR\SHARE\Target" "10"
Description:
Deletes all files older than 10 days in the Target folder and all of its subfolders and write success and failure to the log.
.EXAMPLE
Delete-OldFiles "\\grouphc.net\bnl\DEPARTMENTS\Brussels\CBR\SHARE\Target" "10" -CleanFolders
Description:
Deletes all files older than 10 days and all empty folders in the Target folder and all of its subfolders and write success and failure to the log.
.NOTES
REQUIREMENTS Remote server:
PowerShell 2.0
As admin run 'Set-ExecutionPolicy RemoteSigned'
As amdin run 'Enable-WSManCredSSP -Role Server -Force'
REQUIREMENTS Script server:
Enable-WSManCredSSP -Role Client -DelegateComputer *.grouphc.net -Force
CHANGELOG
2014/05/06 Script born
2014/05/07 Added total runtime of the script to the logfile
2014/05/12 Added timestamps, fail and success messages to the logfile
2014/05/13 Added PowerShell 2.0 compatibility for Windows Server 2003
2014/05/13 Added remove empty directories
2014/05/14 Added comment section on top
2014/05/15 Added parameters to pass variables $Target and $OlderThanDays
2014/05/19 Added CSV input file for easy management
2014/05/20 Created function Delete-OldFiles and Delete-OldFolders
2014/05/22 Rewrote script for calling functions
2014/05/23 Added switch -CleanFolders
2014/06/02 Added password authentication for double hop
2014/06/03 Added loging capability to different files with timestamps
.AUTHOR
Me #>
[CmdletBinding(SupportsShouldProcess=$True)] # Add -WhatIf support for dry run
Param(
[Parameter(Mandatory=$True,Position=1)]
[ValidateScript({Test-Path $_})]
[String]$Target,
[Parameter(Mandatory=$True,Position=2)]
[Int]$OlderThanDays,
[Parameter(Mandatory=$False,Position=3)]
[String]$Server,
[switch]$CleanFolders
)
#__________________________________________________________________________________________________________________________________
# Create logfile with the correct name
# Gets date and reformats to be used in log filename
$TempDate = (get-date).ToString("dd-MM-yyyy")
# Reformats $Target so it can be used in the log filename
$TempFolderPath = $Target -replace '\\','_'
$TempFolderPath = $TempFolderPath -replace ':',''
$TempFolderPath = $TempFolderPath -replace ' ',''
# Combines the date and the path scanned into the log filename
$script:LogFile = "\\DEUSTHEIDIT02\Log\Scheduled Task\Auto_Clean\$Server - $TempFolderPath - $TempDate.log"
#__________________________________________________________________________________________________________________________________
# Check the version of PowerShell
if ($PSVersionTable.PSVersion.Major -ge "3") {
# PowerShell 3+ Remove files older than (FASTER)
Get-ChildItem -Path $Target -Recurse -File |
Where-Object { $_.CreationTime -lt (Get-Date).AddDays(-$OlderThanDays) } |
ForEach {
$Item = $_.FullName
Remove-Item $Item -Recurse -Force -ErrorAction SilentlyContinue
# Log succes/failure
$Timestamp = (Get-Date).ToShortDateString()+" | "+(Get-Date).ToLongTimeString()
if (Test-Path $Item) {
"$Timestamp | FAILLED: $Server $Item (IN USE)"
}
else {
"$Timestamp | REMOVED: $Server $Item"
}
} | Tee-Object $LogFile -Append }
Else {
# PowerShell 2 Remove files older than
Get-ChildItem -Path $Target -Recurse |
Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt (Get-Date).AddDays(-$OlderThanDays) } |
ForEach {
$Item = $_.FullName
Remove-Item $Item -Recurse -Force -ErrorAction SilentlyContinue
# Log succes/failure
$Timestamp = (Get-Date).ToShortDateString()+" | "+(Get-Date).ToLongTimeString()
if (Test-Path $Item) {
Write-Host "$Timestamp | FAILLED: $Server $Item (IN USE)"
"$Timestamp | FAILLED: $Server $Item (IN USE)"
}
else {
Write-Host "$Timestamp | REMOVED: $Server $Item"
"$Timestamp | REMOVED: $Server $Item"
}
} | Out-File $LogFile -Append }
#__________________________________________________________________________________________________________________________________
# Switch -CleanFolders deletes empty folders older than x days
if ($CleanFolders) {
# Check the version of PowerShell
if ($PSVersionTable.PSVersion.Major -ge "3") {
# PowerShell 3+ Remove empty folders older than (FASTER)
Get-ChildItem -Path $Target -Recurse -Force -Directory -ErrorAction SilentlyContinue |
Where-Object { $_.CreationTime -lt (Get-Date).AddDays(-$OlderThanDays) } |
Where-Object { (Get-ChildItem -Path $_.FullName -Recurse -Force -File) -eq $null } |
ForEach {
$Item = $_.FullName
Remove-Item $Item -Recurse -Force -ErrorAction SilentlyContinue
# Log succes/failure
$Timestamp = (Get-Date).ToShortDateString()+" | "+(Get-Date).ToLongTimeString()
if (Test-Path $Item) {
"$Timestamp | FAILLED: $Server $Item (IN USE)"
}
else {
"$Timestamp | REMOVED: $Server $Item"
}
} | Tee-Object $LogFile -Append
}
else {
# PowerShell 2 Remove empty folders older than
Get-ChildItem -Path $Target -Recurse -Force -ErrorAction SilentlyContinue |
Where-Object { $_.PSIsContainer -and (Get-ChildItem -Path $_.FullName -Recurse -Force | Where-Object { !$_.PSIsContainer }) -eq $null } |
Where-Object { $_.CreationTime -lt (Get-Date).AddDays(-$OlderThanDays) } |
ForEach {
$Item = $_.FullName
Remove-Item $Item -Recurse -Force -ErrorAction SilentlyContinue
# Log succes/failure
$Timestamp = (Get-Date).ToShortDateString()+" | "+(Get-Date).ToLongTimeString()
if (Test-Path $Item) {
Write-Host "$Timestamp | FAILLED: $Server $Item (IN USE)"
"$Timestamp | FAILLED: $Server $Item (IN USE)"
}
else {
Write-Host "$Timestamp | REMOVED: $Server $Item"
"$Timestamp | REMOVED: $Server $Item"
}
} | Out-File $LogFile -Append
}
}
}
}
#__________________________________________________________________________________________________________________________________
# Read input file and ignore all lines starting with #
$File = (Import-Csv -Path $ImportFile -Header "Server", "Target", "OlderThanDays" | Where { $_.Server -NotMatch "#" } )
#__________________________________________________________________________________________________________________________________
# If the UNC Path is provided we will run the script locally else it wil be run on the remote server as a job
Foreach ($_ in $File) {
# Set easy names
$Server = $_.Server
$Target = $_.Target
$OlderThanDays = $_.OlderThanDays
if ($Server -eq "UNC")
{
Write-Host "UNC Path detected: $Target, $OlderThanDays" -ForegroundColor Yellow
Start-Job -ScriptBlock {Param($Target, $OlderThanDays, $Server) Delete-OldFiles $Target $OlderThanDays $Server} -InitializationScript $JobFunc -ArgumentList ($Target, $OlderThanDays, $Server) -Name DelFiles
# Remove empty folders to: Delete-OldFiles $Target $OlderThanDays $Server -CleanFolders
}
else
{
Write-Host "Local path detected: $Server, $Target, $OlderThanDays" -ForegroundColor Cyan
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName,$Password
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName,$Password
Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {$JobFunc; Delete-OldFiles $Target $OlderThanDays $Server} -ArgumentList ($Target, $OlderThanDays, $Server) #-AsJob -JobName DelFiles
#Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {Delete-OldFiles $args[0] $args[1] $args[2] -CleanFolders:$args[3]} -ArgumentList ($Target, $OlderThanDays, $Server, $true) -AsJob -JobName DelFiles
# Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server)
#Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server) -AsJob -JobName DelFiles
#Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {Delete-OldFiles $Target, $OlderThanDays, $Server} -ArgumentList ($Target, $OlderThanDays, $Server) #-AsJob -JobName DelFiles
#Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server) #-AsJob -JobName DelFiles
#Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server)
#Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {$JobFunc} -ArgumentList ($Target, $OlderThanDays, $Server) -AsJob -JobName DelFiles
#Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server)
}
}
Thank you for your help.
Try like this:
$sb = {
function Delete-OldFiles {
#...
}
Delete-OldFiles $args[0] $args[1] $args[2] -CleanFolders:$args[3]
}
Invoke-Command -ComputerName $Server -Authentication Credssp `
-Credential $Credentials -ScriptBlock $sb `
-ArgumentList ($Target, $OlderThanDays, $Server, $true)

Remote Registry using Enter-PSSession

I am trying to read strings in a remote registry. When I run the script I am working on, it connects to the workstation in the list, but it only reads the local computer when running, not the remote. any Ideas?
#create open dialog box
Function Get-FileName($initialDirectory)
{
[void] [Reflection.Assembly]::LoadWithPartialName( 'System.Windows.Forms' );
$d = New-Object Windows.Forms.OpenFileDialog;
$d.ShowHelp = $True;
$d.filter = "Comma Separated Value (*.csv)| *.csv";
$d.ShowDialog( ) | Out-Null;
$d.filename;
}
# Set Variables with arguments
$strFile = Get-FileName;
$strComputer = Get-Content $strFile;
$date = Get-Date -Format "MM-dd-yyyy";
$outputFile = "C:\PowerShell\Reports";
$cred = Get-Credential
foreach($computer in $strComputer)
{
Enter-PSSession $computer -Credential $cred
Set-Location HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Reliability
$systemInfo = Get-Item -Name LastComputerName
Write-Host $systemInfo
}
foreach($computer in $strComputer)
{
Enter-PSSession $computer -Credential $cred
..
..
}
The above code won't work. Enter-PSSession is not for using in a script. Anything written after that in a script won't run.
Instead, use Invoke-Command and pass rest of the script block as a parameter value. For example,
foreach ($computer in $strComputer) {
Invoke-Command -ComputerName $computer -Credential $cred -ScriptBlock {
Set-Location HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Reliability
$systemInfo = Get-Item -Name LastComputerName
Write-Host $systemInfo
}
}
As the comments already explained, Enter-PSSession is for interactive use. To read remote registry entries, there are several ways.
Use plain reg.exe, it works well enough. Like so,
foreach($computer in $strComputers) {
reg query \\$computer\hklm\software\Microsoft\Windows\CurrentVersion\Reliability /v LastComputerName
}
Use PSSessions. Create a session and Invoke-Command to read registry. Like so,
function GetRegistryValues {
param($rpath, $ivalue)
Set-Location $rpath
$systemInfo = (Get-ItemProperty .).$ivalue
Write-Host $systemInfo
}
$session = New-PSSession -ComputerName $computer
Invoke-Command -Session $session -Scriptblock ${function:GetRegistryValues} `
-argumentlist "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Reliability",`
"LastComputerName"
Remove-PSSession $session
Use .Net classes, Microsoft.Win32.RegistryKey. Like so,
$sk = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $server)
$k = $sk.opensubkey("SOFTWARE\Microsoft\Windows\CurrentVersion\Reliability", $false)
write-host $k.getvalue("LastComputerName")