{"id":97,"date":"2019-07-06T19:36:04","date_gmt":"2019-07-06T18:36:04","guid":{"rendered":"http:\/\/192.168.8.14\/?p=97"},"modified":"2019-07-06T21:21:47","modified_gmt":"2019-07-06T20:21:47","slug":"find-and-remove-connected-cd-drives-using-powercli","status":"publish","type":"post","link":"https:\/\/www.jasonstreet.com\/?p=97","title":{"rendered":"Find and remove connected CD drives using PowerCLi"},"content":{"rendered":"\n<p>If you work in an environment where no one remembers to disconnect their ISO images when done then this script is for you.<\/p>\n\n\n\n<p>This script will report each VM with a connected CD drive and its ISO path, to a CSV file<br>Also once a specified number of days have passed (assuming this script is run once per day) then the connected ISO is disconnected.<\/p>\n\n\n\n<p>There is an issue with the way in which the script disconnects the CD. When the disconnect request is sent, the VM will pause while vCenter asks if you are sure. There <strong>is<\/strong> a workaround that I will go in to at the end.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\n  $CDLookupFile = &quot;c:\\temp\\CDs.csv&quot;   # the script will write a list of VM with CD ISO files\n  $MaxDaysToKeepCDsMounted = 3  # connected ISO CDs will be removed after this many days.\n  $LogFile = &quot;c:\\temp\\DisconnectedCDs.log&quot;     # path to log file\n  $vCenterServer = &#039;&#039;        # name of vCenter server \n  connect-viserver $vCenterServer\n\n  # import the csv file of known VMs with CD drives, if it exists\n  if (test-path $CDLookupFile)\n  {\n    $ConnectedCDs = @(import-csv $CDLookupFile)\n  }else{\n    $ConnectedCDs = @()\n  }\n\n\n  # loop through each VM\n  $VMs = Get-VM\n  foreach ($VM in $VMs)\n  {\n    # check if there is a CD drive connected to an ISO.\n    $ConnectedCD = Get-CDDrive $VM\n    if ($ConnectedCD.isoPath)\n    { \n      # checking the CSV file to see if this VM is listed.\n      $RowNum = ($ConnectedCDs | where {$_.VM -eq $VM.name}).RowNum\n      if ($rowNum)\n      {\n        # this VM is already listed\n\n        # increase the days detected by 1, then check if days detected is equ to $MaxDaysToKeepCDsMounted\n        $ConnectedCDs&#x5B;$RowNum].Days = &#x5B;int]$ConnectedCDs&#x5B;$RowNum].Days + 1\n        if ($ConnectedCDs&#x5B;$RowNum].Days -eq $MaxDaysToKeepCDsMounted)\n        {\n          # time to dismount the CD\n          $TimeNow = get-date -f &quot;yyyy\/MM\/dd HH:mm&quot;     \n          $ConnectedCD | Set-CDDrive -NoMedia -Confirm:$False\n          if ($?)\n          {\n            &quot;$TimeNow CD disconnected from &quot; + $VM.name + &quot;, path &quot; + $ConnectedCDs&#x5B;$RowNum].ISOPath | out-file $LogFile -append\n            $ConnectedCDs&#x5B;$RowNum].Days = &quot;deleted&quot;\n          }else{\n            &quot;$TimeNow CD failed to disconnect from &quot; + $VM.name + &quot;, path &quot; + $ConnectedCDs&#x5B;$RowNum].ISOPath | out-file $LogFile -append\n          }\n        }\n        \n      }else{\n        # this VM is not listed in the CSV add to list\n\n        $tmpObj = &#039;&#039; | select vm,ISOPath,DS,RowNum,Days\n        $tmpObj.VM = $VM.name\n        $tmpObj.ISOPath = $ConnectedCD.IsoPath\n        $tmpObj.DS = ((($ConnectedCD.IsoPath).split(&quot;]&quot;))&#x5B;0]).replace(&quot;&#x5B;&quot;,&#039;&#039;)\n        $tmpObj.RowNum = $ConnectedCDs.count\n        $tmpObj.Days = 0\n        $ConnectedCDs += $tmpObj\n\n      } # end of is it in the ConnectedCDs array\n    } #end of if connected to ISO \n  } # end of VM loop\n\n\n  # this section of code will reorder the CSV so the RowNum starts at 0\n  $NewRowNum = 0\n  $NewConnectedCDs = @()\n  foreach ($CDRow in $ConnectedCDs)\n  {\n    if ($CDRow.days -ne &quot;deleted&quot;)\n    {\n      $NewConnectedCDs += $CDRow\n      $NewConnectedCDs&#x5B;$NewRowNum].RowNum = $NewRowNum\n      $NewRowNum ++\n    }\n  }\n  $NewConnectedCDs | export-csv $CDLookupFile -NoTypeInformation\n\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">How it works<\/h2>\n\n\n\n<p>Lines 5 &#8211; 11. <br>Import a CSV, if it does not exist just create the $ConnectedCDs array. This will contain a list of VMs with attached ISOs. also the number of days the ISO has been attached, the ISO path and the datastore. <\/p>\n\n\n\n<p>Lines 14 &#8211; 19.<br>Loop through each VM, check if there is a CD drive pointing to an ISO. <\/p>\n\n\n\n<p>Lines 20 &#8211; 24.<br>Check if this VM with ISO is listed in the CSV file ( $ConnectedCDs  array). If it&#8217;s not in the array jump to line 44.<\/p>\n\n\n\n<p>Lines 26 &#8211; 30.<br>Increase the days attribute for this VM in the $ConnectedCDs  array.<br>Then check if the days attribute is the same as the $MaxDaysToKeepCDsMounted variable.<\/p>\n\n\n\n<p>Lines 31 &#8211; 42<br>Disconnect the CD. Report to log file if that command was successful or not.<\/p>\n\n\n\n<p>Lines 44 &#8211; 55.<br>First time this VM has been detected. Create a temporary object and populate its data with VM name, ISO path, Datastore name, number of days (0) and row number. Add this object to the  $ConnectedCDs array<\/p>\n\n\n\n<p>Lines 60 &#8211; 72.<br>This loop will remove any successfully disconnected VMs from the list. It will also re number the list so the deleted rows will not leave gaps. Then save the new array back to the CSV file.<\/p>\n\n\n\n<p>Now as I mentioned at the beginning the script will suspend the VM as vCenter will ask if you really want to disconnect as the OS has a lock on the CD.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"362\" height=\"188\" src=\"http:\/\/192.168.8.14\/wp-content\/uploads\/2019\/07\/Capture.png\" alt=\"\" class=\"wp-image-102\" srcset=\"https:\/\/www.jasonstreet.com\/wp-content\/uploads\/2019\/07\/Capture.png 362w, https:\/\/www.jasonstreet.com\/wp-content\/uploads\/2019\/07\/Capture-300x156.png 300w\" sizes=\"auto, (max-width: 362px) 100vw, 362px\" \/><\/figure>\n\n\n\n<p>The solution for this problem is a function written by Luc Dekens and David A. Stewart. <\/p>\n\n\n\n<p>The URL is here https:\/\/communities.vmware.com\/thread\/440733<br>To use Luc and David&#8217;s function copy the function code to the beginning of the script.<br>Then change line 36 to <br>$VM | Set-CDDriveAndAnswer<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you work in an environment where no one remembers to disconnect their ISO images when done then this script is for you. This script will report each VM with a connected CD drive and its ISO path, to a CSV fileAlso once a specified number of days have passed (assuming this script is run&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[5,4],"tags":[19,18,12,13,20,6],"class_list":["post-97","post","type-post","status-publish","format-standard","hentry","category-powercli","category-powershell","tag-cd","tag-iso","tag-powercli","tag-powershell","tag-vcenter","tag-vmware"],"_links":{"self":[{"href":"https:\/\/www.jasonstreet.com\/index.php?rest_route=\/wp\/v2\/posts\/97","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jasonstreet.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jasonstreet.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jasonstreet.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jasonstreet.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=97"}],"version-history":[{"count":0,"href":"https:\/\/www.jasonstreet.com\/index.php?rest_route=\/wp\/v2\/posts\/97\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.jasonstreet.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=97"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jasonstreet.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=97"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jasonstreet.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=97"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}