Friday, November 1, 2013

Powershell script to check domain password policy and user password status.

One of our domain users tried to change his password and he got the error message:
"Unable to update the password. The value provided for the new password does not meet the length, complexity, or history requirements of the domain."

I tried to find the reason. Many people mentioned that the problem might be the setting of "Min password age", then I found this Power Shell scipt which can give me the setting of password policy and the last time user changed his password.

This is the original link:
http://www.blackops.ca/cms/blog/?p=295

This is the scipt code:
===========================

cls
$searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]'')
While (!$result){
  $UserName = Read-Host 'Username to check : '
  if (!$UserName){
    Write-Host "No Username Entered"exit
  }
  $searcher.Filter = "(&(objectClass=User)(samAccountName=" + $username + "))"
  $result = $searcher.Findone()
}
# get domain password policy (max pw age)
$D = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$Domain = [ADSI]"LDAP://$D"
$MPA = $Domain.maxPwdAge.Value
$MinPA = $Domain.minPwdAge.Value
# Convert to Int64 ticks (100-nanosecond intervals).
$lngMaxPwdAge = $Domain.ConvertLargeIntegerToInt64($MPA)
$lngMinPwdAge = $Domain.ConvertLargeIntegerToInt64($MinPA)
$MinPwdLength = $Domain.minPwdLength
$PwdHistory = $Domain.pwdHistoryLength
# Convert to days.
$MaxPwdAge = -$lngMaxPwdAge/(600000000 * 1440)
$MinPwdAge = -$lngMinPwdAge/(600000000 * 1440)
$lngPwdLastSet =$result.Properties.pwdlastset
$pwdLastSet = [datetime]::FromFileTime($lngPwdLastSet[0])
Write-Host $result.Path
Write-Host $result.Properties.cn " " $result.Properties.userprincipalname
Write-Host "Password Last Set : " $pwdLastSet
Write-Host "Max Password Age : " $MaxPwdAge
Write-Host "Min Password Age : " $MinPwdAge
Write-Host "Password History : " $PwdHistory
Write-Host "Min Password Length : " $MinPwdLength
if ($pwdLastSet -ge (Get-Date).AddDays(-$MinPwdAge)){
  Write-Host -ForegroundColor Red "Password can not be changed - Min Age"
}
if ($pwdLastSet -ge (Get-Date).AddDays($MaxPwdAge)){
  Write-Host -ForegroundColor Red "Password Expired"
}

========== end of scipt =====================

Thursday, July 25, 2013

Active Directory Service Interfaces

Active Directory Service Interfaces (ADSI) is a set of COM interfaces used to access the features of directory services from different network providers. ADSI is used in a distributed computing environment to present a single set of directory service interfaces for managing network resources. Administrators and developers can use ADSI services to enumerate and manage the resources in a directory service, no matter which network environment contains the resource.

ADSI enables common administrative tasks, such as adding new users, managing printers, and locating resources in a distributed computing environment.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa772170(v=vs.85).aspx

Active Directory Service Interfaces Reference
http://msdn.microsoft.com/en-us/library/windows/desktop/aa772218(v=vs.85).aspx

=============================================================

We can use System Providers in ADSI to create object and remotely manage Active Directory.  ADSI includes the service providers listed in this page:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa772235(v=vs.85).aspx


Example:

For ADSI WinNT Provider

We can use Set objUser = GetObject("WinNT://"& strDomain &"/" & strUser) to create an IADsUser object and access the IADsUser object properties.

This page has all the objects of WINNT provider
http://msdn.microsoft.com/en-us/library/windows/desktop/aa772211(v=vs.85).aspx

IADsUser is one of the WINNT objects. This page has the interface of IADsUser, including methods and properties.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa746340(v=vs.85).aspx

This method can set user password: objUser.SetPassword strPassword

Tuesday, July 23, 2013

Remotely access Exchange 2010 with PowerShell Script

Remotely check Exchange 2010 mailbox size

'Run these two commands in PowerShell first to remotely connect to exchange server from local PowerShell

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://(server name)/PowerShell/ -Authentication Kerberos

Import-PSSession $Session


'Do query

'Get one user mailbox size, can also get subfolder size by changing -folder value
Get-MailboxStatistics -Identity UserName | select -Property TotalItemSize


'This can also give the mailbox size
Get-MailboxFolderStatistics -Identity UserName -folderscope all | select -Property FolderAndSubfolderSize -first 1


'Get mailboxe size for all mailboxes
Get-MailboxStatistics -server myExchangeServerName | select Displayname,TotalItemSize | Sort-Object Displayname


'Export result to Excel file
Get-MailboxStatistics -server myExchangeServerName | select Displayname,TotalItemSize | Sort-Object Displayname | Export-CSV c:\temp\inboxsizes.csv


'View all quotas assigned to a mailbox
Get-Mailbox UserName | Format-List *Quota


'export result to Excel file
Get-MailboxStatistics -server mfl67207 | select Displayname,TotalItemSize | Sort-Object Displayname | Export-CSV c:\temp\inboxsizes.csv



'View all quotas assigned to a mailbox
Get-Mailbox <Identity> | Format-List *Quota



'Exporting Message Tracking Logs to .CSV
Get-MessageTrackingLog -Server <Server name> -Start "01/01/13 00:00:00" -End "12/12/13 23:59:59" -Recipient "TheMole@BadGuyCompany.com" -Resultsize unlimited| select sender, recipient, timestamp, messagesubject, totalbytes | export-csv c:\temp\messlog.csv


'Check inbox rule
Get-InboxRule –Mailbox <username> | fl > \temp\outlookClientRules.txt


'Disable a users Outlook Rules
Disable-Inboxrule –Mailbox <Bob Smith> -Identity “<TheOutlookRule>”




'To delete a specific users Outlook Rules
Remove-Inboxrule –Mailbox <Bob Smith> -Identity “<TheOutlookRule>”


'This is a link for Powershell command Get-mailboxstatistics
http://technet.microsoft.com/en-us/library/bb124612(v=exchg.150).aspx


'I found the above command from this page:
http://help.outlook.com/en-us/140/Gg576861.aspx


'This is Microsoft page about Powershell cmdlet
https://technet.microsoft.com/en-us/library/bb123981(v=exchg.160).aspx

Thursday, June 20, 2013

VBScript to manage user accounts

VBscript can use WMI object to access properties of Domain and users.

===============================================
Unlock User Account
-------------------------------------------------------------------------------
This is a sample code to unlock user account when user put wrong password too many times and his account has been locked.

Code 1:

Dim oUser
Set oUser = GetObject("WinNT://DomainName/UserName")
WScript.Echo "user name:" & oUser.Name&vbcr&"Is account locked:" & oUser.IsAccountLocked
oUser.IsAccountLocked = 0
WScript.Echo "user name:" & oUser.Name&vbcr&"Is account locked:" & oUser.IsAccountLocked

A better pice of code can be found here:
http://community.spiceworks.com/scripts/show/54-unlock-user-account

Code 2:

Dim oUser
LDAPpath = ' to find LDAP distinguished name (DN) in AD
Set objUser = GetObject("LDAP://" & LDAPpath)

objUser.IsAccountLocked = False
oUser.SetInfo

===================================================
Reset User Account Password
-------------------------------------------------------------------------------
This is a sample code to reset user account password.

Dim oUser
LDAPpath = ' to find LDAP distinguished name (DN) in AD
Set objUser = GetObject("LDAP://" & LDAPpath)

strPassword = InputBox("Please put a new password.","Reset User password")
oUser.SetPassword strPassword
oUser.SetInfo

===================================================
Force User to Change Account Password at The First Login
-------------------------------------------------------------------------------
This is a sample code to reset user account password.

Dim oUser
LDAPpath = ' to find LDAP distinguished name (DN) in AD
Set objUser = GetObject("LDAP://" & LDAPpath)

objUser.PwdLastSet = 0
oUser.SetInfo
===================================================

Find LDAP distinguished name (DN) in AD
-------------------------------------------------------------------------------

I found this script code on Microsoft website.

http://gallery.technet.microsoft.com/scriptcenter/dee78632-f6d0-4be3-920f-27165fa60767

'**************************************************************
'=  Created By: Devin H.
'=  Function Name: distinguish           Date: 10/19/2005           Version:1.1
'=  
'=  Variables: strObject, strType  
'= 
'=  This function will return the distinguished name of an object stored in 
'=  Active Directory.  This is useful when you don't know exactly where an 
'=  object is located or want to move something.
'=  
'=  Usage: Wscript.Echo distinguish("DevinH","user") 
'=  Returns: cn=DevinH,ou=MyUsers,dc=ScriptCentric,dc=com       
'=
'**************************************************************
Function distinguish(strObject, strType)
    Select case strType
        Case lcase("computer")
            strobject = strObject & "$"
        Case lcase("user")
            'Good
        Case lcase("group")
            'Good
        Case else
            Wscript.Echo "Their is an error in the script"
    End Select
    ' Determine DNS domain name (this could be hard coded).
    Set objRootDSE = getObject("LDAP://RootDSE")
    strDNSDomain = objRootDSE.get("defaultNamingContext")
    
    Const ADS_SCOPE_SUBTREE = 2
    
    Set objConnection = createObject("ADODB.Connection")
    Set objCommand = createObject("ADODB.Command")
    objConnection.Provider = "ADsDSOObject"
    objConnection.Open "Active Directory Provider"
    
    Set objCOmmand.ActiveConnection = objConnection
    objCommand.CommandText = _
    "Select distinguishedname, Name, Location from 'LDAP://" & strDNSDomain & _
    "' Where objectClass='" & strType & "' and samaccountname='" & strobject & "'"
    objCommand.Properties("Page Size") = 1000
    objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 
    Set objRecordSet = objCommand.execute
    objRecordSet.MoveFirst
    
    Do Until objRecordSet.EOF
       distinguish = objRecordSet.Fields("distinguishedname")
       objRecordSet.MoveNext
    Loop
End Function

===================================================

This is my code with all these together

'*********** code begin*****************

On Error Resume Next
strUser = InputBox("Please enter a user name.","user_password")
If strUser = vbNullString then
   MsgBox "Either Cancel was selected or you did not enter a user name.", 16, "User Unlock"
   WScript.Quit
End If
strDomain = "myDOMAIN"
dim LDAPpath
Const STRING_OBJ_TYPE = "user"
LDAPpath = distinguish(strUser,STRING_OBJ_TYPE)
Set objUser = GetObject("LDAP://" & LDAPpath)
If Err.Number <> 0 Then
   MsgBox (strUser) & " isn't a valid user name!", 48,"Reset User password"
   Wscript.Quit
End If
Err.Clear
On Error Resume Next
   style = vbYesNo + vbDefaultButton2
    
   'set new password  
   WantNewPwd = MsgBox("Do you want to reset user's password?", style,"user_password")
   If WantNewPwd = vbYes Then
       strPassword = InputBox("Please put a new password.","Reset User password")
       objUser.SetPassword strPassword
   End If
  
   'force user to change the password at the first time login
   forceNewPsd = MsgBox("Do you want user to change password at first login?", style,"user_password")
   If forceNewPsd = vbYes Then
       objUser.PwdLastSet = 0
   End If
   UnlockAccount = MsgBox("Do you want to unlock user account?", style,"user_password")
   If UnlockAccount = vbYes Then
       objUser.IsAccountLocked = False
   End If 
  
   objUser.SetInfo
If Err.Number <> 0 Then
   MsgBox("An error has occurred. " & Err.Number)
   Err.Clear
Else
   MsgBox "The Password/Account Has Been Changed For " & UCase(strDomain) & "\" & UCase(strUser)
End If
Wscript.Quit

'=====================================================
'=  Created By: Devin H.
'=  Function Name: distinguish           Date: 10/19/2005           Version:1.1
'=  
'=  Variables: strObject, strType  
'= 
'=  This function will return the distinguished name of an object stored in 
'=  Active Directory.  This is useful when you don't know exactly where an 
'=  object is located or want to move something.
'=  
'=  Usage: Wscript.Echo distinguish("DevinH","user") 
'=  Returns: cn=DevinH,ou=MyUsers,dc=ScriptCentric,dc=com       
'======================================================

Function distinguish(strObject, strType)
    Select case strType
        Case lcase("computer")
            strobject = strObject & "$"
        Case lcase("user")
            'Good
        Case lcase("group")
            'Good
        Case else
            Wscript.Echo "Their is an error in the script"
    End Select
    ' Determine DNS domain name (this could be hard coded).
    Set objRootDSE = getObject("LDAP://RootDSE")
    strDNSDomain = objRootDSE.get("defaultNamingContext")
    
    Const ADS_SCOPE_SUBTREE = 2
    
    Set objConnection = createObject("ADODB.Connection")
    Set objCommand = createObject("ADODB.Command")
    objConnection.Provider = "ADsDSOObject"
    objConnection.Open "Active Directory Provider"
    
    Set objCOmmand.ActiveConnection = objConnection
    objCommand.CommandText = _
    "Select distinguishedname, Name, Location from 'LDAP://" & strDNSDomain & _
    "' Where objectClass='" & strType & "' and samaccountname='" & strobject & "'"
    objCommand.Properties("Page Size") = 1000
    objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 
    Set objRecordSet = objCommand.execute
    objRecordSet.MoveFirst
    
    Do Until objRecordSet.EOF
       distinguish = objRecordSet.Fields("distinguishedname")
       objRecordSet.MoveNext
    Loop
End Function

'***************end of code*************

Thursday, June 13, 2013

copy, move, and create files &/or folders with VBScript

We can use the methods in Object FileSystemObject or Shell to copy, move, and create files &/or folders.

The information about Object FileSystemObject is in this page:
http://msdn.microsoft.com/en-us/library/hww8txat(v=vs.84).aspx

The information about Object Shell is in this page:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb774094(v=vs.85).aspx


Example:

To copy files from one folder to another folder:

Using FileSystemObject:
===============
    dim sourcePath
    dim destPath
    dim filesys

    sourcePath="c:\temp\*.*"
    destPath="d:\temp2\"
    set filesys=CreateObject("Scripting.FileSystemObject")
    filesys.CopyFile sourcePath, destPath, True
    set filesys=nothing
================
This code copys all the files from c:\temp to c:\temp2. The script runs at the backgroud


Using Shell:
=============== 
    dim sourcePath
    dim destPath
    sourcePath="c:\temp\*.*"
    destPath="d:\temp2\"

    dim objShell
    dim objFolder   
    dim cFlag
    set objShell = CreateObject("shell.application")
    set objFolder = objShell.NameSpace(destPath)
    cFlage = 48   'only copy the files
    objFolder.CopyHere sourcePath,cFlag
    set objShell = nothing
    set objFolder = nothing
    WScript.Sleep 100
==========================
The function displays a progress dialog box.
Note: for some reason, the option in the method CopyHere does not work on my computer.

Thursday, March 14, 2013

Force reboot of a remote server that has hung shutting down

I had a problem to reboot a remote server. I googled it and found this article. The PSKILL command solved the issue.
********************************************

I had an issue last night when a remote server that I was applying windows updates to, hung while it was shutting down. I will still able to ping the server, and access its file shares, but was unable to get RDP access. I was cursing at this point, with the prospect of a long journey the following day to investigate and bring the server back online. I then considered what other steps I could take to try and force the server to reboot remotely.

 I used the PSTools command psexec to see if I could still get command line access to the remote server, and fortunately I could. Next I tried to force a reboot of the remote server using psexec and the shutdown command as follows, where REMOTE_SERVER_NAME is the name of the remote server that I was trying to reboot:

psexec \\REMOTE_SERVER_NAME shutdown /r /t 01

alternatively you could use:
shutdown /m \\REMOTE_SERVERNAME /r /t 01

This returned the following error:
1115 A system shutdown is in progress

This basically meant that a system shutdown was already in progress, and therefore the command was unable to force a reboot. In the end I used the pskill command to stop the winlogon service on the remote server to try and release whichever process wass causing the server to hang on shutdown. I should stress that this was a last resort, and not something that I would recommend doing unless essential:

pskill \\REMOTE_SERVER_NAME winlogon

Anyway, after another few minutes the remote server did finally restart, although there are a few other things that I should mention that happened in the process. The operating system on this machine was Windows Server 2008 R2. After the server came back up (verified by ping -t REMOTE_SERVER_NAME) I tried to RDP the box again. I was able to enter my credentials and the logon process appeared to start, but after a few seconds the following message appeared on the screen:
Please wait for the Windows Modules Installer
The machine sat like that for quite some time, and then started ‘Configuring Updates’. My RDP session then abruptly ended and the server restarted itself again. Again, when it was back up I tried to RDP the server again and received the ‘Please wait for the windows modules installer message’ for a second time. Thankfully, after a few minutes and another ‘configuring updates’ message, logon continued and ther server was back up and running. On checking the event log and windows update log I was able to verify that all the updates had installed OK, and there were no other errors worthy of note. So in summary, if you want to save yourself a long trip, to most likely press a power or reset switch, you may want to try the above first.

http://oasysadmin.com/2012/03/02/force-reboot-of-a-remote-server-that-has-hung-shutting-down/  

Tuesday, March 12, 2013

Chat with Bother support for adding Brother MFC7860DW as network scanner

Connecting to server...
Found available agent: Hugo  .  You can chat now.
Hugo  : Good morning!
Hugo  : How may I help you?
Jimmy: hi
Jimmy: good morning
Jimmy: I have two MFC7860DW in our office
Jimmy: When I installed CC4, it can only find one machine, not the second one
Jimmy: I can use IE to access both printers
Jimmy: I can also add both printers
Jimmy: but my computer can only find one scanner, ont the other
Hugo  : Mmm have you tried installing over it?
Jimmy: I went to my-computer->network, I can see both machines, but when I tried to install the one has problem, only printer was installed
Jimmy: What do you mean " installing over it"
Hugo  : Yes when you install it will only install one driver for the printer, and one for the scanner
Hugo  : you could add another printer driver manually but not another scanner
Hugo  : you need to isntall the disc again
Hugo  : but when you get to the connection type both machines should show up, select the one that is not already installed
Jimmy: I wil call the good machine: brother A, and the bad machine Brother B.
Jimmy: I tried to run the Windows wizard for adding scanner, but the wizard can only find Brother A
Hugo  : did you connect Brother B to the network? can you print to brother B?
Jimmy: Yes, I can use IE to remote control both A and B
Jimmy: on that web interface, ther is an option: "find devices"
Jimmy: I clicked that, from Brother B, I can see BRother A and the status is ready
Jimmy: from Brother A, I can find brother B as well, but the status is blank
Hugo  : yes what's the operating system on the computer?
Jimmy: The computer is Windows 7
Hugo  : ok and can you tell me what the LCD screen of Brother B is currently saying?
Jimmy: it is sleep
Hugo  : ok on brother B press Menu, 6, 2, 1, 2 and let me know the address
Jimmy: The printer is connected with cable
Jimmy: Brother A is connected with wireless network
Hugo  : network cable or usb cable?
Jimmy: when I tried to connected Brother B to the wireless network, I kept getting message that WLAN router cannot be detected
Jimmy: Brother B has both USB and network cable connected
Jimmy: The computer with USB cable connected has no problem to access Brother B
Hugo  : ok then press Menu, 6, 1, ,1 2 on brother B and let me know the address
Jimmy: but another computer tried to connect to it via network failed
Jimmy: the address is 192.168.40.10
Hugo  : ok, you'll need to install the mfl-pro suite again
Hugo  : either from the disc or online
Hugo  : select Wireless Connection and check Custom Install
Hugo  : when you get to a point that says Select the machine you want to isntall
Chose the one with 192.168.40.10 next to it
Hugo  : when the computer restarts you'll have both options in control center
Jimmy: OK, I will try it, thanks very much
Hugo  : No problem!
Hugo  : Let us know if there is any issue
Jimmy: Since I am not in front of the printer, I will do it later.
Jimmy: Yes, I will
Jimmy: Have a good day

Note: I think disable and enable the LAN port did the trick. I disable the LAN port and enable the WLAN posrt and try to use wireless network. Unfortunately the machine was not able to connect to my wireless network, so I have to change back to the wired network the next day. This time, when I click "find devices" for the other Brother's web interface, I can see the status of the problem machine, which was blank the other day.
I did follow the instructions given by Hugo, installed ControlCenter 4 and used Custom Install and manually put IP address. This time there is no problem to add that brother machine.

Wednesday, February 13, 2013

Fix Windows 7 Desktop Icons Disappearing


If you run Windows 7 you might have noticed that desktop shortcuts disappear with no apparent reason whatsoever. Turns out that System Maintenance is responsible for that. It runs as a weekly maintenance service that affects desktop shortcuts in two ways.

It will first remove desktop shortcuts that have not been used for at least three months. System Maintenance will also remove broken shortcuts on the desktop if there are more than four of them. The problem with the latter is that Windows 7 will recognize shortcuts to disconnected network locations as broken and also shortcuts that link to shell folders.

Microsoft offers two solutions to the problem. The first advice is to keep the number of broken shortcuts below four. This is not always possible due to the problems with broken shortcuts mentioned above.
The second suggestion by Microsoft is to turn off Computer Maintenance:
  • Click Start, and then click Control Panel.
  • Under System and Security, click Find and fix problems.
  • On the left navigation pane, click Change settings.
  • Set Computer Maintenance to Off.
This does however turn off all other computer maintenance related tasks like checking the system time, disk volume errors or the disk space error reports.
All the maintenance tasks are powered by scripts that are located in c:\windows\Diagnostics\Scheduled\Maintenance\. Options are to edit the scripts directly in that directory. The permissions prohibit that the files are edited by the current user.

What we are going to do is to edit the default vaule in the scripts, so the condition in the scripts will never be satisfied and the sctript will not delete anything.

Fixing Windows 7 Desktop Shortcuts Disappearing

Go to C:\Windows\diagnostics\scheduled\Maintenance

The script files are :
TS_BrokenShortcuts.ps1.
and
TS_UnusedDesktopIcons.ps1

Take Ownership option and change the security setting so we can use Notepad to edit it.

Open file TS_BrokenShortcuts.ps1
search for "(Get-ListLength $brokenStartupShortcuts)) -gt 4)"
change 4 to something absurdly large
save file

Open file TS_UnusedDesktopIcons.ps1
search for "if((Get-ListLength $unusedDesktopIcons) -gt 10)"
change 10 to something absurdly large
save file


http://www.ghacks.net/2010/03/30/fix-windows-7-desktop-shortcuts-disappearing/