Send an Email from the Windows Command Prompt or Script, Pt II…

2017-07-27T00:01:03+00:00 November 14th, 2013|Uncategorized|

Following up on the earlier post, “Send an Email from the Windows Command Prompt or Script…

…While I’m somewhat picking up where I left off in Part 1, the situation in that earlier post had special requirements about how the email message had to be sent (controlled source, user interaction, etc.).  But what if you don’t have those requirements?  What if you simply want to send an email from a Windows workstation or Server? 

Well, in that case, simply use PowerShell.  Since version 2, PowerShell has included the Send-MailMessage cmdlet for relatively easy mail sending from almost any modern computer.

Recently, I was telling somebody how do use this method to send messages in a script, and demonstrating the input details such as specifying the SMTP relay server.  The person then asked me, “What if the SMTP server changes?”  Hmm…  Good point.   So I whipped up a few extra lines to work around that problem, and the person thought I should post it here.  Agreed!

Here is the script, put together as plainly as possible, with clearly named variables to help you understand what’s going on:

$MyRecipientEmailAddress = "Fake.Address@CoretekServices.com"
$MySenderEmailAddress = "JPavlov@YourLinuxGuy.com"
$MyRecipient = $MyRecipientEmailAddress.Split("@")
[0] $MyDestinationDomain = $MyRecipientEmailAddress.Split("@")[1] $MyMxRecords = Resolve-DnsName -Type MX -Name $MyDestinationDomain $MyMxRecord = $MyMxRecords[0].NameExchange $MyMessageSubject = "This is a test" $MyMessageBody = "This is the message. Thanks! - Jeremy" Send-MailMessage -To "$MyRecipientEmailAddress" -SmtpServer "$MyMxRecord" -Subject "$MyMessageSubject" -Body "$MyMessageBody" -From "$MySenderEmailAddress"

Remember, the trick is not really the standard options of the cmdlet, but grabbing the possibly-changing MX record for the relay.  This script will dynamically go and get the *current* first-listed MX record for the recipient, and just use that.

And I can almost hear you now, “…But Jeremy, aren’t you side-stepping the built-in fault-tolerance of the MX record?”  Yes, a bit; you can absolutely add a little more code to this and make it aware of the MX ranking, and roll through them and validate until successful.  Maybe I’ll do that in another post…

By the way, while it may not be obvious to you initially, note that I’m just specifying my recipient’s destination SMTP server as my -SmtpServer.  This *should* be fine in many/most cases.  The destination server should be glad to receive and forward the email to the end user that is a part of its own system.  However, some security protection may block this from happening, so be sure to know your destination first.  In my/our case, this was actually being used in an internal system to a friendly destination.  Your result may vary…

Now get out there and send those emails!

How to fix Ownerships and Inheritance on NTFS file systems, Pt. 2…

2017-07-27T00:01:03+00:00 September 18th, 2013|Uncategorized|

For background on this post, make sure to see Part 1, here

Picking up where we left off in Part 1, recall that I had a set of folders that were copied with original source permissions, and as a result, had broken permission “inheritance”.  The copy also brought over the various ownerships, which I was seeking to replace with the local “Administrators” group, according to standard practice of the customer.

So in Part 1, I had written a DOS batch script to loop through the folders and 1.) force down ownership in the new folder sub-structures (in order to follow company standard and be able to seize control of them), and 2.) re-apply inheritance of the administrative permissions from the folders above.  While I’d like to think I accomplished this swimmingly with my batch file, the truth is that it really needs to be in PowerShell in order to satisfy the needs of the team (future-proofing, portability, and such).

Let’s step through the PowerShell version now; but watch carefully because even though it is the same in principle as the DOS batch script in Part 1 (same enough to be worthy of comparison), it actually is a tad different in a few of the steps.

First, we clear the screen, set some variables, and clean up any files from the last run:

clear
$StartDate = date
Write-Host "Setting variables..."
$PARENTDRIVE = "S:"
$PARENTFOLDER = "Apps"
$PARENTPATH = "$PARENTDRIVE$PARENTFOLDER"
$LOCALPATH = "c:temp"
$TAKEOWNLOG = "$LOCALPATHtakeown-FixOwnerships.log"
$ICACLSLOG = "$LOCALPATHicacls-FixInheritance.log"
$ICACLSSUMMARYLOG = "$LOCALPATHicacls-FixInheritance-Summary.log"
Write-Host "Cleaning up log files from previous run..."
del $TAKEOWNLOG
del $ICACLSLOG

Now, with this PowerShell version of the script, I don’t need to write my lists out to a temp file for later processing (like I did with DOS in Part 1); I just dump it all into objects in memory.  Far more efficient!  Like so:

Write-Host "Creating Listing..."
$FolderListing = Get-ChildItem $PARENTPATH

Then, we hit the real work part of the script, where we loop through the folder listing, decend though and fix all the ownerships and inheritance.  This part is actually almost the same as the DOS batch script, actually, except that it’s more… um… awesomer:

Write-Host "Process listing..."
foreach ($FolderItem in $FolderListing)
{
  Write-Host "Fixing ownership: $PARENTPATH$FolderItem"
  Write-Output "Fixing ownership: $PARENTPATH$FolderItem" | Out-File $TAKEOWNLOG -append -encoding Default
  takeown /f $PARENTPATH$FolderItem /R /A /D Y  | Out-File $TAKEOWNLOG -append -encoding Default
  Write-Output "" | Out-File $TAKEOWNLOG -append -encoding Default
  #
  Write-Host "Fixing inheritance: $PARENTPATH$FolderItem"
  Write-Output "" | Out-File $ICACLSLOG -append -encoding Default
  Write-Output "Fixing inheritance: $PARENTPATH$FolderItem" | Out-File $ICACLSLOG -append -encoding Default
  ICACLS $PARENTPATH$FolderItem /inheritance:e | Out-File $ICACLSLOG -append -encoding Default
}

And finally, we create a summary log and create some closing comments before cleaning up:

Write-Host ""
Write-Host "Creating summary log..."
Select-String -pattern "Failed" $ICACLSLOG | Out-File $ICACLSSUMMARYLOG -encoding Default
Write-Host ""
$EndDate = date
Write-Host "Started: $StartDate"
Write-Host "Ended:   $EndDate"
Write-Host ""
Write-Host "...Complete!"

So that’s about it, really.  Note that I’m using the -encoding Default flag  at each Out-File so the file gets written in ANSI (on my system) instead of UniCode.   I don’t know about you, but I can’t stand dealing with UniCode files for text parsing and such.

And in case you prefer it in one contiguous list, here ya go:

clear
$StartDate = date
Write-Host "Setting variables..."
$PARENTDRIVE = "S:"
$PARENTFOLDER = "Apps"
$PARENTPATH = "$PARENTDRIVE$PARENTFOLDER"
$LOCALPATH = "c:temp"
$TAKEOWNLOG = "$LOCALPATHtakeown-FixOwnerships.log"
$ICACLSLOG = "$LOCALPATHicacls-FixInheritance.log"
$ICACLSSUMMARYLOG = "$LOCALPATHicacls-FixInheritance-Summary.log"
Write-Host "Cleaning up log files from previous run..."
del $TAKEOWNLOG
del $ICACLSLOG
Write-Host "Creating Listing..."
$FolderListing = Get-ChildItem $PARENTPATH
Write-Host "Process listing..."
foreach ($FolderItem in $FolderListing)
{
  Write-Host "Fixing ownership: $PARENTPATH$FolderItem"
  Write-Output "Fixing ownership: $PARENTPATH$FolderItem" | Out-File $TAKEOWNLOG -append -encoding Default
  takeown /f $PARENTPATH$FolderItem /R /A /D Y  | Out-File $TAKEOWNLOG -append -encoding Default
  Write-Output "" | Out-File $TAKEOWNLOG -append -encoding Default
  #
  Write-Host "Fixing inheritance: $PARENTPATH$FolderItem"
  Write-Output "" | Out-File $ICACLSLOG -append -encoding Default
  Write-Output "Fixing inheritance: $PARENTPATH$FolderItem" | Out-File $ICACLSLOG -append -encoding Default
  ICACLS $PARENTPATH$FolderItem /inheritance:e | Out-File $ICACLSLOG -append -encoding Default
}
Write-Host ""
Write-Host "Creating summary log..."
Select-String -pattern "Failed" $ICACLSLOG | Out-File $ICACLSSUMMARYLOG -encoding Default
Write-Host ""
$EndDate = date
Write-Host "Started: $StartDate"
Write-Host "Ended:   $EndDate"
Write-Host ""
Write-Host "...Complete!"

Enjoy!

 

 

How to fix Ownerships and Inheritance on NTFS file systems, Pt. 1…

2017-07-27T00:01:03+00:00 August 28th, 2013|Uncategorized|

Following up on Matt’s post last year, and my post about a similar-but-different situation…  I’m just taking Matt’s original notions to the next level, and making the script he described.

It all started after we ran into a situation where someone was migrating some data from one Windows server to another along with the NTFS permissions (using a 3rd-party copy tool).  It was soon discovered that all the permission inheritance was blocked at the point of the copy, and all the ownerships were set to the original owners (not desired in this case).  The company policy dictated that the administrative permissions from the parent folder must flow down, and that all ownerships for files and folders were set to the Administrators group. 

So, I needed to whip up a little script to fix the permission inheritance for all the new subfolders on the destination under one parent folder, and reset the ownerships to the Administrators group for each subfolder as well.

A couple important criteria I had to work around was that I write it so that it only works on the migrated subfolders, so I don’t affect the parent folders under which these new folders were copied (which actually had *intentionally* blocked inheritance and might possibly have intentional alternate owners in some situations).

Well, since all folders ended up in the same destination parent, I naturally wrote a simple little DOS batch script to fix these.  Why DOS batch, you say?  I don’t know, honestly.  Sometimes when I’m thinking through a Linux/Unix scripting situation, I start thinking of it in bash, and change to Perl when I realize it’s too complex.  And similarly in Windows-based environments I start thinking in DOS batch, and then switch to PowerShell when it gets too complex.  Just an old habit that’s hard to break, I guess.

So, walking through the main sections of the script…

First, we do initial setup, set variables for output files and such, and delete the files from the last run of the script (since it would likely be run repeatedly as a maintenance tool):

@ECHO OFF
@cls
1>&2 Echo Setting variables...
SET PARENTDRIVE=S:
SET PARENTFOLDER=Apps
SET PARENTPATH=%PARENTDRIVE%%PARENTFOLDER%
SET LOCALPATH=c:temp
SET FOLDERLIST=FolderList.txt
SET TAKEOWNLOG=takeown-FixOwnerships.log
SET ICACLSLOG=icacls-FixInheritance.log
SET ICACLSSUMMARYLOG=icacls-FixInheritance-Summary.log
1>&2 Echo Cleaning up log files from previous run...
@del %LOCALPATH%%FOLDERLIST%
@del %LOCALPATH%%TAKEOWNLOG%
@del %LOCALPATH%%ICACLSLOG%
@del %LOCALPATH%%ICACLSSUMMARYLOG%

Then, we create a listing file of the top-level folders, and store them in a file (with quotes):

1>&2 Echo Creating Listing...
@FOR /F "tokens=*" %%a in ('"dir %PARENTPATH% /A:D /B"') do @echo "%%a">>%LOCALPATH%%FOLDERLIST%

Now we change to the destination folder, and begin processing.  This is really the meat of the script.  This is where we use takeown to set Adminstrators group ownership to each folder heirarchy, and ICACLS to force permission inheritance (for administrator permissions from the parent):

1>&2 Echo Changing to %PARENTDRIVE% and %PARENTFOLDER%...
%PARENTDRIVE%
CD %PARENTFOLDER%
1>&2 Echo Process listing...
@For /F "tokens=*" %%Q in (%LOCALPATH%%FOLDERLIST%) Do @(
1>&2 Echo Fixing ownership: %%Q
@takeown /f %%Q /R /A /D Y >> %LOCALPATH%%TAKEOWNLOG%
1>&2 Echo Fixing inheritance: %%Q
ECHO Analyzing: %%Q >> %LOCALPATH%%ICACLSLOG%
ICACLS %%Q /inheritance:e /T /C >> %LOCALPATH%%ICACLSLOG%
)

And here is where we wrap it up.  I provide a brief summary report, and say goodbye:

1>&2 Echo Creating summary log...
FindStr /I /C:"failed" /C:"analyzing" %LOCALPATH%%ICACLSLOG% > %LOCALPATH%%ICACLSSUMMARYLOG%
1>&2 Echo ...Complete!

Now here is the whole script again, in once piece:

@ECHO OFF
@cls
1>&2 Echo Setting variables...
SET PARENTDRIVE=S:
SET PARENTFOLDER=Apps
SET PARENTPATH=%PARENTDRIVE%%PARENTFOLDER%
SET LOCALPATH=c:temp
SET FOLDERLIST=FolderList.txt
SET TAKEOWNLOG=takeown-FixOwnerships.log
SET ICACLSLOG=icacls-FixInheritance.log
SET ICACLSSUMMARYLOG=icacls-FixInheritance-Summary.log
1>&2 Echo Cleaning up log files from previous run...
@del %LOCALPATH%%FOLDERLIST%
@del %LOCALPATH%%TAKEOWNLOG%
@del %LOCALPATH%%ICACLSLOG%
@del %LOCALPATH%%ICACLSSUMMARYLOG%
1>&2 Echo Creating Listing...
@FOR /F "tokens=*" %%a in ('"dir %PARENTPATH% /A:D /B"') do @echo "%%a">>%LOCALPATH%%FOLDERLIST%
1>&2 Echo Changing to %PARENTDRIVE% and %PARENTFOLDER%...
%PARENTDRIVE%
CD %PARENTFOLDER%
1>&2 Echo Process listing...
@For /F "tokens=*" %%Q in (%LOCALPATH%%FOLDERLIST%) Do @(
1>&2 Echo Fixing ownership: %%Q
@takeown /f %%Q /R /A /D Y >> %LOCALPATH%%TAKEOWNLOG%
1>&2 Echo Fixing inheritance: %%Q
ECHO Analyzing: %%Q >> %LOCALPATH%%ICACLSLOG%
ICACLS %%Q /inheritance:e /T /C >> %LOCALPATH%%ICACLSLOG%
)
1>&2 Echo Creating summary log...
FindStr /I /C:"failed" /C:"analyzing" %LOCALPATH%%ICACLSLOG% > %LOCALPATH%%ICACLSSUMMARYLOG%
1>&2 Echo ...Complete!

But you know what?  That’s not good enough for Matt and me.  Nope, Matt basically insisted that it had to be done in PowerShell after all.  So of course I did that too, and I’ll put that up next week.  Why PowerShell you say?  I don’t know… Why not?

😉

 

 

PowerShell – How To Discover and Set Permissions on a Folder…

2017-07-27T00:01:03+00:00 June 12th, 2013|Uncategorized|

I’ve written a few posts here in the past about how to use PowerShell to set NTFS permissions, in a couple different fashions.  But recently I was asked something like, “…okay, I know what permissions I’d like to assign in Windows Explorer, but how do I know what the PowerShell equivalent is?” 

The point of the question is that the description of the permission you see in the GUI is not necessarily what you’d actually put in your PowerShell command when you attempt to apply it.  So how do you know the difference and correlation?

There are tons of references out there for learning more about scripting setting permissions in PowerShell, but it’s not always easy to know *which* permission to set with PowerShell.  So let’s imagine the scenario where we need to add a “custom” permission to a folder via a PowerShell script or command (maybe part of a loop, etc.), and the requesting person has only described to you in the most GUI-like terms what is needed. Step1

In this case, what I usually do is:

1.) Ask the person to set the desired permission on an example folder (if it doesn’t exist already) to be sure that you are talking about the same thing, like this example:

…In this example case we are using the following:

Permission 1: Create File / Write Data
Permission 2: Create Folders / Append Data
Permission 3: List Folder / Read Data
At: Folder name “Bogus”
For: This folder, subfolders, and files
To: LABWorkgroup1

 

2.) Use PowerShell command Get-Acl .Bogus | Format-List to get a readable ACL from the example folder:

 Step2

3.) Now, remove that permission from the folder, and run the above command again to see the difference (or just evaluate the SIDs):

Step3

…and now you can see — among the other permissions — that the above listed permissions translate to LABWorkgroup1 Allow  ReadData, CreateFiles, AppendData, Synchronize; and the Sddl, if you need it: (A;OICI;0x100007;;;S-1-5-21-2087276962-282213542-3505124996-1115)

4.) Finally, set the permission on the new folder:

$folder = "Bogus"
$myGroup = "LABWorkgroup1"
$acl = Get-Acl $folder
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$myGroup", "ReadData", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$myGroup", "CreateFiles", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$myGroup", "AppendData", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
Set-Acl $folder $acl

This is a simple example, of course, but it’s an easy way to get it done without chasing down reference documentation.  After a while and frequent use, you begin to kinda’ memorize the various PowerShell permissions options and recognize them — but you can sometimes forget them too, and this is a quick and easy way to figure it out at any time.

😎

 

Powershell – How recursive directory searches got better with PSv3…

2017-07-27T00:01:04+00:00 April 17th, 2013|Uncategorized|

In the old days, we ate dirt for dinner, brushed our teeth with sticks, used PowerShell v2 — and we *liked* it! 

There, that’s my tribute to Dana Carvey as “Grumpy Old Man”.  Google it, kids.

Anyway, I’ve got an absolute ton of old PowerShell scriptlets that I have lying about that I regularly cannibalize or resuscitate back into production.  And since we are in that squishy transitional period between PowerShell v2 and v3, I don’t always bother to check them for compatibility with v3 or update features in the script to take advantage of new capabilities.  But I hit on one v3 improvement the other day that solved a problem has bugged me so much for so long that I wanted to shout from the mountaintops about it!  And since I live in mostly-mountainless Michigan, the blog is the best I can do…

Really it’s such a little thing.  But it’s so overdue.

In the past, if you wanted to recursively inspect a folder structure on a remote server — for instance while fishing for explicit NTFS permissions on folders — you were forced to inspect all folders *and* files, no matter if you only wanted folders.  Basically, you had to ask for everything (all children folders and files, recursively), then parse the result to extract the folders (check psIsContainer) from the listing.  Here’s an example of this, similar to what you might see all around the internet:

# For PowerShell v2
$containers = Get-ChildItem -path $TopPath$CurrentParent -recurse | ? {$_.psIscontainer -eq $true}

 Of course, this could be incredibly wasteful in processing, network bandwidth, time, etc…   All this time I’ve always wished there was a way in my loops to just ask for ONLY the folders, to save all of that waste.  Thankfully, this has arrived with v3.  Behold:

# For PowerShell v3
$containers = Get-ChildItem -Directory -path $TopPath$CurrentParent -recurse

 This has significantly sped up some of my analysis scripts that I run in a large enterprise, cutting as much as half a day off of some of my execution times (I did mention it was large).  So really what this means is that I have to start spending more spare time looking through the v2/v3 differences…  But I won’t have any spare time until I implement more v3 changes…  Quite a conundrum… 

😉

 

Powershell – Query Active Directory for Server Versions…

2013-03-20T22:45:57+00:00 March 20th, 2013|Uncategorized|

Today, I’m writing about a simple-but-useful command that just might help you get a better understanding of the quantity and variety of Windows servers you have in your environment, with just a few caveats.  The most accurate way to get such information, of course, is to query Active Directory in real-time to get the most current information possible.  And the easiest way to do that (in my opinion), is to use PowerShell.  So launch a console and let’s get to it…

But first, if you haven’t launched the pre-loaded Active-Directory PowerShell Module, then let’s do that now:

Import-Module ActiveDirectory

Here’s a first blush at how we can list all AD-based computers, grabbing only the interesting properties we need, formatting the output to a list, and redirecting the results to file (I’ve seen some things like this while ‘Googling):

Get-AdComputer -Filter * -Properties IPv4Address,OperatingSystem,OperatingSystemServicePack | Format-List Name, IPv4Address, OperatingSystem* > OutputServerList.txt

Now, let’s dig deeper, and perhaps refine the command a bit.  First, the filter is a wildcard, and retrieves all computers.  That might be fine in a small environment with few computers; but we’re really only after Servers here, and we might be working in a larger environment.  So, we will change the filter to use an LDAPFilter and get a bit more granular like this:

-LDAPFilter "(OperatingSystem=*Server*)"

Next, I think the results will actually look better if we output them to a CSV, so we’ll drop the redirect and list formatting, and replace it with a pipe like this:

| Export-Csv ExportCsvServerList.csv

Now a warning about the CSV export…  Unfortunately, Microsoft chose to include a “restricted” symbol (little r in a circle) in the Server 2008 (non-R2) name, like this:

Windows Server® 2008 Standard

…and, the CSV export operates only with the ASCII set by default.  Sheesh.  So, we use the UTF8 flag to make sure the wacky “restricted” mark is rendered correctly, like this:

| Export-Csv -Encoding UTF8 ExportCsvServerList.csv

So with all that, we end up with a command looking like this:

Get-AdComputer -LDAPFilter "(OperatingSystem=*Server*)" -Properties IPv4Address,OperatingSystem,OperatingSystemServicePack,OperatingSystemVersion | Export-Csv -Encoding UTF8 ExportCsvServerList.csv

And since it’s a spreadsheet you can further filter/format/manipulate the results how you see fit.

One more thing that causes confusion sometimes: 

Be aware that even though we are calling ActiveDirectory for these servers and their correlating properties, there’s one of these items that don’t come from there: the IP Address.  As you are likely aware, the IP address of a computer object is not stored in the directory; so what is actually happening is that the Get-AdComputer module is retrieving the FQDN of the computer, and doing a DNS query to resolve it to the address for you. 

Now, this can be good or bad, depending on your situation; for instance, it might slow down your 8000+ server export… or might also help alleviate the burden on your AD server as you make the query (while it delays the processing a tad to retrieve the name).  Also, you’d better be able to rely on your DNS to return valid values, or the results might be confusing/misleading! 

I hope that helps…  Thanks for reading, and by all means if you have additional tips, be sure to comment!

 

 

 

PowerShell – Detect Group Membership Type…

2017-07-27T00:01:04+00:00 March 6th, 2013|Uncategorized|

It should come as no surprise that adherence to naming conventions and good Active Directory (AD) Organizational Unit (OU) structure are things that can make an Enterprise Administrator’s life much easier. 

Take, for example, the situation of having a naming convention for group objects in AD that dictates a single-letter suffix of either a “C” (to indicate a group of computer objects) or a “U” (for a group of user objects).  In this case, a group might be named something like, “Detroit Application Data U”, or “Chicago Printers Floor2 C”.  And with intentions such as these — and human beings being what they are — it’s inevitable that some users will end up in computer groups, and vice versa.

So how to we check for this messiness?  With PowerShell, of course…

We create a script that will accept an array of our AD OUs (or group-specific OUs if you’re lucky), loop through them, grab all the groups and the memberships, and do a validation to make sure the members are of the correct class (note that I could fill up pages of the lines of code for this, depending on your specifics; so I’ll just stick with the main conceptual points).  Let’s dive into the code snippets!

First, add your OUs into an array, and other variables.  Of course, you might not be able to just scrape a level with PowerShell and grab all your OUs…  Oh, but you *do* have a perfectly-regulated AD hierarchy, don’t you?  Whether it’s perfect or not, AD structure goes a long way here; and my examples show how convenient it is if you have all your groups in a standard ou=GROUPS structure or some predictable way.

$OUs = @("Detroit", "Chicago", "Los Angeles")
$MyDomain = "dc=MyDomain,dc=org"

Then you start to loop and grab all the groups in an OU:

foreach ($OU in $OUs)
{
  #... skipped a few more lines of code here...
# Here we get the list of our groups for the loop
$OuGroupNames = Get-ADObject -Filter {(ObjectClass -eq "group") -and ((name -like "* U") -or (name -like "* C"))} -SearchBase "ou=Groups,ou=$OU,$MyDomain"

And, now that you have the groups, you can start to evaluate each group like this:

  foreach ($OuGroup in $OuGroupNames)
  {
    #...skip more code.. What are we skipping here? Oh, validations, error-checking, and stuff...
# we need the group name and DN    $OuGroupName = $OuGroup.Name     $OuGroupDn = $OuGroup.DistinguishedName

Now, we can truly check the object membership type!

    # If it is a user group...
if ($OuGroupName -like "* U")     {       $MemberList = Get-ADGroupMember -Identity "$OuGroupName"
# ...it had better be a user...       if ($Member.ObjectClass -like "computer")
{
#...or we kick out an error to the report!

And so on.  Of course, you’d do the converse of the snippet above for a user-type object in a “C” group.  By the way, this can lead to all kinds of other error detection too; in fact, the main reason I couldn’t show all my code is that I ended up adding checks for empty groups, groups with members from external OUs, and so on.  Because basically, once you have the group attributes and its membership list in hand, you may as well do some validation while you’re there…

So have fun with it, and see where it leads you…  And make sure to drop me a line if you need any help putting the whole thing together.

🙂

 

 

 

 

PowerShell v3 and DNS Queries…

2017-07-27T00:01:04+00:00 January 30th, 2013|Uncategorized|

As I mentioned in last week’s post, “PowerShell v2 and DNS Queries…“, it is much easier to do scripted DNS queries in PowerShell v3 on Windows 8 and Windows Server 2012 than it is in v2 — thanks to the new Resolve-DnsName command.  Following along the same lines as the previous post, and using the exact same example hosts, we can show the same correlations and results for comparison. 

We’ll start off with a request similar to our first nslookup in the previous post, but this time using the Resolve-DnsName command:

And as before, the same holds true with out multi-valued results:

On its face, the results are very similar to nslookup results.  However, since we’re dealing with objects here instead of scraped screen executable output, we can actually manage our results very neatly.  Here’s what I mean, as I enclose the object, and only request the “.IpAddress” from it for my two example hosts:

See how neat, clean, and powerful that is?  This same thing works with other object elements, like “.NameHost“, and such.  By the way, I’ve seen some advice posts out on the ‘Net that advise you to use an increment indicator like this:

(Resolve-DnsName $server_name)
[0].IpAddress

…but that will cause you to only get the first result returned!  And sometimes, that may be what you’re after; but in the case of the multivalued host, that’s probably not what you want.

Now, to contrast last week’s post, I’ll show you how we take the 12-line PowerShell v2 script down to a 3-line PowerShell v3 script:

$ARecord = "labdc1.lab.local"
$NameServerQueried = "192.168.6.4"
(Resolve-DnsName -Name $ARecord -Type A -Server $NameServerQueried -ErrorAction SilentlyContinue).IpAddress

 …But of course, it’s only 3 lines because 2 of them are variables; but it’s a fully functional equivalent.  And you can start to see how efficient it can be when looped.  And for the sake of completion of the comparison, here’s the results of my v3 script with the “fakehost” multi-valued host:

…and with the original “labdc1”:

So there you have it.  We love the new commands in PowerShell v3, and they are making our lives soooo much easier (once you know about them).   Now, I’m just waiting for the commands I’ve been asking for… Like Get-MyCoffee… and Get-WorldPeace…. and Solve-GlobalHunger

😉

 

 

 (Updated 20130815)

PowerShell v2 and DNS Queries…

2017-07-27T00:01:04+00:00 January 23rd, 2013|Uncategorized|

For this week’s (and next week’s) post, I decided I’d kill a few birds with one stone.  Since it’s “PowerShell month” here at TekTopics.com, and since I’m still making my way through all the differences between PowerShell v2 and v3 (like we all are), I thought I’d tell you about how I just discovered how a relatively simple thing was relatively hard to do in PowerShell v2, and how it got relatively WAY easier in PowerShell v3:  DNS lookups.

Probably like you, I’ve been doing DNS queries for years in all kinds of scripts and languages — like bash, perl, DOS batch files, and of course, PowerShell.  And up until recently, I treated them all pretty much the same — in that I typically just made a system call out to running OS and used the native DNS client query tool, nslookup.  Of course this requires that I grab the output of the tool, scrape out just the information I want (and ignore other data), and continue on to make use of it.

However, in PowerShell v2, the problem is that when trying to grab the desired results back from the system call, the resulting address from the query is not as easy to discern from the “courtesy” information that is returned along with the answer from nslookup.  What I mean is that searching for the string “Address” could get you in trouble, since you end up with two lines that start with “Address” — the one you don’t want (the address of the server that was queried), and the one you want (the query response). 

And in some cases, they could theoretically be the same value, especially if you’re looping through a list of nameservers and query the name of the server you’re querying.  See what I mean in this unfiltered example query and response: 

 

Note that the record could be multi-valued too, like this example:

So if I just attempt to grab all the strings that match “Address”, as in the following…:

…I could end up with some strange results.  So, instead, I search for all strings in the form of an IP address, and I implement a simple counter to skip the first one, catch any subsequent ones, and split the result to strip out the words.  Here’s the code for my loop:

$ARecord = "fakehost.lab.local"
$NameServerQueried = "192.168.6.4"
$FullAddressList = nslookup -type=a $ARecord $NameServerQueried | findstr "
[0-9].[0-9].[0-9].[0-9]" $counter = 0 foreach ($line in $FullAddressList) { $counter = $counter + 1 if ($counter -ne 1) { write "$line" | %{ $_.Split(" ")[2] } } }

…and here are the results, with the query for the multi-valued “fakehost” host record, as in the $ARecord variable as above (inside my Example.ps1 script):

…and with the original “labdc1” nameserver query, as in my first example:

As you can see, DNS queries are do-able in PowerShell v2, but it’s a pain.  The little snippet above should work just fine inside of a larger loop in a validation script, or on its own, for whatever you need to get done.  And I’m sure there are other ways to accomplish the same thing, but this has worked for me in the past (and present) in PowerShell v2. 

Well — now, there’s a new way of getting the same queries done in PowerShell v3, that is much, much, much easier…  And I will jump into that next week.  See you then!

Next week:   The PowerShell v3 way!

 

PowerShell Basic Commands 101

2017-07-27T00:01:04+00:00 January 16th, 2013|Uncategorized|

It looks like January has turned into “Powershell Month” here at the TekTopics.com! 

And while typically, we write these Powershell-related posts with the assumption that you’re already at least reasonably versed in the language, I thought it might be good to give a few introductory tips to those of you who need the first few basics of Powershell to get you up and running.  Then, you can take these tips and start getting creative with some of the great scripts, loops and commands we’ve talked about here in this blog.

First off, when in the PowerShell command prompt type in “Get-Command” and hit enter:

Get-Command

This will list every PowerShell command available. It is quite lengthy, but can be very helpful if you have the time to scroll through the entire list to discover new and exciting scripting tools.

If you wanted to save this list, you could by outputting it to a file by using the “|” (“pipe”) combined with the “Out-File” command, for example:

Get-Command | Out-File C:Commands.txt

If you are like me and require the list to be sorted by “practical application” then you can sort it by `Module Name’ by simply running:

Get-Command | Sort Module

You can then take it one step further to narrow your search results by filtering by Module name and a “*” (wildcard) as seen here an example of searching for BitLocker:

Get-Command -Module BitLock*

Or if you are looking for a specific command to run to `Enable’ BitLocker:

Get-Command –Module BitLock* -Name Enable* 

From there, if you need usage commands or examples of any newly found Powershell command you can use the “Get-Help” command. The following example would give you helpful information for the “Get-Command” cmdlet as previously mentioned:

Get-Help Get-Command

Or for “Select-String”, the PowerShell equivalent to “FindStr” or the ever-so-popular string search tool called “Grep”:

Get-Help Select-String

One final note to tie this all together: Instead of memorizing the entire cmdlet, module or function names you can use the built-in aliases, which are shorter commands that execute the same command as the long name function, for example: gcm is Get-Command and help is Get-Help

So you could run the following command, which is the same as the above “Get-Help Get-Command”:

help gcm

And you can view the entire list of “Aliases” by running:

gcm -Type Alias

That is all for now! Stay tuned for PowerShell Basic Scripting 101!

 

 

Load More Posts