Showing posts with label Modules. Show all posts
Showing posts with label Modules. Show all posts

Wednesday, August 12, 2009

Use PowerShell to Get Local Group Members from a Remote Computer

I had a friend ask me recently how to get a list of administrators from a server.

"That's easy" I thought. "You just have to... um... actually..."

It turns out that this can be frustratingly difficult in PowerShell, so I wrote this module to make it easier when I'll need to do this in the future. It's comprised of three functions:
  • Add-NoteProperty: About 90% of the time when I want to create a custom PSObject and add some properties, they're all NoteProperties. This function makes adding a property easy, like so: Add-NoteProperty $my_object 'PropertyName' $property
  • Get-COMProperty: This is a kludgy hack to get around the fact that members of groups gotten through ADSI get returned as __ComObject objects, and you have to call the InvokeMember() static method of the class in order to get at their properties. Now I can just do this: Get-COMProperty $com_object 'PropertyName'
  • Get-LocalGroups: This is the function that we needed. It returns a list of custom PSObjects representing the local groups on a server, and each one has a property called Members that is a list of custom PSObjects for each member, including the Name, Domain, and ADSPath. From there, you can use whatever method you want to the object you want, whether it's using Get-QADUser for domain users, or whatever, for example: Get-LocalGroups computername.
If you're using Powershell v2 CTP3 or higher, you can use help on each of the functions to see examples if you forget. You can download the module from Poshcode.org here.



Sunday, September 21, 2008

I'm Not Dead

I've been really busy at work but keep an eye out for a real post very soon. If you want to check out some PowerShell scripts head on over to http://poshcode.org, where you can find PowerShell scripts submitted by users.

There has been talk in the community about trying to come up with a CPAN for PowerShell.  This is not it, but it's a start.  For one thing, CPAN grew enough that they could enforce readability and technique requirements by having someone actually review each module.  PowerShell is still too young for that.

I decided to post my SMS.psm1 module for making command-line managment of SMS easier, so here goes nothing.  I'll do a post on how to use it later.






Note:  You need PowerShell v2 CTP2 in order to use this.   Copy it into %userprofile%\Documents\WindowsPowerShell\Packages\SMS\.

Sunday, July 6, 2008

The DotSource Operator

A while back I asked Stephen Ng if he had seen any documentation on importing scripts as modules or libraries, and he hadn't. I sort of filed it away for future reference, knowing that if we went down this path we'd probably want to find some way to keep a repository of PowerShell scripts for common use.

Fast forward to a few days ago, when the latest entry from The PowerShell Guy showed up in my Google Reader. In his Get-IpConfig function (which I'll discuss in a later post) he has a line with an open parenthesis followed by a dot.wasn't the most readable line of code in the world anyway, but as I was mentally parsing it I hit a snag. I had no idea what that dot was doing just after the open parenthesis.

As it turns out, this is what's known as the dotsource operator. The dotsource operator (I wish people would stop and think a bit when choosing these terrible names) is like the ampersand (&) operator, in that it executes the script or code block that comes after it, but it also declares all variables in the global scope. Why would you want to do this?

Let's use a terrible example and say I have a script that will get a list of users and groups on a computer. I have a script, Get-UsersAndGroups.ps1. It creates two variables, $users and $groups, and exits. I want to be able to use those variables, so I run the following:

PS C:\> .\Get-UsersAndGroups.ps1
PS C:\> $users

I get nothing back, even though I know I created the variable. $users was created in the script's scope, though, and once the script finishes running it takes its variables with it.

I have three options here:
  1. Change my script to send the variables to the output pipeline. Maybe this script is being used by other people, though, so I don't necessarily want to change the pipeline.
  2. Explicitly declare the variables as $global:users and $global:groups in the script. The problem with this is that I don't necessarily always want to declare these variables in the global namespace.
  3. Use the dotsource operator.
The way to use the dotsource operator is like this:

PS C:\> . .\Get-UsersAndGroups.ps1
PS C:\> $users
Tim
Administrator
Alfred E. Neuman

(Note that there is a space between the dots there, otherwise I'd just be telling PowerShell to look in the parent directory.)

To wrap this up, we can take all of this newfound knowledge and see how you can create libraries in PowerShell. By dotsourcing (yes, people even use it as a verb, ugh) a script with functions and constants in it, we can import the functions in a way that makes them usable by our scripts, that way we can reuse the code.

The one big problem is that PowerShell has no concept of a /lib directory that it looks for modules in by default, so you must know the path to the script you will be importing. I'll leave that as a future exercise, but I have a spark of an idea in my head of how we can create a function that looks up a script by its name to import and distribute it using a common company Profile so that all company PowerShell Scripters have a common location for libraries, like sitecustomize.py in Python.