?
Solved

Remote Powershell Script to

Posted on 2014-01-24
18
Medium Priority
?
466 Views
Last Modified: 2014-04-06
Hi, I was wondering if anyone could help me.
When a server has more than five remote powershell sessions running, the sixth is declined.  Without increasing the number of sessions I found this site which manages to solve the issue, by termintaing sessions which are no longer used, Link - http://jrich523.wordpress.com/2012/01/19/managing-remote-wsman-sessions-with-powershell/

I'm just trying to understand how to get this to work within a script using PowerShell v2.

#
param(
	[Parameter(Mandatory = $false,valueFromPipeline=$true)][string] $ChkSSL
)
#
$oldremote = "D:\temp\Remote.csv"
$oldservers = "D:\temp\servers.txt"
#
#
remove-item $oldremote -ErrorAction:SilentlyContinue
remove-item $oldtxt2 -ErrorAction:SilentlyContinue
#
#
$remote = "D:\temp\Remote.csv"
$Servers = "D:\temp\servers.txt"
$ComputerName = Get-Content -Path $Servers
#
#

#
	IF($Computername -eq $NULL) {
		Write-Host "No Computers Names Were Found" -Fore White
	} ELSE {
		
		$port = If($chkssl){5986}else{5985}
		$uri = "http://$($computername):$port/wsman"
		$sessions = Get-WSManInstance -ConnectionURI $URI shell -Enumerate -erroraction:silentlycontinue | Out-Null
		
		Foreach($session in $sessions)

		$hash = @{
					Server = $ComputerName.ToString()
					Session = $session.owner
					clientip = $session.clientIp
					sessiontime = [System.Xml.XmlConvert]::ToTimeSpan($session.shellRunTime).tostring()
					idletime = [System.Xml.XmlConvert]::ToTimeSpan($session.shellInactivity).tostring()         
					shellid = $session.shellid         
					connectionuri = $uri
					ChkSSL = $chkssl
					$results += $object
				}
	
	
	{
		$Object = New-Object
		$Object | Add-Member -Name 'Server' -MemberType Noteproperty -Value $hash.server
		$Object | Add-Member -Name 'owner' -MemberType Noteproperty -Value $hash.owner
		$Object | Add-Member -Name 'clientip' -MemberType Noteproperty -Value $hash.clientip
		$Object | Add-Member -Name 'sessiontime' -MemberType Noteproperty -Value $hash.sessiontime
        $Object | Add-Member -Name 'idletime' -MemberType Noteproperty -Value $hash.idletime
		$Object | Add-Member -Name 'shellid' -MemberType Noteproperty -Value $hash.shellid
		$Object | Add-Member -Name 'connectionuri' -MemberType Noteproperty -Value $hash.connectionuri
		$Object | Add-Member -Name 'ChkSSL' -MemberType Noteproperty -Value $hash.chkssl
		$results += $Object
		}
	}
	{
	$results | Format-Table | Out-File -FilePath $remote
	}

$data = Get-Content -Path $remote
write-host $data.count total lines read from file
 foreach ($line in $data)
 {
     write-host $line
 }

Open in new window

0
Comment
Question by:patelbg2001
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 7
18 Comments
 
LVL 70

Expert Comment

by:Qlemo
ID: 39812316
You don't include that code that way. You should put it into an own file, and import that (using . C:\PathTo\Script.ps1); or put the complete code as-is in front of your own.
In both cases just call the functions defined: Get-RemotePSSession $Computername to get the sessions.
0
 
LVL 6

Author Comment

by:patelbg2001
ID: 39812784
I would just prefer to call it from a .\name.ps1 file. I dont seem to return any values from the script, this is why I'm asking for help. Could you help?
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 39812988
The script is not return anything, because it just defines the tools to use later in your code. You need to "call" the functions. But since you didn't provide the limits you think "inactive" means, and your code making no sense to me, I'll have to guess.

In raw, your script should look like this:
# load the definition
. c:\ScriptPath\Get-RemotePSSession.ps1

# use it
$servers = "D:\temp\servers.txt"
$MaxIdleTime = '00:30:00'   # This means 30 minutes.

Get-Content -Path $Servers | 
  Get-RemotePSSession |
  where { $_.IdleTime -ge $MaxIdleTime } |
  Remove-RemotePSSession

Open in new window

This will kill all WSMan session not doing anything for 30 minutes.
[rant mode on]
Be aware that you have to use exactly that time format of 'hh:mm:ss', because the function converts the idle time to a string, which is plain stupid for processing it further. No clue why the author did that. The functions are clumsy, and there is no need for a custom class definition in it - much ado about nothing ;-).
[rant mode off]
0
Office 365 Training for IT Pros

Learn how to provision tenants, synchronize on-premise Active Directory, implement Single Sign-On, customize Office deployment, and protect your organization with eDiscovery and DLP policies.  Only from Platform Scholar.

 
LVL 6

Author Comment

by:patelbg2001
ID: 39814463
The term 'Get-RemotePSSession' is not recognized as the name of a cmdlet, function, script file, or operable program. So that does not work!
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 39814605
You stuffed the original code of JRich into a file Get-RemotePSSession.ps1, and used the correct path for it in my code snippet? And no error before that "The term ..."?
0
 
LVL 6

Author Comment

by:patelbg2001
ID: 39817550
No, I don't intend to use the complete code, I was looking for better understanding of this code, so I could apply it into something I was looking into. and I was looking for help creating something around this which is just as effective
0
 
LVL 6

Author Comment

by:patelbg2001
ID: 39817972
PowerShell here-strings don’t like whitespace. The here-string’s “@ terminator needs to be on its own line, with no preceding white-space/tabs/whatever.
0
 
LVL 6

Author Comment

by:patelbg2001
ID: 39818227
Still recieving errors, this is being run on Powershellv2

Get-Member : No object has been specified to the get-member cmdlet.
At D:\Bhav\RemoteCheckv2.ps1:25 char:27
+                     $session | Get-Member <<<<
    + CategoryInfo          : CloseError: (:) [Get-Member], InvalidOperationException
    + FullyQualifiedErrorId : NoObjectInGetMember,Microsoft.PowerShell.Commands.GetMemberCommand

Exception calling "ToTimeSpan" with "1" argument(s): "The string '' is not a valid TimeSpan value."
At D:\Bhav\RemoteCheckv2.ps1:32 char:47
+                         $x = [System.Xml.XmlConvert]::ToTimeSpan <<<< ($session.shellRunTime)
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

Exception calling "ToTimeSpan" with "1" argument(s): "The string '' is not a valid TimeSpan value."
At D:\Bhav\RemoteCheckv2.ps1:36 char:47
+                         $y = [System.Xml.XmlConvert]::ToTimeSpan <<<< ($session.shellInactivity)
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

Function Get-RemotePSSession {
	[CmdletBinding()]
	Param ([Parameter(Mandatory=$true,ValueFromPipeline=$true,Position=0)][string] $ComputerName,
					[Switch] $UseSSL
					)
#
#
		
Begin
	{
	Write-Host "Script Begin"
	$results = @()
	}
		
#
#
 Process
	{
	 Write-Host "Script Process"
	 $port = If($usessl){5986}else{5985}
	 $uri = "http://$($computername):$port/wsman"
	 $sessions = Get-WSManInstance -ConnectionURI $URI shell -Enumerate
		foreach($session in $sessions)
					{
					$session | Get-Member
						$obj = New-Object PSObject
						#$obj.owner = $session.owner
						$obj | Add-Member -Name 'owner' -MemberType Noteproperty -Value $session.owner
						#$obj.clientip = $session.clientIp
						$obj | Add-Member -Name 'clientIp' -MemberType Noteproperty -Value $session.clientIp
						# $obj.sessiontime = [System.Xml.XmlConvert]::ToTimeSpan($session.shellRunTime).tostring()
						$x = [System.Xml.XmlConvert]::ToTimeSpan($session.shellRunTime)
						$xx = [String] $x
						$obj | Add-Member -Name 'sessiontime' -MemberType Noteproperty -Value $xx
						# $obj.idletime = [System.Xml.XmlConvert]::ToTimeSpan($session.shellInactivity).tostring()
						$y = [System.Xml.XmlConvert]::ToTimeSpan($session.shellInactivity)
						$yy = [STRING] $y
						$obj | Add-Member -Name 'idletime' -MemberType Noteproperty -Value $yy
						# $obj.shellid = $session.shellid
						$obj | Add-Member -Name 'shellid' -MemberType Noteproperty -Value $session.shellid
						# $obj.connectionuri = $uri            
						$obj | Add-Member -Name 'ConnectionURI' -MemberType Noteproperty -Value $uri
						# $obj.UseSSL = $usessl
						$obj | Add-Member -Name 'SSL' -MemberType Noteproperty -Value $usessl
						$results += $obj
						}
					}
#
#
End
	{
	Write-Host "Script End"
	$results
	}
}

Open in new window

0
 
LVL 70

Expert Comment

by:Qlemo
ID: 39818720
Re "No, I don't intend to use the complete code": In PowerShelll you should use the concept of small functions doing some specific work. It is not praticable to take parts of code into a new script, changing here and there, to get something slightly different, because that is prone to errors, and removes the ability to perform tests in small units.
I see you now followed that advice somehow, which is a good start.

I don't know what to say in regard of your here-string comment - yes, that is true, no spaces in front of the end terminator allowed.

Get-Member will throw that error whenever it encounters an empty var/object, which has the value of $null by definition. You probably run into another issue with the foreach statement, which goes to the loop even if the var is $null. I assume $sessions = Get-WSManInstance -ConnectionURI $URI shell -Enumerate did not return anything, then $sessions is $null, and the loop will be run once.

As far as I can see, your modifications should work that way you do. Though it is less effective to use Add-Member then to provide a hash table with the
$result += New-Object PsObject -Property @{
  name1 = value1
  name2 = value2
}

Open in new window

The only (potential) issue is that foreach behaviour. Another explanation is that you get an error, but ignored that?
0
 
LVL 6

Author Comment

by:patelbg2001
ID: 39818765
The original code is based on v3, so unless it's works for v2, I have no choice but to change the logic to make it fit for this purpose.
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 39818852
It works with v2, and is not based on v3.
I've checked the foreach issue, and I'm correct. If you have no remote session, the loop is still processed once with a $null value.
Instead of
$sessions = Get-WSManInstance -ConnectionURI $URI shell -Enumerate
foreach($session in $sessions)

Open in new window

this should be used:
foreach($session in Get-WSManInstance -ConnectionURI $URI shell -Enumerate)

Open in new window

or, even better,
Get-WSManInstance -ConnectionURI $URI shell -Enumerate | foreach {

Open in new window

but that requires you replace $server with $_ in the loop.
0
 
LVL 6

Author Comment

by:patelbg2001
ID: 39821718
Can you show me your complete code, so I understand, where I am going wrong?
0
 
LVL 70

Expert Comment

by:Qlemo
ID: 39821774
Applied to the code you posted last:
Function Get-RemotePSSession {
  [CmdletBinding()]
  Param ([Parameter(Mandatory=$true,ValueFromPipeline=$true,Position=0)][string] $ComputerName,
         [Switch] $UseSSL
        )
#
#
    
Begin {
  Write-Host "Script Begin"
  $results = @()
}
    
#
#
Process {
  Write-Host "Script Process"
  $port = If($usessl){5986}else{5985}
  $uri  = "http://$($computername):$port/wsman"
  foreach($session in Get-WSManInstance -ConnectionURI $uri shell -Enumerate)
  {
    $results += New-Object PSObject -Property @{
                  owner         = $session.owner
                  clientIP      = $session.clientIp
                  sessionTime   = [System.Xml.XmlConvert]::ToTimeSpan($session.shellRunTime   ).tostring()
                  idleTime      = [System.Xml.XmlConvert]::ToTimeSpan($session.shellInactivity).tostring()
                  shellID       = $session.shellid
                  connectionURI = $uri            
                  UseSSL        = $usessl
                }
  }
#
#
End
{
  Write-Host "Script End"
  $results
}
}

Open in new window

I could not resist to make the script more compact.
0
 
LVL 6

Author Comment

by:patelbg2001
ID: 39852741
the script does not return any data
0
 
LVL 70

Accepted Solution

by:
Qlemo earned 2000 total points
ID: 39852830
The script only defines a function Get-RemotePSSession. You still need to execute that function, after having defined it. E.g. add something like this as last line:
Get-RemotePSSession Pc1, Pc2, Pc3

Open in new window

0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Auditing domain password hashes is a commonly overlooked but critical requirement to ensuring secure passwords practices are followed. Methods exist to extract hashes directly for a live domain however this article describes a process to extract u…
Unified and professional email signatures help maintain a consistent company brand image to the outside world. This article shows how to create an email signature in Exchange Server 2010 using a transport rule and how to overcome native limitations …
The viewer will learn how to count occurrences of each item in an array.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
Suggested Courses

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question