Archive for the ‘Microsoft’ Category

Powershell – Check for PS version and act accordingly…

May 23rd, 2013 by Jeremy Pavlov | No Comments | Filed in Microsoft, PowerShell, Scripting

In recent posts, we’ve been outlining some important day-to-day differences in PowerShell CMDlets and features between v2 and v3.  And right now I’m working with a customer that is in the midst of transitioning between XP and Win7, and between Server 2003 and 2008/2012, where these differences really start to matter performance-wise. 

So, we’ve got lots of PowerShell tools we wrote in v2 that we are slowly getting around to updating to the new features in v3.  But the thing is, we still can’t be certain where these scripts will be run, and by whom.  So we’ve put together a little “version detector” to help run the correct version of the command and give the best performance possible, whenever possible.  And as a result, you — the reader — can apply this type of thing to any script that might be run in a mixed environment.

This example below features the new -Directory flag in the PowerShell v3 Get-ChildItem, though you could just as easily replace that line in each section with any other CMDlet that behaves differently between versions.  Just modify this section, and wrap it around your CMDlet with the updated v3 capability…

 

$hostVersionInfo = (get-host).Version.Major
if ( $hostVersionInfo -eq "2" )
{
  # For PowerShell v2
  write "We appear to be using PS version $hostVersionInfo... That's okay, but this script processes faster with PS v3!"
  write ""
  $containers = Get-ChildItem -path $MoLoPath\$CurrentParent -recurse | ? {$_.psIscontainer -eq $true}
}
elseif ( $hostVersionInfo -eq "3" )
{
  # For PowerShell v3
  write "We appear to be using PS version $hostVersionInfo... Good!"
  write ""
  $containers = Get-ChildItem -Directory -path $MoLoPath -recurse
}
else
{ 
  write-host "Unknown/unapproved version of PowerShell. Exiting!"
  exit
}

 

Normally, I’d explain some of the functionality in the script; but it’s fairly simple, well-commented, and in general pretty descriptive.  It just detects which version of PowerShell you’re running, and runs one of the two version of the CMDlet.  So you should be able to figure it out quickly even if you’re new to this stuff. 

Of course, if you have a question (or have a better way of getting it done), feel free to comment. 

So that’s it, I hope it helps!

:)

 

 

Did you like this? Share it:

Powershell – How recursive directory searches got better with PSv3…

April 18th, 2013 by Jeremy Pavlov | No Comments | Filed in Microsoft, PowerShell, Scripting

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… 

;)

 

Did you like this? Share it:

Tags: , , , , ,

A cool ‘Remote Desktop Connection Manager’ tip!

April 4th, 2013 by Matthew Sharland | No Comments | Filed in Desktop OS, Microsoft, Virtual Desktop Management, Windows 7, Windows 8, Workstation Management

I am constantly monitoring multiple Microsoft Windows Servers and XP workstations via Remote Desktop Connection Manager and having to switch between each console one at a time is a very user-intensive and time-consuming process.  Though, I have recently discovered a very useful and time-saving trick that I will share with you below…

First, by default, the Remote Desktop Connection Manager gives you a thumbnail view of all of your workstations when you click on any “group” of servers from the left server pane list.  I always thought this was a “gimmick” and never thought twice about using it for anything because the dimensions of the thumbnail views of the remote desktops were just way too small to be useful.

But after reviewing the program’s options I found that you can modify the size of the thumbnails (Tools > Options > Client Area > Thumbnail Size)!

But that isn’t all!

The thumbnails are actual “live” clickable Remote Desktop sessions; so if you set the pixel size of the thumbnails to 25%, 30% or 40% of your screen size, you can fit 4-12 active server connections into one very productive window (obviously depending on your monitor size and screen resolution!).  This screen cap should give you a good idea of what I mean:

screenshot

 

I hope you find this tip as useful as I did!  Enjoy!

 

 

Did you like this? Share it:

Tags: , , ,

Installing HKCU keys using a Windows Installer repair, Pt. II

March 28th, 2013 by Paul Opper | No Comments | Filed in Application Packaging, Desktop Management, Microsoft

Previously, in Pt. I of this series, I wrote about how to install HKCU registry keys (which can also be used for installing data anywhere in a user profile).  Now I’ll go into more depth on how to do this using the popular application packaging product Wise Package Studio.

Though Wise Package Studio has been discontinued by Symantec, it’s still quite popular in many packaging environments.  The main tool used for creating and editing Windows Installer projects in Wise Package Studio is the “Windows Installer Editor”, which was previously available alone as “Wise for Windows Installer” (wfwi.exe). 

Most of the packaging work will be done in the “Installation Expert” view, which is a slightly more “user friendly” or “cleaner” project editor.  After creating my new project, I’ll add a couple files to it.  The files I added are Process Explorer (procexp.exe) from “SysInternals” and it’s help file (procexp.chm).  Process Explorer is one of several extremely useful utilities available (free!) in the Sysinternals Suite

 

1.Wise

 

Next, I’ll add an “Advertised” desktop shortcut to “procexp.exe” from the “Shortcuts” page.  By default, when you add a shortcut to point to a file in your installation the “Advertised” check box is marked. 

 

2.Wise

 

Note that “Complete” is listed in the “Current Feature” drop down list.  By default, Wise starts with a feature named “Complete” and puts all files, registry keys, shortcuts, etc. under the “Complete” feature, but we need a “hidden” parent feature.  So, from the Features page “Add” a new feature.  Give it a name, select “<None>” from the Parent drop down list, “Hidden” from the Display drop down, and check the “Required Feature” check box; the rest of the defaults can be left.  After adding the hidden parent feature, I go into the “Complete” feature to select the hidden feature from its “Parent” drop down list. 

 

3.Wise

 

Finally, I add an HKCU registry key to the new hidden feature.  Notice now that I’ve added a new feature, I can select it from the “Current Feature” drop down list from all the pages in Installation Expert. 

 

4.Wise

 

After the project is compiled, the .MSI can be run on any system “per machine” with the “ALLUSERS” value set to ’1′.  When a new user logs onto the machine and clicks on the advertised shortcut, the HKCU key will be installed by the windows installer repair. 

 Next time, I’ll take a look at implementing self repair using InstallShield.  I hope you found this tutorial enlightening, instructive, and maybe even a little fun.  Well..uh..instructive and enlightening should be good enough! 

 

 

 

Did you like this? Share it:

Tags: , ,

Powershell – Query Active Directory for Server Versions…

March 21st, 2013 by Jeremy Pavlov | No Comments | Filed in Microsoft, PowerShell, Scripting

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!

 

 

 

Did you like this? Share it:

Tags: , , , , , , , , , ,

Installing HKCU keys using a Windows Installer repair

March 14th, 2013 by Paul Opper | No Comments | Filed in Application Packaging, Desktop Management, Microsoft

One of the more common (and tricky) issues faced when installing an application in the enterprise is how to install user data.  Typically, the application installer is run silently with no user interaction in the “system” context with administrative privileges.  This method is commonly used so that the software can install in the background without disrupting the end users work.  Fortunately, this method works for a majority of software deployments, because the installer does not need to install anything in the “user” context. 

There are situations, however, when an application requires registry keys or some data files installed in the user’s profile prior to the applications first launch.  One common post-installation method used for installing user data is called “Active Setup”; a full explanation of how to implement this method is beyond the scope of this post… and besides… there’s already been a blog post on this topic

A major drawback of the Active Setup method is that any user logged on to the system when the silent installation occurred must log out of their profile and log back in.  The reason is because the mechanism which initiates Active Setup compares a Local Machine registry keys to one in the User’s profile when the user logs on.  A more convenient and functional method (and slicker, I must say) to install data to the user profile in the user context is by initiating a Windows Installer repair. 

By design, Windows Installer initiates “self repair” or “self healing” when an entry point to the installed application is launched.  Typically, the entry point is an “Advertised” shortcut.  When the user clicks on the shortcut, Windows Installer will perform an integrity check to verify all the “key paths” of the installed application are present; if not present, the Windows Installer repair will install any missing component(s) and their key path.  The key path of a component is typically a file or shortcut. 

One  method for installing Current User registry keys post install is to add a top level “Hidden Feature” (note: the feature doesn’t really have to be hidden, but we do this to ensure that whoever runs the install doesn’t have the option not to install it) to the install which contains all the HKCU keys.  Mark the feature as “required” and make it the “Parent” feature to all other features in your MSI.  Move all HKCU keys to the same component in the required feature.  Finally, add an “advertised” to your application to facilitate the repair.  After the application is installed (in the system context), when a user click on the advertised shortcut a self repair will occur to install the components with the missing key paths… IF the key path doesn’t exist.

Ya see…this blog post was partly inspired by a setup I encountered on a customer location which attempted to use this method for installing the required HKCU registry keys.  When I tested the application, it was not behaving as expected.  I looked into the .MSI that installed it and found that everything had been laid out according to the prescribed method detailed above… except… the component key path holding the HKCU keys was actually an HKLM registry key which already existed on my system!  Thus, the self repair would never “kick off”.  When attempting to initiate a controlled Windows Installer repair, you must ensure the component key path is truly unique, or the repair won’t happen. 

I hope you enjoyed this little insight into Windows Installer and find this method to install user data helpful.  This was just a high level overview; next week, I’ll follow up with a more detailed post on how to implement this functionality. 

 

 

Did you like this? Share it:

Tags: , ,

AD Attributes – LastLogon vs. LastLogonTimeStamp…

February 28th, 2013 by Matthew Sharland | No Comments | Filed in Microsoft, Microsoft Infrastructure, PowerShell, Scripting

A little while back I was working at an enterprise that has many locations across the United States.  I had a list of 30 usernames (from one specific out-of-state location) and a couple brand-new test accounts that I wanted to report on their “last logon times” from the Active Directory domain.  I put together a quick PowerShell script to loop through each user and report on the “lastLogon” time and I had (what I thought were) my results in no-time.  Here is a snippet of the code:

Get-ADUser $UserNameToSearch | Get-ADObject -Properties lastLogon

First, I opened up an RDP session to a domain workstation that I had access to at the out-of-state location that I was working with at the time and I went ahead and logged in with my test user.  I waited a few minutes for the replication to occur back to my location’s domain controller and then I ran the script from my local workstation.  Surprisingly, there were no results reported for that test account, but there were current up-to-date results for 95% of the users who were on my list that are said to work at that same location.

So I logged out, logged back in, waited, and ran the script again.  Still, no “logon time” results for my test user account.

Very interesting….

I did a few minutes of research on the “lastLogon” attribute and then I discovered I was searching the wrong attribute, per Microsoft’s MSDN Attribute Library which states: “This attribute is not replicated and is maintained separately on each domain controller in the domain. To get an accurate value for the user’s last logon in the domain, the Last-Logon attribute for the user must be retrieved from every domain controller in the domain. The largest value that is retrieved is the true last logon time for that user.  But since the enterprise I was working with had more domain controllers than I could count on one hand so I chose to find a simple alternative.

After a few more minutes of research I then found the attribute that is replicated across all domain controllers, the “lastLogonTimeStamp” attribute.  I updated my script to:

Get-ADUser $UserNameToSearch | Get-ADObject -Properties lastLogonTimeStamp

I then had the results that I expected and I carried on with my day.

Hopefully this experience will save you time and effort!

 

 

 

Did you like this? Share it:

Tags: , , , ,

Windows Activation Error: Code 0x8007232b

February 14th, 2013 by Jeremy Pavlov | No Comments | Filed in Microsoft, Windows 8

Every once in a while I like to pass along a helpful tip from another website or blog that helped me.  Today, I want to thank György Balássy for his blog posts (post 1, and post 2) last year that helped me with a goofy error, and maybe they can help you too.  I’ll just summarize the problem and results below.

I build a lot of lab servers and VMs for testing various things (including on my laptop or in my home lab, etc.), and I commonly install new Windows servers or workstations from the MSDN media ISO, using what is effectively a volume license.  Usually, I enter the key early in the build, it is accepted without error, and the install continues. 

However, occasionally after the installation completion, the Windows Server 2012 or Windows 8 machine reports an activation error:

Activation Error: Code 0x8007232b
DNS Name does not exist

And back when this first happened to me, it took a little bit of searching before I stumbled on György’s post.  But I’ve referred back to it a handful of times as this frustrating symptom seems to re-appear at random.  In a nutshell, he explains in his two posts that in order to fix this annoying error, you can do it with either the command prompt or GUI, as follows:

Command Prompt:

slmgr.vbs –ipk "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX"

GUI:

slui 3

And it has worked perfectly for me every time.

Now, mind you, I did mention this problem was intermittent.  And the main reason I’m writing this post today after all this time is that it just happened to me again 3 days ago when I was in a hurry.  And today, when I had time to try and reproduce the error for a screen capture for this post, of course the key registration worked just fine and I cannot make it fail.  Argh.  So please take my word for it.

So thanks again György; and to the rest of you, I hope it helps you as well  And if it should pop up again, I’ll try to get a screen shot…

;)

 

 

Did you like this? Share it:

Tags: , , , ,

Powershell: Get-ADUser Without Errors…

January 3rd, 2013 by Jeremy Pavlov | No Comments | Filed in Microsoft, PowerShell, Scripting

I do a lot of scripting of mass-user searches, server and Home Folder validations, etc., where I rely on the Powershell command “Get-ADUser” in my loops.  And this is one of those cases where Powershell is very forgiving; and as such, things like this can be done a handful of different ways.  Of course, some are better than others…

The shortest and easiest form of the command is often fine enough to get the job done, but not always the best in certain situations.  For instance, if you have an IF loop where you are going through an expected list of users (perhaps from an input file) and trying to retrieve a certain attribute for each, you might be inclined to initially write the loop line something like this:

Get-ADUser -Identity $loopUserId

…and this is fairly standard, of course.  In the resulting loop, it would return something like the standard set of attributes in this capture (using a manual query in my lab for this example)

 However, if you are like me, you might occasionally want to watch the output of your scripts while they run; and you prefer to send nice results to screen (as well as to the output logs) for easy debugging and, well, entertainment. 

And this is where the problem arises with the simple format of the command; you soon become annoyed by all the red error messages for the users that have gone missing since your input file was created, as in the case of this intentional search for a non-existent user:

…this is because by default, the Get-ADUser command will give you a nice set of results when it succeeds, but an ugly red message when there is no result.  Yuck.  This simply won’t do; we don’t want to have to panic as if there were an actual *error* every time we get an empty result on each query in the loop!

Instead, we wish to just get a silent, non-return when there are no results.  So, another way to write the same command so that you don’t get any error messages is by using the -Filter option, like this:

Get-ADUser -Filter {SamAccountName -eq $loopUserId}

In this manual example, you can see that the results are the same as if using the earlier format of the command when successful:

…But this time, we get a nice, quiet, non-result in the event of an empty response; as in the case of the same failed search:

Much better!

Now, you can watch your loop output while having a nice… calm… lunch….

 

 

Did you like this? Share it:

Tags: , , , ,

DFS Replication Validation Script…

December 13th, 2012 by Jeremy Pavlov | No Comments | Filed in Microsoft, Microsoft Infrastructure, Scripting, VMware, VMware ESXi

The other day, while at the enterprise-level customer with whom I’m currently working, I ran into a situation where I needed to validate that certain parts of a DFS hierarchy were properly being replicated across the customer’s AD domain controllers.  As the administrators applied normal, routine DFS changes, the changes sometimes didn’t replicate properly across the enterprise — causing some segments of the DFS structure to not be visible or available. 

Apparently, the DFS problem was a result of using VMware guests as AD DCs.  I understand (from the customer) that a Microsoft hotfix is in the last stages of testing (at the time of this writing) and will be available for release “soon.”   It seemed that even though the DCs in question did not synchronize time with the ESX host upon which they reside, there is a default behavior in VMware Tools that assigns the host time value to the guest — at least up until the “do not sync” routine is processed during startup; after which the guest is then allowed to find its own time.  During this brief time window, the DFS Namespace service sometimes completes assembling its DFS target list and can find itself behind in time, relative to links it has been given by PDCE; which makes no sense to it, and it removes them from its listing.  And as a result, people can’t find their mapped drives or browse some of the DFS Tree.  (Note: I cannot take credit for this timing behavior investigation and results; and while I’d love to credit the folks who are due, I’m not permitted to.)  The customer remedied the situation with a temporary fix, but the real fix is the up-coming aforementioned patch.

Anyway, while the symptoms were being analyzed, I was working on other things and needed to work around the issue as much as possible while the solution was being chased.  So, I whipped up a simple little DOS script to go out and validate the top-levels of the DFS hierarchy across all domain controllers that carry them, in order to find out what would or wouldn’t be properly resolved.

For what it’s worth, I thought I’d pass the script along to you.  Here it is:

 

@SETLOCAL ENABLEDELAYEDEXPANSION
@set AdDomain=MyAdDomain.local
@set DirQuantity=17
@set DestPath=h:\DcList.txt
@REM This requires elevated credentials, otherwise will fail...
@ipconfig /flushdns
@REM First we build the input file...
@nslookup %AdDomain% |findstr [0-9].*.[0-9].*|findstr /V /C:"Address: " > %DestPath%
@ECHO As of 20121212, there should be %DirQuantity% DFS dirs on each server (actual, plus the "." and ".." items).
@REM Now loop through the input file and check the DFS at the destination...
@For /F "tokens=*" %%Q in (%DestPath%) Do @(
@set MYDC=%%Q
@set MYDC=!MYDC:Addresses:  =!
for /f "tokens=* delims=" %%A in ('dir /A:D \\!MYDC!\Corp ^|findstr /C:"Dir(s)"') do @set MYDIR=%%A
for /f "tokens=* delims= " %%G in ("!MYDIR!") do @set MYDIR=%%G
@REM Options A: Use this line if you wish to see all DFS sources:
@ECHO For: !MYDC!  	!MYDIR:~0,9!
@REM Option B: Use this line if you wish to see only those in violation 
@REM (note: there's a space and tab separator for spacing alignment):
@REM @ECHO For: !MYDC!  	!MYDIR:~0,9! |findstr /V /C:"%DirQuantity% Dir(s)"
)

What it does:

The script builds a domain controller list in a static, external file, then iterates through the list, attempting to quantify the available DFS path branches against a numeric count that you supply in another variable.  I provided two different “ends” to the script (one of them commented out), in order to give you a couple different ways to present the results.  Make sure to “set” the variables in the first few lines, to your locally-relevant information; especially the number of *expected* DFS hierarchies.

Of course, I wanted to write it to do more, but I pretty much ran up against the limits of what I *should* do in a DOS script.  I’ll make another version in PowerShell some day that iterates down the hierarchy and validates the entire structure, instead of just the top level… 

…Unless you beat me to it…  ;)

There you go; enjoy!

:)

 

 

Did you like this? Share it:

Tags: , , , , , , ,