The Lowercase w

Disabling WiFi Power Management Permanently for Raspberry PI 3 with Raspbian Jessie

Posted by Ben Liebowitz

One problem I found when playing with my Raspberry PI3 (running Raspbian Jessie), is that the WiFi would drop after a certain amount of inactivity.  This was problematic at VMUG Meetings, and due to lack of having a screen to connect, I was forced to power-cycle the unit to get it back online.  After doing some googling, I found the built-in WiFi for the Raspberry PI 3 had some Power Management features, which were enabled by default.

You can check the status by running the follow command:

sudo iwconfig wlan


I found a simple command to disable the power management features, however the command only lasted until the next reboot and then went back to the default setting. The command is below

sudo iwconfig wlan0 power off

After doing some investigating, I came across this blog post on how to run a script at startup.  This enabled me to put the above command into a script and run it at startup!

The steps were simple.

1.  Make sure you’re in the /home/pi directory

2.  Run the command below to create a script :

sudo nano


3.  Enter the command above into the new file.  Don't forget to include the first line though, or it won't run properly.  You also don't need SUDO before iwconfig here, as the script is being run at an elevated level already. :)

#!/bin/sh -
iwconfig wlan0 power off

CTRL-X then Y and Enter will save the file.

4.  Next, we have to create a configuration file (aka a unit file) that tells systemd what we want to do when…

sudo nano /lib/systemd/system/myscript.service


5.  Enter the text below into the text editor

Description=My Script Service




6. The permissions on the unit file need to be set to 644.

sudo chmod 644 /lib/systemd/system/myscript.service

7.  Verify the permissions were set properly.

ls –l /lib/systemd/system/myscript*



8. Now that the unit file has been defined, we can tell systemd to start it during the boot sequence.

sudo systemctl daemon-reload



9. Next.

sudo systemctl enable myscript.service



10. Finally, REBOOT!

sudo reboot



11. Once your PI is back online, login and check the status now…

sudo iwconfig wlan0

2017-02-12 13_28_44-2017-02-12 13_18_32-pi@raspberrypi_ ~.png - Paint




Ben Liebowitz, VCP, vExpert
NJ VMUG Leader




Setting up the Raspberry PI 3 As A VMUG Registration System

Posted by Ben Liebowitz

Sometime in 2016, there were some posts in the VMUG Leader Workspace on by Patrick Stasko (@PatrickStasko), from Cleveland VMUG, about setting up Raspberry PI as a VMUG Registration System.  I was very intrigued and decided to look into doing it for NJ VMUG!

We purchased the following items:

Raspberry PI 3 Model B Motherboard

CanaKit 5V 2.5A Raspberry PI 3 Power Supply/Adapter/Charger

Official Raspberry PI 3 Case – Black/Grey

Addicore Raspberry PI Heatsink Set for B, B+ 2 and 3 (set of 3 Aluminum Heat Sinks)

SanDisk Ultra 64gb MicroSDXC UHS-I Card

Dymo LabelWriter 450 Thermal Label Printer (1752264)

Dymo Compatible 30857 2 1/4in X 4in Name Badge Labels 6 Pack Kenco Label

ASUS C201PA-DS02 11.6 inch Chromebook (1.8ghz Quad Core, 4GB LPDDR3, 16gb SSD), Navy Blue

Logitech Wireless Mouse M325 with Designed-for-web Scrolling – Light Silver

C-Line Pin Style Name Badge Holders with Inserts, 3 x 4 Inches, 100 per Box (94043)

HOOTOO Wireless Travel Router, USB Port, High Performance- TripMate Nano

The total for all these items came to approx. $420.

As it was my first time with the Raspberry PI, I decided to install Raspbian via Noobs (, the automated Operating System Installer for the Raspberry PI.  The easiest way was to insert the MicroUSB card into my PC and copy Noobs to it, then insert it into the Raspberry PI, to install the OS.

Next, I read up on the “pivmugc” project on Github (  I downloaded the binaries and gave the install script a try.  What I found was, only SOME of the apps installed and barely anything was configured properly.  In doing some research, I found the install script hardcodes the Wi-Fi to use the network.  If you’re Wi-Fi router isn’t configured to use, the script will lose network connectivity partway through.  I am using a Hootoo router (see above) and it’s set to as its IP.  I tried to change it a few times and was unsuccessful, so I decided it was easier to just modify the code to switch from as the router to, and change the network info from to

Lines 85 through 91 of the script must be modified.

Here is an excerpt of the original script:

INTERFACES='# interfaces(5) file used by ifup(8) and ifdown(8)\n\n# Please note that this file is written to be used with dhcpcd\n# For static IP, consult /etc/dhcpcd.conf and "man dhcpcd.conf"\n\n# Include files from /etc/network/interfaces.d:\nsource-directory /etc/network/interfaces.d\n\nauto lo\niface lo inet loopback\n\niface eth0 inet manual\n\niface wlan0 inet static\naddress\nnetwork\nnetmask\nbroadcast'
DHCPCD='\n#WLAN0 Configuration\n\ninterface wlan0\nstatic ip_address=\nstatic routers=\nstatic domain_name_servers='
HOSTAPD_CONF='# Basic configuration\ndriver=nl80211\ninterface=wlan0\nssid=pivmugc\nhw_mode=g\nchannel=8\nauth_algs=1\n\n# WPA configuration\nwpa=2\nwpa_passphrase=PIVMUGCPASS\nwpa_key_mgmt=WPA-PSK\nwpa_pairwise=TKIP\nrsn_pairwise=CCMP\nwpa_ptk_rekey=600\nmacaddr_acl=0'
DHCLIENT_CONF='timeout 10;\nlease {\ninterface "eth0";\nfixed-address;\noption subnet-mask;\nrenew 2 2022/1/1 00:00:01;\nrebind 2 2022/1/1 00:00:01;\nexpire 2 2022/1/1 0:00:01;\n}'

Here is my modified script exerpt:

INTERFACES='# interfaces(5) file used by ifup(8) and ifdown(8)\n\n# Please note that this file is written to be used with dhcpcd\n# For static IP, consult /etc/dhcpcd.conf and "man dhcpcd.conf"\n\n# Include files from /etc/network/interfaces.d:\nsource-directory /etc/network/interfaces.d\n\nauto lo\niface lo inet loopback\n\niface eth0 inet manual\n\niface wlan0 inet static\naddress\nnetwork\nnetmask\nbroadcast'
DHCPCD='\n#WLAN0 Configuration\n\ninterface wlan0\nstatic ip_address=\nstatic routers=\nstatic domain_name_servers='
HOSTAPD_CONF='# Basic configuration\ndriver=nl80211\ninterface=wlan0\nssid=pivmugc\nhw_mode=g\nchannel=8\nauth_algs=1\n\n# WPA configuration\nwpa=2\nwpa_passphrase=PIVMUGCPASS\nwpa_key_mgmt=WPA-PSK\nwpa_pairwise=TKIP\nrsn_pairwise=CCMP\nwpa_ptk_rekey=600\nmacaddr_acl=0'
DHCLIENT_CONF='timeout 10;\nlease {\ninterface "eth0";\nfixed-address;\noption subnet-mask;\nrenew 2 2022/1/1 00:00:01;\nrebind 2 2022/1/1 00:00:01;\nexpire 2 2022/1/1 0:00:01;\n}'

Once I made those changes, and reinstalled Rasbian… I was ready to start again with my modified script. This time, it installed everything I wanted it to.  However, I found some of the printer config wasn’t there when I ran CUPS (the Printer Daemon.)  I had to find and install the Dymo SDK for Linux.  (

Once I had the SDK installed, I was then able to make some modifications I found on another site for using a Dymo label printer with CUPS in Linux (

  • Run this to make sure the user "pi" can access CUPS as an admin:  sudo usermod -a -G lpadmin pi
  • Run the following to make sure remote users can make changes to CUPS:  sudo nano /etc/cups/cupsd.conf
    • Change the text to say:
    • # Only listen for connections from the local machine
      # Listen localhost:631
      Port 631
  • Scroll further down in the config file until you see the “location” sections. In the block below, we’ve bolded the lines you need to add to the config:

< Location / >
# Restrict access to the server...
Order allow,deny
Allow @local
< /Location >

< Location /admin >
# Restrict access to the admin pages...
Order allow,deny
Allow @local
< /Location >

< Location /admin/conf >
AuthType Default
Require user @SYSTEM

# Restrict access to the configuration files...
Order allow,deny
Allow @local
< /Location >

  • Restart CUPS by issuing the following:  sudo /etc/init.d/cups restart
  • You should now be able to access the print server on any local computer by typing http://{raspberry pi's IP address}:631

I was then able to go back to the manual install instructions for pivmugc, and make sure my printer was configured to use the proper labels…

Click on "Add Printer"
Click on the printer under "Local Printers"
Press "Continue"
Press "Add Printer"
Change the "Media Size" to "99014 Name Badge Label"
Change the "Output Resolution" to the highest possible.
Change "Print Density" to "Dark"
Change "Print Quality" to "Barcodes and Graphics"
Press "Set Default Options"
Click on the Printer name
Under the "Administration" drop down, click on "Set As Server Default"

After that, everything worked properly!  But I wanted to do one last thing… I wanted each of the pages to say NJ VMUG.  I already had a logo we used to have stickers made, so I decided to make some changes…

1. I copied the jpg to the root of /usr/local/nginx/html.
2. I edited admin.htm, checkin.htm, register.htm, and index.htm, where I added the line below to the top of each file.
<center><img src="NJVMUG_Sticker.jpg" height=100 width=200></center>

Here is the unit on display, on top of the $5 plastic case (purchased at Target) I use to store/transport everything.

And HERE is the behind the scenes shot of the PI and my Wi-Fi Travel Router. Smile

Thanks to Patrick Stasko as well as Matt Heldstab (@mattheldstab) for the assistance getting this up and running!


Ben Liebowitz, VCP, vExpert
NJ VMUG Leader


Configuring my Dell PowerEdge R920 for dual SD Cards instead of Internal HDs

Posted by Ben Liebowitz

We recently setup a Dell PowerEdge R920 that was in storage to add to our VDI Environment for additional resources.  This server differs from the other R920s in our environment as it has dual SD Cards internally instead of Hard Disks. 

I had to configure the SD Cards in a mirror so we had fault tolerance, so this is the procedure I followed…

1. Power on the server.  The server will undergo a memory test.
2016-12-21 10_25_11-Remote Desktop Manager [CTCGSSAPP12]

2.  Once the memory test is over, the Dell logo will appear, with 4 options in the top right corner and the system will begin to POST.  Press F2 to enter the system setup.
2016-12-21 10_26_20-Remote Desktop Manager [CTCGSSAPP12]

3.  Once you press F2, the system will continue to POST, and you’ll see ENTERING SYSTEM SETUP in the top right corner.
2016-12-21 10_26_30-Remote Desktop Manager [CTCGSSAPP12]

4.  After completing POST, the SYSTEM SETUP MAIN MENU will load.  Choose SYSTEM BIOS.
2016-12-21 10_27_24-Remote Desktop Manager [CTCGSSAPP12]

5.  Then choose MEMORY SETTINGS.
2016-12-21 10_27_51-Remote Desktop Manager [CTCGSSAPP12]

2016-12-21 10_28_40-Remote Desktop Manager [CTCGSSAPP12]

7.  Click FINISH. 
2016-12-21 10_27_51-Remote Desktop Manager [CTCGSSAPP12]

8.  Click EXIT in the top right corner.  Then click YES to confirm.
2016-12-21 10_27_24-Remote Desktop Manager [CTCGSSAPP12]

9.  When the system reboots, press F11 during POST.
2016-12-21 10_26_20-Remote Desktop Manager [CTCGSSAPP12]

10. You’ll see ENTERING BIOS BOOT MANAGER in the top right corner.
2016-12-22 09_27_55-Remote Desktop Manager [CTCGSSAPP12]

11.  When the boot manager loads, choose BIOS BOOT MENU.
2016-12-22 09_30_40-Remote Desktop Manager [CTCGSSAPP12]

12.  Select the installation method you’re using.  In my case, I have a mounted ISO via iDRAC so I’m choosing Virtual CD. 
2016-12-22 09_31_09-Remote Desktop Manager [CTCGSSAPP12]

13.  Select the ESXi Installer.  In my case, I’m installing ESXi 5.5 U2 to match the rest of the hosts in my environment. 
2016-12-22 09_31_22-Remote Desktop Manager [CTCGSSAPP12]

14.  The ESXi Installer will load.
2016-12-22 09_34_03-Remote Desktop Manager [CTCGSSAPP12]

15.  Press ENTER to continue with the installation. 
2016-12-22 09_39_05-Remote Desktop Manager [CTCGSSAPP12]

16.  Press F11 to accept the EULA. 
2016-12-22 09_39_13-Remote Desktop Manager [CTCGSSAPP12]

17.  You’ll see your Dual SD cards ready to accept the vSphere ESXi Installation.  2016-12-22 09_39_41-Remote Desktop Manager [CTCGSSAPP12]

18.  Proceed with your install as you would if installing on disk media. 



Ben Liebowitz, VCP, vExpert
NJ VMUG Leader


Windows 2012 R2: Static IP displays as DHCP IP

Posted by Ben Liebowitz

I ran across this issue this week with a bunch of new servers I built using a new Windows 2012 R2 Image I built and captured using Symantec Altiris.  There must have been some sort of corruption in the image that caused this issue. 

The issue displays like this…  You set a static IP on your server (in this case, they were physical Dell Rack Mount servers).  After clicking OK, you go back into the NIC properties and into IPv4 Properties and it displays as if using DHCP. 

Then, if you do an IPCONFIG, you can see DHCP is disabled…

To fix this…

1. Open Regedit
2. Navigate to HKLM – System – CurrentControlSet – Control – Network
3. Backup the entire NETWORK key by right clicking, choosing EXPORT, and saving network.reg somewhere locally.
4. Delete the CONFIG key
5. Reboot.
6. When the server comes back up, go back into Network Connections and verify the network info is readable.

I couldn’t find a specific KB to fix this, but found a post on by Bob Boener that described a similar issue and what he did to fix it.  His solution worked for me, so I documented each step for my team and thought I’d share it here.

Hope this helps someone. Smile 

Ben Liebowitz, VCP, vExpert
NJ VMUG Leader


VMworld 2016 Scheduling Tip

Posted by Ben Liebowitz

Are you going to VMworld 2016 US in Las Vegas?  I am!  And one thing that annoys me is that you cannot manually add anything to the schedule builder.  Also, this year they removed the old schedule builder and integrated it into the Content Catalog, removing some features the old Schedule Builder had, like exporting to PDF, etc.

A fellow VMUG Leader, Eric Lee from the KC VMUG, gave me the idea to export the Schedule from the Content Catalog as an .ICS file and then import that file into Microsoft Outlook, creating a new Calendar.  From there, I was able to add the things into the calendar that I wanted, and exported it to PDF!

Here’s how:

1. Log into the VMworld Content Catalog.

2.  Click the calendar icon

3.  From there, you can click EXPORT

4.  I choose .ics, but choose the format you wish to export to. Save the file locally on your computer.

5.  In Microsoft Outlook, click FILE – OPEN & EXPORT, and then OPEN CALENDAR.

6.  Browse to the location of the file you exported in step 4.  Select it and click OPEN

7.  The calendar will import into Outlook as UNTITLED.  Right click and go to PROPERTIES.

8.  From here you can click the top line and rename the calendar and click OK.

9.  Now, you can feel free to add whatever events you want to the calendar, like I added Opening Acts, the VMworld Welcome Reception, the VMUG Member Party, vExpert Reception, my VMUG Lounge shift, etc.

10.  Now, you can print to XPS or PDF.  If you don’t have a PRINT TO PDF reader installed, doPDF is a good one and it’s free.


HINT:  If you're traveling from another time zone, temporarily change your time zone in Windows to Pacific Time before you add items to the calendar and save to PDF/Print.  This way, the times in your document match the times local to the event. :)


You can do the same with the Google Calendar.

1.  In the Google Calendar, click the Gear icon and go to SETTINGS.

2. Click the Calendars tab.

2016-08-22 15_46_09-Google Calendar - Settings
4. Name it VMworld 2016 (or whatever you'd like).  You can also designate what time zone this calendar should be for, which is nice!

5.  Go back to SETTINGS and the Calendar tab again.

7. Browse to the ICS file, select the New calendar to import to.  Click IMPORT

8.  You should now see the VMworld 2016 calendar in your MY CALENDARS list.

Hope you find this helpful, like I did.


Ben Liebowitz, VCP, vExpert
NJ VMUG Leader



One of my favorite tools – Remote Desktop Manager by Devolutions

Posted by Ben Liebowitz

One of the tools I’ve been using for many years now is called Remote Desktop Manager by Devolutions.  Based on the name, you’d think it’s just another RDP tool, but it’s much MUCH more!

There are 2 versions of the product.  There is a FREE version, which gives you limited functionality, and an ENTERPRISE version for full functionality.  There is also a RDM Server as well, but I have no experience with that. The free version lets you setup RDP connections, as well as Microsoft Assistance, Apple Remote Desktop, Citrix ICA/Web, Web URLs, TeamViewer, PCAnywhere, RAdmin, Dameware Mini Remote Control, etc.  Where the enterprise version stands above is features like the Credentials Repository, being able to import from other tools/sources/csv  and lots more.  You can view the full feature comparison here:

Some of the features that I use on a regular basis are:

  • “Keep tab on disconnect”
    • This enables the tab to stay open when you reboot the machine you’re working on, allowing you to quickly reconnect.
  • Continuous Ping
    • This does a ping –t to the machine.  Also handy when working on a remote machine when rebooting multiple times to know when it’s back online.
  • Integrated Password Generator
    • This is great when creating/changing service account passwords.  I just have to open the tool, select  the password length, if you want Uppercase, Lowercase, Digits, Underscore, Brackets, Special Characters, Spaces, etc.  When you click generate you get multiple passwords to choose from, you can copy one or more of them to the clipboard to paste into the password change field or into your password management tool.
      • One thing to watch out for that I ran into was passwords which include QUOTATION MARKS!  We had a tool have an issue with the password and once we changed the quote character it worked again.  Smile
  • Credential Manager
    • I love being able to list each of my DOMAIN\username accounts in one place with their passwords and then assign them to each RDP entry, URL, SSH session, etc.
  • Open (with Parameters)
    • This opens the credential manager before connecting and is handy if you want to connect using alternate credentials other than the one already setup.


If you use this tool, please leave a comment and let me know YOUR favorite feature(s)!

Go checkout the tool today!


Ben Liebowitz, VCP, vExpert
NJ VMUG Leader


I NEED YOUR HELP – VMworld & GoFundMe Edition!

Posted by Ben Liebowitz


Last year was my first time attending VMworld.  As someone who’s whole career is currently centered around VMware products, this conference is THE conference to attend.  I received a free conference pass to VMworld in Las Vegas this year, however I am looking for assistance covering the Travel Expenses (Airfare, Hotel, Transportation).  I'll cover meal costs myself.

I am a Systems Engineer for a global news organization.  I’ve had my VCP since 2011 and was elected vExpert by VMware in 2015 and again in 2016.  I was also elected PernixPro.  I’m also a leader of the VMware User Group for New Jersey.  I've spent a lot of my time giving back to the VMware community and now I need your help!

As this is too much to lay out on my own, I’m looking for help funding my trip!  I started a GoFundMe page and my goal is $1000 to cover Hotel, Airfare, and other expenses.  I’m also offering if I receive a donate of $200 or more, I will put your company’s logo on a shirt/backpack/messenger bag that I will wear/carry throughout the event!  Below is an example of what I envision the them to look like... :)


Sample Backpack


Thank you for your time and I hope to see you at VMworld in August!

Here is the link to my GoFundMe page!

Thanks in advance,

Ben Liebowitz, VCP, vExpert
NJ VMUG Leader



Mission: VMUG Virtual Event – May 17, 2016

Posted by Ben Liebowitz

VMUG Virtual Event 3.0

As a VMUG Leader, I felt like I needed to post a blog entry on the upcoming VMUG Virtual event on May 17th, 2016.  The VMUG Virtual Events are always packed with information from VMware and vendors as well.

VMware is presenting on topics like:  VSAN 6.2, vRA & NSX Technical Deepdive, AirWatch, Taking Virtualization to the next level, EUC, & "You Built a Software Defined Datacenter - Horray! Now What?"

Some vendors presenting are: Veeam Software, Nimble Storage, SimpliVity, Zerto, Trend Micro, EMC, Riverbed Technology, Tintri, Hitachi Data Systems, and PernixData.

Sneak a Peek at Space Station VMUG!

The countdown is on for Mission: VMUG Virtual Event! Your opportunity to dock with Space Station VMUG and connect with peers and industry leaders is fast approaching. Instead of meeting in a physical location, join us on our virtual spacecraft to:

✓ Gain valuable knowledge
✓ Network with experts
✓ Visit with partners


Whether you are interested in NSX, vSphere or Virtualization, the Mission: VMUG Virtual Event Agenda has you covered. This year's VMware breakout sessions promise to deliver the necessary knowledge to enhance your skills and benefit your business.

Accept Your Mission Now! View the Agenda!

Connect with Fellow Explorers and Win!

Join us on May 17th, and you'll be eligible to win the Galactic Guru prize, an Amazon Echo! To learn more about all the exciting prizes at Mission: VMUG Virtual Event click here - the stars could align for you!

Stay tuned on Twitter to #MissionVE for update dispatches
from VMUG HQ Mission Control.

Add Mission to Calendar


See you on the VMUG Space Station & try to avoid that black hole!! :)

Ben Liebowitz, VCP, vExpert
NJ VMUG Leader



What do you do when a path to a NFS Datastore goes down?

Posted by Ben Liebowitz

My QA environment uses Isilon as it’s backend storage platform.  The Isilon share is one large storage volume that is setup with different paths (IPs) to the storage.  This environment has 6 datastores (6 paths).  The other day, we had one of those paths go down, taking down approx 75 VMs with it.

I debated attempting to remove the down datastore and then add it back with the same name (with a different IP) but didn’t know what that would do to the VMs, if they’d come back cleanly or not, etc.  In the end, I decided to go down a different path…

While my storage engineer troubleshot the issue on their side, I decided to spin up another datastore, using a different IP.  I then modified my script to migrate VMs between vCenters to pull a list of VMs on that specific datastore, power the VMs off, remove them from inventory on the down datastore, then re-add them back on the newly created one and power them back on.  I left the “update-tools” line in there too as many of the VMs were out of date on the tools version.  A few extra minutes of downtime in a QA environment won’t hurt anything.  Smile

You'll notice a section of the script where it pauses...  I did this so I could then edit the migrate.csv and change the datastore name.  This was easier than taking the time to modify the code to hardcode the new datastore name.  However, if you want to modify line 109 with the actual datastore name and the pause can be removed.  The modified line is here:

$vmxfile = "[NEW_DATASTORE_NAME] $($vmName)/$($vmName).vmx"

Again, props to Luc Dekens (@LucD22 / for the folder path functions!

Next step is to use DNS entries instead of IPs.  This way, if this happens again, it's just a matter of changing the DNS record and waiting for replication. :)

# Script to migrate VMs from down Isilon datastore to the new one
# Created by BLiebowitz on 4/21/2016

# Set Variables
$vcenter = "vcenter_server"
$esxhost = ""
$datastore_old = "Datastore03"
$datastore_new = "Datastore04"

# Load PowerCLI Module
if ( !(Get-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) ) {
. “C:\Program Files (x86)\VMware\Infrastructure\vSphere PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1”

# Connect to vCenter
connect-viserver $vcenter

#Build the BlueFolderPath function
New-VIProperty -Name 'FullPath' -ObjectType 'VirtualMachine' -Value {

$current = Get-View $vm.ExtensionData.Parent
$path = ""
do {
$parent = $current
if($parent.Name -ne "vm"){$path =  $parent.Name + "/" + $path}
$current = Get-View $current.Parent
} while ($current.Parent -ne $null)
} -Force | Out-Null

#Build the Get-folderbypath function
function Get-FolderByPath {
.SYNOPSIS  Retrieve folders by giving a path
.DESCRIPTION The function will retrieve a folder by it's
path. The path can contain any type of leave (folder or
.NOTES  Author:  Luc Dekens
The path to the folder.
This is a required parameter.
.PARAMETER Separator
The character that is used to separate the leaves in the
path. The default is '/'
PS&gt; Get-FolderByPath -Path "Folder1/Datacenter/Folder2"
PS&gt; Get-FolderByPath -Path "Folder1&gt;Folder2" -Separator '&gt;'

[parameter(Mandatory = $true)]
[char]${Separator} = '/'

if((Get-PowerCLIConfiguration).DefaultVIServerMode -eq "Multiple"){
$vcs = $defaultVIServers
$vcs = $defaultVIServers[0]

foreach($vc in $vcs){
foreach($strPath in $Path){
$root = Get-Folder -Name Datacenters -Server $vc
$strPath.TrimStart($Separator).Split($Separator) | %{
$root = Get-Inventory -Name $_ -Location $root -Server $vc -NoRecursion
if((Get-Inventory -Location $root -NoRecursion | Select -ExpandProperty Name) -contains "vm"){
$root = Get-Inventory -Name "vm" -Location $root -Server $vc -NoRecursion
$root | where {$_ -is [VMware.VimAutomation.ViCore.Impl.V1.Inventory.FolderImpl]}|%{
Get-Folder -Name $_.Name -Location $root.Parent -Server $vc

# export list of VMs to Migrate to CSV
Get-Datastore -Name $datastore_old | Get-VM |
Select Name, @{N="Datastore";E={Get-Datastore -VM $_ | Select -ExpandProperty Name}},
@{N="Network";E={Get-VirtualPortgroup -VM $_ | Select -ExpandProperty Name}},
@{N="Parent";E={$_.FullPath}} |
Export-Csv "c:\migrate.csv" -NoTypeinformation -UseCulture

# Shutdown VMs (cleanly)
foreach ($row in (Import-csv c:\migrate.csv))
shutdown-vmguest -vm $row.Name -Confirm:$false
start-sleep -s 60
stop-vm -vm $row.Name -Confirm:$false

# Pause script while CSV is edited to change Old Datastore name to New Datastore name.
<span style="color: #454545;">$HOST.UI.RawUI.ReadKey(“NoEcho,IncludeKeyDown”) | OUT-NULL</span><br style="color: #454545;" /><span style="color: #454545;">$HOST.UI.RawUI.Flushinputbuffer()</span>

## Add backto inventory
foreach ($row in (Import-Csv c:\Migrate.csv)) {
$vmName = $row.Name
$vmxfile = "[$($row.Datastore)] $($vmName)/$($vmName).vmx"
$vmNewVM = New-VM -VMFilePath $vmxfile -VMhost $esxhost

# Move VM to existing folder locaiton
Move-VM -VM $vmName -Destination (get-folderbypath $row.Parent)

# Poweron VMs
Start-VM -VM $vmName -Confirm:$false | wait-tools
Get-VMQuestion -VM $vmName | Set-VMQuestion –Option "I moved it" -confirm:$false

# Wait for VM to boot before updating VMware Tools
start-sleep -s 60

# Update VMware Tools
update-tools $vmName

} ## end foreach


Ben Liebowitz, VCP, vExpert
NJ VMUG Leader


Adding a PowerShell Windows Update Script to my VMware Customizations

Posted by Ben Liebowitz

In my environments, we typically convert the templates to Virtual Machines once a quarter so we can install Windows Updates.  This means, there could be a number of patches to install if you’re 2+ months out from the last time they were updated.  So I decided to use a PowerShell script that my coworker wrote to do Windows Updates and run it during the Run Once phase of the vCenter Customizations.

Typically, I have my customizations set to automatically login once.  I did this so I could deploy a VM and walk away.  When I came back, I could tell it was done when the VM was up and logged into Windows.  So I wanted a way to be able to tell things were done and the VM was ready after deploying the Windows Updates.  I decided that a TXT file being displayed on screen would be a great way to know things were done!

First, I modified the customization by changing the number of times to logon automatically to 2 on the ADMINISTRATOR PASSWORD tab and putting C:\SW\install_update.bat on the RUN ONCE tab.  I should also note that my templates are all configured to start on our build VLAN which runs DHCP.  This allows us to build and configure the VM and then change it to the destination VLAN when ready.


Next, I had to convert my template to a VM and boot it up, so I could copy the required files to a location on the C drive.  I created a folder called c:\SW and copied the files there.  There are 4 files I needed to copy.

1. install_update.bat – This is the file that the customization executes.
2. install_updates.ps1 – This is the PowerShell script that runs Windows Update.
3.  runonce.reg – This adds the txt file to launch at the end of the 2nd reboot.
4.  image.txt – This is the TXT file that displays when the VM has rebooted the 2nd time and is finished.

This is the process that happens when you deploy a VM after I made the changes.

Once you power up the VM, it boots and prepares to run sysprep.

Once it runs sysprep, the system reboots, sysprep will run and will reboot again.
image  image

As configured, Windows will Auto Login as the local administrator and the install_updates.bat file will run.  You’ll see the regedit command run first to add the display of the text file to the RUNONCE key in the registry.  Then the Windows update PowerShell Script will execute.  It will reboot upon completion, even if there are no pending updates.

image image

After the VM reboots, it will Auto Login for a 2nd time. After logging in, the TXT file staying the VM is finished deploying will be displayed.
image image

Once you see the TXT file, you can close Notepad and continue to perform the post-build configuration (like adding users, installing AV, etc.)

Here are the contents of each of the files:


REM Run Once
regedit /s c:\SW\runonce.reg

REM Run Windows Update
powershell.exe -ExecutionPolicy Bypass -File "c:\sw\Install_updates.ps1" -patch 1


$patch = 1
function write-log
{    param([string]$data)
$date = get-date -format "ddMMMyyyy @ hh:mm:ss tt"
write-host "$date $data"
Out-File -InputObject "$date $data" -FilePath $LoggingFile -Append
function Get-StatusValue($value)
{ switch -exact ($value)
{ 0   {"NotStarted"}
1   {"InProgress"}
2   {"Succeeded"}
3   {"SucceededWithErrors"}
4   {"Failed"}
5   {"Aborted"}}}
function patchserver
{    Param([string]$Option)
$needsReboot = $false
$UpdateSession = New-Object -ComObject Microsoft.Update.Session
$UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
write-log " - Searching for Updates"
switch ($Option)
{ 0 { $SearchResult = $UpdateSearcher.Search("IsHidden=0 and IsInstalled=0")}
1 { $SearchResult = $UpdateSearcher.Search("IsAssigned=1 and IsHidden=0 and IsInstalled=0")}
default { $SearchResult = $UpdateSearcher.Search("IsHidden=0 and IsInstalled=0")}}
write-log " - Found [$($SearchResult.Updates.count)] Updates to Download and install"
foreach($Update in $SearchResult.Updates)
$UpdatesCollection = New-Object -ComObject Microsoft.Update.UpdateColl
if ( $Update.EulaAccepted -eq 0 ) { $Update.AcceptEula() }
$UpdatesCollection.Add($Update) | out-null
write-log " + Downloading [$i of $($SearchResult.Updates.count)] $($Update.Title)"
$UpdatesDownloader = $UpdateSession.CreateUpdateDownloader()
$UpdatesDownloader.Updates = $UpdatesCollection
$DownloadResult = $UpdatesDownloader.Download()
$Message = "   - Download {0}" -f (Get-StatusValue $DownloadResult.ResultCode)
write-log $message
write-log "   - Installing Update"
$UpdatesInstaller = $UpdateSession.CreateUpdateInstaller()
$UpdatesInstaller.Updates = $UpdatesCollection
$InstallResult = $UpdatesInstaller.Install()
$Message = "   - Install {0}" -f (Get-StatusValue $DownloadResult.ResultCode)
write-log $message
New-Item -Path C:\Logs -ItemType "directory" -Force > $null
$LoggingFile = "C:\Logs\Updates_" + (Get-Date -f "MMddyyyy_hh-mm-ss_tt") + ".txt"
del $LoggingFile -Confirm:$false -ErrorAction SilentlyContinue
$CurrentTime = Get-Date
write-log "STARTING: $CurrentTime"
switch ($patch)
0 {
write-log "########################"
1 {
write-log "################################"
write-log "###  INSTALLING ALL UPDATES  ###"
write-log "################################"
patchserver 0
Restart-Computer -Force
2 {
write-log "############################"
write-log "###  INSTALLING UPDATES  ###"
write-log "############################"

patchserver 1
Restart-Computer -Force
default {
write-log "Must specify an valid option -- exiting"
return -1


Windows Registry Editor Version 5.00

"Image"="notepad c:\\SW\\image.txt"




UPDATE 3/22/16:

Another way to display that the image is done is to display a popup box...

Delete image.tx, modify the runonce.reg (below), and add image.ps1 (also below)...


Windows Registry Editor Version 5.00

"Image"="powershell.exe -ExecutioinPolicy Bypass -File \"c:\\sw\\image.ps1\""


[System.Windows.Forms.MessageBox]::Show("TEMPLATE DEPLOYMENT COMPLETE.")

Ben Liebowitz, VCP, vExpert
NJ VMUG Leader

Go to top ↑