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.

Where did a User’s Account Get Locked Out?

Updated: May 15, 2015 When this article was originally published, two extra carriage returns were add causing the code to malfunction.  The code below is correct.   My client for this week’s PowerShell class had a really interesting question. They needed to know where an account is being locked out at. OK, interesting. Apparently users hop around clients and forget to log off, leading to eventual lock out of their accounts. The accounts can be unlocked, but are then relocked after Active Directory replication. This problem is solved in two parts. The first one is to modify the event auditing on the network. The second part is resolved with PowerShell. The first part involves creating a group policy that will encompass your Domain Controllers. In this GPO, make these changes. Expand Computer Configuration \ Policies \ Windows Settings \ Security Settings \ Advanced Audit Policy Configuration \ Audit Policies \ Account Management Double click User Account Management C...