Today I learnt about FIPS and SHA1

Sha-familySystem.InvalidOperationException: This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms. at System.Security.Cryptography.SHA1Managed..ctor() at ....

When I say “learnt”, it was more about reading documents to determine what happened to cause the above error.

I suspect either of these:

  1. Microsoft have released a new schannel.dll which removes and/or breaks SHA1 functionally.
  2. The Group Policy setting “System cryptography: Use FIPS compliant algorithms for encryption, hashing, and signing” has been enabled.

My quick “fix” was to change the application to use a different hashing algorithm.

References:

How to delay in a batch file

by using the CHOICE command.  Which is a hack, but it works.

To delay for 5 seconds:
choice /T 5 /D Y

An explanation follows:
/T is the number of seconds before the default choice is made.  In this case, 5 seconds.
/D the default choice.  In this case, Y

The default list of choices for the CHOICE command is YN.

Saturday Link Roundup

Programming Suckscodewithoutlimitsshameitsnoteventswithoutlimits_thumb.jpg
”There will always be darkness
I spent a few years growing up with a closet in my bedroom. The closet had an odd design. It looked normal at first, then you walked in to do closet things, and discovered that the wall on your right gave way to an alcove, making for a handy little shelf. Then you looked up, and the wall at the back of the alcove gave way again, into a crawlspace of utter nothingness, where no light could fall and which you immediately identified as the daytime retreat for every ravenous monster you kept at bay with flashlights and stuffed animals each night.
This is what it is to learn programming. You get to know your useful tools, then you look around, and there are some handy new tools nearby and those tools show you the bottomless horror that was always right next to your bed.”

Internet Explorer (IE) version detection in JavaScript
Minification-safe JavaScript detection of version of Internet Explorer (IE) browser up to version 10 inclusive.

Falsehoods programmers believe about time
”I have repeatedly been confounded to discover just how many mistakes in both test and application code stem from misunderstandings or misconceptions about time. By this I mean both the interesting way in which computers handle time, and the fundamental gotchas inherent in how we humans have constructed our calendar – daylight savings being just the tip of the iceberg.”

Getting a list of printers published in an Active Directory domain

c2800c5000printers-thumb.jpg
So I need to get a list of print servers and printers in the domain.

Using Powershell.

Looking around the interwebs, I found a PowerShell commandline here which formed the basis of this commandline:
Get-ADObject -LDAPFilter "(objectCategory=printQueue)" -Properties cn, drivername, location, printername, portname, servername | select portname, cn, drivername, location, printername, servername | Format-Table -Property * -AutoSize | Out-String -Width 4096 | Out-File C:\wisefaq\printerlist.txt

Which outputs to a text file, like this:
portname cn drivername location printername servername
-------- -- ---------- -------- ----------- ----------
{101.112.138.188} PRT001-APPLELWR001 APPLE LASERWRITER II US/UT/Boort/10 Anytown St APPLELWR001 PRT001.noddyland.com
{112.142.229.22} PRT001-LZR960-2 Dataproducts LZR 960 PS US/UT/Boort/99 Anytown St LZR960-2 PRT001.noddyland.com
{101.192.107.56} PRT001-LZR960-1 Dataproducts LZR 960 PS US/UT/Boort/99 Anytown St LZR960-1 PRT001.noddyland.com
{101.192.107.56} PRT001-LZR960-3 Dataproducts LZR 960 PCL US/UT/Boort/99 Anytown St LZR960-3 PRT001.noddyland.com
{101.46.14.220} PRT001-LZR960-4 Dataproducts LZR 960 PS US/UT/Boort/99 Anytown St LZR960-4 PRT001.noddyland.com
{101.46.14.220} PRT001-LZR960-5 Dataproducts LZR 960 PCL US/UT/Boort/99 Anytown St LZR960-5 PRT001.noddyland.com

So why did I use Out-File instead of Export-CSV?
Export-CSV is refusing to output the {ip.addresses}. I don’t know why, and I’ve wasted an hour trying to work around the issue.

Update: December 2015
Adrian suggests that I could use Powershell Custom Objects to fix the issue of ip.addresses not outputting.

References:
PowerShell Quick Tip: Creating wide tables with PowerShell

Searching for Specific Printers in a Domain (Attributes for the printQueue Object)

Print-Queue class

PowerShell print server inventory script (looks very useful, but you need admin access to each of the printers)

Using VBScript to read though a set of registry keys

I’m currently doing another deployment of Acrobat Reader, this time with VBScript.  I wrote about using Visual Basic to do that here.

Function CheckForPro
    ' returns TRUE if Acrobat Pro found OR we're not able to read registry key

    Dim strHost,sAddRemTmp,iRegRC,objFCReg,strAddRemValue,arrSubKeys,strSubKey
    Const strBaseKey = "Software\Microsoft\Windows\CurrentVersion\Uninstall\"   
    Const HKEY_LOCAL_MACHINE = &H80000002   

    strHost = "."
    sAddRemTmp = ""
    iRegRC = 0
    CheckForPro = False
    Set objFCReg = GetObject("winmgmts://" & strHost & "/root/default:StdRegProv")

    iRegRC = objFCReg.EnumKey (HKEY_LOCAL_MACHINE, strBaseKey, arrSubKeys)
    If iRegRC <> 0 Then
        CheckForPro = True
        Exit Function
    End If
    For Each strSubKey In arrSubKeys
           intAddRemRet = objFCReg.GetStringValue(HKEY_LOCAL_MACHINE, strBaseKey & strSubKey, "DisplayName", strAddRemValue)
           If intAddRemRet = 0 Then
            If InStr(lcase(strAddRemValue),"acrobat") <> 0 Then
                If InStr(lcase(strAddRemValue),"pro") <> 0 Then
                    CheckForPro = True
                    Exit Function
                End If
            End If
           End If
       Next

    CheckForPro = False

End Function

Update 11 DEC 2013:
A clever co-worker also points out that if you have a “acrobat.exe” somewhere in Acrobat Program Files directory, then this means you have a Acrobat Pro installation.

VS2010 & .Net 2 Framework Selection

.Net 2 is not the default framework option …  No, you get .Net 4.  To change it, you select Project / <your project name> Properties / Compile / Advanced Compile Options, and select the Target Framework you want.
WinXP SP3 WS2010-2012-03-07-12-50-14

I prefer to use the .Net 2 Framework as it’s the lowest common denominator on the systems I write code for.  And yes, I documented this, as I can’t remember where the option is, and Google Search wasn’t my friend at the time.

Using Visual Basic to read though a set of registry keys.

The problem we have with a corporate deployment of Acrobat Reader, was that we need to uninstall various older versions of Acrobat Reader.  Normally to do this, you need to know the uninstall command string, which changes with each Acrobat Reader release.  One of our senior application packagers said

Why don’t just loop though SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, detect Acrobat Reader in the DisplayName key, then grab the UninstallString.

By jove, what a clever idea.

Doing that in Visual Basic .Net proved me with an afternoon’s programming exercise.  Here is the simplified result:

Dim SoftwareRegistry = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, ".")
Dim SoftwareUninstall = SoftwareRegistry.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", False)
Dim sDisplayName As String = vbEmpty
Dim sReaderUninstallString As String = vbEmpty
Dim sMSIUninstallGUID As String = vbEmpty


For Each item In SoftwareUninstall.GetSubKeyNames
'MessageBox.Show(item)

    Dim SoftwareUninstallItemKey = SoftwareRegistry.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" + "\" + item, False)

    sDisplayName = SoftwareUninstallItemKey.GetValue("DisplayName")

    If InStr(LCase(sDisplayName), "adobe reader", CompareMethod.Text) Then
sReaderUninstallString = SoftwareUninstallItemKey.GetValue("UninstallString")
If sReaderUninstallString <> "" Then
MessageBox.Show(sMSIUninstallGUID)
End If
End If

    SoftwareUninstallItemKey.Close()
Next

SoftwareUninstall.Close()
SoftwareRegistry.Close()

Code to launch an Internet Explorer window from VBscript.

set IE = WScript.CreateObject("InternetExplorer.Application")

dim ObjTitle

IE.Navigate(“about:blank”)
IE.Document.Title = “Software Update”
IE.FullScreen = 1
IE.Left       = 0
IE.Top        = 0
IE.MenuBar    = 0
IE.Toolbar    = 0
IE.StatusBar  = 0
IE.Width      = 540
IE.Height     = 151
IE.Visible    = 1

Set ObjBody  = IE.Document.Body
strHTML = “<b><h2>Software Update In Progress</H2><br>” &_
“Please do not use your computer during this time.  Thank you</B>”
objBody.InnerHTML = strHTML

My Corporate DNS Server was lying to me, often.

I was trying to copy some files to a group tonormaldnsoperation a computers.  What I’d do is check if the computer is alive first, by doing a network ping.  If the computer answered the Ping, then the computer was alive, so I would then copy files to it.

It mostly worked, except when it didn’t.  Here is the clue which lead me to the answer:

C:\>ping alfred

Pinging ALFRED [192.168.1.5] with 32 bytes of data:
Reply from 192.168.1.5: bytes=32 time<1ms TTL=128

C:\>ping powergirl

Pinging POWERGIRL [192.168.1.5] with 32 bytes of data:
Reply from 192.168.1.5: bytes=32 time<1ms TTL=128

C:\>

The DNS server was returning the same IP address for two different computers.  As POWERGIRL was powered on, it answered the Ping request for ALFRED.  When I tried to copy to ALFRED, it failed as the file copy was trying to verify that ALFRED was at 192.168.1.5, and it wasn’t.

The cause?  The DNS server was retaining IP addresses for 24 hours.  Sometimes a computer’s IP will change more often than that.  So the DNS server ended up with 2 or more DNS computer records with the same IP.
The fix?  Tell the DNS server to only retain DNS records for 2 hours.  (for the more technically minded, we adjusted the Time To Live value).

How I originally detected the DNS server was lying to me?
I pinged the computer (ALFRED) to get it’s IP address (192.168.1.5).
I then asked IP address 192.168.1.5 what it’s computer name was.  In the example above, it was actually POWERGIRL.

The code to do that is in the Reachable function, below:

Continue reading