Monday, September 19, 2016

Snapshot Report from Multiple VCenter - POWERCLI

<#
.SYNOPSIS
    Report snapshot status in multiple VCenter
.DESCRIPTION
    This script will send mail report with proper format,
    with details of snapshot from multiple VCenter
.NOTES
    File Name  : Get-SnapshotReport.ps1
Author     : Shankar Sahu
Requires   : PowerShell V3 + PowerCLI 5 or above
.HISTORY
    First published : 15.9.2016
Updated         : 19.9.2016 - validated for Verstion 2.
                               - added link references
.LINK
    This script posted to:
       http://scriptchef.blogspot.in/
#>


$htmlfile="D:\script\Status_Report.html"

$svr="10.1.0.4","10.1.0.3"

New-Item -ItemType file $htmlfile -Force

# CSS styling for report format and table - HTML

$htmlcss="<head>
    <title>Snapshot Status Report!</title>
<style>

body {
    width: 600px;
    margin: 40px auto;
    font-family: 'trebuchet MS', 'Lucida sans', Arial;
    font-size: 14px;
    color: #444;
}

table {
    *border-collapse: collapse; /* IE7 and lower */
    border-spacing: 0;
    width: 100%;  
}

.bordered {
    border: solid #ccc 1px;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;
    -webkit-box-shadow: 0 1px 1px #ccc;
    -moz-box-shadow: 0 1px 1px #ccc;
    box-shadow: 0 1px 1px #ccc;      
}

.bordered tr:hover {
    background: #fbf8e9;
    -o-transition: all 0.1s ease-in-out;
    -webkit-transition: all 0.1s ease-in-out;
    -moz-transition: all 0.1s ease-in-out;
    -ms-transition: all 0.1s ease-in-out;
    transition: all 0.1s ease-in-out;  
}  
 
.bordered td, .bordered th {
    border-left: 1px solid #ccc;
    border-top: 1px solid #ccc;
    padding: 10px;
    text-align: left;  
}

.bordered th {
    background-color: #dce9f9;
    background-image: -webkit-gradient(linear, left top, left bottom, from(#ebf3fc), to(#dce9f9));
    background-image: -webkit-linear-gradient(top, #ebf3fc, #dce9f9);
    background-image:    -moz-linear-gradient(top, #ebf3fc, #dce9f9);
    background-image:     -ms-linear-gradient(top, #ebf3fc, #dce9f9);
    background-image:      -o-linear-gradient(top, #ebf3fc, #dce9f9);
    background-image:         linear-gradient(top, #ebf3fc, #dce9f9);
    -webkit-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset;
    -moz-box-shadow:0 1px 0 rgba(255,255,255,.8) inset;
    box-shadow: 0 1px 0 rgba(255,255,255,.8) inset;      
    border-top: none;
    text-shadow: 0 1px 0 rgba(255,255,255,.5);
}

.bordered td:first-child, .bordered th:first-child {
    border-left: none;
}

.bordered th:first-child {
    -moz-border-radius: 6px 0 0 0;
    -webkit-border-radius: 6px 0 0 0;
    border-radius: 6px 0 0 0;
}

.bordered th:last-child {
    -moz-border-radius: 0 6px 0 0;
    -webkit-border-radius: 0 6px 0 0;
    border-radius: 0 6px 0 0;
}

.bordered th:only-child{
    -moz-border-radius: 6px 6px 0 0;
    -webkit-border-radius: 6px 6px 0 0;
    border-radius: 6px 6px 0 0;
}

.bordered tr:last-child td:first-child {
    -moz-border-radius: 0 0 0 6px;
    -webkit-border-radius: 0 0 0 6px;
    border-radius: 0 0 0 6px;
}

.bordered tr:last-child td:last-child {
    -moz-border-radius: 0 0 6px 0;
    -webkit-border-radius: 0 0 6px 0;
    border-radius: 0 0 6px 0;
}
</style>
</head>
"
$counter=0
$date = ( get-date ).ToString('yyyy/MM/dd')
Function Header($File)
{

Add-content $File "<html>"
    Add-content $File $htmlcss
    Add-content $File "<body><h2>Snapshot Status Report</h2>"
    Add-content $File "<table class='bordered'>"
    Add-content $File " <thead>"
    Add-content $File "<tr>"
    Add-content $File "<th>VM</th>      
        <th>Name</th>
        <th>vCENTER</th>
        <th>Created_Date</th>
<th>SizeGB</th>
        <th>Description</th>
        </tr>
        </thead>"
}
Function Footer($File)
{
Add-Content $File "</table>"
Add-Content $File "</body>"
Add-Content $File "</html>"
}
Header $htmlfile
Function Connect($server)
{
      # $user=Read-Host -Prompt "Username"
      # $pass=Read-Host -Prompt "Password" -AsSecureString
      # $usercred=new-object system.management.automation.pscredential ($user,$pass)
      # Connect-VIserver -Server $server -credential $usercred
      # uncomment if you want to run it with different credential
      Connect-VIserver -Server $server   # Use vCenter admin credential to run script
}

Function Disconnect($svr)
{
Disconnect-VIServer $svr -Force -Confirm:$false
Write-host "Host is Disconnected"
}


foreach($s in $svr){
Connect($s)
Write-Host "=======VCenter:$s========"
   
        $Machine=Get-VM -Name * -Server $s | Get-snapshot | Select-object VM,Name,Created,Description,SizeGB -ErrorAction ignore
        foreach($info in $Machine){
                Add-Content $htmlfile "<tr>"
Add-Content $htmlfile "<td>$($info.VM)</td>"    
Add-Content $htmlfile "<td>$($info.Name)</td>"
Add-Content $htmlfile "<td>$($s)</td>"
Add-Content $htmlfile "<td>$($info.Created_Date)</td>"
                $size=[math]::round($($info.SizeGB),2)
Add-Content $htmlfile "<td>$($Size)</td>"
Add-Content $htmlfile "<td>$($info.Description)</td>"
Add-Content $htmlfile "</tr>"
            }
            Disconnect($s)
        }
Footer $htmlfile

Function Mailme
{
param($from,$to,$subject,$smtp,$flname)
$body = Get-Content $flname
$smtp= New-Object System.Net.Mail.SmtpClient $smtp
$msg = New-Object System.Net.Mail.MailMessage $from, $to, $subject, $body
$msg.isBodyhtml = $true
$smtp.send($msg)
}
Mailme adbadmin@shanky.com adbgroup@shanky.com "Snapshot Service Status - $Date" 10.1.0.67 $htmlfile

Sunday, August 14, 2016

Customising your Shell


One of the problems with having multiple command shells open at the same time is figuring out which window does what. After all, they all look the same, right Well, not necessarily. You can use a few handly tricks to make different windows more distinguishable.

:: Change the background and foreground colours.
:: Change the Windows size
:: Change the windows title

Adding colour to your world

You can easily change the background and foreground colors to suit your
preference. For example, you can change the background color to magenta
and the foreground color (the color the text is displayed in) to blue by typing
these commands at the PSH prompt.

$Host.UI.RawUI.BackgroundColor=”magenta”
$Host.UI.RawUI.ForegroundColor=”blue”






$Host is a special variable that is a reference to the current console object.

You assign the appropriate color to the UI.RawUI.BackgroundColor and UI.RawUI.ForegroundColor properties of the console object.

Getting size-specific with your windows

The $Host.UI.RawUI object is actually pretty useful. You can query or manipulate additional properties through this object to affect the console’s appearance besides the foreground and background colors. You can change the window size, the buffer size, and even change the window’s title. (The following section covers how to change the title.)

The buffer size is the width and height of the window retained in memory where as the window size is the portion of the buffer that’s visible. Because of this, the only real constraint is that your window size must be smaller than your buffer size. (PSH won’t let you screw this up even if you try.) The buffer height is important because it controls essentially how far back you can scroll in your window as you run more and more commands. The default buffer height is 3,000, which means the buffer keeps up to 3,000 lines of output before it starts to discard older entries.
You change the window or buffer size by changing the value of either the BufferSize or WindowSize property of $Host.UI.RawUI. If you want to find out the current value, run the following PSH commands:
$Host.UI.RawUI.BufferSize
$Host.UI.RawUI.WindowSize

The output of either command is the width and height displayed in a tabular format. Now, you might be tempted to try something like this to change the window size:
$Host.UI.RawUI.WindowSize.Width = 110
$Host.UI.RawUI.WindowSize.Height = 40

Although PSH doesn’t complain, the window size doesn’t change, and if you query the value of WindowSize again, you’ll find that the old values are still there. The correct way to change WindowSize is by assigning a new value to this property directly. Because WindowSize is an object, you need to somehow create an object of that type, set its width and height properties, then assign this new value to WindowSize. You can change the window size by using the following command sequence:
$size = $Host.UI.RawUI.WindowSize
$size.Width = 100
$size.Height = 25
$Host.UI.RawUI.WindowSize = $size

Here I store the value of WindowSize in a variable called $size. I don’t really care so much about what the current value is, but I need to have an object that’s the same data type as WindowSize so I can make the change.
Now that I have such an object, I assign my new width and height values to it and then reassign this entire object back to WindowSize. If you want to change the buffer size, simply replace WindowSize with BufferSize.

Window and buffer width and height dimensions aren’t measured in pixels —
rather, width is measured by the number of characters that fit on one row, and height refers to the number of rows it can accommodate.

Reference - CookBook Powershell

Saturday, July 9, 2016

Powershell for VMware - Part II

On part two for PowerCLI cmdlets for handling virtual machine for VMware environment. We will start with some task and command associated with it. It will help to clear your basic handling for virtual machine and you can test some of cmdlets from below on your environment. 

Listing VMs, Hosts, Datastores, And Resource Pools.(Beginner)
Task
Solution
Connect to Virtual Center
Get-VC 10.0.0.2
Obtain a list of all VMs
Get-VM
Obtain a list of all Hosts
Get-VMHost
Obtain a list of all Datastores
Get-Datastore
Obtain a list of all Resource Pools
Get-Resourcepool

Creating a VM.
Task
Solution
Create a VM called “MyFirst_VM” on ESX1. Give the VM 256 MB of RAM and 1GB of disk
Get-VMHost ESX1 | New-VM  -Name ”MyFirst_VM”  -Memorymb 256 –diskmb 1024 –pool  (Get-resourcepool sales-esx1) –location (Get-folder sales)
Create a VM called “MySecond_VM” on ESX2. Give the VM 2 CPUs, and configure it to host Windows 2008 as the guest operating system.
Get-VMHost ESX2 | New-VM –Name “MySecond_VM” –Memorymb 1024 –diskmb 2048 –guestif Win2008ServGuest –pool  (Get-Resourcepool sales-esx2) –location (Get-folder sales)

Basic VM Modification
Task
Solution
Change the number of virtual CPUs configured for “Sales1” from 1 to 2
Get-VM “Sales1”  | Set-VM –numcpu 2
Change the amount of RAM configured for “Sales1” from 256mb to 1024mb
Get-VM “Sales1” | Set-VM –memorymb 1024
Verify that your modifications were successful
Get-VM “Sales1”

Powering VMs ON & OFF
Task
Solution
Determine the power status of all available VMs
Get-VM |ft name,powerstate
Power on the “Server1” virtual machine
Get-VM  “Server1”| Start-VM
Reset the “Server1” virtual machine
Get-VM “Server1” | Stop-VM
Suspend the “Server1” virtual machine
Get-VM “Server1” | Suspend-VM
Resume the “Server1” virtual machine
Get-VM “Server1” | Start-VM
Power off the “Server1” virtual machine
Get-VM “Server1” | Stop-VM


Sunday, July 3, 2016

Powershell for VMware - Part I


Powershell is an interactive command-line interpreter, much like the familiar DOS prompt, or the shell environment in UNIX.

What really sets Powershell apart from other command-line environments is that applications are being  built with Powershell manageability expressly in mind, which means that in the Windows world. Powershell will become increasingly important for managing large numbers of servers and applications.

You can use powershell for managing VMware environments, handling large virtual machines is very tideous task for administrators.

PowerCLI is a Windows PowerShell interface for managing VMware vSphere.

VMware describes PowerCLI as "a powerful command-line tool that lets you automate all aspects of vSphere management, including network, storage, VM, guest OS and more. PowerCLI is distributed as a Windows PowerShell snapin, and includes over 370 PowerShell cmdlets for managing and automating vSphere and vCloud, along with documentation and samples.

In this blog, I will cover some cmdlets

1. Connect-VIServer: To connect to any vSphere connect, you need to use connect-viserver.
    Example: Connect-VIServer -server 10.0.0.2 -User Shanky\admin
    This examples connects to you shell to VI server at 10.0.0.2. You can mention username and               password

2. Get-VIServer: Before you can do any VMware management from
    PowerShell you must first connect to a VC server or ESX host.
    Example: Get-VIServer 10.0.0.2
    This example connected machine is VI server at 10.0.0.2 . In order to complete the
    connection you will be asked for a user name and password.

3. Get-VM: This VMware cmdlet retrieves managed virtual machines.
    Example: Get-VM | select name, memorymb
    This example: displays all VMs in the virtual infrastructure, along with the
    amount of memory allotted to the VM.

4. Get-VMHost: This VMware cmdlet retrieves VM hosts (
    Example: Get-VMHost | select name
    This example creates custom report about all VM hosts that are available in the
    virtual infrastructure.

Friday, July 1, 2016

Creating Users On Windows Server 2012 Using PowerShell


        Scripting user creation in Windows Server is something we’ve long done using LDIF files; however, when building a system that creates users in more of a one-off capacity it’s pretty easy to script the creation process using PowerShell, piping information in from other solutions. To create a user, use the New-ADUser cmdlet.

         I’ve found that we usually need to populate this with a few pieces of information, including the account name (SamAccountName), the password (AccountPassword), the full name (name) enabling the account (enabled), setting the password not to expire (PasswordNeverExpires) and forcing the user to change their password when they log on (ChangePasswordAtLogon). Respectively, the following example would create user cedge with a password of mypassword, a name of Charles Edge, enabling the account, allowing the password to expire and forcing me to change my password the first time I log in:
New-ADUser -SamAccountName cedge -AccountPassword (read-host "Set user password" -mypassword) -name "Shankar Sahu" -enabled $true -PasswordNeverExpires $false -ChangePasswordAtLogon $true

        Once created, the account likely needs to be made a member of some groups. At this point, we’ll need to identify the user by cn (so if the user is in a specific OU, that would need to be included in the -Identity parameter. Because namespace collisions can happen, you’ll need to provide the full CN of both the user (using the Identity parameter) and the group (using the MemberOf parameter). Let’s say I’m going to add that account that I just created, which is in Users of krypted.com to the Enterprise Admins group of the same domain, that would look like this:
Add-ADPrincipalGroupMembership -Identity "CN=Mumbai BR,CN=Users,DC=Shanky,DC=com" -MemberOf "CN=Enterprise Admins,CN=Users,DC=Shanky,DC=com","CN=Domain Admins,CN=Users,DC=Shanky,DC=com"

Overall, it’s pretty easy to call these cmdlets from other scripts, so for example, if you wanted to build a system that allowed an HR professional to enter a username and password for a user then create their account in AD, Google Apps and a few other solutions, this would make for the first step, piping that account name and password into each.


Monday, June 27, 2016

Scheduling Job using Powershell


Sometime we need some job or trigger to execute at specific time. We can trigger this by using powershell cmdlets. With new version of Powershell, we get cmdlets for scheduling triggers at time required. Job scheduling allows you to schedule execution of a windows powershell background job for a later time. First thing you do is create a job trigger. This defines when the job will execute.

You need to import PSScheduledJob first then associated cmdlets would be available.

You can import module by command
Import-Module PSScheduledJob

and check associated cmdlets by

Get-Command -Module *PSScheduled*

For creating job, you need to use New-JobTrigger(trigger) cmdlet and need to register the job with specific schedule and command.

$Newtrig=New-JobTrigger -Daily -At 7PM   # This is new trigger which we can use while registering Job

Register-ScheduledJob -Name Copyfile -trigger $Newtrig -ScriptBlock {Copy-Item D:\Shanky\ "\\10.89.0.9\Shanky\Daily" -Recurse}

Once the trigger has fired and the job has run, You can work with it the same way you do with regular background jobs.

Get-Job -Name Copyfile | Receive-Job

You can start a scheduled job manually, rather than waiting for the trigger to fire:

Start-job -DefinitionName Copyfile

Other cmdlets available from PSScheduledJob

Friday, June 17, 2016

DHCP Scope Monitoring



Previously we have face many issue with client on able to get IP because of DHCP scope gets full. We can take help of new DHCP module to monitor all scope on DHCP server and provides us mail.

Below Script will monitor all scopes in DHCP server using Get-DhcpServerv4ScopeStatistics and will mail to your email address. You can set your threshold on variable $threshold, which I have set it to 90.

Script can be scheduled for every 15 minutes or 30 minutes according to your preferences and critical scope.

Import-Module DHCP

$threshold = 90
$email_to = "admin_group@shanky.com”
$email_from = “Monitoring@shanky.com”
$email_server = “10.1.36.9”
$scopes = Get-DhcpServerv4ScopeStatistics

foreach ($scope in $scopes) {
    if($scope.PercentageInUse -gt $threshold){
        $email_body = “Scope: $($scope.ScopeId) – pool IPs in use is $([math]::round($scope.PercentageInUse, 0))% on $(hostname)”
        Send-MailMessage -To $email_to -From $email_from -SmtpServer $email_server -Subject “Scope threshold exceeded – $($scope.ScopeId)” -Body $email_body
    }
}



Saturday, June 11, 2016

History / Version of Powershell

PowerShell 1.0

PowerShell 1.0 was released in November 2006 for Windows XP SP2, Windows Server 2003 and Windows Vista. It is an optional component of Windows Server 2008.

PowerShell 2.0

Windows PowerShell ISE v2.0, an integrated development environment for PowerShell scripts
PowerShell 2.0 is integrated with Windows 7 and Windows Server 2008 R2 and is released for Windows XP with Service Pack 3, Windows Server 2003 with Service Pack 2, and Windows Vista with Service Pack 1.

PowerShell V2 includes changes to the scripting language and hosting API, in addition to including more than 240 new cmdlets.

New features of PowerShell 2.0 include:


  • PowerShell Remoting: Using WS-Management, PowerShell 2.0 allows scripts and cmdlets to be invoked on a remote machine or a large set of remote machines.
  • Background Jobs: Also called a PSJob, it allows a command sequence (script) or pipeline to be invoked asynchronously. Jobs can be run on the local machine or on multiple remote machines. An interactive cmdlet in a PSJob blocks the execution of the job until user input is provided.
  • Transactions: Enable cmdlet and developers can perform transactional operations. PowerShell 2.0 includes transaction cmdlets for starting, committing, and rolling back a PSTransaction as well as features to manage and direct the transaction to the participating cmdlet and provider operations. The PowerShell Registry provider supports transactions.
  • ScriptCmdlets: These are cmdlets written using the PowerShell scripting language. The preferred name for script cmdlets is now Advanced Functions.[citation needed]
  • SteppablePipelines: This allows the user to control when the BeginProcessing(), ProcessRecord() and EndProcessing() functions of a cmdlet are called.
  • Modules: This allows script developers and administrators to organize and partition PowerShell scripts in self-contained, reusable units. Code from a module executes in its own self-contained context and does not affect the state outside the module. Modules can define a restricted runspace environment by using a script. They have a persistent state as well as public and private members.
  • Data Language: A domain-specific subset of the PowerShell scripting language that allows data definitions to be decoupled from the scripts and allows localized string resources to be imported into the script at runtime (Script Internationalization).
  • Script Debugging: It allows breakpoints to be set in a PowerShell script or function. Breakpoints can be set on lines, line & columns, commands and read or write access of variables. It includes a set of cmdlets to control the breakpoints via script.
  • Eventing: This feature allows listening, forwarding, and acting on management and system events. Eventing allows PowerShell hosts to be notified about state changes to their managed entities. It also enables PowerShell scripts to subscribe to ObjectEvents, PSEvents, and WmiEvents and process them synchronously and asynchronously.
  • Windows PowerShell Integrated Scripting Environment (ISE): PowerShell 2.0 includes a GUI-based PowerShell host that provides integrated debugger, syntax highlighting, tab completion and up to 8 PowerShell Unicode-enabled consoles (Runspaces) in a tabbed UI, as well as the ability to run only the selected parts in a script.
  • Network File Transfer: Native support for prioritized, throttled, and asynchronous transfer of files between machines using the Background Intelligent Transfer Service (BITS).
  • New Cmdlets: Including Out-GridView, which displays tabular data in the WPF GridView object.
  • New Operators: -Split, -Join, and Splatting (@) operators.
  • Exception Handling with Try-Catch-Finally: Unlike other .NET languages, this allows multiple exception types for a single catch block.
  • Nestable Here-Strings: PowerShell Here-Strings have been improved and can now nest.
  • Block Comments: PowerShell 2.0 supports block comments using <# and #> as delimiters.
  • New APIs: The new APIs range from handing more control over the PowerShell parser and runtime to the host, to creating and managing collection of Runspaces (RunspacePools) as well as the ability to create Restricted Runspaces which only allow a configured subset of PowerShell to be invoked. The new APIs also support participation in a Windows PowerShell managed transaction.


PowerShell 3.0

PowerShell 3.0 is integrated with Windows 8 and with Windows Server 2012. Microsoft has also made PowerShell 3.0 available for Windows 7 with Service Pack 1, for Windows Server 2008 with Service Pack 1, and for Windows Server 2008 R2 with Service Pack 1.

PowerShell 3.0 is part of a larger package, Windows Management Framework 3.0 (WMF3), which also contains the WinRM service to support remoting. Microsoft made several Community Technology Preview releases of WMF3. An early community technology preview 2 (CTP 2) version of Windows Management Framework 3.0 was released on 2 December 2011. Since then, updated versions have been shipped in the Windows 8 and Server 2012 beta and release candidate versions.[citation needed]

New features in PowerShell 3.0 include:


  • Scheduled jobs: Jobs can be scheduled to run on a preset time and date.
  • Session connectivity: Sessions can be disconnected and reconnected. Remote sessions have become more tolerant of temporary network failures.
  • Improved code writing: Code completion (IntelliSense) and snippets are added. PowerShell ISE allows users to use dialog boxes to fill in parameters for PowerShell cmdlets.
  • Delegation support: Administrative tasks can be delegated to users who do not have permissions for that type of task, without granting them perpetual additional permissions.
  • Help update: Help documentations can be updated via Update-Help command.
  • Automatic module detection: Modules are loaded implicitly whenever a command from that module is invoked. Code completion works for unloaded modules as well.
  • New commands: Dozens of new modules were added, including functionality to manage disks, volumes, firewalls, network connections and printer management, previously performed via WMI.[further explanation needed]


PowerShell 4.0

PowerShell 4.0 is integrated with Windows 8.1 and with Windows Server 2012 R2. Microsoft has also made PowerShell 4.0 available for Windows 7 SP1, Windows Server 2008 R2 SP1 and Windows Server 2012.

New features in PowerShell 4.0 include:

  • Desired State Configuration: Declarative language extensions and tools that enable the deployment and management of configuration data for systems using the DMTF management standards and WS-Management Protocol.
  • New Default Execution Policy: On Windows Servers, the default execution Policy is now RemoteSigned
  • Save-Help: Help can now be saved for modules that are installed on remote computers.
  • Enhanced debugging: The debugger now supports debugging workflows, remote script execution and preserving debugging sessions across PowerShell session reconnections.
  • -PipelineVariable switch: A new ubiquitous parameter to expose the current pipeline object as a variable for programming purposes.
  • Network diagnostics to manage physical and Hyper-V's virtualized network switches.
  • Where and ForEach method syntax provides an alternate method of filtering and iterating over objects.

PowerShell 5.0

An initial public preview of PowerShell 5.0 was made available with Windows Management Framework 5.0 (WMF5) on April 3, 2014. Key features include OneGet PowerShell cmdlets to support Chocolatey's repository-based package management and extending support for switch management to layer 2 network switches.

On November 18, 2014, Microsoft released the November 2014 Preview of the Windows Management Framework Core 5.0 package. Improvements were made to Desired State Configuration (DSC), OneGet, PowerShellGet, PowerShell class definitions, and debugging for PowerShell background jobs and PowerShell runspaces in remote processes. On August 31, 2015, Microsoft released a further preview of its Windows Management Framework (WMF) 5.0 solution billed as "production ready", and which will be fully supported until 90 days after WMF 5.0 RTM.

PowerShell 5.0 was released to web on December 16, 2015, only to be retracted on December 23, because of an unresolved bug. Once the bug was fixed, PowerShell 5.0 was re-released 70 days later on February 24, 2016.

New features in PowerShell 5.0 include:


  • PowerShell class definitions (properties, methods)
  • PowerShell .NET Enumerations
  • Debugging for PowerShell Runspaces in remote processes
  • Debugging for PowerShell Background Jobs
  • Desired State Configuration (DSC) Local Configuration Manager (LCM) version 2.0
  • DSC partial configurations
  • DSC Local Configuration Manager meta-configurations
  • Authoring of DSC resources using PowerShell classes

Reference - Wiki

Powershell CMDLETS for DHCP



DHCP is very important technology in any organisational infrastructure. Many administrators finds very difficultly in managing DHCP and DHCP scopes in large farm.
There are many commands for managing DHCP which are used by administrators and networks guys, but still there is no willing results which can be retrieved from this commands.

Like "netsh dhcp server show scope"

We need DHCP cmdlet to be available in order to manage DHCP. By default, the DHCP module is not loaded in Powershell. We need to install and import the DHCP module before we can use it.

It is available from Windows server 2012 and windows server 2012R2 onwards.

Before you use any DHCP cmdlets, you need to import DHCP module

Import-Module DhcpServer

Note - You have to install DHCP role with management tools, to get this module on system. It can be also installed by PS command for Adding Windows Featured

Add-WindowsFeature -Name DHCP -IncludeManagementTools

The following new DHP PowerShell cmdlets have been introduced in Windows Server 2012 R2:

Add-DhcpServerSecurityGroup : Adds security groups to a DHCP server.
Add-DhcpServerv4MulticastExclusionRange: Adds a range of addresses to exclude from a multicast scope.
Add-DhcpServerv4MulticastScope: Adds a multicast scope on the DHCP server.
Get-DhcpServerDnsCredential: Gets an account that the DHCP Server service uses to register or deregister client records on a DNS server.
Get-DhcpServerv4MulticastExclusionRange: Retrieves the exclusion range for a specified multicast scope.
Get-DhcpServerv4MulticastLease: Retrieves multicast leases for a specified scope name.
Get-DhcpServerv4MulticastScope: Gets multicast scope objects.
Get-DhcpServerv4MulticastScopeStatistics: Gets multicast scope statistics.
Get-DhcpServerv4SuperscopeStatistics: Returns statistics for superscopes.
Remove-DhcpServerDnsCredential: Removes the credential that the DHCP Server service uses to register or deregister client records on a DNS server.
Remove-DhcpServerv4MulticastExclusionRange: Removes a range of addresses previously excluded from a multicast scope.
Remove-DhcpServerv4MulticastLease: Removes one or more multicast scope leases for a specified multicast scope or IP address.
Remove-DhcpServerv4MulticastScope: Removes multicast scopes.
Rename-DhcpServerv4Superscope: Renames a superscope.
Repair-DhcpServerv4IPRecord: Reconciles inconsistent lease records in the DHCP database.
Set-DhcpServerDnsCredential: Sets credentials that the DHCP Server service uses to register or deregister client records on a DNS server.
Set-DhcpServerv4MulticastScope: Modifies the properties of a multicast scope.


There are many things which you can achieve using this cmdlets

@@@@ Get list of all DHCP scopes on a DHCP server

Get-DhcpServerv4Scope -ComputerName Server1 | fl
Get-DhcpServerv4Scope -ComputerName Server1,Server2 | Select-Object Scopeid,Name,State,StartRanage, EndRange
# Will give you specific details on DHCP scope details from remote server named Server1 and Server2

@@@@ Adding new scope using ADD-DhcpServerv4Scope
Add-DHCPServerv4Scope -Name Test_Scope -StartRange 192.168.100.50 -EndRange 192.168.100.100 -SubnetMask 255.255.255.0

@@@@ Count DHCP Server in environment
(Get-Command -Module DHCPServer).count

@@@@ To authorize a new DHCP server in Active Directory Domain
Add-DhcpServerInDC -DnsName Script.Chef.com -IPAddress 10.9.0.78

@@@@ Configuring multiple scope in DHCP server

$Scopes = Get-Content -Path C:\Scopes.csv    #Reading Scopes from txt file

$DnsServer=10.9.0.7,10.990.8,10.9.0.0
$Domain=Shanky.chef.com
$Router=10.9.0.1

Foreach($Scope in $Scopes)
{
Set-DHCPServerv4OptionValue -ComputerName DhcpSrv1 -ScopeId $Scope -DnsServer $DnsServer -DnsDomain $Domain -Router $Router
}


@@@@ Create a reservation for a client with the IP-address 10.44.1.88:

Get-DhcpServerv4Lease -ComputerName DhcpSvr1 -IPAddress 10.44.1.88 | Add-DhcpServerv4Reservation -ComputerName DhcpSvr1

You can perform a mass reservation of IP-addresses for computers listed in a CSV file. To do it, create a text file in the following format:

ScopeId,IPAddress,Name,ClientId,Description

10.44.1.0,10.44.1.88,Client1,b3-ac-5c-fd-9e-6f,Reservation DhcpSvr1

10.44.1.0,10.44.1.89,Client2,b3-ac-5c-fd-9e-3f,Reservation DhcpSvr1

Save this file as c:\dhcp\DHCP_Reservations.csv and run the next command that imports the data from the CSV file and creates reservations for the clients:

Import-Csv –Path c:\dhcp\DHCP_Reservations.csv | Add-DhcpServerv4Reservation -ComputerName DhcpSvr2


@@@@ You can get DHCP server statistics (the number of scopes and reservations, the percentage of used addresses, etc.).

Get-DhcpServerv4Statistics -ComputerName DhcpSvr1

Wednesday, June 8, 2016

DNS Scripts - Powershell


This script just gets and displays host details returned by GetHostByName.

     $hostInfo = [system.net.Dns]::GetHostByName("www.google.com");
     $hostinfo | fl * -force














This script just gets IP address of remote computer

Demonstrates use of the GetHostIP method of System.Net.DNS Class

param (
[string] $HostName = "localhost"
)

###
# Start of Script
###

#Get Host details

$hostentrydetails = [System.Net.Dns]::GetHostEntry($hostname)

# Print details:
"Host Name    : {0}" -f $hostentrydetails.HostName
foreach ($alias in $hostentrydetails.alises) {
"Alias        : {0}" -f $alias
}
foreach ($addr in $hostentrydetails.addresslist) {
"Address      : {0}" -f $Addr.ipaddresstostring
}







There is another way to get DNS host Entries,

###
# Start of Script
###

# Convert $hostaddres to IPaddress class. 

# Create one for next call
$HostIp = [System.Net.IPAddress]::Parse("127.0.0.1")
if (! ([system.Net.IPAddress]::TryParse($hostaddress, [ref] $HostIP))) {"Not valid IP address"; return}

# Get Host info
$hostentrydetails = [System.Net.Dns]::GetHostEntry($HostIP)

# Print details:
"Host Name    : {0}" -f $hostentrydetails.HostName
foreach ($alias in $hostentrydetails.alises) {
"Alias        : {0}" -f $alias
}
foreach ($addr in $hostentrydetails.addresslist) {
"Address      : {0}" -f $Addr.ipaddresstostring
}

# End of script


Get System Environment value of remote computer - Powershell Script


<#
.SYNOPSIS
    This script demonstrates the use of System.Environment
.DESCRIPTION
    This script Uses a variety of the members of System.Environment and is
    a re-write of a MSDN Sample Script
.EXAMPLE
    PSH [C:\foo]: .\Get-System.Environment.ps1' foo1 foo2 foo3
    My system drive is C: and my system root is C:\Windows

.PARAMETER
    None, but if any are provided, they are displayed above
#>

##
# Start of Script
##

# Setup two variables for later use
[String] $str;
[string] $nl = [System.Environment]::NewLine

# Now display members of the environment class
"-- Environment members --"
#  Assume: You Invoke this sample with an arbitrary set of command line arguments.
"CommandLine       : {0}"   -f [system.environment]::CommandLine
$arguments = [System.Environment]::GetCommandLineArgs()
"GetCommandLineArgs: {0}"   -f [system.string]::join(", ", $arguments)
#  <-- Keep this information secure! -->
"CurrentDirectory  : {0}"   -f [System.Environment]::CurrentDirectory
"ExitCode          : {0}"   -f [System.Environment]::ExitCode
"HasShutdownStarted: {0}"   -f [System.Environment]::HasShutdownStarted
#  <-- Keep this information secure! -->
"MachineName       : {0}"   -f [System.Environment]::MachineName
"NewLine           : {0}  first line{0}  second line{0}  third line" -f [System.Environment]::NewLine
"OSVersion         : {0}"   -f [System.Environment]::OSVersion.ToString()
"StackTrace        : '{0}'" -f [System.Environment]::StackTrace
#  <-- Keep this information secure! -->
"SystemDirectory   : {0}"    -f [System.Environment]::SystemDirectory
"TickCount         : {0}"    -f [System.Environment]::TickCount
#  <-- Keep this information secure! -->
"UserDomainName    : {0}"    -f [System.Environment]::UserDomainName
"UserInteractive   : {0}"    -f [System.Environment]::UserInteractive
#  <-- Keep this information secure! -->
"UserName          : {0}"    -f [System.Environment]::UserName
"Version           : {0}"    -f [System.Environment]::Version.ToString()
"WorkingSet        : {0}"    -f [System.Environment]::WorkingSet
#  No example for exit(exitCode) because doing so would terminate this example.
#  <-- Keep this information secure! -->
$query = "My system drive is %SystemDrive% and my system root is %SystemRoot%";
$str = [System.Environment]::ExpandEnvironmentVariables($query)
"ExpandEnvironmentVariables: {0}  {1}" -f $nl,$str
"GetEnvironmentVariable: {0}  My temporary directory is {1}." -f $nl,[System.Environment]::GetEnvironmentVariable("TEMP")
""
"GetEnvironmentVariables: "
[System.Environment]::GetEnvironmentVariables()
"GetFolderPath: {0}" -f [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::System)
[String[]] $drives = [System.Environment]::GetLogicalDrives()
"GetLogicalDrives: {0}" -f [System.String]::Join(", ", $drives)
#End of Script

Reference - MSDN Gallery

Fix File Name - Powershell Script


<#
.SYNOPSIS
    Defines a function to remove 'invalid' characters
    from a file name
.DESCRIPTION
    Some programs do not like certain 'invalid' characters
    in a file name used by that application. The function
    takes a look at each the file name and replaces some invalid
    characters with '-'.

    This function takes a file name and 'fixes' it and returns
    the 'fixed' file name. Needless to say the characters to match
    and what to replace them with is an application specific decision!
.NOTES
    Requires   : PowerShell Version 3.0
.EXAMPLE
    Psh> .\Fix-FileName.ps1
    File name was: 123{}{{{|[\]
    Fixed name is: 123--------
#>


Function Fix-FileName {
[CMdletbinding()]
Param (
$fn = $(throw 'no file name specified - returning')
)

Switch -Regex ($fn) {
  "}"  { $fn = $fn -replace '{','-'  }
  "}"  { $fn = $fn -replace '}','-'  }
  "\]" { $fn = $fn -replace ']','-'  }
  "\[" { $fn = $fn -replace '\[','-' }
  "\\" { $fn = $fn -replace '\\','-' }
  "\|" { $fn = $fn -replace '\|','-' }
}
$fn
}

$fn = "123{}{{{|[\]"
$fnf = Fix-FileName $fn
"File name was: $fn"
"Fixed name is: $fnf"


Reference - pshscripts.blogspot.com

Sunday, June 5, 2016

PS command for AD user management - one liners

1#How to check Powershell Version?
$host.Version.Major
OR
$psversiontable
OR
:::::::::Microsoft Powershell:::::::
Get-Host | Select-Object Version

2#How to find Users from an OU using ADSI?
$test =
[adsi] "LDAP://localhost:389/ou=test,dc=contoso,dc=COM"
$searcher = [adsisearcher] $test
$searcher.Filter = '(objectClass=User)'
$searcher.FindAll()
3#All AD Users All attrs.
Get-ADUser -F * -PR * | Export-Csv Usersreports.csv -NoTypeInformation

4#How to find Locked out accounts?
search-adaccount -u -l | ft name,lastlogondate -auto

4A#To unlock an account
Unlock-ADAccount -Identity Shanky

5#Finding the Lockout Events
#Windows 2008
Get-EventLog -log Security | ? EventID -EQ 4740
#Windows 2003
Get-EventLog -log Security | ? EventID -EQ 644

6#Find some specific attributes for an OU users
get-aduser -f * -Searchbase "ou=powershell,dc=contoso,dc=com" -pr SamAccountName,PasswordExpired,whenChanged,UserPrincipalName

7#Find some specific attributes using input file
get-content c:\users.txt | get-aduser -pr SamAccountName,PasswordExpired,whenChanged,UserPrincipalName

8#How to reset the passwords for some specific users
get-content c:\users.txt | get-aduser | Set-ADAccountPassword -NewPassword (ConvertTo-SecureString -AsPlainText monster@me123 -Force)

9#How to update the manager field for bulk users?
get-content c:\users.txt | get-aduser | Set-ADUser -Manager "shanky"

10#How to update "ProfilePath","homeDrive" & "HomeDirectory" based on a input file?
Get-Content users.txt | ForEach-Object {
  Set-ADUser -Identity $_ -ProfilePath "\\WIN-85IOGS94Q68\profile\$_" -homedrive "Y:" -homedirectory "\\WIN-85IOGS94Q68\netshare\$_"
}

11#Find Users exist in AD or Not?
$users = get-content c:\users.txt
foreach ($user in $users) {
$User = Get-ADUser -Filter {(samaccountname -eq $user)}
If ($user -eq $Null) {"User does not exist in AD ($user)" }
Else {"User found in AD ($user)"}
}

12#Find users are enabled and have E-Mail and Homedirectory and PasswordExpired -eq false)}
PS C:\> Get-ADUser -Filter {(enabled -eq $true) -and (EmailAddress -like "*") -and (Homedirectory -like "*") -and (PasswordExpired -eq $false)}

13#Also finding the Groupmembership.
PS C:\>  Get-ADUser -Filter {(enabled -eq $true) -and (EmailAddress -like "*") -and (Homedirectory -like "*") -and
(PasswordExpired -eq $false) -and (MemberOf -eq "CN=rock2,OU=win7,DC=Jaihanuman,DC=net")}

14#ProtectedFromAccidentalDeletion for all the users
Get-ADObject -filter {(ObjectClass -eq "user")} | Set-ADObject -ProtectedFromAccidentalDeletion:$true

15# How to find the users property using ADSI.
$users1=[ADSI]"LDAP://cn=copy,cn=users,dc=contoso,dc=com"
$users1 | select *

16#search-adaccount (Accounts Disable,inactive)
search-adaccount (Accounts Disable,inactive)
search-adaccount -u -accountd -searchb "ou=test,dc=contoso,dc=com"
search-adaccount -u -accountd
search-adaccount -u -accounti -t "90"
search-adaccount -u -accounti -da "28 feb 2013"

17# Enable Bulk AD user accounts based on a  input file
Cat c:\users.txt | get-aduser | Enable-ADAccount

18# Disabled Bulk AD user accounts based on a  input file
Cat c:\users.txt | get-aduser | Disable-ADAccount


::::::::Quest Powershell:::::::::
1#Find the Disabled members from multiple GROUPS.
Get-Content c:\groups.txt | ForEach-Object {
  Get-QADGroupMember $_ -Disabled
}
2#Find the E-MAILs of Users form an particular OU
get-QADuser -SearchRoot 'contoso.com/test' | select samaccountname,mail



Reference - Miscrosoft Technet

Friday, May 20, 2016

Get Symantec Version from Registry - Remote machines

# to read registry and output Symantec version
# you can also use this script to get any registry from machines

$HKLM = 2147483650 #HKEY_LOCAL_MACHINE
# Attribute declaration 
$SERVERS = get-content "C:\temp\Hosts.txt"
# place your machines IP or names on this file
foreach($Serv in $SERVERS)
{
         $reg = [wmiclass]'\\'+$Serv+'\root\default:StdRegprov'
         $key = "SOFTWARE\Symantec\Symantec Endpoint Protection\CurrentVersion" | Select                   productversion"
        $value = "productversion"



       
        $reg.GetStringValue($HKLM, $key, $value)  
## REG_SZ
}

Sunday, May 15, 2016

Working with VBScript Variable


Description
Most modern programming languages use the concept of variables, items that are used as placeholders or storage for values and information, VBScript is no different.
Naming Restrictions
VBScript enforces some standard rules that apply to variable names:
  • They must begin with an alpha character (A...Z)
  • The must be less than 256 characters in length
  • They can not contain embedded periods (".")
  • They are case sensitive (i.e. "String", "STRING" and "string" all refer to different variables)
  • Must be unique in the scope in which it is declared
Variable Types
Since not all data is the same VBScript includes a range of variable types for storing different types of data. The table below summarizes the types available.
Subtype
Boolean ==> Contains either True or False
Byte ==> Contains integer in the range 0 to 255
Currency ==> Floating-point number in the range -922,337,203,685,477.5808 to 922,337,203,685,477.5807
Date(Time) ==> Contains a number that represents a date between January 1, 100 to December 31, 9999
Double ==> Contains a double-precision, floating-point number in the range -1.79769313486232E308 to -4.94065645841247E-324 for negative values; 4.94065645841247E-324 to 1.79769313486232E308 for positive values
Empty ==> Uninitialized Variant
Error ==> Contains an error number used with runtime errors
Integer ==> Contains integer in the range -32,768 to 32,767
Long ==> Contains integer in the range -2,147,483,648 to 2,147,483,647
Null ==> A variant containing no valid data
Object ==> Contains an object reference
Single ==> Contains a single-precision, floating-point number in the range -3.402823E38 to -1.401298E-45 for negative values; 1.401298E-45 to 3.402823E38 for positive values
String ==> Contains a variable-length string that can be up to approximately 2 billion characters in length

Declaring Variables
VBSCript supports both explicit and implicit variable declarations. To declare a variable explicitly you use the Dim keyworrd, for example:
Dim strVariable
strVariable = "This is a string"

You can also declare multiple variables by separating each variable name with a comma. For example:
Dim name, url, email
You can declare a variable implicitly by simply using its name in a script, without first using the Dim keyword.
Although declaring a variable implicitly may seem simpler it can lead to problems if one or more variables are misspelled. This could lead to unexpected results when the script was run, because the variable names would not be checked to make sure they are valid.
The use of the Option Explicit statement forces all variables to be explicitly declared before use.
Example
Option ExplicitDim strVariable 'declare the variablestrVariable = "This is a string" 'assign a valueWScript.echo strVariable 'display the variable

Saturday, May 14, 2016

Get System Properties of Remote machines from CSV



On error resume Next

Set WshNetwork = WScript.CreateObject("WScript.Network")
strFileName = "C:\" & WshNetwork.ComputerName & "_Software_Details.xls"
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objfso = CreateObject("Scripting.FileSystemObject")
set sf = objfso.OpenTextFile("C:\" & WshNetwork.ComputerName & "_Software_Details.csv",2,True)
Set colSoftware = objWMIService.ExecQuery ("Select * from Win32_Product")'
Set colSettings = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")
'Software Information'
'sf.WriteLine("SOFTWARE LIST")
'sf.WriteLine("=============")
For Each objSoftware in colSoftware
sf.WriteLine(objSoftware.Caption)
Next


Wscript.sleep 30000

Dim objOutl
Set objOutl = CreateObject("Outlook.Application")
Set objMailItem = objOutl.CreateItem(olMailItem)
'comment the next line if you do not want to see the outlook window
objMailItem.Display
strEmailAddr  = "shankar.sahu@tcs.com"
objMailItem.Recipients.Add strEmailAddr
objMailItem.Body = "Details of Machines"
objMailItem.Subject = "Daily Report"
objMailItem.Attachments.Add "C:\" & WshNetwork.ComputerName & "_Software_Details.csv"
'objMailItem.Attachments.Add "C:\" & WshNetwork.ComputerName & "_Hardware_Details.xls"
objMailItem.Send
Set objMailItem = nothing
Set objOutl = nothing

Script to list users of local computer with last logon date/time - sorted



Details - Sometime you need to list of users with last login time to system. It is bit difficult to get with security events/audit. This script will list all users who has logged on system and their last login time. 

Catch - NTUSER.DAT file is created with every profile once user login. Script check modified date of this file and then use bubble sort to arrange it and present.

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' File - Check_User.vbs
' Author - Shankar Sahu
' Date - 09/06/2015
' Description - To Check users of local computer with last logon date/time
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'Option Explicit
'===============================================================
'To check the OS version
'===============================================================

Dim strComputer, objWMIService, objItem,colItems, OSVersion, Shell, OSName, FPath, sysdrive
Set Shell = CreateObject("Wscript.Shell")
sysdrive = Shell.ExpandEnvironmentStrings("%SYSTEMDRIVE%")
strComputer = Shell.ExpandEnvironmentStrings("%computername%")
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_OperatingSystem",,48)
For Each objItem in colItems
OSVersion = Left(objItem.Version,3
'Case to convert number to Name

Select Case OSVersion
Case "6.2"
OSName = "Windows 8"
FPath = sysdrive+"\Users"
Case "6.1"
OSName = "Windows 7"
FPath = sysdrive+"\Users"'WScript.Echo FPath
Case "6.0"
OSName = "Windows 2008"
FPath = sysdrive+"\Users"
Case "5.2"
OSName = "Windows 2003"
FPath = sysdrive+"\Documents and Settings"
Case "5.1"
OSName = "Windows XP"
FPath = sysdrive+"\Documents and Settings"
Case "5.0"
OSName = "Windows 2000"
FPath = sysdrive+"\Documents and Settings"
Case "4.0"
OSName = "Windows NT 4.0" 
FPATH = sysdrive+"\Documents and Settings"
Case Else
OSName = "Newer/Old Version"
FPath = sysdrive+"\Users"
End Select
Next

'===============================================================
'To Find the Recent Modified file in Folders and Sub Folders
'===============================================================
Dim strFolder, objFolder, objFile, dtmDate , objFSO , recentFile, ModifiedDate
Dim strLog, objLog , fc, Fusers , FSOpath , File , ModDate
Dim Day,today, indexi ,index
Dim fordisp

'Iteration Through the Sub Folders
strFolder = FPath
Set recentFile = Nothing

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(strFolder)
Set fc = objFolder.SubFolders 
indexi = 0
For Each Fusers in fc
indexi=indexi+1
Next

Redim arr(indexi,1)
indexy = 0


For Each Fusers in fc
objFolder= FPath & "\" & Fusers.Name
'WScript.Echo ObjFolderSet
objFSO = CreateObject("Scripting.FileSystemObject")
Set FSOpath = objFSO.GetFolder(objFolder)
File = FSOpath + "\NTUSER.DAT"'
WScript.Echo " " & File
If(objFSO.FileExists(File)) then
Set objFile = objFSO.GetFile(File+"")
arr(indexy,0)=objFile.DateLastModified
arr(indexy,1)=Fusers.Name
indexy=indexy+1
End If
Next

'===============================================================
'Sorting 
'===============================================================
'Sorting Multidimensional array in Descending order

Dim i , j , Temp, Temp1
For i=0 to indexi
For j=1 to indexi-1
if arr(i,0) > arr(j,0) then
Temp=arr(j,0)
Temp1=arr(j,1)
arr(j,0)=arr(i,0)
arr(j,1)=arr(i,1)
arr(i,0)=Temp
arr(i,1)=Temp1
End If
Next
Next
j=indexi
For i=0 to indexi-1
Wscript.Echo "OK: The user " & arr(i,1) &" had logged this machine at "& formatDate(arr(i,0)) 
' Displaying Data
j=j-1
Next


'===============================================================
'Custom Sub to check the latest file in the Folders & Sub Folders - Not Used
'===============================================================
Sub EnumFiles(ByVal objParent)
Dim objChild , recentFile 
recentFile=False
For Each objFile in objParent.Files
If not recentFile Then
recentFile = False
ElseIf (objFile.DateLastModified > recentFile.DateLastModified) Then
Set recentFile = True
End If
If not recentFile Then
WScript.Echo recentFile & " " & recentFile.DateLastModified
Else
WScript.Echo recentFile & " " & recentFile.DateLastModified
End If
Next
For Each objChild in objParent.SubFolders
Call EnumFiles(objChild)
Next
End Sub

'===============================================================
'As No built function to customize Date & Time Format
'===============================================================
Public Function formatDate(sDate)
Dim String2, indexNum, sDay, sMonthYear, sMonth, sYear, sHour ,sMinute,sSec
sYear = Year(sDate) 
sMonth = LPad(Month(sDate), "0", 2) 
String2 = FormatDateTime(sDate, vbShortDate)
indexNum = inStr(String2, "/")
'sDay = Left(sDate, indexNum - 1) 
sHour = LPad(Hour(sDate), "0", 2)
sDay = LPad(DatePart("d", sDate), "0", 2) 
sMinute = LPad(Minute(sDate), "0", 2)
sSec = LPad(Second(sDate), "0", 2) 
formatDate = sYear & "-" & sMonth & "-" + sDay + " " & sHour & ":" & sMinute & ":" & sSec 
End Function

Function LPad (str, pad, length)
LPad = String(length - Len(str), pad) & str
End Function

Windows Server 2016 Key Features and License Prospects

If you are planning to move to Windows 2016 and looking for benefits, I have listed down below : Why Windows Server 2016? ·     ...