Skip to main content

Getting Hard Drive Information from Remote Clients

Today on LinkedIn, I noticed that someone was trying to get hard drive information and then save it to a CSV file.  I believe the purpose was to present the data in Excel.  Nothing wrong with this, but it does raise a few questions.

1. What if there is an inconsistent number of drives on the client?

2. Is the client online?

3. Do you want all drives, or just the fixed drives?

4. How to maintain a list of clients that were offline at the time?

The two big things for me are the multiple hard drives question and the “what if” the client is offline question.  When it comes down to an unknown number of objects being returned, XML is really the way to go.  It allows me to create a single property at the root of the object that can hold that unknown number of child objects (multiple hard drives).  Also, I may need to account for clients that were offline.  My data will have a property called Online that will be set to TRUE or FALSE.  That way I can feed that data file through again and be able to execute against just those clients that were offline during the previous run.  That will save time and prevent a duplication of data.  Get ready, this is a big hunk of code.  In all actuality, much of it is one of my templates. To learn more about how to use it, check out the help file.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

Function Get-HDSizeInfo

{

[CmdletBinding()]

Param(

   

    [parameter(Mandatory=$true,

                ValueFromPipeline=$true,

                ValueFromPipelineByPropertyName=$true)]

    [String[]]

    $ComputerName,

 

    [Switch]

    $Fixed   

   

    )

 

BEGIN

{

    # Place all private functions here.

 

    # Main Object Creation

    Function New-CustomObject

    {

        $Obj = New-Object -TypeName PSObject -Property @{

            "ComputerName" = $Null

            "Online" = $False

            "Drives" = $Null

        }

        $obj.PSObject.TypeNames.Insert(0,'HDInfo')

        Write-Output $Obj

    }

 

}

PROCESS

{

    # Get a fresh copy of the output object.

    $CustomeObject = New-CustomObject

 

    # Cycle through each client and process.

    ForEach ($C in $ComputerName)

    {

        Write-Verbose "Connecting to: $C"

 

        # Initialize the output data.

        $Data = $CustomeObject

 

        # Add the name of the current client being processed to the Object.

        $Data.ComputerName = $C

     

        Try

        {

            # Establish the PowerShell Session

            $SO = New-PSSessionOption -OpenTimeout 500 -NoMachineProfile

            $SessionHash = @{

                "ComputerName" = $C

                "SessionOption" = $SO

                "ErrorAction" = "Stop"

            }

         

            # Establish the new session.

            $S = New-PSSession @SessionHash

 

            # Execute on the remote client.

            $Hash = @{

                "Session" = $S

                "ArgumentList" = $CustomeObject

            }

            $Data = Invoke-Command -Session $S -ScriptBlock {

                Param ($Obj, $Fixed)

                # Place all code to run remotely here.

     

                # Function to create the Hard Drive Object.

                # This function will run for each discovered drive.

                Function New-HDObject

                {

                    $Obj = New-Object -TypeName PSObject -Property @{

                        "Drive" = ""

                        "SizeGB" = 0

                        "UsedGB" = 0

                        "FreeGB" = 0

                    }

                    $obj.PSObject.TypeNames.Insert(0,'HDInfo.Drive')

                   

                    # Send the object to the calling statement.

                    Write-Output $Obj

                } # END: Function New-HDObject

 

                # Set the ComputerName.

                $Obj.ComputerName = HostName

           

                # Mark the client as being "Online"

                $Obj.Online = $True

 

                # Get the Hard Drive Info.

                If (!($Fixed))

                {$Drives = Get-CimInstance Win32_LogicalDisk}

                Else

                {$Drives = Get-CimInstance Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3}}

 

                # Cycle through each drive and add the drive info to the array.

                $DInfo = @()

                ForEach ($D in $Drives)

                {

                    $SingleDrive = New-HDObject

                    $SingleDrive.Drive = $D.Caption

                    $SingleDrive.SizeGB = $D.Size/1gb

                    $SingleDrive.UsedGB = ($D.Size-$D.FreeSpace)/1gb

                    $SingleDrive.FreeGB = $D.FreeSpace/1gb

 

                    # Add this drive to the $DInfo Array.

                    $DInfo += $SingleDrive

                }

 

                    # Add the $DInfo array to the "Drives" Property.

                    $Obj.Drives = $DInfo

 

                # Return the object to the calling client.

                Write-Output $Obj

 

                # End of remote commands.

            } -ArgumentList $Data, $Fixed

       

            # Remove the PS Session.

            $S | Remove-PSSession

 

            Write-Verbose "Finished processing: $C"

        } # END: TRY BLOCK

        Catch

        {

        Write-Verbose "Error connecting to: $C."

        $Data.ComputerName = $C

        } # END: CATCH BLOCK

        

        # Write the data to the pipeline.

        Write-Output $Data

    }

} # END: Process

END{} # END: END BLOCK

 

<#

.SYNOPSIS

Returns data on remote hard drives.

 

.DESCRIPTION

Utilizes PowerShell Remoting to access hard drive information on remote computers. 

This cmdlet returns information on each drive for size, free space, and used space.

 

.PARAMETER ComputerName

The name of the client to recover drive information from.

 

.PARAMETER Fixed

Returns only local fixed hard drives.

 

.EXAMPLE

Get-HDSizeInfo -ComputerName Cl1, DC2, EX1, DC1 -Fixed

 

Returns the fixed hard drive information for clients CL1, DC2, EX1, and DC1.

 

.EXAMPLE

Get-ADComputer -Filter * | Select-Object -Property @{N="ComputerName";E={$_.Name}} | Get-HDSizeInfo

 

Returns the drive information for all clients listed in an Active Directory Domain.

You must have access to the Active Directory module from Windows PowerShell to

execute this example.

 

.EXAMPLE

Get-HDSizeInfo -ComputerName Ex1, DC1 | Export-Clixml -Path "HDData.XML"

 

Get's hard driving information for two clients and exports the data to an XML file.

 

.EXAMPLE

Import-Clixml -Path "HDData.xml" | Where Online -eq $False | Get-HDInfo

 

Reads and XML file produced by a previous run of this cmdlet and executes

against clients that were offline during the previous run.

 

.NOTES

Requirements:

- PowerShell Remoting is enabled.

- You are logged on with credentials that allow you to remote to other clients.

===============================================================================

== Cmdlet: Get-HDSizeInfo                                                    ==

== Author: Jason A. Yoder                                                    ==

== Company: MCTExpert of Arizona                                             ==

== Date: February 17, 2015                                                   ==

== Copyright: All rights reserved.                                           ==

== Version: 1.0.0.0                                                          ==

== Legal: The user assumes all responsibility and liability for the usage of ==

== this PowerShell code.  MCTExpert of Arizona, Its officers, shareholders,  ==

== owners, and their relatives are not liable for any damages.  As with all  ==

== code, review it and understand it prior to usage.  It is recommended that ==

== this code be fully tested and validated in a test environment prior to    ==

== usage in a production environment.                                        ==

==                                                                           ==

== Does this code make changes: NO                                           ==

===============================================================================

#>

} # End Function Get-HDSizeInfo

  

 

Comments

Popular posts from this blog

Adding a Comment to a GPO with PowerShell

As I'm writing this article, I'm also writing a customization for a PowerShell course I'm teaching next week in Phoenix.  This customization deals with Group Policy and PowerShell.  For those of you who attend my classes may already know this, but I sit their and try to ask the questions to myself that others may ask as I present the material.  I finished up my customization a few hours ago and then I realized that I did not add in how to put a comment on a GPO.  This is a feature that many Group Policy Administrators may not be aware of. This past summer I attended a presentation at TechEd on Group Policy.  One organization in the crowd had over 5,000 Group Policies.  In an environment like that, the comment section can be priceless.  I always like to write in the comment section why I created the policy so I know its purpose next week after I've completed 50 other tasks and can't remember what I did 5 minutes ago. In the Group Policy module for PowerShell V3, th

Return duplicate values from a collection with PowerShell

If you have a collection of objects and you want to remove any duplicate items, it is fairly simple. # Create a collection with duplicate values $Set1 = 1 , 1 , 2 , 2 , 3 , 4 , 5 , 6 , 7 , 1 , 2   # Remove the duplicate values. $Set1 | Select-Object -Unique 1 2 3 4 5 6 7 What if you want only the duplicate values and nothing else? # Create a collection with duplicate values $Set1 = 1 , 1 , 2 , 2 , 3 , 4 , 5 , 6 , 7 , 1 , 2   #Create a second collection with duplicate values removed. $Set2 = $Set1 | Select-Object -Unique   # Return only the duplicate values. ( Compare-Object -ReferenceObject $Set2 -DifferenceObject $Set1 ) . InputObject | Select-Object – Unique 1 2 This works with objects as well as numbers.  The first command creates a collection with 2 duplicates of both 1 and 2.   The second command creates another collection with the duplicates filtered out.  The Compare-Object cmdlet will first find items that are diffe

How to list all the AD LDS instances on a server

AD LDS allows you to provide directory services to applications that are free of the confines of Active Directory.  To list all the AD LDS instances on a server, follow this procedure: Log into the server in question Open a command prompt. Type dsdbutil and press Enter Type List Instances and press Enter . You will receive a list of the instance name, both the LDAP and SSL port numbers, the location of the database, and its status.