Tuesday, 31 March 2015

Test Remote Powershell Management is Enabled or Not

We can check whether the powershell remoting is configured or not in a particular remote computer using the powershell cmdlet Test-WsMan. This command tests whether the WinRM service is running on the remote computer and the computers can communicate with each other.
Test-WsMan COMPUTER
The below command check whether powershell remoting is enabled or not in the remote computer MCOM12.
Test-WsMan MCOM12
The command displays powershell version if remote powershell management is successfully configured or otherwise it will displays an error message.

Check Powershell Remoting Management is Enabled or Not

Sunday, 29 March 2015

Execute Remote PowerShell Commands

We can run powershell commands on remote computer using the powershell cmdlet Invoke-Command.

Syntax of Invoke-Command:
Invoke-Command -ComputerName COMPUTER -ScriptBlock { COMMAND } -credential USERNAME
COMPUTER - The name of the computer to connect.
COMMAND - The powershell command to run in remote computer
USERNAME - The user account to run the command as on the remote computer. You will be prompted to enter a password for the username.

The below sample execute the command on the remote computer MCOM12, find the remote host name and display as output.
Invoke-Command -ComputerName MCOM12 -ScriptBlock { 'This command running on {0}.' -f (hostname) } -credential Morgan

Remote PowerShell Session

If you want to run series of PowerShell commands on a remote computer, you can start a remote PowerShell session for the particular remote computer using the Enter-PSSession cmdlet and then you can run multiple commands, instead of running a single command:
Enter-PSSession -ComputerName COMPUTER -Credential USER
The below sample command creates new session for the remote computer MCOM12.
Enter-PSSession -ComputerName MCOM12 -Credential Administrator
Execute Remote PowerShell Commands

Saturday, 28 March 2015

Enable Remote PowerShell and Run Commands

You can enable powershell remoting on computers running Windows 7 and later versions which includes WinRM 2.0 or later. The Windows PowerShell Remoting features are supported by the WS-Management protocol and the Windows Remote Management (WinRM) service that implements WS-Management in Windows.

Follow the below steps to enable PowerShell Remoting:

Start Windows PowerShell with elevated privilege (Run as Administrator) by right-clicking the Windows PowerShell shortcut and selecting Run As Administrator.

Case 1: If your computers (local and remote machine) are in the same domain network, then run the following powershell commands in remote machine to enable PS Remoting in the remote system.
1. Enable-PSRemoting -Force
2. Restart-Service WinRm
Case 2: If your computers (local and remote machine) are in different domain or work group, then you need to configure the Trusted hosts settings in both the systems.

Run the following command in PowerShell (both local and remote machines)
1. Enable-PSRemoting -Force
2. Set-Item wsman:\localhost\client\trustedhosts -Value <IP_ADDRESS_OF_THE_OTHER_SYSTEM>
3. Restart-Service WinRm

Test Powershell Remote Connection:

You can use the Test-WsMan cmdlet to test your remote configuration settings. This command tests whether the WinRM service is running on the remote computer and the computers can communicate with each other.
Test-WsMan MCOM12
Enable PowerShell Remoting and Run commands on Remote Computer

Run Remote Powershell Commands:

Use the powershell cmdlet Invoke-Command to run a command on the remote system.

Syntax of remote powershell command:
Invoke-Command -ComputerName COMPUTER -ScriptBlock { COMMAND } -credential USERNAME
COMPUTER - The name of the computer to connect.
COMMAND - The powershell command to run in remote computer
USERNAME - The user account to run the command as on the remote computer. You will be prompted to enter a password for the username.

The below sample execute the command on the remote computer MCOM12, find the remote host name and display as output.
Invoke-Command -ComputerName MCOM12 -ScriptBlock { 'This command running on {0}.' -f (hostname) } -Credential (Get-Credential)

Tuesday, 24 March 2015

Powershell: Set AD User Must Change Password At Next Logon

We can set AD user property values using powershell cmdlet Set-ADUser. The Set-ADUser cmdlet modifies the properties of an Active Directory user. Normally, you can force an AD user to change password at next logon by setting the AD user's pwdLastSet attribute value as 0, but this Set-ADUser cmdlet supports the extended property ChangePasswordAtLogon, you can directly set True or False value in this property and the cmdlet itself internally update the pwdLastSet attribute.

Powershell command to reset user to change password at next logon:

Set-ADUser -Identity <samAccountName> -ChangePasswordAtLogon $true
The Identity parameter specifies the Active Directory user to modify. You can identify a user by its samAccountName, distinguished name (DN), GUID and SID.

Set Users Specific OU:

You can select AD users from specific OU and set user must change password at next logon by using Get-ADUser and Set-ADUser cmdlets. You can set target OU scope by using the parameter SearchBase in Get-ADUser cmdlet. This following command select and set pwdLastSet attribute value as 0 of the Active Directory users the Organization Unit 'TestOU'.
Import-Module ActiveDirectory
Get-ADUser -Filter * -SearchBase "OU=TestOU,DC=TestDomain,DC=Local" |
  Set-ADUser -ChangePasswordAtLogon:$True

Update Specific set of AD Users with Filter:

You can filter sepecific set of AD users by using SQL like filter with Get-ADUser, users who are not familiar with LDAP filter can easily use this filter to get only specific set of AD users
Import-Module ActiveDirectory
Get-ADUser -Filter 'department -like "*Admin*"' |
  Set-ADUser -ChangePasswordAtLogon:$True
You can also use LDAP filter with Get-ADUser powershell cmdlet with more flexibility to filter Active Directory users.
Import-Module ActiveDirectory
Get-ADUser -LDAPFilter '(Department=*Admin*)' |
  Set-ADUser -ChangePasswordAtLogon:$True

Modify Bulk AD Users Password Never Expire flag from CSV:

You can read Active Directory from csv file using Powershell cmdlet Import-CSV. Consider the CSV file ADUsers.csv (Ex file: Download ADUsers.csv) which contains set of AD users with the attribute samAccountName.

Set Bulk AD Users to Change Password At Next Logon from CSV
Import-Module ActiveDirectory
Import-Csv "C:\Scripts\ADUsers.csv" | ForEach-Object {
 $samAccountName = $_."samAccountName"
Get-ADUser -Identity $samAccountName | 
 Set-ADUser -ChangePasswordAtLogon:$True
}

Modify specific AD Group Members:

You can set user must change password at next logon for the specific AD group members by getting group members using Get-ADGroupMember cmdlet. The following powershell script select all the members TestGroup group and set the users to change password at next logon.
Import-Module ActiveDirectory
Get-ADGroupMember -Identity "TestGroup" |
  Set-ADUser -ChangePasswordAtLogon:$True

Friday, 20 March 2015

Powershell: Set AD Users Password Never Expires flag

We can set Active Directory user property values using Powershell cmdlet Set-ADUser. The Set-ADUser cmdlet modifies the properties of an Active Directory user. Normally, you can configure an AD user as password never expire user by setting the flag DONT_EXPIRE_PASSWORD (65536) in the AD user's userAccountControl attribute, but this Set-ADUser cmdlet supports the extended property PasswordNeverExpires, you can directly set value in this property and the cmdlet itself internally update the userAccountControl flag.

Powershell command to Configure Password Never Expires flag:

Set-ADUser -Identity <samAccountName> -PasswordNeverExpires $true
The Identity parameter specifies the Active Directory user to modify. You can identify a user by its samAccountName, distinguished name (DN), GUID and SID.

Modify AD Users from Specific OU:

You can select AD users from specific OU and set as password never expire users by using Get-ADUser and Set-ADUser cmdlets. You can set target OU scope by using the parameter SearchBase in Get-ADUser cmdlet. This following command select and set as password never expires flag of Active Directory users from the Organization Unit 'TestOU'.
Import-Module ActiveDirectory
Get-ADUser -Filter * -SearchBase "OU=TestOU,DC=TestDomain,DC=Local" |
  Set-ADUser -PasswordNeverExpires:$True

Update Specific set of AD Users with Filter:

You can filter sepecific set of AD users by using SQL like filter with Get-ADUser, users who are not familiar with LDAP filter can easily use this filter to get only specific set of AD users
Import-Module ActiveDirectory
Get-ADUser -Filter 'department -like "*Admin*"' |
  Set-ADUser -PasswordNeverExpires:$True
You can also use LDAP filter with Get-ADUser powershell cmdlet with more flexibility to filter Active Directory users.
Import-Module ActiveDirectory
Get-ADUser -LDAPFilter '(Department=*Admin*)' |
  Set-ADUser -PasswordNeverExpires:$True

Modify Bulk AD Users Password Never Expire flag from CSV:

You can read Active Directory from csv file using Powershell cmdlet Import-CSV. Consider the CSV file ADUsers.csv (Ex file: Download ADUsers.csv) which contains set of AD users with the attribute samAccountName.

Modify Bulk AD Users Password Never Expire flag from CSV file
Import-Module ActiveDirectory
Import-Csv "C:\Scripts\ADUsers.csv" | ForEach-Object {
 $samAccountName = $_."samAccountName"
Get-ADUser -Identity $samAccountName | 
 Set-ADUser -PasswordNeverExpires:$True
}

Modify specific AD Group Members:

You can set password never expires flag for only specific Active Directory group members by getting AD group members using Get-ADGroupMember cmdlet. The following powershell script select all the members "TestGroup"  group and set as password never expire users.
Import-Module ActiveDirectory
Get-ADGroupMember -Identity "TestGroup" |
  Set-ADUser -PasswordNeverExpires:$True

The type or namespace name 'automation' does not exist in the namespace 'system.management'

I have added the reference Assembly System.Management.Automation in my C# application to run PowerShell scripts from C# project. but I am getting following error during compilation of the code.
Error 30 The type or namespace name 'Automation' does not exist in the namespace 'System.Management' (are you missing an assembly reference?)
This is my C# code:
using System.Management.Automation;
using System.Management.Automation.Runspaces;
//-----------------------------------
static void Main(string[] args)
{
    Runspace runspace = RunspaceFactory.CreateRunspace();
    runspace.Open();
    Pipeline pipeline = runspace.CreatePipeline();
    pipeline.Commands.AddScript("Get-Date");
    Collection<PSObject> results = pipeline.Invoke();
    runspace.Close();
    StringBuilder stringBuilder = new StringBuilder();
    foreach (PSObject obj in results)
    {
        Console.WriteLine(obj.ToString());
    }
}

Fix/Solution:

The issue was fixed after I have changed the reference of System.Management.Automation to c:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\System.Management.Automation.dll.

I have added the reference Assembly System.Management.Automation from the location "C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0" and my C# projects targets .NET Framework 3.5. Initially I didn't find the the reference System.Management.Automation.dll when I search the Assemblies in Add Reference window, so that I have added the reference by manual browse option from the location "C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0".

Finally I found that the assembly file System.Management.Automation.dll (under the folder PowerShell 3.0) is supported only .NET Framework 4.0, so that have changed the reference Assembly to c:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0\System.Management.Automation.dll to fix this issue.

Wednesday, 18 March 2015

Change the location of Windows Search Index

If you enabled the Windows Search and Index service in your windows system, the file named "Windows.edb" will be placed under the location "C:\ProgramData\Microsoft\Search\Data\Applications\Windows" and its size will be growing day by day. You have to change the location of the file if you are facing disk storage size overflow problem due to this file.

Change location of Windows Search Index

By default, Search Index file(Windows.edb) stored at C:\ProgramData\Microsoft\Search\Data folder, which is a hidden system folder. You can change the location of the Search Index under Indexing Options in the Control Panel. Follow the steps to change the location of Windows Search Index.

1.  Open Control Panel in its ‘Large Icons view’, and click on Indexing Options.

Change the location of Windows Search Index

2.  In new Window, click on Advanced button.

Change the location of Windows Search Index

3.  Under the Index location section, click Select new button.

Change the location of Windows Search Index

4.  Select the folder where you want to store the new search index file and click on OK.

Change the location of Windows Search Index

Note:This process will restart Windows Search Service and Indexing and save the Search Index file at new location.

Tuesday, 17 March 2015

TF400324: Team Foundation services are not available from server...

Problem:

We faced the TFS connection failure problem while connecting TFS source project from Visual Studio 2013. We got the error message "TF400324: Team Foundation services are not available from server - The underlying connection was closed: An unexpected error occurred on a receive".

Complete error message:

TF400324: Team Foundation services are not available from server TFS-Server.
Technical information (for administrator):
 The underlying connection was closed: An unexpected error occurred on a receive.

Solution:

After I have analysed some time, found the following quick fix to resolve this error.
  1. Close Visual Studio Solution and related applications.
  2. Browse the TFS AppData Cache folder path: %LocalAppData%\Microsoft\Team Foundation\5.0\Cache
  3. Delete all the contents under the folder Cache (don't worry it will be automatically re-created when you open Visual Studio and connect TFS again),
For better fix, you can refer this solution: http://www.codeproject.com/Articles/613214/TF-Team-Foundation-services-are-not-availabl

C# - Set Full Control Permission to a Directory

In C#, we can easily add full access control permission on a file or folder for an user account or everyone (Everybody) account using .NET classes Directory and DirectorySecurity.

The below C# code set the full control permission on the given directory for the given user account. It also applies the full control permissions to folder, subfolders and files.
public static void SetFullAccessPermission(string directoryPath,string username)
{
    DirectorySecurity dir_security = Directory.GetAccessControl(directoryPath);
            
    FileSystemAccessRule full_access_rule = new FileSystemAccessRule(username,
                     FileSystemRights.FullControl, InheritanceFlags.ContainerInherit |   
                     InheritanceFlags.ObjectInherit,PropagationFlags.None,
                     AccessControlType.Allow);

    dir_security.AddAccessRule(full_access_rule);

    Directory.SetAccessControl(directoryPath, dir_security);
}
In some cases, situation may require us to configure full control permission to every users (Everyone/Everybody account). In that case, get the everyone identity from the enum WellKnownSidType.WorldSid instead of giving the string "Everyone" because the string value "Everyone" differs other languages. The below C# code set full access control permission on the given directory for everyone account.
public static void SetFullAccessPermissionsForEveryone(string directoryPath)
{
    //Everyone Identity
    IdentityReference everyoneIdentity = new SecurityIdentifier(WellKnownSidType.WorldSid,
                                               null);

    DirectorySecurity dir_security = Directory.GetAccessControl(directoryPath);

    FileSystemAccessRule full_access_rule = new FileSystemAccessRule(everyoneIdentity,
                    FileSystemRights.FullControl, InheritanceFlags.ContainerInherit |   
                     InheritanceFlags.ObjectInherit,PropagationFlags.None,
                     AccessControlType.Allow);
    dir_security.AddAccessRule(full_access_rule);

    Directory.SetAccessControl(directoryPath, dir_security);
}

Monday, 16 March 2015

Export AD Users to CSV using PowerShell

We can generate and export Active Directory users report to CSV file using Powershell cmdlets Get-ADUser and Export-CSV. Get-ADUser cmdlet supports SQL like filter and LDAP filter to filter AD Users. By using these filter we can generate any kind of Active Directory Reports. You can select any user attribute that supported in Active Directory using Get-ADUser cmdlet and it also supports Extended Properties like AccountLockoutTime, Enabled,LockedOut (refer this article:Get-ADUser Default and Extended Properties to know more supported AD attributes).

Export AD Users to CSV using Powershell

The following powershell script exports the selected properties of all Active Directory users to CSV file.
Import-Module ActiveDirectory
Get-ADUser -Filter * -Properties * |
 Select -Property SamAccountName,Mail,Department | 
 Export-CSV "C:\\AllADUsers.csv" -NoTypeInformation -Encoding UTF8

Select Users from specific OU:

We can set target OU scope by using the parameter SearchBase. The following powershell script select all the AD users from the Organization Unit 'TestOU' and export it to CSV file.
Import-Module ActiveDirectory
Get-ADUser -Filter * -SearchBase "OU=TestOU,DC=TestDomain,DC=Local" -Properties * |
 Select -Property SamAccountName,Mail,Department | 
 Export-CSV "C:\\TestOUUsers.csv" -NoTypeInformation -Encoding UTF8

Add more Properties in export report:

You can add any extra attribute that supported in Active Directory in property list. If you want to add the attributes displayName and mobile with this script, you can simply add these attributes as comma separated values.
Import-Module ActiveDirectory
Get-ADUser -Filter * -SearchBase "OU=TestOU,DC=TestDomain,DC=Local" -Properties * |
 Select -Property SamAccountName,Mail,Department,displayName,mobile | 
 Export-CSV "C:\\ADUsers.csv" -NoTypeInformation -Encoding UTF8
Along with normal attributes, you can also add the Extended Properties like AccountLockoutTime, Enabled, LockedOut  (refer this article:Get-ADUser Default and Extended Properties to know more supported extended AD attributes).
Import-Module ActiveDirectory
Get-ADUser -Filter * -SearchBase "OU=TestOU,DC=TestDomain,DC=Local" -Properties * |
 Select -Property SamAccountName,AccountLockoutTime,Enabled,LockedOut | 
 Export-CSV "C:\\ADUsers.csv" -NoTypeInformation -Encoding UTF8

Apply SQL Like filter to get specific users:

Get-ADUser cmdlet supports SQL like filter, users who are not familiar with LDAP filter can easily use this filter to get only specific set of AD users. This following powershell script export the selected properties to CSV file of AD users whose City contains the text 'Austin'.
Import-Module ActiveDirectory
Get-ADUser -Filter 'City -like "*Austin*"' |
  Select -Property Name,City,Mail,Department,DistinguishedName | 
  Export-CSV "C:\\ADUsers.csv" -NoTypeInformation -Encoding UTF8
You can use both normal AD attribute and Extended Properties in this filter. The following powershell script export all the enabled Active Directory users whose PasswordNeverExpires flag value is equal to False by filtering with Extended Properties Enabled and PasswordNeverExpires.
Import-Module ActiveDirectory
Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} |
  Select -Property Name,Mail,Department,DistinguishedName | 
  Export-CSV "C:\\ADUsers.csv" -NoTypeInformation -Encoding UTF8

Apply LDAP Filter to get specific set of AD users:

If your are familiar with LDAP filter, instead of normal filter, you can also use LDAP filter with Get-ADUser powershell cmdlet with more flexibility to filter Active Directory users. The below script exports all the users who are belongs to Admin department.
Import-Module ActiveDirectory
Get-ADUser -LDAPFilter '(Department=*Admin*)' -Properties * |
  Select -Property Name,Mail,Department,DistinguishedName | 
  Export-CSV "C:\\AdminUsers.csv" -NoTypeInformation -Encoding UTF8
The below powershell script exports only enabled AD users with LDAP filter. Refer this article (AD LDAP Filter Examples) to get more LDAP filter examples.
Get-ADUser -LDAPFilter '(!userAccountControl:1.2.840.113556.1.4.803:=2)' -Properties * |
  Select -Property Name,Mail,Department,DistinguishedName | 
  Export-CSV "C:\\EnabledUsers.csv" -NoTypeInformation -Encoding UTF8

Powershell - Export AD Users CSV output:

Powershell - Export AD Users Report to CSV File

C# - Change Service Account Username and Password

In C#, We modify Windows service account username and password using the WMI class Win32_Service and we can also update service account information using the Win32 API function ChangeServiceConfig. In this article, I am going to write C# examples to change service account name and password in local machine and remote machine.

Summary:

Change Service Account Information using Win32 API

Use the below C# sample code to update service account username and password. It uses the Win32 API function ChangeServiceConfig. The ChangeServiceConfig function changes the configuration information for the specified service in the service control manager database.
private const int SC_MANAGER_ALL_ACCESS = 0x000F003F;
private const uint SERVICE_NO_CHANGE = 0xffffffff; //this value is found in winsvc.h
private const uint SERVICE_QUERY_CONFIG = 0x00000001;
private const uint SERVICE_CHANGE_CONFIG = 0x00000002;

[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern Boolean ChangeServiceConfig(IntPtr hService, UInt32 nServiceType, 
    UInt32 nStartType,UInt32 nErrorControl,String lpBinaryPathName,String lpLoadOrderGroup,
    IntPtr lpdwTagId, [In] char[] lpDependencies, String lpServiceStartName, 
    String lpPassword, String lpDisplayName);

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, 
     uint dwDesiredAccess);

[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, 
    CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr OpenSCManager(string machineName, string databaseName, 
     uint dwAccess);

public static bool ChangeServiceAccountInfo(string serviceName, string username,
       string password)
{
    try
    {
        IntPtr scm_Handle = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS);
        if (scm_Handle == IntPtr.Zero)
          throw new System.Runtime.InteropServices.ExternalException(
                      "Open Service Manager Error");

        IntPtr service_Handle = OpenService(scm_Handle, serviceName,
                                        SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG);
        if (service_Handle == IntPtr.Zero)
          throw new System.Runtime.InteropServices.ExternalException("Open Service Error");
        //Changing the user account and password for the service.
        if (!ChangeServiceConfig(service_Handle, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 
             SERVICE_NO_CHANGE, null, null,IntPtr.Zero, null, username, password, null))
        {
            int nError = Marshal.GetLastWin32Error();
            Win32Exception win32Exception = new Win32Exception(nError);
            throw new System.Runtime.InteropServices.ExternalException("Could not change 
          user account and password : " + win32Exception.Message);
        }
        Console.WriteLine("Service account information changed successfully");
        return true;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
        return false;
    }
}

Change Service Login Username and Password using WMI in C#

The below C# code sample uses the WMI class Win32_Service to update windows service user name and password. To use WMI service, we need to add the reference System.Management.

Note: Use the fully qualified user name (i.e. TestDomain\Morgan) instead of simple user name (Morgan) if your remote computer is connected with Active Directory domain.

using System.Management;
//--------------------------
public static void ChangeServiceAccountInfobyWMI(string serviceName, string username,
          string password)
{
    string mgmntPath = string.Format("Win32_Service.Name='{0}'", serviceName);
    using (ManagementObject service = new ManagementObject(new ManagementPath(mgmntPath)))
    {
        object[] accountParams = new object[11];
        accountParams[6] = username;
        accountParams[7] = password;
        uint returnCode = (uint)service.InvokeMethod("Change", accountParams);
        if (returnCode == 0)
        {
             Console.WriteLine("Service account information changed successfully");
        }
        else
        {
             Console.WriteLine("Failed to change Service account information");
             Console.WriteLine("Error code: " + returnCode);
             // Support link to check the message for corresponding Return code:
             // https://msdn.microsoft.com/en-us/library/aa393660(v=vs.85).aspx
        }
    }
}

Update Service Account Username and Password in Remote Server

Use the below C# code sample to update windows service user name and password in remote machine using the WMI class Win32_Service. To use WMI service, we need to add the reference System.Management and use admin credentials if required to update service information in remote computer.

Note: Use the fully qualified user name (i.e. TestDomain\Morgan) instead of simple user name (Morgan) if your remote computer is connected with Active Directory domain.

If you are receiving error code, get the error message for corresponding return code from this Microsoft support link: https://msdn.microsoft.com/en-us/library/aa393660(v=vs.85).aspx


using System.Management;
//--------------------------
static void ChangeRemoteServiceAccountInfo(string remoteComputer, string serviceName, 
            string username, string password)
{
    try
    {
        ConnectionOptions connectionOptions = new ConnectionOptions();
        // Use credentials if needed
        //connectionOptions.Username = "Administrator";
        //connectionOptions.Password = "AdminPassword";
        //connectionOptions.Impersonation = ImpersonationLevel.Impersonate;
        ManagementScope scope = new ManagementScope("\\\\" + remoteComputer + 
                                             "\\root\\CIMV2", connectionOptions);
        scope.Connect();
        string mgmntPath = string.Format("Win32_Service.Name='{0}'", serviceName);
        using (ManagementObject service = new ManagementObject(scope,
                                 new ManagementPath(mgmntPath),new ObjectGetOptions()))
        {
            object[] accountParams = new object[11];
            accountParams[6] = username;
            accountParams[7] = password;
            uint returnCode = (uint)service.InvokeMethod("Change", accountParams);
            if (returnCode == 0)
            {
                Console.WriteLine("Service account information changed successfully");
            }
            else
            {
                Console.WriteLine("Failed to change Service account information");
                Console.WriteLine("Error code: " + returnCode);
                // Support link to check the message for corresponding Return code:
                // https://msdn.microsoft.com/en-us/library/aa393660(v=vs.85).aspx
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

Friday, 13 March 2015

Powershell - Get AD Users Password Expiry Date

We can find and list the password expiry date of AD user accounts from Active Directory using the computed schema attribute msDS-UserPasswordExpiryTimeComputed. In PowerShell, we get a list AD Users properties by using the cmdlet Get-ADUser. We can use SQL like filter and LDAP filter with Get-ADUser cmdlet to get only particular set of users.

Summary:

Get Password Expiry Date of all Enabled AD Users

The following powershell script find all the enabled Active Directory users whose PasswordNeverExpires flag value is equal to False and list the attribute value samAccountName and Password Expire Date. The Active Directory computed attribute msDS-UserPasswordExpiryTimeComputed is timeStamp attribute and its value will be stored as integer, so we are using expression to convert timestamp value into normal date time.
Import-Module ActiveDirectory
Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} `
 –Properties "SamAccountName","msDS-UserPasswordExpiryTimeComputed" |
Select-Object -Property "SamAccountName", @{Name="Password Expiry Date"; `
Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}} | FT
You can add any extra attribute that supported in Active Directory in property list. If you want to add the attributes mail and pwdLastset with this script, you can simply add these attributes as comma separated values.
Import-Module ActiveDirectory
Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} `
–Properties "SamAccountName","mail","pwdLastSet","msDS-UserPasswordExpiryTimeComputed" |
Select-Object -Property "SamAccountName","mail",@{Name="Password Last Set";`
Expression={[datetime]::FromFileTime($_."pwdLastSet")}}, @{Name="Password Expiry Date";`
Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}} | FT
Instead of normal filter, you can also use LDAP filter with Get-ADUser powershell cmdlet to filter Active Directory users.
Import-Module ActiveDirectory
Get-ADUser -LDAPFilter '(&(!userAccountControl:1.2.840.113556.1.4.803:=2)(!userAccountControl:1.2.840.113556.1.4.803:=65536))'`
–Properties "SamAccountName","msDS-UserPasswordExpiryTimeComputed" |
Select-Object -Property "SamAccountName", @{Name="Password Expiry Date";`
Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}} | FT
Here, the userAccountControl flag value 2 indicates disabled account status and the flag 65536 indicates PasswordNeverExpires.

Powershell - Get AD Users Password Expiry Date

Get AD Users Password Expiration Report from Specific OU

We can set target OU scope by using the parameter SearchBase in powershell's Get-ADUser cmdlet. This following command select and list all the enabled AD users password expiration report from the Organization Unit 'TestOU'.
Import-Module ActiveDirectory
Get-ADUser -SearchBase "OU=TestOU,DC=TestDomain,DC=Local"`
 -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} `
–Properties "SamAccountName","msDS-UserPasswordExpiryTimeComputed" |
Select-Object -Property "SamAccountName", @{Name="Password Expiry Date";`
Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}} | FT

Export AD Users Password Expiration Report to CSV with Powershell

We can export powershell output into CSV file using Export-CSV cmdlet. The following powershell command export selected properties and password expiry date of all the enabled Active Directory users to CSV file.
Import-Module ActiveDirectory
Get-ADUser -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} `
–Properties "SamAccountName","mail","pwdLastSet","msDS-UserPasswordExpiryTimeComputed" |
Select-Object -Property "SamAccountName","mail",@{Name="Password Last Set";`
Expression={[datetime]::FromFileTime($_."pwdLastSet")}}, @{Name="Password Expiry Date";`
Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}} | 
 Export-CSV "C:\\PasswordExpirationReport.csv" -NoTypeInformation -Encoding UTF8

CSV Output of AD Users Password Expiration Date Report:

Export AD Users Password Expiration Report to CSV with Powershell

Kill a process that won't die when you use End Task in Task Manager

Problem:

Unfortunately, today I have executed a time consuming powershell script through Windows Powershell Command utility. I have waited so much of time to get result but there was no luck, So have decided to terminate the program (kill a process) but it ignores any attempt by Task Manager to kill the process.

Solution: Kill or Terminate a not responding process

After I have analyzed some time found the below solutions for this issue.

Solution 1:

- In Task Manager, go to under the tab Applications and right-click on the program that you want to kill and click Go To Process.
Kill a process that won't die when you use End Task in Task Manager
- Then right-click on the highlighted process and click on End Process. You can also try with End Process Tree.

Solution 2:

- You can also use the utility program "Process Explorer" written by Mark Russinowich of Sysinternals...it is available at the Microsoft website....Download the utility from this link: http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx
- Run the Process Explorer utility, locate and kill the corresponding prcoess.

Kill a process that won't die when you use End Task in Task Manager

Thursday, 12 March 2015

Powershell – Check If File Exists or Not

We can check and test if a file or folder exist or not by using the PowerShell cmdlet Test-Path.

The below powershell script will check whether the file test.txt is already exists or not under the path C:\Share\.
$FileName = "C:\Share\test.txt"
if (Test-Path $FileName) 
{
  Write-Host "File Exists"
}
else
{
  Write-Host "File Not Exists"
}

Powershell – Delete File If Exists

We can test and check if a file exist or not by using the PowerShell cmdlet Test-Path and we can remove/delete a file by using the cmdlet Remove-Item.

The below powershell script delete the file test.txt if it already exists under the path C:\Share\.
$FileName = "C:\Share\test.txt"
if (Test-Path $FileName) 
{
  Remove-Item $FileName
}

GPO Update Failed - User and Computer policy could not be updated successfully

Problem:

I am using Windows Server 2008 R2 , today, I have modified some settings in one of Group Policy and as usual I have tried the command gpupdate / force to update gpo settings. After some time, I have receive the error "User policy could not be updated successfully" and "Computer policy could not be updated successfully".

User policy could not be updated successfully. The following errors were encountered:

The processing of Group Policy failed. Windows attempted to read the file \\TestDomain.local\sysvol\TestDomain.local\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\gpt.ini from a domain controller and was not successful. Group Policy settings may not be applied until this event is resolved. This issue may be transient and could be caused by one or more of the following:
a) Name Resolution/Network Connectivity to the current domain controller.
b) File Replication Service Latency (a file created on another domain controller has not replicated to the current domain controller).
c) The Distributed File System (DFS) client has been disabled.

Computer policy could not be updated successfully. The following errors were encountered:

Fix/Solution: 

Browse the Sysvol directory (\\domainname\Sysvol\) from Start\Run. then you will get below error message. .
Network Error-Windows cannot access \\domainname\sysvol\

Check the spelling of the name. Otherwise, there might be a problem with your network. To try to identify and resolve network problems, Error code: 0x800704cf - The network location cannot be reached. For information about network troubleshooting, see Windows Help.
If you got this error message, you are facing the same problem that I faced. Then try to browse the Sysvol directory by Domain Controller name or FQDN (\\DC1\Sysvol\) instead of domain name from Start\Run. now you can access the sysvol without any problem, so the ultimate cause for this issue is Name Resolution/Network Connectivity problem. The root cause of the Name Resolution will differs for every environment.

In my environment, I have fixed the Name Resolution issue by following below steps:

- Checked Name Resolution by Ping command (Ping YourDomain.local)
- Ping result shows, it is trying to connect wrong IP address instead of IP of current DC, and ensured the wrong IP address is nothing but the IP of my another DC which is not active.

Finally, I have confirmed this is the root cause for my problem, the IP address of inactive DC is cached in DNS entries for the domain name, Now, I started that DC and confirmed everything is working fine now.

Note: Name Resolution/Network Connectivity problem is generic DNS problem, so please try to resolve DNS cache issue as per your own need.

Other Useful References:

- http://support.microsoft.com/kb/934907
- https://social.technet.microsoft.com/Forums/windowsserver/en-US/2a1dae75-90bb-43c3-963e-b5a668f4fd33/gpupdate-returns-event-id-1058-error-code-53
- https://social.technet.microsoft.com/Forums/en-US/d8f2b1a0-17a3-4756-b2de-7ffbd9bf1d92/user-policy-could-not-be-updated-successfully-the-following-errors-were-encountered-please-help-me?forum=winserverGP

Wednesday, 11 March 2015

Get NTFS File Permissions with PowerShell script

We can read the owner and permissions of a file, folders and registry keys with Powershell’s Get-Acl cmdlet. In this article, I am going to write poweshell script samples to read file permissions, folder level permissions and export folder level permissions to csv file.

Summary:

The below command read and list the permissions of the folder.
Get-Acl -path "C:\Windows"
The above command displays Access Control List as combined text. So the output may not give clear idea about who has what permissions. We can get clear ACL information by expanding the individual ACEs (access control entries) using the parameter expand
Get-Acl -path "C:\Windows" | Select -expand Access 
When you read permissions by using Get-Acl cmdlet, you can notice some of the entries display the number 268435456 as FileSystemRights. This number is nothing but the Full Controll permission. (Powershell can't resolve following special permissions: Modify, Delete, FullControl -> -1610612736, –536805376, and 268435456).

Read NTFS File Permissions with filter in PowerShell:

You can filter files in the provider's format or language. The value of this parameter qualifies the Path parameter. The syntax of the filter, including the use of wildcards, depends on the provider. The following script get permissions of all the files under the directory C:\Windows.
Get-Acl C:\Windows\*.* | FL
The following script read permissions of all the log files under the directory C:\Windows.
Get-Acl C:\Windows\*.log | FT
The following script read permissions of all the files from the directory C:\Share and its sub-directory by recursively. The where filter $_.PsIsContainer -eq $false excludes the folders and list only files.
Get-ChildItem "C:\Share" -recurse |  where {$_.PsIsContainer -eq $false} | Get-Acl | FT

Read NTFS Folder Level Permissions in PowerShell:

The following PowerShell command read all the sub folders from C:\Share by recursively and list the permissions of the sub folders. The where filter $_.PsIsContainer -eq $true excludes the files and list only folders.
Get-ChildItem "C:\Share" -recurse | where {$_.PsIsContainer -eq $true} | Get-Acl | FT

Export Folder Permissions to CSV with PowerShell:

The following PowerShell script will export all NTFS Folder permissions to a CSV file. Change the $RootPath variable to your own root folder path that you want to export permissions . You can also change the name and location of the CSV file by modifying the $CSV_File_Path variable.
$CSV_File_Path = "C:\Permissions.csv"
$Header = "Folder Path,Identity Name,Access,IsInherited,InheritanceFlags,PropagationFlags"

If (Test-Path $CSV_File_Path){
 Remove-Item $CSV_File_Path
}

Add-Content -Value $Header -Path $CSV_File_Path 

$RootPath = "C:\Share"

$Folders = Dir $RootPath -recurse | where {$_.PsIsContainer -eq $true}

foreach ($Folder in $Folders){
 $ACLs = get-acl $Folder.fullname | ForEach-Object { $_.Access  }
 foreach ($ACL in $ACLs){
 $permission = $Folder.Fullname + "," + $ACL.IdentityReference  + "," + $ACL.AccessControlType + "," + $ACL.IsInherited + "," + $ACL.InheritanceFlags + "," + $ACL.PropagationFlags
 Add-Content -Value $permission -Path $CSV_File_Path
 }}

Concatenate string and Int in SQL server

In this article, I am going to write t-sql query to concatenate two strings and concatenate string and Int in SQL server.
You can concatenate or combine two or more string values using + operator in SQL Server. The + operator returns a string that is the result of concatenating two or more string values.
Declare @str1 varchar(50) ='hello'
Declare @str2 varchar(50) ='world'
SELECT (@str1+' '+@str2) as Result
You can also concatenate two different data type values using + operator. But you need to convert the all the values into single data type before concatenate the values.

Concatenate string and Int as string value in SQL server

Declare @str1 varchar(50) ='hello'
Declare @int1 int =10
SELECT (@str1+' '+cast(@int1 as varchar(50))) as Result

Concatenate string and Int as integer value in SQL server

Declare @str1 varchar(50) ='100'
Declare @int1 int =10
SELECT (cast(@str1 as int)+@int1) as Result

Note:

If you are using SQL Server 2012 and later versions, you can concatenate or combine two or more string values using CONCAT function. The CONCAT function returns a string that is the result of concatenating two or more string values.
SELECT CONCAT ( 'Happy ', 'Birthday ', 11, '/', '25' ) AS Result;
You will get below error, if your run this query in older version of SQL Server like SQL Server 2008 r2.
Msg 195, Level 15, State 10, Line 1
'CONCAT' is not a recognized built-in function name.

Tuesday, 10 March 2015

How to Ping a Computer with PowerShell

We can check whether a computer is active or down by using Ping class in Powershell. Ping allows an application to determine whether a remote computer is accessible over the network.

We need create new instance of System.Net.NetworkInformation.Ping to use Send function of ping class. The below command displays the Ping status and IP Address of the computer.
$ping = New-Object System.Net.NetworkInformation.Ping
$ping.Send("Computer-Name")
We can also set a timeout so that our computer doesn’t wait for long time on a server that won’t respond. Let’s add a timeout of a 10 seconds, we will first need to convert this to milliseconds, so that’s 10,000ms.
$ping = New-Object System.Net.NetworkInformation.Ping
$ping.Send("Computer-Name", 10000)
How to Ping a Computer with PowerShell

Ping a Computer by IP Address using PowerShell

: Instead of computer name, you can also give ip address of the computer as input to send ping command.
$ping = New-Object System.Net.NetworkInformation.Ping
$ping.Send("222.68.1.74", 10000)

Trend Micro Improves Enterprise Endpoint Sensor Protection

Trend Micro improves smart protection platform to better prevent, detect, analyze and respond to broad range of threats. Next-generation endpoint sensor and enhanced network threat defense accelerate protection, remediation of targeted attacks. In today's complex and IT-constrained environment, organizations need a complete, systematic approach for thwarting the massive volume of traditional threats, while handling the rise of newer, more sophisticated attacks. At RSA 2014, Trend Micro Incorporated is announcing the latest enhancements to the Trend Micro™ Smart Protection Platform, building upon a set of unified threat defense capabilities that already enable customers to protect their organization against known threats, yet also detect and respond to new targeted attacks, immediately guarding against further intrusion.

The primary improvement to the company's Smart Protection Platform is the new Smart Sensor product, described as "a context-aware endpoint monitoring solution that enables threat investigators to rapidly detect and assess the nature and extent of targeted attacks on endpoints and servers, speeding time to remediation."

The new Smart Sensor works in conjunction with the company's Deep Discovery solution designed to protect against targeted attacks.

Smart Sensor monitors process-level and network communications so security investigators can conduct multi-level "signature-less" analysis using "indicators of compromise" parameters produced by Deep Discovery or other sources of network security intelligence.

Trend Micro said investigators can use Smart Sensor to examine the chain of events associated with a targeted attack across enterprise systems, including endpoints on-premise, at remote locations or in the cloud. These events can include system infiltration, malicious "command and control" incursions and possibly dangerous account activities.

Introduced at the RSA 2014 security conference in San Francisco, Smart Sensor helps investigators "understand actual malware behavior including delivery method, execution, communications and system implications," the Tokyo-based company said.

Other enhancements include a Deep Discovery Email Inspector designed to complement other email security measures and protect against "spear phishing" emails, described by Trend Micro as a common point of entry for the types of targeted attacks now in use. "It uses proven sandboxing and other advanced detection engines to identify malicious attachments or embedded URLs, allowing the customer to analyze the threats and to set automatic policies for email blocking or quarantine," the company said.

Yet another component is Deep Discovery Inspector v3.6, which the company said helps large-scale enterprises improve and extend sandboxing analysis and better investigate threats with better event management (SIEM) integration and a new 4 Gbps model.

"Customers can now create more custom sandbox images, concurrently analyze more files and more rapidly analyze attack details within Deep Discovery or their SIEM systems," Trend Micro said. "In addition, [with] the new 4Gbps model, Deep Discovery Inspector supports broader deployment options to better protect against targeted attacks."

Wednesday, 4 March 2015

Powershell - Change Service Account Username and Password

In Powershell, we can change Windows Service Account username and password using WMI based powershell cmdlet Get-WmiObject and the WMI class Win32_Service. You can even easily change Service account infromation in Remote Computer.

Powershell: Change Service Account username and password

Use below sample powershell script to change service account username and password. Before using this script, change the user credentials and service name with your own values in the script.
# Change service user name and password 
# www.morgantechce.com
#
$UserName = "TestDomain\Morgan"  
$Password = "MyPa55w0rd" 
$Service = "TestService" #Change your own service name
$svc_Obj= Get-WmiObject Win32_Service -filter "name='$service'"
$StopStatus = $svc_Obj.StopService() 
If ($StopStatus.ReturnValue -eq "0") 
    {Write-host "The service '$Service' Stopped successfully"} 
$ChangeStatus = $svc_Obj.change($null,$null,$null,$null,$null,
                      $null, $UserName,$Password,$null,$null,$null)
If ($ChangeStatus.ReturnValue -eq "0")  
    {Write-host "User Name sucessfully for the service '$Service'"} 
$StartStatus = $svc_Obj.StartService() 
If ($ChangeStatus.ReturnValue -eq "0")  
    {Write-host "The service '$Service' Started successfully"} 

Powershell: Change Service user name and password in Remote Server

Use below sample powershell script to change service user name and password from remote computer. Before using this script, change the user credentials, remote server name and service name with your own values in the script.
# Change service username and password in Remote Computer
# www.morgantechspace.com
#
$UserName = "TestDomain\Morgan"  
$Password = "MyPa55w0rd" 
$Service = "TestService" #Change your own service name
$computer = "Your-Remote-PC" #Change your own server/computer name
#Prompt you for user name and password to access remote computer 
$Cred = Get-Credential 
$svc_Obj= Get-WmiObject Win32_Service -ComputerName $computer -filter "name='$service'" -Credential $cred
$StopStatus = $svc_Obj.StopService() 
If ($StopStatus.ReturnValue -eq "0") 
    {Write-host "The service '$Service' Stopped successfully in $computer"} 
$ChangeStatus = $svc_Obj.change($null,$null,$null,$null,$null,
                    $null,$UserName,$Password,$null,$null,$null)
If ($ChangeStatus.ReturnValue -eq "0")  
    {Write-host "User Name sucessfully for the service '$Service' in $computer"} 
$StartStatus = $svc_Obj.StartService() 
If ($ChangeStatus.ReturnValue -eq "0")  
    {Write-host "The service '$Service' Started successfully in $computer"}