≡ Menu

In this post, we will discuss how to set or remove the Password Never Expires check box in Active Directory User object properties under the Account tab. Using this script mentioned in this post, you can do it for single or multiple users accounts.

This script relies on Get-ADUser and Set-ADUser cmdlets in ActiveDirectory module. So make sure it is installed before you run this script. Script has two inputs. First one is list of user accounts for which you want to set or remove the password never expires option. The user accounts list can be from a text file with one user account per line or can be passed directly to the parameter as a comma separated values. Second input is what is operation you want to perform, i.e set or remove operation.

Input parameters:

  1. UserAccounts : List of user accounts which you want to set or remove the password never expires operation
  2. SetOption : Enables Password Never Expires option if not already enabled.
  3. RemoveOption : Removes Password Never expires option if enabled

You can look at the example section below to understand how to use this script. The output of the script will clearly indicate the status for each account whether it has enabled it or there are some errors etc.

 

Script : Update-PasswordNeverExpires.ps1


[CmdletBinding()]
param(
    [Parameter(Mandatory=$true)]
    [string[]]$UserAccounts,
    [Parameter(ParameterSetName="set", Mandatory=$true)]
    [switch]$SetOption,
    [Parameter(ParameterSetName="remove", Mandatory=$true)]
    [switch]$RemoveOption
)

foreach($UserAccount in $UserAccounts) {
    try {
        $UserObj = Get-ADUser -Identity $UserAccount -EA Stop -Properties PasswordNeverExpires
        if($UserObj.PasswordNeverExpires) {
            if($RemoveOption) {
                Set-ADUser -Identity $UserAccount -PasswordNeverExpires:$false -EA Stop
                Write-Host "$UserAccount : Successfully removed the password never expires option" -ForegroundColor Green
            } else {
                Write-Host "$UserAccount : Option already enabled" -ForegroundColor Yellow
            }
        } else {
           if($SetOption) {
               Set-ADUser -Identity $UserAccount -PasswordNeverExpires:$true -EA Stop
               Write-Host "$UserAccount : Successfully enabled password never expires option" -ForegroundColor Green
           } else {
               Write-host "$UserAccount : Option already removed" -ForegroundColor Yellow
           }

       }

    } catch {
      Write-host "$UserAccount : Error Occurred. $_" -ForegroundColor Red

}

}

Examples:

Set Password Never expires option for Single User


Update-PasswordNeverExpiresFlag.ps1 -UserAccounts LabUser01 -SetOption

Remove Password Never expires option for Single User


Update-PasswordNeverExpiresFlag.ps1 -UserAccounts LabUser01 -RemoveOption

Set Password Never Expires option for multiple users


$Users = Get-Content c:\temp\users.txt

Update-PasswordNeverExpiresFlag.ps1 -UserAccounts $Users -SetOption

Remove Password Never Expires option for multiple users


$Users = Get-Content c:\temp\users.txt

Update-PasswordNeverExpiresFlag.ps1 -UserAccounts $Users -RemoveOption

As you can see from the screenshots, the output of the script will give you the status of execution.

Hope this helps.

 

{ 0 comments }

Get closest domain controller using PowerShell

Finding nearest domain controller for a given Active Directory domain is very useful when writing scripts using ActiveDirectory PowerShell module in multi-domain/forest environments.

This is because the cmdlets in ActiveDirectory module will by default query the domains controllers that belongs to local machine domain. If you need to query any other domains, then you need to pass the value of domain controller from that domain to -Server parameter of the cmdlet. Some people will use FQDN of the domain and pass it to -Server parameter to query that domain. While it works, it may cause slowness sometimes as you don’t know which DC you are connecting to perform the search or update operation. So, the better way is to query the nearest domain controller in that domain and use it to perform the operation. This way it is easy to debug any search slowness or update issues.

Ok, let us now proceed. You can find nearest domain controller of a domain using Get-ADDomainController cmdlet. This cmdlet has variety of options. We will be focusing on couple of them to get the results we need.

Query the nearest domain controller of current domain

Below code will print the FQDN of the domain which is in your local site. If there is no DC in your local AD site, then it will return one from nearest AD site.


$DC = Get-ADDomainController -Discover

$DCName = $DC.Hostname

write-host $DCName

Query nearest domain controller for other domain


$DC = Get-ADDomainController -Discover -DomainName techibee.local

$DCName = $DC.Hostname

Write-host $DCName

Query the Domain Controller that holds PDC role


$DC = Get-ADDomainController -Discover -Service PrimaryDC

$DCName = $DC.Hostname

Write-host $DCName

Query a writable domain controller if you have RODCs in your domains


$DC = Get-ADDomainController -Discover -Writable

$DCName = $DC.Hostname

Write-host $DCName

Query a domain controller which has at least Windows Server 2008 operating system


$DC = Get-ADDomainController -Discover -MinimumDirectoryServiceVersion Windows2008

$DCName = $DC.Hostname

Write-host $DCName

Once you have the DC details, you can pass it to other cmdlets to query information from it. For example, you can pass it to Get-ADUser cmdlet to query all users whose name starts with labuser.


Get-ADUser -Filter { name -like "lab*"} -Server $DC

Hope this helps. Let me know if you have any other scenario that you want to query DCs.

{ 0 comments }

Convert a string into number using PowerShell

In this post, I will show you how to convert a number in string format to integer. Before we jump further and see how to do it, I want to begin with help you understand why we need to do it. If a number is stored as a string, you can cannot perform addition or any other numeric operations on that variable until you convert it to integer or any other numeric types.

Let us see an example of what I am mean. As you can see from the below screenshot, a number(100) is stored in $string variable. When I perform an addition operation on it expecting the value to increase to 110, but it appended 10 to 100 in string fashion and returning the value of 10010. So, it is necessary to convert to a numeric value before we perform addition.


$string="100"

$string + 10

Converting a string to number is very easy. For this purpose I am using Parse() method in System.Int32 class.


$string = "100"

$numval = [int]::Parse($string)

$numval

$numval.gettype()

$numval + 10

As you can see from the output, the $numval variable is a int32 type and now the addition operation on the value is working as expected.

Hope this helps.

{ 0 comments }

Check if a string contains numbers in it using PowerShell

In this post, we are going to learn how to test if a given variable has numbers in it using PowerShell. There are two scenarios here to cover. First one is checking if the whole value is number and second scenario is checking if part of the value is number and rest are characters or any other symbols.

Let us talk about our first case, checking if given string variable contains a number. Look at the below example. The variable $myvar has a value “123”. Though it is a numeric number, PowerShell sees it as a String.


$myvar = "123"

$myvar -is [int]

$myvar.gettype()

So how do we determine if the value contains the number? Well, here regular expressions comes handy. Since the value is a string type we can use a regex to very if this string value is completely a number or not.


$myvar = "123"

$myvar -match "^\d+$"

As you can see it returned true which means this string contains number only. The regex I used is a very simple one which checks if there are digits in the given string(\d+) and ^,$ at the beginning and ending represents that should start with a number and end with a number. This satisfies all the required rules to figure out if a string value is number or not.

Now, how do we deal with a case where the string is mix of numbers and characters. There is a solution for it. Take the below example.


$myvar = "edf123xyz"

$myvar -match ".*\d+.*"

Here I am using another regex but in a different way. I am checking if the given string has numbers anywhere in the string. This is sufficient enough to very if given string value has numbers in it.

 

Hope this helps.

{ 0 comments }

I have upgraded Safari to v11 couple of days back and ever since I am noticing a strange problem while singing out of Gmail. I see the address that my connection is going to partner.andriod.com and sometimes seeing FORBIDDEN ERROR 403 message.

This experience is weird. I haven’t seen this even when I was using a android Phone. I tried from other browsers on mac like Chrome and Firefox and haven’t experienced this issue. It appears to be happening only from Safari.

I searched over web and many people are reporting about this issue. I suspect that Gmail is treating my safari as Andriod client for reason and redirecting to it? Could be a Safari Update problem? I suspect this at the moment.

I haven’t come across any solution for this problem either from Apple or from Google so far. I will update as soon I see something.

You managed to find a solution for this? Please post in the comments section, I will test and add it to the article for everyone’s benefit.

26-09-2017 Update:

One of my blog reader recommended reporting it to Google. It’s a good idea. The more people reports this issue and the visibility it gets. Apple should own this problem in my opinion, will report it to them and see what they say.

{ 2 comments }

PowerShell: Get unique values from array

This post is about finding unique values from PowerShell array by removing redundant/duplicate items. We will discuss various options available to list the unique values in array and their benefits/downsides.

There are multiple ways to do this.

  1. Get-Unique cmdlet
  2. Select-Object cmdlet
  3. Sort-Object cmdlet (the winner)

Get-Unique

This is the most well known and famous option. It is because of intuitiveness in the name. But many feel it is cumbersome to use and some couldn’t figure out how to use this. This is because Get-Unique cmdlet works by comparing each item in sorted list to the next item to eliminate the duplicates. That means if you plan to use this cmdlet you need to make sure the input list of sorted. Also this cmdlet is case-sensitive. See what happens when I pass array of duplicate items to this to get the unique ones.

As you noticed in the output, it returned everything in the array. It because they differ by case. So you need to convert everything to lowercase/upper case, sort it, and then pass to this cmdlet to get the actual result.

Is there no other easy way? Yes, read on…

Select-Object

Let us see what happens when we pass the same array to select-object cmdlet by specifying -Unique cmdlet.


$letters = @("A","a","b","c","F","c","a","E","d")

$letters | select -unique

As you can see it worked better than Get-Unique but it still failed to match items which are different in case. The -Unique switch of Select-Object looks for duplicate items through out the list to remove them. But it does case sensitive search to do that. So, you need to convert the list to lower or upper case before passing it to select-object to get unique items.

Sort-Object

Looking at the name of the cmdlet, you might wonder whether it will really remove the duplicates. But it does and does better job than other two above. Now let us pass the same array to Sort-Object by specifying the -Unique switch.


$letters = @("A","a","b","c","F","c","a","E","d")

$letters | sort -unique

 

Hurray.. it worked. It searched for duplicate items throughout the list and removed the duplicates irrespective of case. This is what most of the systems need when they want to remove duplicates from array using PowerShell.

 

{ 0 comments }

Telnet using PowerShell

Ever since telnet client is not enabled by default in Windows Server 2008(also in 2012 and 2016), SysAdmins has tough time using telnet command when they need it. In this post, let us see what are the options for us to telnet without using actual telnet.exe

We have two options when there is no telnet.exe command.

  • Using .Net classes to perform the telnet
  • Using Test-NetConnection cmdlet (available from Windows Server 2012 onward)

Using .Net Classes to perform the telnet

The System.Net.Sockets.TCPClient class provides facility to perform telnet operation to remote host on specified port. I have posted about this in past with the title Test Port Connectivity using PowerShell. This article has a function which you can import into your shell and use it to perform the telnet operation.

This method works for all versions of windows operating systems as it is using underlying .Net Module.

Using Test-NetConnection cmdlet

Starting Windows Server 2012, Microsoft has provided a inbuilt function for this purpose. It is called Test-NetConnection. This function can be used to perform telnet, traceroute and many other operations. In this post I will limit the discussion to telnet functionality.

To telnet to a port on remote computer you have to use –ComputerName and –Port parameters of this function. For example, if you want to check if google.com is responding on port 80, then use below command.


Test-NetConnection -ComputerName google.com -Port 80

After completing the execution, it returns an object which will tell you the output of the telnet. The TCPTestSucceeded value will be True if the telnet is successful and will be False if the telnet has failed.

Look at the below screenshots for understanding this.

Telnet Successful:

Telnet Failure:

As mentioned before this works on Windows Server 2012 or above only. If you need same thing for previous versions you need to use the first approach that I mentioned.

Hope this helps.

{ 2 comments }

It is a very common requirement to have just file name extracted from full path while working on your PowerShell scripts. For example, your script received a file full path(c:\abc\xyz\test.txt) and you want to just get the file name from it with or without extension(ex: test or test.txt). In this post how to achieve this.

There are several ways to do this. For example, a programmer with good regex knowledge tend to write a regex to extract the file name. Or you can also use Split-Path cmdlet in PowerShell do this. The approach I am going to share here is based on .Net classes and my favourite approach. I am not against using cmdlets but thing is they also internally use the .Net classes. So why not use them directly?

Get File name from full path.

[System.IO.Path]::GetFileName("C:\abc\xyz\test.txt")

Get File name with extension from full path

[System.IO.Path]::GetFileNameWithoutExtension("C:\abc\xyz\test.txt")

As you can see I am using System.IO.Path classes to perform this work. You can explore the other methods available in these modules and there are many useful functions.

 

{ 4 comments }

Add a file to existing ZIP file using PowerShell

One of the popular posts on this blog about managing ZIP/compressed/Archived Files is reading the contents from ZIP file. Several people asked how to add a file to existing ZIP file using PowerShell which I will cover in this blog post.

We will be using System.IO.Compression.FileSystem Assembly which contains the required classes to open an existing ZIP file and add new files to it. We have used the same assembly to read the contents of the ZIP file. To perform the add operation to existing zip file, we first need to open the ZIP file in Update mode and then add new file using CreateEntryFromFile method in System.IO.Compression.ZipFileExtension class. Don’t worry much about these classes and methods. I mentioned them for your understanding. You can explore further using these classes if you have any other requirements in managing the ZIP files.

Let us jump into the code now.

Code:


[CmdletBinding()]
Param(
[string]$ZIPFileName,
[string]$NewFileToAdd
)

try {
[Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') | Out-Null
$zip = [System.IO.Compression.ZipFile]::Open($ZIPFileName,"Update")
$FileName = [System.IO.Path]::GetFileName($NewFileToAdd)
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip,$NewFileToAdd,$FileName,"Optimal") | Out-Null
$Zip.Dispose()
Write-Host "Successfully added $NewFileToAdd to $ZIPFileName "
} catch {
Write-Warning "Failed to add $NewFileToAdd to $ZIPFileName . Details : $_"

}

Usage:

Now let us see how to use this script. Save the above code into a file(Add-ToZipFile.ps1) or download the script from GitHub(https://github.com/techibee/PowerShell/blob/master/Add-ToZIPFile.ps1) and start using it with below example.

Add c:\test.txt to c:\myzip.zip file


PS C:\> .\Add-ToZIPFile.ps1 -ZIPFileName C:\myzip.zip -NewFileToAdd C:\test.txt

Hope this helps. I will add more examples related to zip files and Powershell in upcoming days.

{ 0 comments }

Get current directory using Python

In today’s post we will see how to find current directory(or working directory) using python. Current directory is nothing but the folder from where your script is running. This is not the path where your py script is located, but we will explore how to find it as well.

Get the path of current working directory

To accomplish this task we will use os module in python. It has a method called getcwd() which will return current working directory. It is that simple. It returns full path(absolute) of the current working directory. If you want just the directory name then either you can split by “/” or use another function called basename from os.path module.

Below is the code that returns both absolute path of the current working directory and its name.


import os

dirpath = os.getcwd()
print("current directory is : " + dirpath)
foldername = os.path.basename(dirpath)
print("Directory name is : " + foldername)

Copy the above code into a file and save it as get_path.py and run it to see the results.

As you can see in the above screen, the script(get_path.py) is stored in python directory. When ran this script from same directory as script it returned the directory name as python. Same script when ran from another directory(Documents) using relative path, it returned the directory name as Documents. So it always returns the current working directory from where your script is triggerred.

Get the path of script file

Now let us see how to get the path of script it self irrespective of from where you are running it. For this purpose we will utilise the special variable called __file__ and pass it to realpath method of os.path module.


import os

dirpath = os.getcwd()
print("current directory is : " + dirpath)
foldername = os.path.basename(dirpath)
print("Directory name is : " + foldername)
scriptpath = os.path.realpath(__file__)
print("Script path is : " + scriptpath)

Copy the above code into a file and execute it to see the results. In the below demonstration, I have executed it from another directory using the relative path and you see that script location is being displayed properly.

As you can see in the screenshot, the script path is being displayed.

Hope this helps and stay tuned for more.

{ 2 comments }