PowerShell – Java2Blog https://java2blog.com A blog on Java, Python and C++ programming languages Tue, 21 Nov 2023 10:35:32 +0000 en-US hourly 1 https://wordpress.org/?v=6.2.9 https://java2blog.com/wp-content/webpc-passthru.php?src=https://java2blog.com/wp-content/uploads/2022/09/cropped-ICON_LOGO_TRANSPARENT-32x32.png&nocache=1 PowerShell – Java2Blog https://java2blog.com 32 32 Get Password Policy for User in Active Directory in PowerShell https://java2blog.com/powershell-get-password-policy-for-user-in-active-directory/?utm_source=rss&utm_medium=rss&utm_campaign=powershell-get-password-policy-for-user-in-active-directory https://java2blog.com/powershell-get-password-policy-for-user-in-active-directory/#respond Sun, 20 Aug 2023 10:41:00 +0000 https://java2blog.com/?p=24709 Using Get-ADDefaultDomainPasswordPolicy Cmdlet

The Get-ADDefaultDomainPasswordPolicy is used to get the default password policy for the specified domain. We can use it differently in different use cases; let’s learn a few of them below.

Use the Get-ADDefaultDomainPasswordPolicy cmdlet with the -Current parameter to get the default password policy for the currently logged-on user in an active directory. Here, the user can be an Administrator or any XYZ name.

Get-ADDefualtDomainPasswordPolicy -Current LoggedOnUser
ComplexityEnabled           : True
DistuniguishedName          : DC=maslab,DC=com
LockoutDuration             : 00:30:00
LockoutObservationWindow    : 00:30:00
LockoutThreshold            : 0
MaxPasswordAge              : 42.00:00:00
MinPasswordAge              : 1.00:00:00
MinPasswordLength           : 7
objectClass                 : {domainDNS}
objectGuid                  : 574e7bd0-a042-45d2-8fdd-00ca4cb0a769
PasswordHistoryCount        : 24
ReversibleEncryptionEnabled : False

Alternatively, we can use the Get-ADDefualtDomainPasswordPolicy cmdlet alone to retrieve the default password policy from the currently logged-on user domain.

Use the Get-ADDefaultDomainPasswordPolicy cmdlet with the -Identity parameter to get the default password policy for the specified domain in an active directory; in our case, it is maslab.com.

Get-ADDefaultDomainPasswordPolicy -Identity maslab.com
ComplexityEnabled           : True
DistuniguishedName          : DC=maslab,DC=com
LockoutDuration             : 00:30:00
LockoutObservationWindow    : 00:30:00
LockoutThreshold            : 0
MaxPasswordAge              : 42.00:00:00
MinPasswordAge              : 1.00:00:00
MinPasswordLength           : 7
objectClass                 : {domainDNS}
objectGuid                  : 574e7bd0-a042-45d2-8fdd-00ca4cb0a769
PasswordHistoryCount        : 24
ReversibleEncryptionEnabled : False

Use Get-ADForest with Get-ADDefaultDomainPasswordPolicy

Use the Get-ADForest cmdlet along with the Get-ADDefaultDomainPasswordPolicy cmdlet to retrieve default password policy objects from all domains in the specified forest.

(Get-ADForest -Current LoggedOnUser).Domains |
ForEach-Object{ 
    Get-ADDefaultDomainPasswordPolicy -Identity $_
}
ComplexityEnabled           : True
DistuniguishedName          : DC=maslab,DC=com
LockoutDuration             : 00:30:00
LockoutObservationWindow    : 00:30:00
LockoutThreshold            : 0
MaxPasswordAge              : 42.00:00:00
MinPasswordAge              : 1.00:00:00
MinPasswordLength           : 7
objectClass                 : {domainDNS}
objectGuid                  : 574e7bd0-a042-45d2-8fdd-00ca4cb0a769
PasswordHistoryCount        : 24
ReversibleEncryptionEnabled : False

First, we used the Get-ADForest cmdlet to retrieve details about a current Active Directory forest using the domain of a currently logged-on user. You might be thinking that how this cmdlet would know about logged-on users. It was because we specified the -Current parameter and set its value to the LoggedOnUser. This cmdlet got the forest object containing the forest name, forest functional level, domain names, etc.

Then, we used the .Domain property to get all domains in the current Active Directory forest, which was then piped to the ForEach-Object cmdlet. The ForEach-Object cmdlet iterated over all the objects. In each iteration, we used the Get-ADDefaultDomainPasswordPolicy cmdlet with the -Identity parameter to get the password policy for the current object ($_).

We got the same output because we have one domain forest (maslab.com) in our case.

Use Get-ADUser with Get-ADDefaultDomainPasswordPolicy

Use the Get-ADUser cmdlet with the Get-ADDefaultDomainPasswordPolicy cmdlet to retrieve the detailed password policy for the specified user in the active directory.

$user_name = "Administrator"
$user = Get-ADUser -Identity $user_name -Properties *
$domain_policy = Get-ADDefaultDomainPasswordPolicy
$password_policy_for_one_user = @{
    "Password Never Expires" = $user.PasswordNeverExpires
    "Password Last Set" = $user.PasswordLastSet
    "Password Expired" = $user.PasswordExpired
    "Minimum Password Length" = $domain_policy.MinPasswordLength
    "Minimum Password Age" = $domain_policy.MinPasswordAge
    "Maximum Password Age" = $domain_policy.MaxPasswordAge
    "Password Complexity" = $domain_policy.ComplexityEnabled
    "Password HistoryCount" = $domain_policy.HistoryLength
    "Lockout Threshold" = $domain_policy.LockoutThreshold
    "Lockout Duration" = $domain_policy.LockoutDuration
}
$password_policy_for_one_user
Name                            Value
----                            -----
"Lockout Duration"              00:30:00
"Password Last Set"             7/16/2023 4:35:46 PM
"Minimum Password Length"       7
"Password Expired"              False
"Password Complexity"           True
"Lockout Threshold"             0
"Minimum Password Age"          1.00:00:00
"Maximum Password Age"          42.00:00:00
"Password History Count"        {}  
"Password Never Expires"        False

First, we initialized the $user_name variable with the Administrator; don’t forget to replace the Administrator with your username. Then, we used the Get-ADUser cmdlet with -Identity parameter to retrieve the user from the active directory and stored it in the $user variable; this $user would have all the properties because we set the -Properties parameter to the wildcard character (*) to retrieve all properties.

Next, we used the Get-ADDefaultDomainPasswordPolicy cmdlet to get the default password policy and assigned it to the $domain_policy variable. After that, we create a HashTable to set the keys with corresponding values. We stored this HashTable in the $password_policy_for_one_user variable to further display it on the PowerShell console.

Do we have any option to use calculated properties to meet the project needs; for instance, if we want to know the password age meaning the time since the last password was changed? Yes, of course! See the following example.

Use the Get-ADUser cmdlet with the Get-ADDefaultDomainPasswordPolicy cmdlet to display calculated properties for the mentioned user in the active directory.

$user_name = "Administrator"
$user = Get-ADUser -Identity $user_name -Properties *
$domain_policy = Get-ADDefaultDomainPasswordPolicy
$password_age = (Get-Date) - $user.PasswordLastSet
$password_age_days = $password_age.TotalDays
$password_policy_for_one_user = @{
    "Password Never Expires" = $user.PasswordNeverExpires
    "Password Last Set" = $user.PasswordLastSet
    "Password Age Days" = $password_age_days
    "Password Expired" = $user.PasswordExpired
    "Minimum Password Length" = $domain_policy.MinPasswordLength
    "Minimum Password Age" = $domain_policy.MinPasswordAge
    "Maximum Password Age" = $domain_policy.MaxPasswordAge
    "Password Complexity" = $domain_policy.ComplexityEnabled
    "Password HistoryCount" = $domain_policy.HistoryLength
    "Lockout Threshold" = $domain_policy.LockoutThreshold
    "Lockout Duration" = $domain_policy.LockoutDuration
}
$password_policy_for_one_user
Name                            Value
----                            -----
"Lockout Duration"              00:30:00
"Password Last Set"             7/16/2023 4:35:46 PM
"Minimum Password Length"       7
"Password Expired"              False
"Password Complexity"           True
"Lockout Threshold"             0
"Password Age Days"             0.293340765600694
"Minimum Password Age"          1.00:00:00
"Maximum Password Age"          42.00:00:00
"Password History Count"        {}  
"Password Never Expires"        False

Using net accounts Command

Use the net accounts command to get password policy details on the local computer.

net accounts
Force user logoff how long after time expires?:     Never
Minimum password age (days):                        1
Maximum password age (days):                        42
Minimum password length:                            7
Length of password history maintained:              24
Lockout threshold:                                  Never
Lockout duration (minutes):                         30
Lockout observation window (minutes):               30
Computer role:                                      PRIMARY
The command completed successfully.

Using Group Policy Management Editor

To use the group policy management editor, follow the given steps:

Step 1: Open group policy management editor.

Step 2: Navigate to the Default Domain Policy. Right-click on it and select Edit.

powershell get password policy for user in active directory - edit group policy management

Step 3: Navigate to the Password Policy as shown in the following screenshot. You will find the password policy on the left hand (see box number 2). Double-click on any property in the box-2 to edit the details (if you want).

powershell get password policy for user in active directory - password policy

That’s all about how to get password policy for user in active directory in PowerShell.

]]>
https://java2blog.com/powershell-get-password-policy-for-user-in-active-directory/feed/ 0
Get Proxy Settings in PowerShell https://java2blog.com/powershell-get-proxy-settings/?utm_source=rss&utm_medium=rss&utm_campaign=powershell-get-proxy-settings https://java2blog.com/powershell-get-proxy-settings/#respond Sun, 20 Aug 2023 10:24:24 +0000 https://java2blog.com/?p=24785 1. Introduction

In environments where internet access is controlled through a proxy, PowerShell scripts often need to be aware of these settings to function correctly. This article will guide you through different methods to get proxy settings using PowerShell, focusing on the proxy address, port, and its operational status.

2. Using Net.WebProxy Class

The Net.WebProxy class from the .NET Framework is a straightforward approach to obtain the system’s default proxy settings.

$proxy = [System.Net.WebProxy]::GetDefaultProxy()
"Address: " + $proxy.Address
"Bypass On Local: " + $proxy.BypassProxyOnLocal

Here,
[System.Net.WebProxy]::GetDefaultProxy(): Retrieves the default proxy settings.
$proxy.Address: Shows the proxy server’s URI.
$proxy.BypassProxyOnLocal: Indicates if local addresses bypass the proxy.

The settings and information obtained through Net.WebProxy are relevant to applications using the .NET framework. They may not reflect proxy configurations used by non-.NET applications or services.

3. Using netsh Command

The netsh (Network Shell) is the command-line tool in Windows, utilized to communicate with different network-related settings.

Let’s use netsh command to get proxy settings:

netsh winhttp show proxy
Current WinHTTP proxy settings:
    Proxy Server(s) : 10.0.0.21:8080
    Bypass List     : (none)

On Windows machines, the above command is useful for checking the current proxy settings and it is beneficial for verifying proxy settings and troubleshooting network connectivity.

The winhttp specified the context for the netsh, which indicates that we desire to work with the Windows HTTP services settings (WinHTTP settings). The show proxy is the particular command within the WinHTTP context, which displays the current proxy settings on the PowerShell console.

After executing this command, we got the current proxy server, port number, and any bypass list that had been configured (see the above output).

It’s important to note that netsh winhttp show proxy does not display the proxy settings configured for a user in their web browser (like Internet Explorer, Chrome, or Firefox). Those settings are user-specific and are stored separately from the WinHTTP settings.

4. Accessing Internet Explorer Proxy Settings

Accessing Internet Explorer Proxy Settings involves querying the Windows Registry to find out the proxy configuration specifically set for Internet Explorer (IE). This approach is based on the fact that many Windows applications, including some older or legacy systems, use the proxy settings defined in Internet Explorer.

Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" | 
Select ProxyEnable, ProxyServer
ProxyEnable         ProxyServer
-----------         -----------
         1          10.0.0.21:8080

The above code got the proxy settings from the Windows registry. How? In this example, we used the Get-ItemProperty cmdlet to get the properties of the specified item. In our case, it was the registry key specified using the -Path parameter.

In the registry key path, the HKCU denotes the HKEY_CURRENT_USER hive in the Windows registry. This registry key contains Internet Settings, particularly the proxy settings for the current user. We piped the output of the Get-ItemProperty cmdlet to the Select cmdlet to choose the ProxyEnable and ProxyServer properties with corresponding values.

The ProxyEnable shows the status of the proxy whether it is enabled or not. If the value of the ProxyEnable property is 1, it meant the proxy is enabled. Whereas, the value of 0 for this property represents that the proxy is not enabled. The ProxyServer property contains the proxy-server related details as Server_IP:Port.

The Select cmdlet is an alias of the Select-Object cmdlet in PowerShell.

5. Using WebRequest Class

This method involves creating a web request to extract proxy settings using WebRequest class.

$request = [System.Net.WebRequest]::Create("http://www.example.com")
$proxy = $request.Proxy
if ($null -ne $proxy) {
    "Proxy URI: " + $proxy.GetProxy($request.RequestUri).ToString()
} else {
    "No proxy"
}

WebRequest: creates an object for a specific URL.
$request.Proxy: Retrieves the proxy used by this request.
GetProxy($request.RequestUri).ToString(): Outputs the proxy’s URI.

6. Using Windows Settings

Navigate to the Windows Settings > Network & Internet > Proxy and see the details about the proxy server; check the following screenshot.

powershell get proxy settings - proxy server details

We can also use chrome://net-internals/#proxy in Google address bar and click Enter.

7. Conclusion

We explored four methods to obtain proxy settings in PowerShell, catering to various network configurations and requirements.

These methods range from using .NET Framework classes, querying the Windows Registry, to executing system commands like netsh. Each technique offers a reliable way to ensure that PowerShell scripts can correctly identify and utilize proxy settings in a networked environment.

]]>
https://java2blog.com/powershell-get-proxy-settings/feed/ 0
Get Memory Usage Percentage in PowerShell https://java2blog.com/powershell-get-memory-usage-percentage/?utm_source=rss&utm_medium=rss&utm_campaign=powershell-get-memory-usage-percentage https://java2blog.com/powershell-get-memory-usage-percentage/#respond Sun, 20 Aug 2023 10:04:42 +0000 https://java2blog.com/?p=24675

We can have multiple use cases for getting memory usage percentages. For example:

  • Getting overall memory usage percentage
  • Getting overall memory usage percentage history
  • Getting memory usage percentage for one/all processes

Let’s learn them one by one.

Overcall Memory Usage Percentage

We can use Get-Counter and Get-WmiObject cmdlets to retrieve the overall memory usage percentage. Let’s explore them below in detail.

Use Get-Counter Cmdlet

Use the Get-Counter cmdlet to get total memory usage in percentage.

$performance_counter = Get-Counter '\Memory\% Committed Bytes In Use'
$usedMemoryPercentage = $performance_counter.CounterSamples[0].CookedValue
Write-Host "Used Memory Percentage: $usedMemoryPercentage%"
Used Memory Percentage: 57.7237514214878%

We used the Get-Counter cmdlet to get the performance counter for the percentage of used memory bytes on the system and stored it in the $performance_counter variable. The counter path '\Memory\% Committed Bytes In Use' specified the memory counter that measured the proportion of committed memory bytes compared to the total physical memory available.

Then, we retrieved the performance counter’s value from $performance_counter and assigned it to the $usedMemoryPercentage variable. Now, how did we get the value of the performance counter? For that, we used the CounterSamples property of the $performance_counter variable, which contained an array of performance counter samples.

Since we intended to retrieve the first counter sample, we used [0] to access it. Then, we used the CookedValue property of the counter sample to get the message usage percentage. Finally, we used the Write-Host to display it on the PowerShell console.

Use Get-WmiObject Cmdlet

Use the Get-WmiObject cmdlet to get the memory usage percentage if you use PowerShell version 3.0 or earlier.

$usedMemory = Get-WmiObject -Class Win32_OperatingSystem
$totalMemory = $usedMemory.TotalVisibleMemorySize
$freeMemory = $usedMemory.FreePhysicalMemory
$usedMemoryPercentage = ($totalMemory - $freeMemory) / $totalMemory * 100
Write-Host "Used Memory Percentage: $usedMemoryPercentage%"
Used Memory Percentage: 54.8795984097428%

We used the Get-WmiObject cmdlet to get details about the OS, particularly the Win32_OperatingSystem, which we specified using -Class parameter. We stored the retrieved details in the $usedMemory variable.

Then, we used the TotalVisibleMemorySize and FreePhysicalMemory properties of the $usedMemory variable to get the visible memory size and free physical memory, respectively. We stored them in two separate variables named $totalMemory and $freeMemory.

After that, we calculated the percentage of the memory usage by subtracting the amount of $freeMemory from the $totalMemory, dividing the output by the $totalMemory, then multiplying it by 100. Finally, we stored this calculated percentage in the $usedMemoryPercentage variable, which we further used with the Write-Host cmdlet to print on the PowerShell console.

Prefer using Get-CimInstance cmdlet if you are using PowerShell version 3.0 or higher because the Get-WmiObject has been superseded by Get-CimInstance since PowerShell 3.0.

$usedMemory = Get-CimInstance -Class Win32_OperatingSystem
$totalMemory = $usedMemory.TotalVisibleMemorySize
$freeMemory = $usedMemory.FreePhysicalMemory
$usedMemoryPercentage = ($totalMemory - $freeMemory) / $totalMemory * 100
Write-Host "Used Memory Percentage: $usedMemoryPercentage%"
Used Memory Percentage: 54.8795984097428%

Until now, we have learned how to get the overall memory usage percentage; what if you only want to know how much memory percentage has been consumed by the current process on your machine? Let’s see how we can do it.

Overcall Memory Usage Percentage History

Use the Get-Counter cmdlet to get the overall memory usage percentage history.

Get-Counter '\Memory\% Committed Bytes In Use' -Continuous -SampleInterval 5
Timestamp                  CounterSamples
---------                  --------------
7/15/2023 11:38:12 AM      \\desktop-nkk10jm\memory\% committed bytes in use :
                           57.3812244593588

7/15/2023 11:38:17 AM      \\desktop-nkk10jm\memory\% committed bytes in use :
                           57.3770478035736

7/15/2023 11:38:22 AM      \\desktop-nkk10jm\memory\% committed bytes in use :
                           57.3751683014853

7/15/2023 11:38:27 AM      \\desktop-nkk10jm\memory\% committed bytes in use :
                           57.3706575337263

We already learned the Get-Counter cmdlet and counter path in the first example code. Here, we set the -SampleInterval parameter to 5 to get performance counter data for the percentage of the committed memory bytes in use, with the sample interval of 5 seconds. However, the -Continous parameter was used to continuously update the data until the user entered Ctrl+C from the keyboard to stop it.

Memory Usage Percentage for One/More Processes

We can use the Get-Process and Get-WmiObject cmdlets to find the memory usage percentage for one or all processes.

Use Get-Process Cmdlet

Use the Get-Process cmdlet to get the memory usage percentage for the current process on the local machine.

$current_process = Get-Process -Id $PID
$usedMemoryPercentage = ($current_process.WorkingSet / (Get-WmiObject -Class Win32_ComputerSystem).TotalPhysicalMemory) * 100
Write-Host "Used Memory Percentage: $usedMemoryPercentage%"
Used Memory Percentage: 0.918036721468859%

We used the Get-Process cmdlet with the -Id parameter to get the information about the current process. We specified the current process using the $PID variable, which contained the process ID (a.k.a PID) of the current PowerShell process.

By setting the -Id with $PID, we got the process details for the current PowerShell session, which we assigned to the $current_process variable.

Then, we calculated the memory usage percentage and assigned it to the $usedMemoryPercentage variable, which was used with Write-Host to display on the console. But how did we calculate the memory usage percentage?

For that, we divided the WorkingSet property of the $current_process object (which contained the amount of memory the process was using) by the TotalPhysicalMemory property of the Win32_ComputerSystem WMI class (which contained the total amount of physical memory installed on the computer), and then multiplying the result by 100.

This way, the above code retrieved the process object of the current process, calculated the memory usage percentage of that process, and then displayed the output on the PowerShell console.

Use Get-WmiObject Cmdlet

Use the Get-WmiObject cmdlet to get the memory usage percentage for all the processes on the local machine.

Get-WmiObject -Class Win32_PerfFormattedData_PerfProc_Process |
Select-Object Name, IDProcess, 
@{Name="Memory Usage %";Expression={($_.WorkingSetPrivate / (Get-WmiObject Win32_ComputerSystem).TotalPhysicalMemory) * 100}}
Name                           IDProcess       Memory Usage %
----                           ---------       --------------
ApplicationFrameHost                8556   0.0132102058275879
CalculatorApp                      15368  0.00387112258683896
CompPkgSrv                         14692  0.00532279355690357
CxMonSvc                            3224   0.0582120058995908
CxUtilSvc                           3248  0.00503245936289065
Greenshot                          10684   0.0124359813102202
HPHotkeyNotification               15640  0.00832291356170376
HotKeyServiceUWP                    3740    0.011323033566504
HxAccounts                         10436   0.0434533510372673
HxOutlook                            480 0.000435501291019383
HxTsr                               5836   0.0515343194372936
Idle                                   0 9.67780646709739E-05
IntelCpHDCPSvc                      1264                    0
IntelCpHeciSvc                      1384  0.00508084839522613
LanWlanWwanSwitchingServiceUWP      3104   0.0180007200288012
Locator                             3504                    0
Memory Compression                  1888     3.33555277694979
MicTray64                           2348  0.00479051420121321
...                                 ...   ...
...                                 ...   ...
...                                 ...   ...

The above code retrieved information about the currently running processes on the machine and calculated the memory usage percentage by each process. How?

First, we used the Get-WmiObject cmdlet with Win32_PerfFormattedData_PerfProc_Process class to get performance counter date for all the processes running on the machine. Note that we used the -Class parameter to specify the Win32_PerfFormattedData_PerfProc_Process class; however, we can also omit this parameter.

Then, we piped the output, produced by the Get-WmiObject, to the Select-Object cmdlet to select the Name, IDProcess, and corresponding memory usage percentage. We calculated the memory percentage by dividing the process’s private working set by the computer’s total physical memory and then multiplying it by 100.

Note that we used a HashTable to create a calculated property named Memory Usage %.

That’s all about how to get memory usage percentage in PowerShell.

]]>
https://java2blog.com/powershell-get-memory-usage-percentage/feed/ 0
Get Fully Qualified Domain Name in PowerShell https://java2blog.com/powershell-get-fully-qualified-domain-name/?utm_source=rss&utm_medium=rss&utm_campaign=powershell-get-fully-qualified-domain-name https://java2blog.com/powershell-get-fully-qualified-domain-name/#respond Sun, 20 Aug 2023 09:39:06 +0000 https://java2blog.com/?p=24684 Using Environment Variable

Use an environment variable to get a fully qualified domain name.

$computer_name = $env:COMPUTERNAME
$fqdn = $env:USERDNSDOMAIN
Write-Output "Fully Qualified Domain Name: $computer_name.$fqdn"
Fully Qualified Domain Name: MAS-DC-01.MASLAB.COM

First, we assigned the value of the environment variable ($evn:COMPUTERNAME) to the $computer_name variable. The environment variable COMPUTERNAME stored the current computer’s name or you can say the current host’s name; both meaning the same.

Then, we assigned the $fqdn variable with the value of the $env:USERDNSDOMAIN environment variable. Here, the USERDNSDOMAIN stored the DNS domain name, which was associated with the current user. This meant it indicated the domain name in which the user account was registered.

Finally, we joined the value of the $computer_name and $fqdn by separating them with a dot. We used the Write-Output cmdlet to display it on the PowerShell console.

Using System.Net.Dns Class

Use the System.Net.Dns class to get a fully qualified domain name.

$host_name = [System.Net.Dns]::GetHostName()
$ip_addresses = [System.Net.Dns]::GetHostAddresses($host_name)
foreach ($current_ip in $ip_addresses) {
    if ($current_ip.AddressFamily -eq 'InterNetwork') {
        $fqdn = [System.Net.Dns]::GetHostEntry($current_ip).HostName
        break
    }
}
Write-Output "Fully Qualified Domain Name: $fqdn"
Fully Qualified Domain Name: MAS-DC-01.maslab.com

The GetHostName() method was called using the Dns class. We used it to retrieve the local machine name, which was further assigned to the $host_name variable.

We used another method called GetHostAddresses(), providing it with the $host_name as a parameter to get an array of all IP addresses associated with the $host_name. We stored this array in the $ip_addresses variable.

Then, we used the foreach loop to loop the $ip_addresses array. In each iteration, we used the if statement with the -eq (equal to) operator to determine whether the address family (AddressFamily) of a current IP address ($current_ip) was equal to the InterNetwork, which resembled the IPv4 addresses.

The GetHostEntry() method, which required the $current_ip parameter to create a System.Net.IPHostEntry object, was utilized if the requirement was met. We used the HostName property of the System.Net.IPHostEntry object to get the FQDN, which was stored in the $fqdn variable. Next, we exit the loop using the break statement.

Why did we exit the for loop? Because we only wanted to use the first IPv4 address to get the FQDN. Lastly, we used the Write-Output cmdlet to print $fqdn on the console.

The following are the one-line solution:

[System.Net.Dns]::GetHostEntry($env:COMPUTERNAME).HostName
#OR
[System.Net.Dns]::GetHostEntry([string]"localhost").HostName
MAS-DC-01.maslab.com
MAS-DC-01.maslab.com

According to the documentation, the GetHostByName() and Resolve() methods are deprecated ..

Using ping Command

Use the ping command to get a fully qualified domain name.

$fqdn= $(ping localhost -n 1)[1].split(" ")[1]
Write-Output "Fully Qualified Domain Name: $fqdn"
Fully Qualified Domain Name: MAS-DC-01.maslab.com

We used the ping command, which is a PowerShell command to get the local computer’s FQDN by pinging the hostname and parsing the result. How did the ping work in the above example? The ping localhost -n 1 was used to ping the local computer once to retrieve the hostname and IP address.

Then, we used the command substitution ($(...)) to capture the output of the ping localhost -n 1 command; however, the [1] got the captured output’s second line containing the hostname. Moreover, we chained the split(" ") method to split this second line into the array of words using a space as a delimiter and retrieved the second word (a hostname) by accessing the 1 index as [1].

We stored the final output in the $fqdn variable, which was further used with the Write-Output cmdlet to print its value on the PowerShell console.

If you do not access the index 1 twice as demonstrated in the above example, you will get more detailed output including the information about packets (sent, received, lost), round trip times (minimum, maximum, average), etc.

Using Get-WmiObject Cmdlet

Use the Get-WmiObject cmdlet to get a fully qualified domain name.

$computer_name = $env:COMPUTERNAME
$wmi_obj = Get-WmiObject -Class Win32_ComputerSystem -Namespace 'root\CIMv2'
$domain_name = $wmi_obj.Domain
Write-Output "Fully Qualified Domain Name: $computer_name.$domain_name"
Fully Qualified Domain Name: MAS-DC-01.maslab.com

We started by using the $env:COMPUTERNAME environment variable to get the computer name of a local machine and saved it in the $computer_name variable. Remember, the $env:COMPUTERNAME contained the current computer’s name.

Then, we used the Get-WmiObject cmdlet to query the Windows Management Instrumentation to get details about a computer system; particularly, we targeted the Win32_ComputerSystem class of root\CIMv2 namespace, which contained different properties about computer’s operating system and hardware. We stored the details in the $wmi_obj variable. Here, the $wmi_obj represented the WMI object.

We specified the Win32_ComputerName class and 'root\CIMv2' namespace using -Class and -NameSpace parameters, respectively.

Further, we used this variable to access the value of its Domain property representing the name of an Active Directory domain to which a computer was joined. The resulting value was stored in the $domain_name variable. Finally, we used the Write-Output cmdlet to print the fully qualified domain name on the PowerShell console.

Alternatively, we can use the alias of the Get-WmiObject cmdlet as demonstrated below:

(gwmi -Class Win32_ComputerSystem).DNSHostName+"."+(gwmi -Class Win32_ComputerSystem).Domain
MAS-DC-01.maslab.com

Here, we used the .DNSHostName and .Domain properties to get the local machine’s computer name and the domain to which the local computer was joined. We concatenated the both using concatenation operator (+) by separating them with a dot (.).

Using Get-CimInstance Cmdlet

Use the Get-CimInstance cmdlet to get a fully qualified domain name. Go ahead with the below solution if you’re using PowerShell 3.0+. Why? As of PowerShell 3.0, the Get-WmiObject has been superseded by Get-CimInstance. Remember, you can use Get-CimInstance on Windows platforms only.

(Get-CimInstance -Class Win32_ComputerSystem).Name+"."+(Get-CimInstance -ClassWin32_ComputerSystem).Domain
MAS-DC-01.maslab.com

This snippet resembles the last example learned in the previous section but we used GetCimInstance cmdlet to retrieve information about the Win32_ComputerSystem class. We used the .Name and .Domain properties to get the name of a local computer and the domain to which this computer was joined.

Using Get-ADComputer Cmdlet

Use the Get-ADComputer cmdlet to get a fully qualified domain name. You must install the Active Directory on your machine to use this cmdlet.

$fqdn = (Get-ADComputer $(hostname)).DNSHostName
Write-Output "Fully Qualified Domain Name: $fqdn"
Fully Qualified Domain Name: MAS-DC-01.maslab.com

The above command retrieved the local computer’s DNS hostname using the Active Directory module. How did it work? We used the hostname command as $(hostname) to get the hostname of a local computer, which was specified as an argument to the Get-ADComputer cmdlet.

Then, the Get-ADComputer cmdlet accessed the information regarding a computer object in the Active Directory. Finally, we used the DNSHostName property to have the DNS hostname of the computer object. We assigned the resulting value to the $fqdn variable to further display it on the console using the Write-Output cmdlet.

Using Registry

Use the registry to get a fully qualified domain name. You can use this solution if you have installed Active Directory on your computer.

$domain_name = (Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters').Domain
$computer_name = $env:COMPUTERNAME
$fqdn = "$computer_name.$domain_name"
Write-Output "Fully Qualified Domain Name: $fqdn"
Fully Qualified Domain Name: MAS-DC-01.maslab.com

We used the Get-ItemProperty cmdlet to access the ‘HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters’ registry key to retrieve its properties. The registry key we used for this code contained network-related configuration settings.

We used the .Domain property to retrieve the domain name of the computer. This domain name is often set in the registry when a computer connects to the Active Directory domain. We stored the value of the .Domain property in the $domain_name variable.

After that, we used the $env:COMPUTERNAME to get the local computer’s name and stored it in the $computer_name variable. Next, we joined the $computer_name and $domain_name by separating them using a dot (.), and assigned the concatenated value to the $fqdn variable, which was further used with Write-Output to display it on the PowerShell console.

That’s all about how to get fully qualified domain name in PowerShell.

]]>
https://java2blog.com/powershell-get-fully-qualified-domain-name/feed/ 0
Loop Through JSON File in PowerShell https://java2blog.com/powershell-loop-through-json-file/?utm_source=rss&utm_medium=rss&utm_campaign=powershell-loop-through-json-file https://java2blog.com/powershell-loop-through-json-file/#respond Sun, 20 Aug 2023 09:07:03 +0000 https://java2blog.com/?p=24668 Using ConvertFrom-Json Cmdlet

We can use the ConvertFrom-Json cmdlet to traverse the JSON file with first and nested-level keys; Let’s explore them below.

Traverse JSON File Containing First-Level Keys

Use ConvertFrom-Json with the foreach loop to traverse the JSON file having first-level keys only.

{
    "name": "John Christoper",
    "age": 40,
    "city": "Washington"
}
$jsonData = Get-Content -Path "./file.json" -Raw | ConvertFrom-Json
foreach ($current_property in $jsonData.PSObject.Properties) {
    Write-Host "$($current_property.Name): $($current_property.Value)"
}
name: John Christoper
age: 40
city: Washington

We used the Get-Content cmdlet to read the contents of a JSON file located at ./file.json path, which we specified using the -Path parameter. The -Raw parameter ensured the file’s entire content was read as a single string before passing to the ConvertFrom-Json cmdlet.

We used the ConvertFrom-Json cmdlet to convert the JSON string into a PowerShell object (PSObject), which we stored in the $jsonData variable. Then, we used the for loop to iterate over all properties in the $jsonData.

How did we retrieve all properties? This expression $json.PSObject.Properties retrieved the properties of the $jsonData object as a collection.

For each property ($current_property), we used $current_property.Name and $current_property.Value to retrieve the current property name and its corresponding value, respectively.

After that, we constructed a string by combining the property name and its value as "$($current_property.Name): $($current_property.Value)" to further display on the PowerShell console using the Write-Host cmdlet.

Let’s take another example, but we will take the key from the user this time; see the following example.

{
    "name": "John Christoper",
    "age": 40,
    "city": "Washington"
}
$jsonData = Get-Content -Path "./file.json" -Raw | ConvertFrom-Json
$key = Read-Host -Prompt "Enter key"

foreach ($record in $jsonData) {
   if ($record |
       Select-Object -ExpandProperty $key -ErrorAction SilentlyContinue){
           Write-Host "$($record.$key)"
    }else{
           Write-Host "The given key was not found."
    }
}
Enter key: name
John Christopher
Enter key: random
The given key was not found.

Again, we used the Get-Content and ConvertFrom-Json to read the JSON file’s content and assign it to the $jsonData variable. After that, we used the Read-Host cmdlet with the -Prompt parameter to prompt the user and enter the desired key. We stored this key in the $key variable.

Next, we used the foreach loop (a.k.a. foreach statement) to iterate over the $jsonData. In each iteration, we piped the $record to the Select-Object cmdlet with the -ExpandProperty parameter to select and expand the property given by the $key.

We set the -ErrorAction to the SilentlyContinue to suppress the error message because we wanted to show our custom message rather than the error generated by the PowerShell.

So, if the $key was present in the JSON file, the Write-Host cmdlet from the if block would be executed to print the corresponding value; otherwise, the else block would be executed to display a message on the console saying the given know not found.

Let’s dive deeper and work with the JSON file with nested keys.

Traverse JSON File Containing First-Level Keys

Use ConvertFrom-Json with the foreach loop to traverse the JSON file having nested keys.

{
    "student1": {
        "name": {
            "firstName": "John",
            "lastName": "Doe"
        },
        "age": 30,
        "Courses": {
            "CS123": "Introduction to Computer Science",
            "DS234": "Introduction to DataScience"
        }
    },
    "student2": {
        "name": {
            "firstName": "Thomas",
            "lastName": "Nelsan"
        },
        "age": 28,
        "Courses": {
            "CS123": "Java Programming",
            "Ph234": "Introduction to Psychology"
        }
    }
}
#Define a function named TraverseJson that takes a JSON object ($json)
#and an optional prefix ($prefix)
function TraverseJson($json, $prefix = '') {

    # Iterate over each property in the JSON object
    foreach ($property in $json.PSObject.Properties) {

        # Get the name and value of the property
        $propertyName = $property.Name
        $propertyValue = $property.Value

        # Check if the property value is a nested object
        if ($propertyValue -is [System.Management.Automation.PSCustomObject]) {

            # Check if it's the first level of keys
            if ($prefix -eq '') {
                # Display the available first-level keys
                Write-Host "First level keys:"
                foreach ($firstLevelKey in $json.PSObject.Properties.Name) {
                    Write-Host "- $firstLevelKey"
                }

                # Prompt the user to choose a first-level key
                $firstLevelKey = Read-Host "Choose a first level key (enter 'exit' to exit)"

                # If 'exit' is entered, return and exit the recursion
                if ($firstLevelKey -eq "exit") {
                    return
                }

                # If the chosen first-level key is valid
                elseif ($json.PSObject.Properties.Name -contains $firstLevelKey) {
                    # Get the available second-level keys for the chosen first-level key
                    $secondLevelKeys = $json.$firstLevelKey.PSObject.Properties.Name
                    Write-Host "Second level keys under '$firstLevelKey':"
                    foreach ($secondLevelKey in $secondLevelKeys) {
                        Write-Host "- $secondLevelKey"
                    }

                    # Prompt the user to choose a second-level key
                    $secondLevelKey = Read-Host "Choose a second level key (enter 'exit' to exit)"

                    # If 'exit' is entered, return and exit the recursion
                    if ($secondLevelKey -eq "exit") {
                        return
                    }

                    # If the chosen second-level key is valid
                    elseif ($secondLevelKeys -contains $secondLevelKey) {
                        # Get the nested value corresponding to the chosen keys
                        $nestedValue = $json.$firstLevelKey.$secondLevelKey
                        Write-Host "Value of '$firstLevelKey.$secondLevelKey': $nestedValue"
                    }

                    else {
                        Write-Host "Invalid second level key. Please try again."
                    }

                    # Recursively call the TraverseJson function with the
                    #nested value and an updated prefix
                    TraverseJson $json.$firstLevelKey.$secondLevelKey ($firstLevelKey + '.' + $secondLevelKey + '.')
                }
                else {
                    Write-Host "Invalid first level key. Please try again."
                }

                # Return to exit the recursion
                return
            }

            # If it's not the first level of keys
            else {
                # Recursively call the TraverseJson function with the
                #nested object and an updated prefix
                TraverseJson $propertyValue ($prefix + $propertyName + '.')
            }
        }

        # If the property value is an ArrayList
        elseif ($propertyValue -is [System.Collections.ArrayList]) {
            # Iterate over each item in the ArrayList
            $index = 0
            foreach ($item in $propertyValue) {
                #Recursively call the TraverseJson function with the item
                #and an updated prefix, including the array index
                TraverseJson $item ($prefix + $propertyName + "[$index].")
                $index++
            }
        }

        # If it's a regular property (not a nested object or ArrayList)
        else {
            # Display the key and value
            Write-Host "${prefix}${propertyName}: ${propertyValue}"
        }
    }
}

#Read the content of the JSON file and convert it to a JSON object
$json = Get-Content -Path "./file.json" -Raw | ConvertFrom-Json

#Call the TraverseJson function with the JSON object
TraverseJson $json
First level keys:
- student1
- student2
Choose a first level key from the options above (or enter 'exit' to exit): student1
Second level keys under 'student1':
- name
- age
- Courses
Choose a second level key from the options above (or enter 'exit' to exit): age
Value of 'student1.age': 30
First level keys:
- student1
- student2
Choose a first level key from the options above (or enter 'exit' to exit): student2
Second level keys under 'student2':
- name
- age
- Courses
Choose a second level key from the options above (or enter 'exit' to exit): Courses
Value of 'student2.Courses': @{CS123=Java Programming; Ph234=Introduction to Psychology}
student2.Courses.CS123: Java Programming
student2.Courses.Ph234: Introduction to Psychology

Don’t be afraid to look at the code; it is very simple and straightforward; Let’s learn it step by step below:

  • First, we defined the TraverseJson function, which took two parameters: $json represented the JSON object, and $prefiex stored the prefix for nested keys. This function recursively traversed the JSON object and displayed the key-value pairs.
  • The TraverseJson function began with the foreach loop, which iterated over the properties of the $json object using $json.PSObject.Properties.
  • Inside the foreach loop, the name and value for every property are assigned to the $propertyName and $propertyValue variables, respectively.
  • Then, the above code checked if the $propertyValue was a nested object using the -is operator and the type [System.Management.Automation.PSCustomObject]. If it was, the code entered the if block.
  • There was an additional check for the $prefix variable within the if block. We were at the first level of keys if it was an empty string. In this case, the code displayed the available first-level keys by iterating over $json.PSObject.Properties.Name and prompted the user to choose a first-level key.
  • If the user entered exit, the function returned and exited the recursion. Otherwise, if the chosen first-level key was valid ($json.PSObject.Properties.Name -contains $firstLevelKey), the code displayed the available second-level keys for the chosen first-level key.
  • The second-level keys were obtained from $json.$firstLevelKey.PSObject.Properties.Name and displayed to the user.
  • The user was prompted to choose a second-level key. If exit was entered, the function returned and exited the recursion. If the chosen second-level key was valid ($secondLevelKeys -contains $secondLevelKey), the code retrieved the corresponding nested value using $json.$firstLevelKey.$secondLevelKey and displayed it.
  • If the chosen second-level key was invalid, an error message was displayed, and the user was prompted to try again.
  • Finally, the TraverseJson function called itself recursively with the selected nested value ($json.$firstLevelKey.$secondLevelKey) and an updated prefix ($firstLevelKey + '.' + $secondLevelKey + '.').
  • If the $prefix was not empty (indicating nested keys), the function recursively called TraverseJson on the nested object ($propertyValue) with an updated prefix ($prefix + $propertyName + '.').
  • If the $propertyValue was an ArrayList, the code entered an elseif block and iterated over each item in the ArrayList using a foreach loop. It recursively called TraverseJson on every item with an updated prefix that included the array index.
  • If the $propertyValue was neither a nested object nor an ArrayList, it entered the else block and displayed the full key path along with the corresponding value using the Write-Host cmdlet.
  • Finally, outside the function, the code read the JSON file content using the Get-Content cmdlet, converted it to a JSON object using ConvertFrom-Json, and called the TraverseJson function with the JSON object.

So, the above code allowed the user to interactively traverse a JSON object, select keys at different levels, and view their corresponding values. This code is limited to second-level keys; you can add value to it to fit your requirements.

What is the importance of using ConvertFrom-Json, which compels us to use it in every above solution? Because PowerShell can’t iterate over the JSON objects directly, we used the ConvertFrom-Json to convert the JSON string to a PSCustomObject, where each property represents a JSON field.

The above solutions will work if you use PowerShell version 3.0+; run the $PSVersionTable.PSVersion to check your PowerShell version. If you are using PowerShell version 2.0 or looking for an alternative, the following solution is for you.

Using JavaScriptSerializer Class

Use the JavaScriptSerializer class to loop through the JSON if you are using PowerShell version 2.0.

Add-Type -AssemblyName System.Web.Extensions
$JS = New-Object System.Web.Script.Serialization.JavaScriptSerializer
$json = @'
[{"id":1,"firstName":"John","lastName":"Doe","age":32},
{"id":2,"firstName":"Thomas","lastName":"Christoper","age":30},{"id":3,"firstName":"Johny","lastName":"Daniel","age":29}]
'@
$data = $JS.DeserializeObject($json)
$data.GetEnumerator() | foreach-Object {
    foreach ($key in $_.Keys){
        Write-Host "$key : $($_[$key])"
    }
}
id : 1
firstName : John
lastName : Doe
age : 32
id : 2
firstName : Thomas
lastName : Christoper
age : 30
id : 3
firstName : Johny
lastName : Daniel
age : 29

First, we used the Add-Type command to load the System.Web.Extensions assembly into the current session. This assembly provides classes for working with JSON data in .NET applications.

Then, we used the New-Object cmdlet to create an object of the JavaScriptSerializer class from the System.Web.Script.Serialization namespace, which we stored in the $JS variable.

After that, we used the DeserializeObject() method of the $JS object. This method took JSON string ($json) as a parameter to deserialize it into the PowerShell object. We stored the resulting object in the $data variable.

Next, we loop through each item in the $data using the GetEnumerator() method and foreach-Object cmdlet. Inside the foreach-Object, we used the foreach loop with the Keys property of the current item to iterate over each key in the current item. We displayed the corresponding key-value pair using the Write-Host cmdlet.

That’s all about how to Loop through JSON File in PowerShell.

]]>
https://java2blog.com/powershell-loop-through-json-file/feed/ 0
Get History of Commands in PowerShell https://java2blog.com/powershell-get-history-of-commands/?utm_source=rss&utm_medium=rss&utm_campaign=powershell-get-history-of-commands https://java2blog.com/powershell-get-history-of-commands/#respond Sun, 20 Aug 2023 08:56:11 +0000 https://java2blog.com/?p=24773 Using Get-History Cmdlet

Using Get-History to get the complete history of the executed commands in PowerShell.

Get-History
Id CommandLine
  -- -----------
   1 Get-History
   2 ls
   3 ping example.com
   4 Get-History
   5 Get-History
   6 Get-Process
   7 Get-Service

In this example, the history of the commands is obtained using the Get-History cmdlet. On execution of the above code, we can see the list of executed commands is returned and displayed on the screen with their respective Id (showing the sequence of the execution of the commands) and the CommandLine (showing the text or command we entered). From the above output, we can see 7 commands were executed in PowerShell.

By default, Get-History does not display all the object properties on execution. To display all the object properties on the console consider the below example:

Get-History | Select-Object -Property *
Id                 : 1
CommandLine        : Get-History
ExecutionStatus    : Completed
StartExecutionTime : 7/19/2023 3:37:00 PM
EndExecutionTime   : 7/19/2023 3:37:00 PM

Id                 : 2
CommandLine        : ls
ExecutionStatus    : Completed
StartExecutionTime : 7/19/2023 3:37:04 PM
EndExecutionTime   : 7/19/2023 3:37:05 PM

Id                 : 3
CommandLine        : ping example.com
ExecutionStatus    : Completed
StartExecutionTime : 7/19/2023 3:37:58 PM
EndExecutionTime   : 7/19/2023 3:38:02 PM

Id                 : 4
CommandLine        : Get-History
ExecutionStatus    : Completed
StartExecutionTime : 7/19/2023 3:38:13 PM
EndExecutionTime   : 7/19/2023 3:38:13 PM

Id                 : 5
CommandLine        : Get-History
ExecutionStatus    : Completed
StartExecutionTime : 7/19/2023 3:52:33 PM
EndExecutionTime   : 7/19/2023 3:52:33 PM

Id                 : 6
CommandLine        : Get-Process
ExecutionStatus    : Completed
StartExecutionTime : 7/19/2023 3:53:13 PM
EndExecutionTime   : 7/19/2023 3:53:14 PM

Id                 : 7
CommandLine        : Get-Service
ExecutionStatus    : Completed
StartExecutionTime : 7/19/2023 3:53:25 PM
StartExecutionTime : 7/19/2023 3:53:25 PM

In this code, the output of Get-History is passed to the Select-Object cmdlet using the pipe operator (|) with the -property * option to get all the object properties on the console. We can observe, the given command returned Id, CommandLine, ExecutionStatus and the duration of the command.

Get Specific Commands from the History

If you want to get the last three executed commands from the history check the below example

Get-History -Count 3
Id CommandLine
  -- -----------
   5 Get-History
   6 Get-Process
   7 Get-Service

In the above example, the -Count option is used with the Get-History cmdlet to get the last 3 executed commands from the history. Consider the below example if you want to get the range of commands.

Note: You can change the value of -Count according to your requirement. For example, if you want to get the list of the last 20 executed commands run set count as -Count 20.

Re-execute Commands from History

If you want to run a specific command again from the history that you have executed. Consider the below example.

Invoke-History -Id 6
Get-Process

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    336      19     9204      24588       0.14  11012   5 ApplicationFrameHost
    624      44    29696       1492       1.11  16968   5 CalculatorApp
    285      19    21348      43392       0.50   2152   5 chrome
    387      24   227000     202836      65.38   2772   5 chrome
    445      23    92284     130664      10.91   3184   5 chrome
    283      19    21556      38792       0.28   3564   5 chrome
    325      22    64852     108200      15.77   6476   5 chrome
    370      24   110008     134700       7.47   7424   5 chrome
    246      16    15172      19488       0.56   7628   5 chrome
   1001      44   152880     139736     172.61   7644   5 chrome
    293      20   101448      71412      10.50   7800   5 chrome
    292      20    39724      62776       1.64   8096   5 chrome
    438      23   139896     165516      48.23   8832   5 chrome
    279      19    21992      41580       0.38   9356   5 chrome

In this code snippet, the Invoke-History cmdlet is used to invoke the History command and execute the command with the given id. In the above case, the command id 6 is executed which is the Get-Process cmdlet. Another way to write the same command is as follows:

!6

In this way, you can re-execute the command from the history using the exclamation mark (!) followed by the command id. On execution of this command, you will get the same output as above.

Save the Command History to a File

If you want to save the history of executed commands for the current session in the form of a CSV file for future use check the following example.

Get-History | Export-CSV -Path 'C:\History\CommandHistory.Csv'

In this PowerShell script, the output of Get-History is passed to the Export-CSV cmdlet as input using the | pipe operator. Here, the -Path option is used to specify the path where we want to save the history commands in the form of CSV.

On execution of the above command, no output is displayed on the screen. However, the list of executed commands is stored at path C:\History\CommandHistory.Csv with all the object properties.

Note: The history of executed commands in the current session is stored in memory by default. Once the PowerShell window is closed the history will be lost. To store the history between sessions by default configure the PowerShell to save the history to a file.

Clear History

Use Clear-History to clear the command history in PowerShell.

Clear-History

By executing the above command the history of the current PowerShell session is removed.

That’s all about how to get history of Commands in PowerShell.

]]>
https://java2blog.com/powershell-get-history-of-commands/feed/ 0
Get Password Expiration Date in PowerShell https://java2blog.com/powershell-get-password-expiration-date/?utm_source=rss&utm_medium=rss&utm_campaign=powershell-get-password-expiration-date https://java2blog.com/powershell-get-password-expiration-date/#respond Tue, 15 Aug 2023 19:04:00 +0000 https://java2blog.com/?p=24764 Using Get-ADUser Cmdlet

Use the Get-ADUser cmdlet to get the password expiration date for one specific user in an Active Directory.

Get-ADUser -Identity Administrator 
–Properties "SamAccountName", "msDS-UserPasswordExpiryTimeComputed" |
Select-Object -Property "SamAccountName",
@{Name="PasswordExpiryDate";Expression={[DateTime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}
SamAccountName      PasswordExpiryDate
--------------      ------------------
Administrator       8/27/2023 4:35:46 PM

The Get-ADUser cmdlet is used to get one or multiple users from an active directory. We used it with the -Identity parameter to only get the Administrator user with SamAccountName and msDS-UserPasswordExpiryTimeComputed properties. We specified these properties using the -Property parameter.

We piped the details (retrieved from the Get-ADUser cmdlet) to the Select-Object cmdlet to select the values of the SamAccountName and PasswordExipryDate properties. Where did the PasswordExpiryDate property come from while we retrieved msDS-UserPasswordExpiryTimeComputed using Get-ADUser?

We used a HashTable to define custom PowerShell object to create a calculated/custom property whose name would be PasswordExpiryDate and the value would be calculated using msDS-UserPasswordExpiryTimeComputed property.

While creating a calculated property, the expression computed the value of the PasswordExpiryDate property. It used the FromFileTime() method of the DateTime class to convert the msDS-UserPasswordExpiryTimeComputed to a DateTime object.

The reason for doing so was to make the output easier to understand. In HashTable, the semicolon was used as a separator. If you don’t want to use it, define Name and Expression on separate lines by hitting Enter from the keyboard.

Use the Get-ADUser cmdlet to get the password expiration date for all users in an Active Directory.

Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} 
–Properties "SamAccountName", "msDS-UserPasswordExpiryTimeComputed" |
Select-Object -Property "SamAccountName",
@{Name="PasswordExpiryDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}
SamAccountName      PasswordExpiryDate
--------------      ------------------
Administrator       8/27/2023 4:35:46 PM

This example resembles the previous one but we got the expiration date for all the users in an active directory using the specified conditions. Here, we used the -Filter parameter to select only those uses whose Enabled and PasswordNeverExpires properties were equal to $True and $False, respectively. We used -eq to determine the equality while -and was a logical AND operator, which makes the conditional expression true if both conditions are true.

In our case, the conditions were only met for the Administrator user, so we got its password expiry date.

Use the following script if you want to export the sorted output to a CSV file.

Get-ADUser -Filter {Enabled -eq $True -and PasswordNeverExpires -eq $False} 
–Properties "SamAccountName", "msDS-UserPasswordExpiryTimeComputed" |
Select-Object -Property "SamAccountName",
@{Name="PasswordExpiryDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}|
Sort-Object "PasswordExpiryDate" | Out-File C:\PasswordExpiryDates.csv
SamAccountName      PasswordExpiryDate
--------------      ------------------
Administrator       8/27/2023 4:35:46 PM

This code snippet is the same as the previous one with two additional cmdlets. We used the Sort-Object cmdlet to sort the received input based on the PasswordExpiryDate and piped it to the Out-File cmdlet, which wrote it into the specified file. In our case, it was PasswordExpiryDates.csv

The Sort-Object by default sorts in ascending order. Use the -Descending parameter to sort in descending order.

Using net user Command

Use the net user command to get the password expiration date in the active directory. Usually, this command is used when you quickly want to retrieve the password expiry date for one particular user.

net user Administrator /domain | find "Password expires"
Password expires        8/27/2023 4:35:46 PM

Let’s take another example below.

net user john.powell /domain | find "Password expires"
Password expires        Never

Do not forget to replace the Administrator and john.powell with your username.

That’s all about get password expiration date in PowerShell.

]]>
https://java2blog.com/powershell-get-password-expiration-date/feed/ 0
Get AD User Home Directory and Home Drive in PowerShell https://java2blog.com/powershell-get-ad-user-home-directory-and-home-drive/?utm_source=rss&utm_medium=rss&utm_campaign=powershell-get-ad-user-home-directory-and-home-drive https://java2blog.com/powershell-get-ad-user-home-directory-and-home-drive/#respond Tue, 15 Aug 2023 18:51:14 +0000 https://java2blog.com/?p=24767 Using Get-ADUser Cmdlet

We use Get-ADUser differently based on various use cases; let’s explore a few of them below.

Get Home Directory & Drive for One User

Use the Get-ADUser cmdlet to get the ad user’s home directory and home drive.

$username = 'Administrator'
Get-ADUser -Identity $username -Properties * |
Select HomeDirectory, HomeDrive
HomeDirectory                                  HomeDrive
-------------                                  ---------
\\mas-dc-01\Users\Administrator\Documents       D:

First, we initialized the $username variable with the Administrator; this was the username for whom we wanted to get the home directory and home drive. Don’t forget to replace it with your username.

Then, we used Get-AdUser cmdlet with -Identity and -Properties parameters to retrieve the specified username’s all properties. As we intended to grab all properties for further processing, we used the * wildcard character, which means all properties.

We piped them to the Select cmdlet (an alias of Select-Object) to select the HomeDirectory and HomeDrive with corresponding values. In our case, we set the HomeDirectory to a network share path; here mas-dc-01 was our computer name and Users\Administrator\Documents was the directory in the C: drive.

We can get network share path by mapping drives; see this article.

Get Home Directory & Drive for All Users

Use the Get-ADUser cmdlet to get a home directory and home drive for all users in an active directory.

Get-ADUser -Filter * -Properties * |
Select HomeDirectory, HomeDrive
HomeDirectory                                  HomeDrive
-------------                                  ---------
\\mas-dc-01\Users\Administrator\Documents       D:

This code fence is similar to the previous example but we set the -Filter parameter to * to get all user’s required properties. We got the same output because we had only one user whose home directory and home drive were set.

Use CN Attribute to Get Home Directory & Drive

Use the Get-ADUser cmdlet to get SAMAccountName, HomeDirectory, and HomeDrive properties using the common name (`CN) attribute in an active directory.

Get-ADUser -Filter * -SearchBase "CN=Administrator,CN=Users,DC=maslab,DC=com" -Properties * |
Select SAMAccountName, HomeDirectory, HomeDrive
SamAccountName      HomeDirectory                                  HomeDrive
--------------      -------------                                  ---------
Administrator       \\mas-dc-01\Users\Administrator\Documents       D:

The above code snippet resembles the previous ones but has two new things: the -SearchBase parameter, and the SAMAccountName property. The SamAccountName denoted the log-on name, while the -SearchBase parameter is used to specify the distinguished name (DN) of a search base for a user search.

Remember, the DN is always a unique identifier for an object in the active directory, which indicated the location of that object in the directory hierarchy. In the above example, we set the -SearchBase parameter to the "CN=Administrator,CN=Users,DC=maslab,DC=com".

It means that the search for user objects would be limited to a container with the DN as "CN=Administrator,CN=Users,DC=maslab,DC=com". In the specified DN, the CN=Administrator component specified the container’s name, whereas the CN=Users,DC=maslab,DC=com denoted the domain components (DCs) of a container’s parent object.

Using the -SearchBase parameter, we limited the scope of the search and improved the performance of the Get-ADUser cmdlet. This parameter is specifically useful when we need to search for the user objects in the large active directory domains with multiple containers and objects.

Can we do the same using the OU attribute? Yes, let’s do it by creating a brand new organizational unit and adding three users to it.

Use OU Attribute to Get Home Directory & Drive

To get a home directory and home drive for all users in an active directory:

  • Use the New-ADOrganizationalUnit cmdlet to create a new organizational unit.
  • Use the New-AdUser cmdlet thrice to create three different users in the newly created OU.
  • Use Get-ADUser cmdlet to get required properties in a particular OU.
New-ADOrganizationalUnit -Name "Test" -Path "DC=maslab,DC=com"

New-ADUser -Name "Sam Bracewell" -AccountPassword (ConvertTo-SecureString "P@ssw0rd123" -AsPlainText -Force) -Path "OU=Test,DC=maslab,DC=com"

New-ADUser -Name "johnwells" -AccountPassword (ConvertTo-SecureString "P@ssw0rd456" -AsPlainText -Force) -Path "OU=Test,DC=maslab,DC=com"

New-ADUser -Name "mary.pearson" -AccountPassword (ConvertTo-SecureString "P@ssw0rd789" -AsPlainText -Force) -Path "OU=Test,DC=maslab,DC=com"

Get-ADUser -Filter * -SearchBase "OU=Test,DC=maslab,DC=com" -Properties * |
Select SAMAccountName, HomeDirectory, HomeDrive
SamAccountName      HomeDirectory                                  HomeDrive
--------------      -------------                                  ---------
mary.pearson        \\mas-dc-01\Mary                                D:
johnwells       \\mas-dc-01\John                                D:
Sam Bracewell           \\mas-dc-01\SamBracewell                            E:

We used the New-ADOrganizationalUnit cmdlet with -Name and -Path parameters to create an active directory organizational unit. Then, we used New-ADUser to create active directory users in the newly created organizational unit (OU). How?

We specified the name and password of the new user account using the -Name and -AccountPassword parameters, while the -Path parameter specified the location of the OU where the new user account would be created. The ConvertTo-SecureString was used to convert the plain text to secure strings; we used this cmdlet while setting the password of the new user account.

Finally, we used the Get-ADUser cmdlet to retrieve all users’ SamAccountName, HomeDirectory, and HomeDrive from the Test organizational unit. Looking for the -SearchBase parameter explanation? We wrote about it in detail in the previous section.

We can also use the Out-File cmdlet as follows to export the output to the specified CSV file; see the following example.

Get-ADUser -Filter * -SearchBase "OU=Test,DC=maslab,DC=com" -Properties * |
Select SAMAccountName, HomeDirectory, HomeDrive | 
Out-File C:\Output.csv
SamAccountName      HomeDirectory                                  HomeDrive
--------------      -------------                                  ---------
mary.pearson        \\mas-dc-01\Mary                                D:
johnwells       \\mas-dc-01\John                                D:
Sam Bracewell           \\mas-dc-01\SamBracewell                            E:

That’s all about get AD USer home directory and home drive in PowerShell.

]]>
https://java2blog.com/powershell-get-ad-user-home-directory-and-home-drive/feed/ 0
Get Mapped Drives for All Users in PowerShell https://java2blog.com/powershell-get-mapped-drives-for-all-users/?utm_source=rss&utm_medium=rss&utm_campaign=powershell-get-mapped-drives-for-all-users https://java2blog.com/powershell-get-mapped-drives-for-all-users/#respond Tue, 15 Aug 2023 18:35:06 +0000 https://java2blog.com/?p=24610 Using net use Command

Use the net use command to get mapped drives for all users in PowerShell.

net use
New connections will be remembered.

Status   Local     Remote                          Network
------------------------------------------------------------------------------
OK       K:        \\DESKTOP-NKK10JM\JavaProject   Microsoft Windows Network
OK       Z:        \\DESKTOP-NKK10JM\Share         Microsoft Windows Network

The command completed successfully.

In the above example, we used the net use command to list all the mapped drives for all users on the local machine. Both drive letters (K: and Z:) were mapped to the same user.

Let’s map another drive to a different user and then execute the net use command again to see if the recently mapped drive is also displayed. See the following example.

net use M: \\DESKTOP-NKK10JM\AnotherFolder
net use
New connections will be remembered.

Status  Local  Remote                           Network
------------------------------------------------------------------------------
OK      K:     \\DESKTOP-NKK10JM\JavaProject    Microsoft Windows Network
OK      M:     \\DESKTOP-NKK10JM\AnotherFolder  Microsoft Windows Network
OK      Z:     \\DESKTOP-NKK10JM\Share          Microsoft Windows Network

The command completed successfully.

First, we specified the drive letter (M:) that we wanted to map the network drive to, followed by the UNC path of the resource that we wanted to share. Remember, we can use any letter to map the network drive; it would be successfully done if it was not already used. Don’t forget to enclose the file share within the quotes if it contains spaces, such as \\DESKTOP-NKK10J\"Another Folder".

If you do not want to struggle with what device to map a drive to, you can use the asterisk for a device (here, device means the drive letter).

net use * \\DESKTOP-NKK10JM\Share
net use
Drive Y: is now connected to \\DESKTOP-NKK10JM\Share.
The command completed successfully.
New connections will be remembered.

Status  Local   Remote                            Network
------------------------------------------------------------------------------
OK      K:      \\DESKTOP-NKK10JM\JavaProject    Microsoft Windows Network
OK      M:      \\DESKTOP-NKK10JM\AnotherFolder  Microsoft Windows Network
OK      Y:      \\DESKTOP-NKK10JM\Share          Microsoft Windows Network
OK      Z:      \\DESKTOP-NKK10JM\Share          Microsoft Windows Network

The command completed successfully.

Using *, we told the Windows to find and map the next available device (drive letter). See the above output; it also informed that the drive Y: was connected to the \\DESKTOP-NKK10JM\Share.

Until now, we used the net use to authenticate the mapped drives as logged-on users. What if we want to authenticate to the shared resource via alternate credentials meaning with a specific username and password? Or what if we’re going to create a device-less connection (No Drive Letter)? Will the net use command be able to retrieve these drives? Let’s find it in the following example.

net use \\DESKTOP-NKK10JM\"Script Files" /u:Domain\Mehvish 12345
net use
New connections will be remembered.

Status  Local   Remote                             Network
------------------------------------------------------------------------------
OK      K:      \\DESKTOP-NKK10JM\JavaProject     Microsoft Windows Network
OK      M:      \\DESKTOP-NKK10JM\AnotherFolder   Microsoft Windows Network
OK      Y:      \\DESKTOP-NKK10JM\Share           Microsoft Windows Network
OK      Z:      \\DESKTOP-NKK10JM\Share           Microsoft Windows Network
OK              \\DESKTOP-NKK10JM\Script Files    Microsoft Windows Network

The command completed successfully.

In the above example, we used the /u parameter to specify the username (Mehvish) followed by the password (12345) for authentication and did not mention the drive letter, but the net use command listed this mapped drive too; hence, the net use can retrieve the mapped drives for all users whether those are device-less or not, or authenticated or not.

We can not only create or view mapped drives for all users but can delete also. Execute the net use /? command to see all the options that can be used with this command.

Is it possible to retrieve certain properties of the mapped drives? Yes, it is; continue with us to explore them below.

Using Get-WmiObject/Get-CimInstace Cmdlets

Use the Get-WmiObject cmdlet to get specific properties for all mapped drives for all users in PowerShell. This solution is preferred if you use any PowerShell version earlier than 3.0.

Get-WmiObject -Class Win32_MappedLogicalDisk |
Select-Object Name, Compressed
Name Compressed
---- ----------
K:        False
M:        False
Y:        False
Z:        False

The Get-WmiObject cmdlet is used to get the instances of WMI (Windows Management Instrumentation) classes or details about the available classes. We used this cmdlet with the Win32_MappedLogicalDisk class to retrieve its instances and access all properties associated with each mapped drive.

These properties include DeviceID, ProviderName, SessionID, FileSystem, Name and Compressed. We specified the Win32_MappedLogicalDis class using the -Class parameter, which we can omit as well, but using this parameter made the code easy to understand.

Then, we piped the output of the Get-WmiObject cmdlet to the Select-Object cmdlet, which is used to select objects or the specified object properties. We used the Select-Object cmdlet to choose each object’s Name and Compressed properties. The Name showed the drive letter while the Compressed displayed Boolean values (True: drive is compressed, False: drive is not compressed).

We can also use the alias of the Get-WmiObject by replacing it with gwmi.

Use the Get-CimInstance cmdlet to get specific properties for all mapped drives for all users in PowerShell. If you are using PowerShell 3.0 or above, you can continue with this solution as an alternative to using the Get-WmiObject cmdlet because the Get-WmiObject has been superseded by the Get-CimInstance cmdlet since PowerShell 3.0.

Get-CimInstance -Class Win32_MappedLogicalDisk |
Select-Object Name, Compressed
Name Compressed
---- ----------
K:        False
M:        False
Y:        False
Z:        False

The Get-CimInstance cmdlet produced the same results as we got in the previous example; this cmdlet retrieves the CIM (Common Information Model) instances of the class from a CIM server. Remember, we can only use the Get-CimInstance cmdlet on Windows platforms.

We got one empty line at the end in the output produced by the Get-WmiObject and Get-CimInstance because these cmdlets did not display any details about the device-less connection that we previously created for the user named Mehvish; see the last example in Use net use Command. These device-less connections are not even visible in File Explorer.

Using Get-SmbMapping Command

Use the Get-SmbMapping cmdlet to get specific properties for all mapped drives for all users in PowerShell.

Get-SmbMapping |
Select-Object LocalPath, RemotePath, Status
LocalPath RemotePath                            Status
--------- ----------                            ------
Z:        \\DESKTOP-NKK10JM\Share                   OK
K:        \\DESKTOP-NKK10JM\JavaProject             OK
M:        \\DESKTOP-NKK10JM\AnotherFolder           OK
Y:        \\DESKTOP-NKK10JM\Share                   OK
          \\DESKTOP-NKK10JM\Script Files  Disconnected

The Get-SmbMapping cmdlet is used to get the Server Message Block (SMB) client directory mappings made for the server. We used this cmdlet to retrieve the list of SMB mappings and their associated properties for each particular mapped drive.

Then, we piped the output of the Get-SmbMapping cmdlet to the Select-Object cmdlet to select the LocalPath, RemotePath, and Status properties for all the mapped drives, including the device-less connection.

In the above output, the LocalPath showed the local path, which was used to map the remote path on this computer (this computer means where you ran the command). The RemotePath displayed the path accessed from this computer. Finally, the Status property indicates whether it is connected. We would see the OK status if it was connected; otherwise, Disconnected.

Mapped drives are not persistent by default; you have to make them persistent if you want; how? Set the /persistent parameter to yes using the net use command. Setting the /persistent:yes ensures the connection stays around even after the reboot.

Another worth noting point is that Windows remember the persistent settings of the last created connection. If you will set /persistent to yes for one connection, all the subsequent connections will be persistent until you set the /persistent to no as /persistent:no.

Wondering how to make all previously created connections persistent? We can use the net use command as net use /persistent:yes to make all connections persistent in the current session.

Can we know the owner who mapped drives for all users? Can we also get the share names? Yes, see the following example.

Get-SmbConnection | 
Select-Object UserName, ShareName
UserName                ShareName
--------                ---------
DESKTOP-NKK10JM\Mehvish AnotherFolder
DESKTOP-NKK10JM\Mehvish JavaProject
DESKTOP-NKK10JM\Mehvish Share

The Get-SmbConnection cmdlet established connections from the SMB client to SMB servers. We used this cmdlet to get the owner’s UserName and the ShareName. Remember, the Share was connected twice, with drive letters Z: and Y:, but it would be listed once in the above example. You can find more about this cmdlet here.

Using Get-PSDrive Cmdlet

Use the Get-PSDrive cmdlet to get mapped drives for all users in PowerShell .

Get-PSDrive  -PSProvider FileSystem
Name  Used (GB)  Free (GB) Provider      Root   CurrentLocation
----  ---------  --------- --------      ----   ---------------
C     35.34      82.59     FileSystem    C:\     Users\Mehvish
D     19.92      468.36    FileSystem    D:\
E     3.82       439.41    FileSystem    E:\
K     3.82       439.41    FileSystem    \\DESKTOP-NKK10JM\JavaProject
M     3.82       439.41    FileSystem    \\DESKTOP-NKK10JM\AnotherFolder
Y     3.82       439.41    FileSystem    \\DESKTOP-NKK10JM\Share
Z     3.82       439.41    FileSystem    \\DESKTOP-NKK10JM\Share

Here, we used the Get-PSDrive to get all drives in the current session provided by the FileSystem, which we specified using the -PSProvider parameter. If we would not specify this parameter, then the Get-PSDrive would retrieve the Windows logical drives, session-specified temporary drives, drives exposed by the PowerShell, and persistent mapped network drives.

Learn the difference between temporary and persistent drives ere.

Let’s look at the following example to understand what we said in the last paragraph clearly.

Get-PSDrive
Name   Used (GB)   Free (GB)   Provider    Root      CurrentLocation
----   ---------   ---------   --------    ----      ---------------
Alias                          Alias
C      35.38       82.56       FileSystem  C:\        Users\Mehvish
Cert                           Certificate \
D      19.92       468.36      FileSystem  D:\
E      3.82        439.41      FileSystem  E:\
Env                            Environment
Function                       Function
HKCU                           Registry    HKEY_CURRENT_USER
HKLM                           Registry    HKEY_LOCAL_MACHINE
K      3.82        439.41      FileSystem  \\DESKTOP-NKK10JM\JavaProject
M      3.82        439.41      FileSystem  \\DESKTOP-NKK10JM\AnotherFolder
Variable                       Variable
WSMan                          WSMan
Y      3.82        439.41      FileSystem   \\DESKTOP-NKK10JM\Share
Z      3.82        439.41      FileSystem   \\DESKTOP-NKK10JM\Share

We explored different solutions; you can choose any based on your project needs.

That’s all about how to get mapped drive for all users in PowerShell.

]]>
https://java2blog.com/powershell-get-mapped-drives-for-all-users/feed/ 0