Tag Archives: PowerShell

Custom FSRM notification script

I’ve been working on a script to generate an informative message to users when they exceed quota thresholds on our file server. The features of the File Server Resource Manager (FSRM) provides a variety of useful variables that can be plugged into an automated email. However, we have found that it’s often very useful to provide more information about the kind of files that a user is storing, something akin to the output of the very useful and free utility WinDirStat.

I’ve made progress on the script that generates the email. However, I’ve run into a snarl in trying to configure the quota notification to run the script. The script runs just fine from a command prompt, even from a command prompt running as the Local System account. But when I trigger an FSRM event that should drive the script, I get an error in the Application Log:

 

Continue reading

Powershell Join-String function

Update: better yet, read about the -Join and -Split PowerShell operators. Live and learn.
—Geoff

Something I’ve found myself missing in PowerShell is a function to combing the elements of a list with a given separator, like Perl’s join() function. I finally got annoyed enought to write one. It seems to do what I want, so I’m going to add it to my profile.

Here it is in action:

PS C:\> $array = 3.14,'Puppy',$false,'','Green',$null,'foo'
PS C:\> $array | Join-String
3.14,Puppy,False,,Green,,foo
PS C:\> $array | Join-String -collapse
3.14,Puppy,Green,foo
PS C:\> $array | Join-String -collapse ' - '
3.14 - Puppy - Green - foo

Update: Now supports list items as parameter (non-pipeline) usage:

PS C:\> $y = Join-String $array -collapse
PS C:\> $y
3.14,Puppy,False,Green,foo
PS C:\> $y.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

Here’s the code:

# Join-String - A simple pipeline-oriented function to
# concatenate a bunch of strings together with a separator
# Geoffrey.Duke@uvm.edu  Wed 11/17/2010
#   updated 11 July 2013 to handle non-pipeline usage

function Join-String
(   
    [string[]] $list,
    [string] $separator = ',',
    [switch] $Collapse
)
{ 

[string] $string = ''
$first  =  $true

# if called with a list parameter, rather than in a pipeline...
if ( $list.count -ne 0 ) {
    $input = $list
}

foreach ( $element in $input  ) {
    #Skip blank elements if -Collapse is specified
    if ( $Collapse -and [string]::IsNullOrEmpty( $element)  ) {
        continue
    }

    if ($first) {
        $string = $element
        $first  = $false
    }
    else {
        $string += $separator + $element 
    }
}
 
    write-output $string
}

If you have a notion for how it could be improved, please comment.

Event data mining with PowerShell

On Server 2008 and 2008 R2, if your Domain Controllers aren’t configured to require LDAP signing and disallow simple LDAP binds in plaintext, Active Directory Domain Services logs a warning event on startup, and summary events every 24 hours.

A couple weeks ago, I followed the recommendation to enable logging of unsigned and plaintext LDAP authentication requests. Setting the LDAP Interface Events value to 2 generates a Directory Services event 2889 for each connection.

Now I want to do some analysis of the collected events. The event structure puts the important details, namely the client name and IP address, in the big description text field. It looks like this:

Log Name: Directory Service
Source: Microsoft-Windows-ActiveDirectory_DomainService
Date: 11/3/2010 11:46:38 AM
Event ID: 2889
Task Category: LDAP Interface
Level: Information
Keywords: Classic
User: ANONYMOUS LOGON
Computer: CDC01.campus.ad.uvm.edu
Description:
The following client performed a SASL (Negotiate/Kerberos/NTLM/Digest) LDAP bind without requesting signing (integrity verification), or performed a simple bind over a cleartext (non-SSL/TLS-encrypted) LDAP connection.

Client IP address:
132.198.124.202:53298
Identity the client attempted to authenticate as:
CAMPUS\myhost0256BB4$

Previously, I’ve exported the logs to CSV format, then used Excel and some text-mangling functions to pull out the important details. But I noted that the two important values were nicely separated in the XML representation of the event:

Event Xml: 
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"> 
  <System> 
    <Provider Name="Microsoft-Windows-ActiveDirectory_DomainService" Guid="{0e8478c5-3605-4e8c-8497-1e730c959516}" EventSourceName="NTDS LDAP" /> 
    <EventID Qualifiers="16384">2889</EventID>
    <Version>0</Version> 
    <Level>4</Level> 
    <Task>16</Task> 
    <Opcode>0</Opcode> 
    <Keywords>0x8080000000000000</Keywords> 
    <TimeCreated SystemTime="2010-11-03T15:46:38.219250600Z" /> 
    <EventRecordID>122013</EventRecordID> 
    <Correlation /> 
    <Execution ProcessID="512" ThreadID="3396" /> 
    <Channel>Directory Service</Channel> 
    <Computer>CDC01.campus.ad.uvm.edu</Computer> 
    <Security UserID="S-1-5-7" /> 
  </System> 
  <EventData> 
    <Data>132.198.124.202:53298</Data> 
    <Data>CAMPUS\myhost0256BB4$</Data> 
  </EventData> 
</Event>

Continue reading

PowerShell – find a free IP

Since we don’t use DHCP in our server subnets, I frequently have to locate free IP addresses when deploying a server. I remembered reading a TechNet Magazine article by Don Jones that used the PowerShell PROCESS block and the Win32_PingStatus WMI class in a sample script.

I took that and rewrote the function a little:

function Ping-Address {
  PROCESS {
    $ping = 'unreachable'
    $formatstring = "{0,-15}  {1,-12} {2}"
    $queryString  = "SELECT * FROM Win32_PingStatus"
    $queryString += " WHERE Address = '$_' AND"
    $queryString += " ResolveAddressNames = $true"
    $results = Get-WmiObject -query $queryString
    
    foreach ($result in $results) {
      if ($results.StatusCode -eq 0) {
        $ping = 'ping!'
      }
    }
    $formatstring -f $_,$ping,$results.ProtocolAddressResolved
   }
}

I can then use this function like so:

PS Z:\> (14..20) | %{ '132.198.59.'+ $_.ToString()} | Ping-Address
132.198.59.14    ping!        132.198.59.14
132.198.59.15    ping!        132.198.59.15
132.198.59.16    ping!        xxxxxxx.campus.ad.uvm.edu
132.198.59.17    ping!        xxxxxxx.uvm.edu
132.198.59.18    unreachable
132.198.59.19    ping!        xxxx.uvm.edu
132.198.59.20    unreachable

I’ve already used it a bunch of times. I think I will probably grow this into a real script, taking the IP address range info as parameters. Another day.

Monday – 2009-09-28

Today’s issues:

  • Backup issues
  • Shared folder quotas
  • Printer configurations
  • Data execution protection

I created a Server 2008 x64 guest for managing 64-bit drivers on our shared printers. It works much better than trying to use Printer Management MMC in RSAT on Windows 7.

One hiccup I ran into while install the Ricoh PCL6 Driver for Universal Print was that it was missing a file. Fortunately, I had also download and extracted the non-universal PCL6 drivers and the file was present in the drivers for the corresponding platforms (x86, x64).

Looking at adding a –WhatIf switch parameter to my SharePoint Backup powershell script. Useful info at Negating PowerShell switch parameters.

Now wrestling with Task Scheduler and PowerShell invocation syntax.

Friday – The 13th of March

Thirteen is a lucky number!

Found the UVM Webteam’s official style guide. Nice level of detail.

Installed WinSCP to help a user, then a Windows 7 update. My system rebooted and was unresponsive. After trying several different things, I ended up booting into safe mode and removing WinSCP. Whatever!

Get together with Greg to review his home migration script-fu.

Completed initial provisioning of new homedir q-trees, including quotas and cifs homedir configs.

Looks like I can run 32-bit Perl on 64-bit Windows. It appears that the various packages I used from the theory.uwinnipeg.ca ppm repository are there for Perl 5.10, so I’ll go ahead and use that.

A couple small administrivia requests peppered throughout the day.

Worklog – Wednesday, Feb 25

Service restarts on some hosts.

Looked into automating some periodic restarts. One app vendor suggests using SQL Agent. I don’t really like the idea of using SQL Agent for non-database tasks. Found an interesting exercise in CMD batch file writing in a Microsoft script to restart IIS services. Powershell is another possibility.

Problems with SharePoint search service.

Greg worked on the problem, but emailed me on his day off that the problem continues. Given that the message indicates “access denied,” it seems worthwhile to verify that the gatherer is running with sufficient credentials. But starting with a google search, I found:

http://social.technet.microsoft.com/Forums/en-US/sharepointgeneral/thread/e7e20e0b-0315-4c14-8974-993f445e6a3b/

I checked SharePoint Central Administration, App Management, and “Manage Search Service,” but I receive an error indicating that the search service isn’t running. I have verified that the “Windows SharePoint Services Search” service is running, and checked the account under which it is running.

Checking logs at C:Program FilesCommon FilesMicrosoft Sharedweb server extensions12LOGS. Looking at the log file corresponding to the warning event time, SHAREPOINT1-20090225-1002.log. Looks like a search process kicked off at 10:16:38.

There are some errors indicating “No administration site found for SSP SharedServices.” But later, the gather is committing changes to the admin site. Nothing leaps out at me, here. Except a ton of errors like this:

02/25/2009 11:32:55.43     w3wp.exe (0x0E58)                           0x0AF4    Windows SharePoint Services       General                           8e1f    High        Failed to find the XML file at location ’12TemplateFeaturesBatchSiteManagerLinksfeature.xml’

I also see a message about the Search Service being disabled. It now makes sense to me that the normal windows indexing service is disabled, and thus the “Manage Search Service” option is disabled. I found the Microsoft Search Server program group, but when I launch the Administrator app, I see an icon appear briefly on the task bar, and then it vanishes. Checking the command-line, I see it runs a STSADM.EXE command. Perhaps I can run that command from a command prompt.

Z:>”C:Program FilesCommon FilesMicrosoft Sharedweb server extensions12BINSTSADM.EXE” -o osearch -action showdefaultsspadmin

‘showdefaultsspadmin’ action failed. Additional information: The site with the id [GUI] could not be found.

So maybe there really is a problem with the administration site. I tried stopping and restarting the Windows SharePoint Services Search service, but that didn’t appear to change anything.

However, it is clear that I don’t know much about Microsoft Search Service and the way it has been deployed.

Getting started with Search Server 2008

http://www.microsoft.com/enterprisesearch/serverproducts/searchserver/features.aspx

 

File locked issue

Examining a reported locked file, I see that it is held open by sa_ss_srchserv. Related to our search problem above?

Problem with Canon Printer Job codes

Printer is installed correctly, and “Get Device Status” successfully returns information, including Job Code setting. Created footprint 43362 from email thread.

Back to restarting services

A one-line powershell script:

restart-servce PncPrintSpooler*

Run as a scheduled task in the early morning. Found some good pointers on starting a powershell script.