Find Users Actively Connected to a Share

The work I do for AT&T deals extensively with performing data migrations; moving user and group data from one server to another.  To make the data transition easier for the active share users I send emails to them indicating when a share is going to move, and what its new location will be?

Q:How do I capture that active user information?

A:  I use a WMI query using the class Win32_ServerConnection.

With Powershell you can easily query a remote server to find out what accounts are connected to all shares, or a specific share.

One of the very nice things about Powershell is that you can create a “one-liner” to grab the information quickliy.  This would be used  as a quick reference.  Here is an example of a one liner to find all of the employees connected to server ServerBravo1

Get-WmiObject Win32_ServerConnection -ComputerName ServerBravo1 select username, sharename, computername | sort sharename | Format-Table -AutoSize

Here is the break down of that command:

Get-WmiObject Win32_ServerConnection: Performs the WMI query using the Get-WMIObject cmdlet.

-ComputerName ServerBravo1: Runs the query on the remote server ServerBravo1.  If the -ComputerName property is excluded then the command is run on the local computer.

selectusername, sharename, computername:  This determines which properties are returned from the query.  I find these to be the most useful properties, but there are a lot more that can be returned.

Here is a list of the properties that could be useful:

Name                           MemberType
—-                                ———-
ActiveTime               Property
Caption                       Property
ComputerName      Property
ConnectionID          Property
Description              Property
InstallDate               Property
Name                          Property
NumberOfFiles       Property
NumberOfUsers     Property
ShareName              Property
Status                         Property
UserName                Property

sort sharename: This sorts the results based on the value of the ShareName property.

Format-Table-AutoSize: This formats the output in columns.  The -autosize option places the columns in a nice compact presentation.  Other output options include format-list, and my personal favorite out-gridview.

The one-liner is nice but you have to type the full text each time.  Since I use this command so much, I prefered to make a function where I can type the function name followed by a server name.  The required typing is a lot less for each use, and you don’t really need to remember the specific property names.

Here is how that funtion would look:

Function to Find Active Share Users on a Server

function get-ShareUsers

{

<#

.SYNOPSIS

Determine which shares are actively being used by employees.

.DESCRIPTION

This provides a live time view of shares currently being accessed by employees. The output can be to the Powershell screen, the out-gridview window, a CSV file, or all of the above.

 

.PARAMETER <paramName>

ServerName – Used to determine the server to scan.

GridView – Enables the output to the gridview.

Export – Enables the output to a CSV file using the export-csv cmdlet.

.EXAMPLE

get-ShareUsers S47715C014001

Description

———–

This command scans a server called S47715C014001 for active share users. The result is sent to the Powershell screen.

.EXAMPLE

get-ShareUsers S47715C014001 -Gridview

Description

———–

This command scans a server called S47715C014001 for active share users. The result is sent to the Powershell screen, and to the out-gridview window.

.EXAMPLE

get-ShareUsers S47715C014001 -Gridview -Export

Description

———–

This command scans a server called S47715C014001 for active share users. The result is sent to the Powershell screen, to the out-gridview window, and to a CSV file called S47715C014001 _Share_Users.csv

#>

[CmdletBinding()]

Param

(

#First parameter

[parameter(Mandatory=$true, #Makes this a required parameter. The user will be prompted for this item if it is not provided.

ValueFromPipeline=$true)] #Allows the server name to be “Piped” into the function.

[String[]] $ServerName, #The name against which to run the query.

#Second parameter – Sends the output to the out-gridview display.

[switch] $Gridview,

#Third parameter – Sends the output to a CSV file for later used.

[switch] $Export

)

 

#Default output to the Powershell interface.

Get-WmiObject Win32_ServerConnection -ComputerName $ServerName | select username, sharename, computername | sort sharename | Format-Table -AutoSize

if ($Gridview -eq $true) #Use this switch if you want to output to the Out-Gridview window.

{

Get-WmiObject Win32_ServerConnection -ComputerName $ServerName | select username, sharename, computername | sort sharename | Out-GridView -Title “$computername Share Users”

}

if ($Export -eq $true) #Use this switch if you want to output to a CSV file.{

[string]$filename = $ServerName+ “_Share_Users.csv”

Get-WmiObject Win32_ServerConnection -ComputerName $ServerName | select username, sharename, computername | sort sharename | Export-Csv -Path $filename -NoTypeInformation

}

}

A few final comments:

  • To make this function available all of the time when you are using PowerShell, paste the function into your PowerShell profile document.  When you do that it will load each time you start PowerShell.
  • Once it is loaded into your PowerShell session, you can find help on this function by typing the following in the PowerShell command line window:

help get-shareusers -Full

This will give examples of how to use the function, and also give detailed information on each of the parameters.

  • Finally, to make it easier to use this function, I have uploaded the text of the script here at my Google page:

Get-ShareUsers.ps1

I hope this is a helpful utility for you.

Please let me know if you have any questions about this, or any of my other posts.

Have a good day.

Patrick

Get-DriveSpace on One or Multiple Computers

One common administrative task is to find the  available disk space on a server.  The standard methods to do this are connecting to the computer remotely to verify disk space, and using VBScript scripting to gather the data.  But there is a better way…

With Powershell’s extensive use of WMI and the “piping” options, a very useful one-liner can be used to retrieve the disk space for one or more servers.

Here is the WMI property that we will be using: Win32_LogicalDisk.

To find the disk space available for one computer you would use this one-liner:

get-wmiobject Win32_LogicalDisk -computername Server001 | select __server, Name, Description, FileSystem, @{Label=”Size”;Expression={“{0:n0} MB” -f ($_.Size/1mb)}}, @{Label=”Free Space”;Expression={“{0:n0} MB” -f ($_.FreeSpace/1mb)}} | out-gridview -Title “Disk Space Scan Results”

Lets take a look at the different sections of that one-liner.

get-wmiobject Win32_LogicalDisk -computername Server001 |

This is the standard cmdlette for accessing WMI in Powershell.  The number of available WMI classes is quite extensive.  In the above example, -computername would be followed by a valid computer name. The output of that is piped  into the  Select-Object cmdlette.

select __server, Name, Description, FileSystem, @{Label=”Size”;Expression={“{0:n0} MB” -f ($_.Size/1mb)}}, @{Label=”Free Space”;Expression={“{0:n0} MB” -f ($_.FreeSpace/1mb)}} |

Select-Object, in this one-liner aliased as select, allows us to choose which properties of the returned query we want to use.  By default the Win32_LogicalDisk class provides us with the following properties:

DeviceID     : C:

DriveType    : 3

ProviderName :

FreeSpace    : 10997723136

Size         : 21478666240

VolumeName   : C_Drive

We do two things differently with our one-liner. First we grab an extra property that is always available, but not always needed.  We are requesting the “__server” property.  This will be useful when we put everything in columns later on, and really useful when we are asking for the disk space on multiple servers.

The second thing we are doing differently is to apply formatting to the “Size: Property and “Free Space” property. If you notice above the output is in bytes.  We are use to thinking of hard drives in MB or GB, not bytes.  That is way too weird.  So we are going to created two calculated properties.  There is a calculated property for “freespace” and “size”.

The calculated property is much simpler than it might first appear. To specify a calculated property we need to create a hash table; that’s what the @{} syntax does for us.  Inside the curly braces we specify the two elements of our hash table: the property Label (in this case Size or Free Space) and the property Expression (that is, the script block we’re going to use to calculate the property value).  The Label property is easy enough to specify; we simply assign a string value to the Name, like so:

Label=”Size” and Label=”Free Space”

And, believe it or not, the Expression property (which is separated from the name by a semicolon) isn’t much harder to configure; the only difference is that Expression gets assigned a script block rather than a string value:

Expression={“{0:n0} MB” -f ($_.Size/1mb)}} and Expression={“{0:n0} MB” -f ($_.FreeSpace/1mb)}} are the expressions we are using.  So what actually is going on here?

Using .NET to Format Numbers in Windows PowerShell

Powershell doesn’t have any built-in functions or cmdlettes for formatting numbers. But that’s OK; we don’t need any built-in functions or cmdlettes. Instead, we can use the .NET Framework formatting methods.

The heart-and-soul of our command is this little construction: “{0:N0}”. That’s a crazy-looking bit of code to be sure, but it’s also a bit of code that can easily be dissected:

The initial 0 (That’s a zero)  (the one that comes before the colon) represents the index number of the item to be formatted. For the time being, leave that at 0 and everything should work out just fine.

The N represents the type of format to be applied; in this case, the N is short for Numeric. Are there other types of formats we can apply? Yes there are, and we’ll show you a few of those in just a moment.

The second 0 (the one after the N) is known as the “precision specifier,” and, with the Numeric format, indicates the number of decimal places to be displayed. In this case we don’t want any decimal places, so we set this parameter to 0. Suppose we wanted to display three decimal places? No problem; this command takes care of that: “{0:N3}” -f $a. Run that command and you’ll end up with output that looks like this: 19,385,790,464.000.

That’s about all we have to do; after specifying the format type we tack on the –f (format) parameter, then follow that by indicating the value we want to format $_.FreeSpace and $_.Size.

In our one-liner we are dividing the number variables $_.size and $_.freespace by the Powershell constant mb. We could do kb or gb as well. It depends what output you want to see.

For a more extensive discussion on .net formatting, please go here:

http://technet.microsoft.com/en-us/library/ee692795.aspx

http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx

This is the source I used for much of this information.

The final section of the one-liner outputs the results to the Out-Gridview window.  I have modified the “title” property so that it shows what we are attempting to do with the query.

| out-gridview -Title “Disk Space Scan Results”

 

The above information details how to find the disk space for one server.  Because the “computername” property of the Get-WmiObject cmdlette will accept an array, or a single string.  This allows us to check mutiple servers with the same one liner.  This can be done two ways.

In the first method, the computer names can be directly type into the one liner:

get-wmiobject Win32_LogicalDisk -computername server1, server2, server3

In the second method the computer names can be read from a test file using the get-content cmdlette.

get-wmiobject Win32_LogicalDisk -computername (Get-Content c:\temp\computers.txt) `

select __server, Name, Description, FileSystem, @{Label=”Size”;Expression={“{0:n0} MB” -f ($_.Size/1mb)}},`

@{Label=”Free Space”;Expression={“{0:n0} MB” -f ($_.FreeSpace/1mb)}}`

| out-gridview -Title “Disk Space Scan Results”

I prefer the second method because you can gather the disk information on many servers very quickly.

Please let me know if you have any questions about this procedure.  I would be glad to explain anything, or answer any questions.

Thanks,

Patrick

Creating a Folder Named After a Date

I like to create folders on the fly for logging  purposes, as well as for keeping track of re-occurring actions, like scanning for disk usage on a given date.

The following PowerShell command is useful for creating a folder with a name in the format YYYYMMDD.

$folderName = “folder1_” + (Get-Date -uFormat  “%Y%m%d”)
This command makes a folder call folder1_20110226.

Another technique is do make the folder, and assign the date to the name all at once.

md (“folder2_” + (Get-Date -uFormat  “%Y%m%d”)).

Below you will see both techniques used, and then the old DIR command just to show that they were created successfully.

Make Folders with Date Names.

Instead of the DIR command I could have used the Powershell commandlette Get-ChildItem folder*, and it would have worked just as well.  I like DIR because I am use to it, and because it is less typing.

That’s all for this entry. Have a nice day.

Thanks,

Patrick