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

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.

How to run GPResult on a remote client with PowerShell

In the past, to run the GPResult command, you would need to either physically visit this client, have the user do it, or use and RDP connection.  In all cases, this will disrupt the user.  First, you need PowerShell remoting enabled on the target machine.  You can do this via Group Policy . Open PowerShell and type this command. Invoke-Command –ScriptBlock {GPResult /r} –ComputerName <ComputerName> Replace <ComputerName> with the name of the target.  Remember, the target needs to be online and accessible to you.

Error icon when creating a GPO Preference drive map

You may not have an error at all.  Take a look at the drive mapping below. The red triangle is what threw us off.  It is not an error.  It is simply a color representation of the Replace option of the Action field in the properties of the drive mappings. Create action This give you a green triangle. The Create action creates a new mapped drive for users. Replace Action The Replace action gives you a red triangle.  This action will delete and recreate mapped drives for users. The net result of the Replace action is to overwrite all existing settings associated with the mapped drive. If the drive mapping does not exist, then the Replace action creates a new drive mapping. Update Action The Update action will have a yellow triangle. Update will modify settings of an existing mapped drive for users. This action differs from Replace in that it only updates settings defined within the preference item. All other settings remain as configured on the mapped drive. If the