Get Raw Drive Size - powershell

I need to gather volume capacity sizes for all fixed drives on a server. I am limited to using PowerShell 2 because that is what the sysadmins have deployed on the servers. I can get the information on the formatted drives very easily, using the Get-WmiObject Win32_Volume function.
$ComputerName = "."
Get-WmiObject -ComputerName "$computername" Win32_Volume -Filter "DriveType=3" | foreach {
New-Object PSObject -Property #{
SystemName = $_.SystemName
UsageDate = $((Get-Date).ToString("yyyy-MM-dd HH:mm:ss"))
Label = $_.Label
VolumeName = $_.Name
FileSystem = if ($_.FileSystem -eq $null) {"RAW"} else {$_.FileSystem}
Size = if ($_.FileSystem -eq $null) {
Show-Capacity
} else {
$([Math]::Round(($_.Capacity/1GB), 2))
}
Free = if ($_.FileSystem -eq $null) {
"0.00"
} else {
$([Math]::Round(($_.FreeSpace/1GB), 2))
}
PercentFree = if ($_.Capacity -gt 0) {
$([Math]::Round((([float]$_.FreeSpace/[float]$_.Capacity) * 100), 2))
} else {
'0.00'
}
}
}
The Show-Capacity function is as follows:
function Show-Capacity {
$drive=$_.Name
$dpscript = #"
Select Volume '$drive'
Detail Volume
"#
$Temp= #()
[array]$Temp += ,$dpscript | diskpart
foreach ($line in $Temp) {
if ($line.StartsWith("Volume Capacity") ) {
$Values = $line.Split(":")
}
}
$Capacity = $Values.Trim("G", "T", "M", "B", " ")
$Capacity[1]
}
The formatted drives show up correctly as follows:
UsageDate : 2017-11-09 08:08:17
SystemName : MyServerName
Label :
VolumeName : C:\
Size : 99.9
Free : 77.04
PercentFree : 77.11
The Raw Drives show up as follows:
UsageDate : 2017-11-09 08:08:15
SystemName : MyServerName
Label :
VolumeName : I:\
Size :
Free : 0.00
PercentFree : 0.00
I want Raw Drives to show up this way:
UsageDate : 2017-11-09 08:08:15
SystemName : MyServerName
Label :
VolumeName : I:\
Size : 12000.0
Free : 0.00
PercentFree : 0.00
In the PowerShell logs I see the error: "Cannot index into a null array. At {path}:12 char 11. I'm also getting a trim error, but that is of lesser concern. I've been working on this and reading lots of posts for about 2 weeks now and have not been successful.
I tried the method outlined in this line of posts:
https://blogs.technet.microsoft.com/heyscriptingguy/2013/08/30/automating-diskpart-with-windows-powershell-part-5/
This will always be run on local computer, but will be exported to CSV and aggregated.

Related

Output OS in Azure DevOps

I'm trying to get the disk config, amongst other information from the guest OS (windows) and I can't seem to work out how to get the information using Azure DevOps, this is required as we would like to Automate the task at the point of migration to see what size disks are added and what spare capacity there is. Also we'll be expanding on this with further WMI queries, but I think once I can run a script against the guest OS I can pull out most of the details I need.
Azure DevOps has Contributor on the subscription
I'm using an inline script:
Invoke-AzVMRunCommand -ResourceGroupName "$(ResourceGroupName)' -Name '$(VMName)' -CommandId 'RunPowerShellScript' -ScriptPath ".\_snapshots\drop\CSV\disk.ps1" -Confirm:$false
The disk.ps1 script is:
$lists = Get-WmiObject Win32_LogicalDisk | ? {$_.VolumeName -ne "Temporary Storage"}
$Report = #()
foreach ($list in $lists) {
$info = "" | Select-Object DeviceID,"Size (GB)","FreeSpace (GB)","% FreeSpace",VolumeName
$info.DeviceID = $list.DeviceID
$info.'Size (GB)' = [math]::Round($list.size / 1GB)
$info.'FreeSpace (GB)' = [math]::Round($list.FreeSpace / 1GB)
$info.'% FreeSpace' = [math]::Round((($info.'FreeSpace (GB)' * 100) / $info.'Size (GB)'),0)
$info.VolumeName = $list.VolumeName
$report+=$info
}
$report
The output I get is:
Value : {Microsoft.Azure.Management.Compute.Models.InstanceViewStatus,
Microsoft.Azure.Management.Compute.Models.InstanceViewStatus}
Name :
StartTime :
EndTime :
Status : Succeeded
Error :
Output :
Capacity : 0
Count : 0
Item :
What should I get is:
Value[0] :
Code : ComponentStatus/StdOut/succeeded
Level : Info
DisplayStatus : Provisioning succeeded
Message : DeviceID : C:
Size (GB) : 127
FreeSpace (GB) : 117
% FreeSpace : 92
VolumeName : Windows
I get this when I run the script through PowerShell, same version in both cases.
Can anyone see what I'm missing or where I'm going wrong?
Thanks in advance :)
Try to change the inline script as below:
$run = Invoke-AzVMRunCommand -ResourceGroupName "$(ResourceGroupName)' -Name '$(VMName)' -CommandId 'RunPowerShellScript' -ScriptPath ".\_snapshots\drop\CSV\disk.ps1" -Confirm:$false
Write-Host $run.Value[0]
If you want to get the specific message, you could also use:
Write-Host $run.Value[0].Message

PowerShell Script to set the size of pagefile.sys

How to set the size of Page File on Windows(pagefile.sys) via PowerShell?
This is how we can update the size of pagefile.sys via PowerShell:
# PowerShell Script to set the size of pagefile.sys
$computersys = Get-WmiObject Win32_ComputerSystem -EnableAllPrivileges;
$computersys.AutomaticManagedPagefile = $False;
$computersys.Put();
$pagefile = Get-WmiObject -Query "Select * From Win32_PageFileSetting Where Name like '%pagefile.sys'";
$pagefile.InitialSize = <New_Value_For_Size_In_MB>;
$pagefile.MaximumSize = <New_Value_For_Size_In_MB>;
$pagefile.Put();
Execute the script as below:
PS> .\update_pagefile_size.ps1;
HERE is the solution
THIS is to set C VOL page file to 16384MB, static and D VOL page file to System managed:
# PowerShell Script to set the size of pagefile.sys
# update_pagefile_size.ps1
$pagefile = Get-WmiObject Win32_ComputerSystem -EnableAllPrivileges
$pagefile.AutomaticManagedPagefile = $false
#$pagefile.put() | Out-Null
Gwmi win32_pagefilesetting | where{$_.caption -like 'C:*'}
$pagefileset = Gwmi win32_pagefilesetting | where{$_.caption -like 'C:*'}
$pagefileset.InitialSize = 16384
$pagefileset.MaximumSize = 16384
$pagefileset.Put() | Out-Null
if((Set-WmiInstance -Class Win32_PageFileSetting -Arguments #{name="C:\pagefile.sys";InitialSize = $pagefileset.InitialSize; MaximumSize = $pagefileset.MaximumSize} -EnableAllPrivileges -Verbose) -icontains "already exists"){
$pagefileset = Gwmi win32_pagefilesetting | where{$_.caption -like 'C:*'}
$pagefileset.Delete()
$pagefileset.InitialSize = 16384
$pagefileset.MaximumSize = 16384
Set-WmiInstance -Class Win32_PageFileSetting -Arguments #{name="C:\pagefile.sys";InitialSize = $pagefileset.InitialSize; MaximumSize = $pagefileset.MaximumSize} -EnableAllPrivileges
Gwmi win32_pagefilesetting | where{$_.caption -like 'C:*'}
}
$pagefileset = Gwmi win32_pagefilesetting | where{$_.caption -like 'D:*'}
$pagefileset.InitialSize = 0
$pagefileset.MaximumSize = 0
$pagefileset.Put() | Out-Null
Gwmi win32_pagefilesetting | where{$_.caption -like 'D:*'}
Set-WmiInstance -Class Win32_PageFileSetting -Arguments #{name="D:\pagefile.sys";InitialSize = 0; MaximumSize = 0} -EnableAllPrivileges | Out-Null
Write-host "Don't forget to reboot"
#shutdown /r /t 120 /c "rebooting to fix pagefile"
Well, to GET the pagefile with Powershell use this function I got from Mike Kanakos: "function-getpagefilessize.ps1", which, for some reason, does not work from the profile as a PS file or PSM file:
Function Get-PageFileInfo {
<#
.Synopsis
Returns info about the page file size of a Windows computer. Defaults to local machine.
.Description
Returns the pagefile size info in MB. Also returns the PageFilePath, PageFileTotalSize, PagefileCurrentUsage,
and PageFilePeakusage. Also returns if computer is using a TempPafeFile and if the machine's pagefile is
managed by O/S (AutoManaged = true) or statically set (AutoManaged = False)
.Example
Get-PageFileInfo -computername SRV01
Returns pagefile info for the computer named SRV01
Computer : SRV01
FilePath : C:\pagefile.sys
AutoManagedPageFile : True
TotalSize (in MB) : 8192
CurrentUsage (in MB) : 60
PeakUsage (in MB) : 203
TempPageFileInUse : False
.Example
Get-PageFileInfo SRV01, SRV02
Returns pagefile info for two computers named SRV01 & DC02.
Computer : SRV01
FilePath : C:\pagefile.sys
AutoManagedPageFile : True
TotalSize (in MB) : 8192
CurrentUsage (in MB) : 60
PeakUsage (in MB) : 203
TempPageFileInUse : False
Computer : SRV02
FilePath : C:\pagefile.sys
AutoManagedPageFile : True
TotalSize (in MB) : 8192
CurrentUsage (in MB) : 0
PeakUsage (in MB) : 0
TempPageFileInUse : False
.Example
Get-PageFileInfo SRV01, SRV02, SRV03 | Format-Table
Returns pagefile info for three computers named SRV01, SRV02 & SRV03 in a table format.
Computer FilePath AutoManagedPageFile TotalSize (in MB) CurrentUsage (in MB) PeakUsage (in MB) TempPageFileInUse
-------- -------- ------------------- ----------------- -------------------- ----------------- -----------------
SRV01 C:\pagefile.sys True 8192 60 203 False
SRV02 C:\pagefile.sys True 13312 0 0 False
SRV03 C:\pagefile.sys True 2432 0 0 False
.Parameter computername
The name of the computer to query. Required field.
.Notes
NAME: Get-PageFileInfo
AUTHOR: Mike Kanakos
Version: v1.1
LASTEDIT: Thursday, August 30, 2018 2:19:18 PM
.Link
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,ValueFromPipeline=$True)]
[string[]]$ComputerName
)
# Main Part of function
Foreach ($computer in $ComputerName)
{
$online= Test-Connection -ComputerName $computer -Count 2 -Quiet
if ($online -eq $true)
{
$PageFileResults = Get-CimInstance -Class Win32_PageFileUsage -ComputerName $Computer | Select-Object *
$CompSysResults = Get-CimInstance win32_computersystem -ComputerName $computer -Namespace 'root\cimv2'
$PageFileStats = [PSCustomObject]#{
Computer = $computer
FilePath = $PageFileResults.Description
AutoManagedPageFile = $CompSysResults.AutomaticManagedPagefile
"TotalSize(in MB)" = $PageFileResults.AllocatedBaseSize
"CurrentUsage(in MB)" = $PageFileResults.CurrentUsage
"PeakUsage(in MB)" = $PageFileResults.PeakUsage
TempPageFileInUse = $PageFileResults.TempPageFile
} #END PSCUSTOMOBJECT
} #END IF
else
{
# Computer is not reachable!
Write-Host "Error: $computer not online" -Foreground white -BackgroundColor Red
} # END ELSE
$PageFileStats
} #END FOREACH
} #END FUNCTION
#AUTHOR: Mike Kanakos#
But setting the page file then runs into ALL kinds of issues. Like, it gets REAL buggy. IF it is set you can change it, if it is not, you must first set to system managed and then set to something, like 16384/16384 on C and System managed on D:.
I am working on the answer myself, because I need this, and I will get back to ya'll when I get it sorted (amongst my long list of other scripts to do)...
But, ITMT, the function will help. Do a ForEach to a list like this:
remove-item -Force volumeletter:\folder\outputfile.txt
$results = (Get-PageFileInfo -Verbose server1.domain,server2.domain |select * |format-table -AutoSize)
$results |out-file volumeletter:\folder\outputfile.txt -Force ascii
OR you load up the Function in ISE, run it to load into memory and then query each server manually from the PS cmd:
Get-PageFileInfo server1.domain
Computer : server1.domain
FilePath : {C:\pagefile.sys, D:\pagefile.sys}
AutoManagedPageFile : False
TotalSize(in MB) : {16384, 768}
CurrentUsage(in MB) : {88, 62}
PeakUsage(in MB) : {120, 84}
TempPageFileInUse : {False, False}
You will see blanks if you are required to use FQDN...
IF you have the standard system managed the function will give you the usage, and that will tell you if you have to set the static sizes:
Get-PageFileInfo server2.domain
Computer : server2.domain
FilePath : C:\pagefile.sys
AutoManagedPageFile : True
TotalSize(in MB) : 7679
CurrentUsage(in MB) : 1763
PeakUsage(in MB) : 4867
TempPageFileInUse : False
For newer versions of PowerShell:
Starting in PowerShell 3.0, the Get-WmiObject cmdlet has been superseded by Get-CimInstance.
$PageFile = Get-CimInstance -ClassName Win32_PageFileSetting -Filter "Name like '%pagefile.sys'"
$PageFile | Remove-CimInstance
$PageFile = New-CimInstance -ClassName Win32_PageFileSetting -Property #{ Name= "C:\pagefile.sys" }
$PageFile | Set-CimInstance -Property #{ InitialSize = 0; MaximumSize = 0 }
Note: you will need administrator privileges to change the pagefile.

Using PowerShell to replicate right clicking a folder and selecting properties

I am trying to gather the Size/Size on disk and number of files/folders on a very large folder tree.
I have been using a script like the follow to gather some of this:
Get-ChildItem "C:\test" -recurse | Measure-Object -Sum Length | Select-Object `
#{Name="Path"; Expression={$directory.FullName}},
#{Name="Files"; Expression={$_.Count}},
#{Name="Size"; Expression={$_.Sum}}
Path Files Size
---- ----- ----
C:\test 470 11622961
But when I want to gather information on the number of folders and size on disk I'm having to run a separate script; which recuse through the folder tee again (Which takes a long time).
Is there an easy way of accessing the all this information the same way you can get it when you right click a folder and select properties shown below?
Are there any callable .exe files within system32 that can do this?
According to this answer in the Technet forums you can calculate the size on disk like this:
$afz = [MidpointRounding]::AwayFromZero
[math]::Round($_.Length / $clusterSize + 0.5, $afz) * $clusterSize
$clusterSize can be determined with the fsutil command (e.g. for drive C:):
PS C:\> fsutil fsinfo ntfsinfo C:\
NTFS Volume Serial Number : 0x648ac3ae16817308
Version : 3.1
Number Sectors : 0x00000000027ccfff
Total Clusters : 0x00000000004f99ff
Free Clusters : 0x0000000000158776
Total Reserved : 0x00000000000003e0
Bytes Per Sector : 512
Bytes Per Physical Sector : 512
Bytes Per Cluster : 4096
Bytes Per FileRecord Segment : 1024
Clusters Per FileRecord Segment : 0
...
Note that running fsutil requires admin privileges.
With that you can collect the information you're interested in like this:
$rootDir = "C:\test"
$afz = [MidpointRounding]::AwayFromZero
$clusterSize = fsutil fsinfo ntfsinfo (Get-Item $rootDir).PSDrive.Root `
| Select-String 'Bytes Per Cluster' `
| % { $_.ToString().Split(':')[1].Trim() }
$stat = Get-ChildItem $rootDir -Recurse -Force `
| select Name, Length, #{n="PhysicalSize";e={
[math]::Round($_.Length / $clusterSize + 0.5, $afz) * $clusterSize
}}, #{n="Folder";e={[int]($_.PSIsContainer)}},
#{n="File";e={[int](-not $_.PSIsContainer)}} `
| Measure-Object -Sum Length, PhysicalSize, Folder, File
$folder = New-Object -TypeName PSObject -Property #{
"FullName" = $rootDir;
"Files" = ($stat | ? { $_.Property -eq "File" }).Sum;
"Folders" = ($stat | ? { $_.Property -eq "Folder" }).Sum;
"Size" = ($stat | ? { $_.Property -eq "Length" }).Sum;
"SizeOnDisk" = ($stat | ? { $_.Property -eq "PhysicalSize" }).Sum - $clusterSize;
}
You're going to have to accumulate your data in a custom object as you see each item:
$path = "C:\Users\aaron\Projects\Carbon"
$properties = New-Object PsObject -Property #{ 'Path' = $path; 'Files' = 0; 'Folders' = 0; 'Size' = 0 }
Get-ChildItem -Path $path -Recurse |
ForEach-Object {
if( $_.PsIsContainer )
{
$properties.Folders++
}
else
{
$properties.Size += $_.Length
$properties.Files++
}
}
$properties

How to find amount of time mstsc is used and by whom?

Our team has geographically dispersed and many virtual machine will be connected by them using remote desktop. I would like to find who is accessing a remote desktop session and how long it is being used.
I tried to do it with powershell. I wrote a script where user will invoke mstsc using powershell. It will log who has logged in and when he logged. But i would like to find when some one log off from mstsc or disconnect mstsc . Is there any way to capture that information in log file using powershell. Whether any event will be triggered while closing mstsc which could be used for it?
I wrote a PowerShell module,PSTerminalServices (http://psterminalservices.codeplex.com), that is built on Cassia.
Here's a sample command output:
PS> Get-TSSession | fl *
IPAddress :
State : Active
ApplicationName :
Local : False
RemoteEndPoint :
InitialProgram :
WorkingDirectory :
ClientProtocolType : Console
ClientProductId : 0
ClientHardwareId : 0
ClientDirectory :
ClientDisplay : Cassia.Impl.ClientDisplay
ClientBuildNumber : 0
Server : Cassia.Impl.TerminalServer
ClientIPAddress :
WindowStationName : Console
DomainName : homelab
UserAccount : homelab\shay
ClientName :
ConnectionState : Active
ConnectTime : 12/15/2011 2:47:02 PM
CurrentTime : 12/23/2011 4:35:21 PM
DisconnectTime :
LastInputTime :
LoginTime : 12/15/2011 3:11:58 PM
IdleTime : 00:00:00
SessionId : 1
UserName : shay
You could use Cassia to get rdp session information (which could be periodically logged to a log file).
Here's a quick example of how to use cassia in Powershell:
[reflection.assembly]::loadfile("d:\cassia.dll")
$manager = new-object Cassia.TerminalServicesManager
$server = $manager.GetRemoteServer("<name of your server>")
$server.open()
$server.getsessions()
It will return something like this (for every session):
ClientDisplay : Cassia.Impl.ClientDisplay
ClientBuildNumber : 0
Server : Cassia.Impl.TerminalServer
ClientIPAddress :
WindowStationName :
DomainName : CONTOSO
UserAccount : CONTOSO\admin
ClientName :
ConnectionState : Disconnected
ConnectTime : 22/12/2011 19:02:00
CurrentTime : 23/12/2011 9:00:42
DisconnectTime : 22/12/2011 22:22:35
LastInputTime : 22/12/2011 22:22:35
LoginTime : 22/12/2011 10:40:21
IdleTime : 10:38:06.4220944
SessionId : 33
UserName : admin
If you can establish an RPC connexion with the server itself you can use QWinsta.exe to see who is logon a TS and RWinsta.exe to remote close a connexion (see Managing Terminal Services Sessions Remotely)
I run this function once per 15 minutes, it relies on Module PSTerminalServices. Basically what it does, is it pulls the last time someone RDPed in, then stores it in an XML, overwritting an older value if it exists, if no one is currently logged on, it returns the latest value from the XML instead.
Function Get-LastLogonTime
{
<#
.SYNOPSIS
Get-LastLogonTime returns the last date that someone logged on to a computer.
.DESCRIPTION
Get-LastLogonTime returns the last date that someone logged to a computer.
If admin rights are missing on the server it will return False.
.EXAMPLE
Get-LastLogonTime "nameofcomputer"
.NOTES
gets last access time from the user folder
.LINK
http://winfred.com
#>
Param(
[Parameter(Position=0, Mandatory=$true)]$ComputerName
)
$StoredRDPSessions = Import-Clixml "RDPSessions.xml"
$myobj = "" | select ComputerName, LastAccessedDate, UserName
$myobj.ComputerName = $ComputerName
$LastConnectedUser = Get-TSSession -ComputerName $ComputerName | where `
{
($_.WindowStationName -ne "Services") -and `
($_.State -ne "Listening") -and `
($_.WindowStationName -ne "Console")
} | sort-object -property LastAccessTime -Descending
if($LastConnectedUser -is [array])
{
$myobj.LastAccessedDate = $LastConnectedUser[0].ConnectTime
$myobj.UserName = $LastConnectedUser[0].UserName
}elseif($LastConnectedUser){
$myobj.LastAccessedDate = $LastConnectedUser.ConnectTime
$myobj.UserName = $LastConnectedUser.UserName
}else{
$myobj.LastAccessedDate = $Null
$myobj.UserName = "Unknown"
}
if(($myobj.LastAccessedDate) -and ($myobj.UserName))
{
$StoredRDPSession = $StoredRDPSessions | where {$_.ComputerName -eq $ComputerName}
if($StoredRDPSession)
{
if($myobj.LastAccessedDate -gt $StoredRDPSession.LastAccessedDate)
{
write-verbose "Newer LastAccessedDate, updating XML"
$StoredRDPSession.LastAccessedDate = $myobj.LastAccessedDate
$StoredRDPSession.UserName = $myobj.UserName
$StoredRDPSessions | Export-Clixml "RDPSessions.xml"
}
}else{
write-verbose "No Entry found Adding to XML"
$NewStoredRDPSessions = #()
$StoredRDPSessions | % {$NewStoredRDPSessions += $_}
$NewStoredRDPSessions += $myobj
$NewStoredRDPSessions | Export-Clixml "RDPSessions.xml"
}
}
if((!($myobj.LastAccessedDate)) -and $StoredRDPSessions)
{
write-verbose "no current session, pulling from stored XML"
$StoredRDPSession = $StoredRDPSessions | where {$_.ComputerName -eq $ComputerName}
if($StoredRDPSession)
{
$myobj.LastAccessedDate = $StoredRDPSession.LastAccessedDate
$myobj.UserName = $StoredRDPSession.UserName
}else{
write-verbose "Sadness, nothing stored in XML either."
}
}
write-verbose "Get-LastLogonTime $ComputerName - $($myobj.LastAccessedDate) - $($myobj.UserName)"
Return $myobj
}

Cannot execute same powershell function twice, gives error

I'm fairly new to powershell and I'm basically writing a script which performs a join on several .csv files based on a primary column. I am using the Join-Collections script from here: http://poshcode.org/1461
As I need to combine 5 .csv files, I need to run this function 4 times.
On the first run, it works fine, but then trying to run the function again gives 'No object specified to the cmd-let' errors.
In trying to debug, I've literally copy-and-pasted the line and only changed the variable name to make a new variable.
I must be doing something fundamentally wrong...
$SumFile = "VMSummary.csv"
$MemFile = "VMMemory.csv"
$ProcFile = "VMProcessor.csv"
$OSFile = "VMOS.csv"
$NicFile = "VMNics.csv"
$SumFileCSV = Import-Csv $SumFile | Select VMElementName,GuestOS,Heartbeat,MemoryUsage,IpAddress
$MemFileCSV = Import-Csv $MemFile | Select VMElementName,Reservation
$ProcFileCSV = Import-Csv $ProcFile
$OSFileCSV = Import-Csv $OSFile
$NicFileCSV = Import-Csv $NicFile
$JoinColumn = "VMElementName"
function Join-Collections {
PARAM(
$FirstCollection
, [string]$FirstJoinColumn
, $SecondCollection
, [string]$SecondJoinColumn=$FirstJoinColumn
)
PROCESS {
$ErrorActionPreference = "Inquire"
foreach($first in $FirstCollection) {
$SecondCollection | Where{ $_."$SecondJoinColumn" -eq $first."$FirstJoinColumn" } | Join-Object $first
}
}
BEGIN {
function Join-Object {
Param(
[Parameter(Position=0)]
$First
,
[Parameter(ValueFromPipeline=$true)]
$Second
)
BEGIN {
[string[]] $p1 = $First | gm -type Properties | select -expand Name
}
Process {
$Output = $First | Select $p1
foreach($p in $Second | gm -type Properties | Where { $p1 -notcontains $_.Name } | select -expand Name) {
Add-Member -in $Output -type NoteProperty -name $p -value $Second."$p"
}
$Output
}
}
}
}
$Temp = Join-Collections $SumFileCSV $JoinColumn $MemFileCSV $JoinColumn
$Temp
##BREAKS HERE
$Temp2 = Join-Collections $SumFileCSV $JoinColumn $MemFileCSV $JoinColumn
UPDATE
It gives the following error:
No object has been specified to the get-member cmdlet
+ foreach($p) in $Second | gm <<<< -type Properties | Where { $p1 -notcontains $_.Name } | select -expand Name)
The csv data is pretty straight forward. When I print out $Temp just before it breaks, it spits out:
GuestOS : Windows Server (R) 2008 Standard
Heartbeat : OK
IpAddress : 192.168.48.92
MemoryUsage : 1024
VMElementName : VM015
Reservation : 1024
GuestOS : Windows Server (R) 2008 Standard
Heartbeat : OK
IpAddress : 192.168.48.151
MemoryUsage : 1028
VMElementName : VM053
Reservation : 1028
GuestOS : Windows Server (R) 2008 Standard
Heartbeat : OK
IpAddress : 192.168.48.214
MemoryUsage : 3084
VMElementName : VM065
Reservation : 3084
GuestOS :
Heartbeat :
IpAddress :
MemoryUsage :
VMElementName : VM074
Reservation : 1024
GuestOS : Windows Server 2008 R2 Standard
Heartbeat : OK
IpAddress : 192.168.48.32
MemoryUsage : 3072
VMElementName : VM088
Reservation : 3072
GuestOS : Windows Server (R) 2008 Enterprise
Heartbeat : OK
IpAddress : 192.168.48.81
MemoryUsage : 3084
VMElementName : VM090
Reservation : 3084
GuestOS : Windows Server 2008 R2 Enterprise
Heartbeat : OK
IpAddress : 192.168.48.82
MemoryUsage : 5120
VMElementName : VM106
Reservation : 5120
The rest of the .csv data is the same sort of stuff - just stats on different servers.
Ideally what I want to do is this :
$Temp = Join-Collections $SumFileCSV $JoinColumn $MemFileCSV $JoinColumn
$Temp = Join-Collections $Temp $JoinColumn $ProcFileCSV $JoinColumn
$Temp = Join-Collections $Temp $JoinColumn $OSFileCSV $JoinColumn
$Temp = Join-Collections $Temp $JoinColumn $NicFileCSV $JoinColumn | Export-Csv "VMJoined.csv" -NoTypeInformation -UseCulture
This code works fine on Powershell v3 CTP 2 (which is probably what #manojlds is using). In Powershell V2 however the parameter $second of the Join-Object function is not bound when invoking Join-Collections the second time. This can be easily verified by adding the following line to the process block inside the Join-Object function:
$psboundparameters | out-host
You will notice that when invoking Join-Collections for the first time both parameters (of Join-Object are bound, however the second time $second is no longer bound.
It is unclear what is causing this behaviour, but since it seems to be working in Powershell V3 I'm guessing it's a bug.
To make the function work in Powershell V2 one could explicitly bind the parameters by replacing this line:
$SecondCollection | Where{ $_."$SecondJoinColumn" -eq $first."$FirstJoinColumn" } | Join-Object $first
by this line:
$SecondCollection | Where{ $_."$SecondJoinColumn" -eq $first."$FirstJoinColumn" } | %{Join-Object -first $first -second $_}