Friday 15 June 2012

System File Checker

This is handy tool I found. Have you had a Windows system encounter problems due to corrupted system DLLs? A while back I encountered that on a Win7 system that would refuse to run Windows Updates with a "Program cannot start because sqmapi.dll is missing" error. It wouldn't run an offline SP1 install either due to the same problem.

The solution: System File Checker.

Steps:
  1. Open an elevated command prompt (Start -> type "cmd" -> Right-click the cmd shortcut and select "Run as Administrator"
  2. Provide admin credentials if UAC prompts you.
  3. Type: SFC /scannow and press enter. The program will take a few minutes to check each system dll for corruption and for wrong versions, and replace them as needed.
  4. When it's finished, type findstr /c:"[SR]" %windir%\Logs\CBS\CBS.log >%userprofile%\Desktop\sfcdetails.txt to put a log file onto your desktop, which you can review to see what was updated.
  5. Repeat steps 3-4 two more times (run SFC three times) to ensure that no files were missed. You may want to reboot after each run - though when I did it I didn't have to.
  6. Profit! (ie I was once again able to run Windows Update normally and get the Service Pack installed)
I've only used this on Windows 7 (Enterprise), but it's a feature that was introduced with Vista.

Microsoft support link:
http://support.microsoft.com/kb/929833

Wednesday 13 June 2012

VBScript to authenticate against Active Directory

Came across this function somewhere online a long time ago to validate provided user credentials against Active Directory in VBScript (mainly if you had to update a "Classic" ASP 3.0 application to use AD authentication vs some other non-IIS integrated method - like querying a database). More recently I noticed that this was hard to find thanks to the age of ASP, so here it is for posterity.

Thanks to whomever wrote it all those years ago!

Here it is, basically the function takes a username & password as parameters, and in the example has the domain hard-coded in the domainName variable, though you can easily change it to pass that as a parameter as well. It then uses ADO to connect to the Active Directory domain using the provided credentials to try to execute a simple query. If it succeeds, then the credentials are good. If it errors out, then the username/password combination is bad.

Note: I've only used this approach on computers that are joined to the AD domain in question.
Function validateUser(username, password)
    Dim adConn, adCom, adRS
    Dim domainName

    On Error Resume Next
  
    domainName = "mydomain.com"
    err.clear

    Set adConn = Server.CreateObject("ADODB.Connection")

    adConn.provider ="ADsDSOObject"
    adConn.properties("user id") = username
    adConn.properties("password") = password
    adConn.Properties("Encrypt Password") = true
    adConn.Open "DS Query"

    Set adCom = CreateObject("ADODB.Command")
    Set adCom.ActiveConnection = adConn

    adCom.CommandText = _
          "select cn from 'LDAP://" & domainName & "' WHERE objectCategory='user'"
    Set adRS = adCom.Execute

    If err.Number = 0 Then
        validateUser = True
    Else
        validateuser = False
    End If

    adRS.close
    adConn.close

    Set adRS=nothing
    Set adCom=nothing
    Set adConn=nothing

End Function


In use:


<%
Dim bLoggedIn, usr, pwd

bLoggedIn = False

usr = Trim(Request("user"))  'validate your input IRL (In Real Life)!
pwd = Trim(Request("pwd"))

If usr<>"" and pwd<>"" Then
    bLoggedIn = validateUser (usr, pwd)
End If
%>

<html>
<body>

<% If bLoggedIn = False Then %>
    <form method=post>
    <p>Username: <input type="text" name="user" value="" /><br/>
       Password: <input type="password" name="pwd" value="" /><br/>
       <input type="submit" value="Login" /></p>
    </form>
<% Else %>
    <h2>Logged in!</h2>
<% End If %>

</body>
</html>


Saturday 9 June 2012

First Post (second actually)

My actual first post was about a problem I encountered at work. This "First!: post is to introduce the blog.

The main point in setting this up is to document for myself, and anyone else who would find it helpful, various problems and solutions that I've come across in my work as an IT Guy™. In time I'll be posting various code snippets from scripts & queries etc. that I've used in my work.

My first post was just the problem & stepping back/recovering from it, and does not yet have an actual solution. Hopefully that won't be the dominant trend.

Friday 8 June 2012

Problem with expiring old user profiles on Windows 7



I was testing the "Delete user profiles older than a specified number of days on system restart" local policy - which deletes the profile from the computer if it hadn't been logged into for X days - on two Windows 7 Enterprise (32-bit) computers that are used a lot of different people logging in with their own domain accounts, so I wanted old profiles to get deleted & not cruft up the local system over time (these are local profiles not roaming profiles).

The problem I've run into now that the first profiles have started to expire is:

a) If the user comes back X+ days after their last login to use the computer again, they can't log on at all with a "The User Profile Service failed the logon. User profile cannot be loaded." error.

b) The user profile folder still exists - it's just empty. Not really a problem in itself - but could it be a symptom/cause of a)?

The problem profile SIDs are removed (no longer listed in the registry under Local_Machine\..\Windows NT\CurrentVersion\ProfileList nor do they appear in Advanced System Settings -> User Profiles.  (ie they appear to be properly deleted).

The policy has since been turned off so it won't affect any more people, but why is this preventing those old users from logging back in? I'd expect Windows to just rebuild the profile like it would for a brand new user, instead it errors out.

I know Vista has a hotfix for a problem relating to that policy, but that was for premature deletion, not this error. 7 doesn't appear to have any related updates.

Just had a bad thought: could that policy have deleted the Default profile? I wonder if whomever built that system image did something kooky when setting it up that would allow that.

---
Update: the error also happens for a user account that has never logged into the machine as well. That does sound like a Default profile problem.

---
Update 2: Damn. Advanced System Settings > User Profiles, for one computer, there is no entry for "Default profile". The other one has it, but zero bytes. Looks like I'm going to have to re-install the suckers when I'm back next week unless if anyone knows a quick way of re-establishing a new default profile for the system. I'll try a System Restore first, with luck it'll save it. Either way it'll have to wait.

How could that policy delete the default profile anyways? Can a machine be set so that the default profile is C:\Users\regularuser instead of the normal (hidden) Default user folder?

---
Update 3: Stayed on it & managed to get it fixed.

System Restore brought back the default profile (but that in turn broke the trust relationship with the domain... leaving & rejoining the domain under a new PC name fixed that). Domain users with no existing profile (either old & deleted, or never existed on that PC) are now able to log in normally.

Now these computers are working as they should, but the question remains of how this happened in the first place: why did the profile expiry policy delete the default profile? I may need to figure out some things with the original system image.