Thursday, 16 April 2015

PowerShell - Testing if a String is NULL or EMPTY

Checking if a string is NULL or EMPTY is very common requirement in Powershell script. If we do not checked that we will get some unwanted results when we try to perform some operation on that string variable which is empty or null.

The following method is used to check if a string is NULL or empty.
$mystring ='hello'
if($mystring) {            
    Write-Host "Your string is not EMPTY"            
} else {            
    Write-Host "Your string is EMPTY or NULL"            
}
We can also use the .NET Class “System.String” to check null or empty string. It has a method IsNullOrEmpty() which returns true if the passed string is null or empty. Check the below example.
$mystring ='hello'
IF([string]::IsNullOrEmpty($mystring)) {            
    Write-Host "Your string is EMPTY or NULL"            
} else {            
    Write-Host "Your string is not EMPTY"            
}
We can also use the method IsNullOrWhiteSpace() from “System.String” class to detect a given string is NULL or EMPTY and whether it has WHITESPACE.
$mystring = " "            
IF([string]::IsNullOrWhiteSpace($mystring)) {            
    Write-Host "Your string is NULL or EMPTY or it has WHITESPACE"            
} else {            
    Write-Host "Your string is not EMPTY"            
}     
Note: The method IsNullOrWhiteSpace() is available only from .NET Frmaework 4.0, so, this method do not work in Powershell 2.0 and it will work only from Powershell 3.0.

You will get below error, when you run this method in Powershell 2.0.

IsNullOrWhitespace : Method invocation failed because [System.String] doesn’t contain a method named ‘IsNullOrWhiteSpace’

Friday, 10 April 2015

Get AD Group Membership of User with Powershell

In this article, I am going write PowerShell script to find and list Active Directory Groups of an AD user is a Member Of using the PowerShell's cmdlet Get-ADPrincipalGroupMembership.

Run the following command to import Active Directory cmdlets.
Import-Module ActiveDirectory
The below powershell command find and list all the Active Directory Groups which contains the user account Morgan as member.
Get-ADPrincipalGroupMembership Morgan | Select Name,DistinguishedName

Export set of AD User's Group Membership to CSV

The below PowerShell script get AD users from the OU TestOU and enumerate membership of all AD Users. It writes the group membership output into csv file using the powershell cmdlet Export-CSV.
$users = Get-ADUser -SearchBase "OU=TestOU,DC=TestDomain,DC=com" -Filter * 
$users |  ForEach-Object {
  $user= $_.Name
  $groupNames = ""
  $groups = Get-ADPrincipalGroupMembership $_.SamAccountName 
  $groups |  ForEach-Object {
    if($groupNames -eq "")
     {
       $groupNames = $_.Name
     }
    else
     {
       $groupNames = $groupNames +";"+$_.Name
     }

 New-Object -TypeName PSObject -Property @{
       UserName= $user
       Groups = $groupNames }
}} | Export-CSV "C:\ADGroupMembership.csv" -NoTypeInformation -Encoding UTF8

CSV Output of Group Membership for AD Users :

Find and Export AD Users Group Membership to CSV

C# - Get PowerShell Output from MultiValuedProperty Value

In C#, you can execute powershell commands and get output in separate runspace. The following C# example returns the exchange server's mailbox audit report. The audit setting fields (AuditDelegate,AuditAdmin,AuditOwner) are multi-valued property field, so we can not read value directly from this field. The datatype of this field is "Deserialized.Microsoft.Exchange.Data.Directory.ADMultiValuedProperty`1[[Microsoft.Exchange.Data.Directory.MailboxAuditOperations, Microsoft.Exchange.Data.Directory, Version=14.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]". So, here, I have written the C# code to extract value from ADMultiValuedProperty field.
public static void GetMailBoxAuditReport()
{
    string shellUri = "http://schemas.microsoft.com/powershell/Microsoft.PowerShell";
    var secured = new SecureString();
    foreach (char letter in "MyPassword")
    {
        secured.AppendChar(letter);
    }
    secured.MakeReadOnly();
    var credential = new PSCredential(@"MyExchDomain\Administrator", secured);
    var connectionInfo = new WSManConnectionInfo(false, "MyExchServer", 5985, "/wsman", shellUri, credential);
    Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo);
    runspace.Open();
    Pipeline pipeline = runspace.CreatePipeline();
    pipeline.Commands.AddScript("Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010");
    pipeline.Commands.AddScript("Get-Mailbox | Select Name, AuditEnabled, AuditLogAgeLimit,AuditAdmin,AuditDelegate,AuditOwner");
    Collection<PSObject> results = pipeline.Invoke();
    if (results.Count > 0)
    {
        foreach (PSObject psObject in results)
        {
            List<string> output = new List<string>();
            foreach (PSPropertyInfo psInfo in psObject.Properties)
            {
                if (psInfo.Value != null)
                {
                    string dataType = psInfo.TypeNameOfValue;
                    if (dataType.Contains("ADMultiValuedProperty"))
                    {
                        string multiValueOutput = string.Empty;
                        PSObject childObj = (PSObject)psInfo.Value;
                        foreach (PSObject info in (ArrayList)childObj.ImmediateBaseObject)
                        {
                            multiValueOutput += info.ToString() + ";";
                        }
                        output.Add(multiValueOutput);
                    }
                    else if (dataType.Equals("System.String[]"))
                    {
                        string[] childObj = (string[])psInfo.Value;
                        output.Add(string.Join(";", childObj));
                    }
                    else
                    {
                        output.Add(psInfo.Value.ToString());
                    }
                }
            }
            Console.WriteLine(string.Join(";", output.ToArray()));
            Console.WriteLine("----------------------");
        }
    }
}

Wednesday, 8 April 2015

PowerShell - Convert Ticks to DateTime and Vise Versa

You can convert Date to Ticks and Ticks to Date Time using the PowerShell Get-Date cmdlet.

Convert Ticks to DateTime

Use the below powershell command to convert ticks to date.
Get-Date 635641048517131910

Wednesday, April 08, 2015 3:47:31 PM
You can also convert ticks to datetime by simple DateTime type casting.
[DateTime]635641048517131910

Wednesday, April 08, 2015 3:47:31 PM

Convert DateTime to Ticks

Use the below powershell command to convert date to ticks.
(Get-Date).ticks

635641051132584348
(Get-Date "04/20/2014").ticks

635335488000000000

PowerShell - Convert Large Integer value to DateTime string

If you are working with Active Directory, you should have come across the attributes like LastLogonTimestamp. This LastLogonTimestamp attribute is stored in the Active Directory database as a Large Integer (TimeStamp) value so we need to convert it to a normal date format string to make it readable.

Use the following PowerShell command to Convert Large Integer value to Date Time string

$lastLogonTimestamp = "130724281432636780"
[DateTime]::FromFiletime([Int64]::Parse($lastLogonTimestamp))
PowerShell - Convert Large Integer value to Date Time string

Event 1530 - Windows detected your registry file is still in use

Problem:

One of my installed Apllication's Windows Service not started automatically and I tried to start it manually, but it again failed to start, then I have started to analyze through event logs and find the below warning event 1530 with error message "Windows detected your registry file is still in use by other applications or services. The file will be unloaded now. The applications or services that hold your registry file may not function properly afterwards".
Log Name:      Application
Source:        Microsoft-Windows-User Profiles Service
Date:          4/8/2015 01:45:18 AM
Event ID:      1530
Level:         Warning
Computer:      myPC.myDomain.Com
Description:
Windows detected your registry file is still in use by other applications or services. The file will be unloaded now. The applications or services that hold 
your registry file may not function properly afterwards.  

 DETAIL - 
 1 user registry handles leaked from \Registry\User\S-1-5-21-745457877-148782331-813991262-2636_Classes:
Process 1984 (\Device\HarddiskVolume3\Program Files
\Program Files\MTS\MyService.exe) has opened key \REGISTRY\USER\S-1-5-21-745457877-148782331-813991262-2636_CLASSES

Cause:

After I have analyzed some time, found this warning event was logged due to service account (The service account used only to run widows service and it was not used to login into system). This warning event (1530) is logged by the behavior of system design.

Other related links

- http://support.microsoft.com/en-us/kb/947238
- http://answers.microsoft.com/en-us/windows/forum/windows_7-security/event-id1530-microsoft-windows-user-profiles/a1ca9fd0-5449-46b6-aae2-35e3edcf8425
- http://social.technet.microsoft.com/wiki/contents/articles/3134.user-profile-service-event-1530-the-windows-operating-system-detected-that-your-registry-file-is-still-in-use-by-other-applications-or-services.aspx