none
Working with command line variables RRS feed

  • Question

  • So I have fudged together from various google searches the following:

    Foreach-Object -Begin {gwmi Win32_LogicalDisk -filter drivetype=3 | select-object deviceid} -Process {select-object deviceid -End {sdelete -z}

    It actually works and I get nice output like this:

    deviceid
    ---------
    C:
    D:
    H:
    S:

    But I'd like to be able to on the command line list D: H: S: so that C: empty space would not be zeroed.  How is this done?

    • Moved by Bill_Stewart Friday, July 7, 2017 6:09 PM This is not "teach me fundamentals and basics one incremental post at a time" forum
    Tuesday, May 9, 2017 6:18 PM

All replies

  • Oh.  The output is when I use Write-Host vice sdelete.  The sdelete works also, but I just control C it to stop it after I did the initial testing.
    • Edited by sullivange Tuesday, May 9, 2017 6:20 PM add more details
    Tuesday, May 9, 2017 6:19 PM
  • Your code doesn't make much sense.  Start by reading the help for your CmdLets.  Test all of the examples until you understand what is happening.

    Get-WmiObject Win32_LogicalDisk -filter 'drivetype=3 and DeviceId <> "C:"'  |
    	ForEach-Object{ 
    		sdelete $_.DeviceID
           }


    \_(ツ)_/


    • Edited by jrv Tuesday, May 9, 2017 6:24 PM
    Tuesday, May 9, 2017 6:24 PM
  • There are lots of ways to do this, I came up with this:

    $drives = Get-WmiObject -Class Win32_LogicalDisk -Filter 'drivetype=3' | Where-Object { $_.DeviceID -ne 'C:' } | Select-Object -ExpandProperty DeviceID
    
    ForEach ($drive in $drives) {
        Invoke-Expression -Command 'sdelete $drive'
    }

    Tuesday, May 9, 2017 6:49 PM
  • Thanks all for your input.  I appreciate it. I know so little about powershell.  I can give the Help a try.   I was just trying to avoid using a Batch File since powershell, from just the examples I've looked at, seemed so much more powerful.  I still want the option of including the C drive.  I just wanted to be able to pick and choose on the command line like these examples:

    my-zero-wipe.ps1 C: H: S:

    my-zero-wipe.ps1 H:

    my-zero-wipe.ps1 C: S:

    my-zero-wipe.ps1 
        error:   No drive(s) entered.


    • Edited by sullivange Wednesday, May 10, 2017 12:39 PM Corrected original thoughts.
    Wednesday, May 10, 2017 11:13 AM
  • Ok.  I did some basic Help and research and came up with this, which I am having one small problem with.

    <# Sorry ... the Foreach-Object below is the only way I can find, so far, to get a list of my drives
    in a nice and neat column.

    #>

    Foreach-Object -Begin {gwmi Win32_LogicalDisk -filter drivetype=3 | select-object deviceid} -Process {select-object deviceid -End {Write-Host} Write-Host "Your drives are listed above." Write-Host "" $zerolist = Read-Host -Prompt 'Write zeros to the empty space on which of these drives? ' foreach ($i in $zerolist) { If ($i -notlike '*:*') { Write-Host "Did you forget your colon?" Exit } { Else Write-Host "Colons entered." } }

    So now I am trying to make sure the user entry includes a colon after each drive letter. 

    If I enter C: I get the "Colons entered" which is correct.   If I enter C: D I still get the "Colons entered" and not the "Did you forget your colons."   The D should also have a colon.  I was guessing the ForEach would evaluate each item of the user entry.  Am I in the ballpark here?


    Wednesday, May 10, 2017 12:37 PM
  • Have user enter a comma delimited list of drives and add the colons:

    $drives = Read-Host
    $drives = ($drives -split ',' -join ':,') +':'

    sdelete  $drives


    \_(ツ)_/

    Wednesday, May 10, 2017 12:54 PM
  • Eureka.  This seems to work.

    If ($i -notlike '*:')

    There was no need to have wildcard expansion after the colon.

    Wednesday, May 10, 2017 12:57 PM
  • if('A:' -match '^.:'){'gpod'}else{'bad'}

    This will enforce only one character before the colon.


    \_(ツ)_/

    Wednesday, May 10, 2017 1:13 PM
  • Try this:

    function Show-Deme-DriveCleaner_psf {
    	
    	#----------------------------------------------
    	#region Import the Assemblies
    	#----------------------------------------------
    	[void][reflection.assembly]::Load('System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
    	[void][reflection.assembly]::Load('System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
    	[void][reflection.assembly]::Load('System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
    	#endregion Import Assemblies
    	
    	#----------------------------------------------
    	#region Generated Form Objects
    	#----------------------------------------------
    	[System.Windows.Forms.Application]::EnableVisualStyles()
    	$form1 = New-Object 'System.Windows.Forms.Form'
    	$flowlayoutpanel1 = New-Object 'System.Windows.Forms.FlowLayoutPanel'
    	$buttonExecute = New-Object 'System.Windows.Forms.Button'
    	$textbox1 = New-Object 'System.Windows.Forms.TextBox'
    	$buttonOK = New-Object 'System.Windows.Forms.Button'
    	$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
    	#endregion Generated Form Objects
    	
    	#----------------------------------------------
    	# User Generated Script
    	#----------------------------------------------
    	
    	$form1_Load = {
    		Get-WmiObject Win32_LOgicalDisk -filter 'DriveType=2 OR Drivetype=3' |
    		ForEach-Object{
    			$c = New-Object System.Windows.Forms.CheckBox
    			$c.Padding = '4,4,4,4'
    			$c.Text = $_.DeviceID
    			$c.Width = 40
    			$c.TextAlign = 'MiddleLeft'
    			$flowlayoutpanel1.Controls.Add($c)
    		}
    	}
    	
    	$buttonExecute_Click = {
    		
    		foreach ($c in $flowlayoutpanel1.Controls) {
    			if ($c.Checked) {
    				Write-Host $c.Text
    				$out = d:\tools\sdelete\sdelete $c.Text
    				$textbox1.Lines += $out
    			}
    		}
    	}
    	# --End User Generated Script--
    	#----------------------------------------------
    	#region Generated Events
    	#----------------------------------------------
    	
    	$Form_StateCorrection_Load =
    	{
    		#Correct the initial state of the form to prevent the .Net maximized form issue
    		$form1.WindowState = $InitialFormWindowState
    	}
    	
    	$Form_Cleanup_FormClosed =
    	{
    		#Remove all event handlers from the controls
    		try {
    			$buttonExecute.remove_Click($buttonExecute_Click)
    			$form1.remove_Load($form1_Load)
    			$form1.remove_Load($Form_StateCorrection_Load)
    			$form1.remove_FormClosed($Form_Cleanup_FormClosed)
    		} catch { Out-Null <# Prevent PSScriptAnalyzer warning #> }
    	}
    	#endregion Generated Events
    	
    	#----------------------------------------------
    	#region Generated Form Code
    	#----------------------------------------------
    	$form1.SuspendLayout()
    	#
    	# form1
    	#
    	$form1.Controls.Add($flowlayoutpanel1)
    	$form1.Controls.Add($buttonExecute)
    	$form1.Controls.Add($textbox1)
    	$form1.Controls.Add($buttonOK)
    	$form1.AcceptButton = $buttonOK
    	$form1.AutoScaleDimensions = '8, 17'
    	$form1.AutoScaleMode = 'Font'
    	$form1.ClientSize = '540, 474'
    	$form1.FormBorderStyle = 'FixedDialog'
    	$form1.Margin = '5, 5, 5, 5'
    	$form1.MaximizeBox = $False
    	$form1.MinimizeBox = $False
    	$form1.Name = 'form1'
    	$form1.StartPosition = 'CenterScreen'
    	$form1.Text = 'Form'
    	$form1.add_Load($form1_Load)
    	#
    	# flowlayoutpanel1
    	#
    	$flowlayoutpanel1.Location = '17, 13'
    	$flowlayoutpanel1.Margin = '6, 6, 6, 6'
    	$flowlayoutpanel1.Name = 'flowlayoutpanel1'
    	$flowlayoutpanel1.Size = '399, 95'
    	$flowlayoutpanel1.TabIndex = 3
    	#
    	# buttonExecute
    	#
    	$buttonExecute.Location = '424, 14'
    	$buttonExecute.Margin = '4, 4, 4, 4'
    	$buttonExecute.Name = 'buttonExecute'
    	$buttonExecute.Size = '100, 30'
    	$buttonExecute.TabIndex = 2
    	$buttonExecute.Text = 'Execute'
    	$buttonExecute.UseVisualStyleBackColor = $True
    	$buttonExecute.add_Click($buttonExecute_Click)
    	#
    	# textbox1
    	#
    	$textbox1.Location = '17, 116'
    	$textbox1.Margin = '4, 4, 4, 4'
    	$textbox1.Multiline = $True
    	$textbox1.Name = 'textbox1'
    	$textbox1.Size = '507, 278'
    	$textbox1.TabIndex = 1
    	#
    	# buttonOK
    	#
    	$buttonOK.Anchor = 'Bottom, Right'
    	$buttonOK.DialogResult = 'OK'
    	$buttonOK.Location = '424, 428'
    	$buttonOK.Margin = '4, 4, 4, 4'
    	$buttonOK.Name = 'buttonOK'
    	$buttonOK.Size = '100, 30'
    	$buttonOK.TabIndex = 0
    	$buttonOK.Text = '&OK'
    	$buttonOK.UseVisualStyleBackColor = $True
    	$form1.ResumeLayout()
    	#endregion Generated Form Code
    	
    	#----------------------------------------------
    	
    	#Save the initial state of the form
    	$InitialFormWindowState = $form1.WindowState
    	#Init the OnLoad event to correct the initial state of the form
    	$form1.add_Load($Form_StateCorrection_Load)
    	#Clean up the control events
    	$form1.add_FormClosed($Form_Cleanup_FormClosed)
    	#Show the Form
    	return $form1.ShowDialog()
    	
    } #End Function
    
    Show-Deme-DriveCleaner_psf
    


    \_(ツ)_/

    Wednesday, May 10, 2017 1:34 PM
  • jrv:  I don't know exactly what that is, but it looks AWWWWESOOOOOME!!!!!  :)  Seems to be a cool form of some sort.  I will have to get that downloaded and transfer it over to the other network so I can work with it.  We have an isolated network that can't connect to the internet.  And that is where I am working with this sdelete situation.

    I think the issue might be the sdelete.exe command itself.

    I took out a bunch of my other code shown in previous post just to get to the core of the issue and I then put in the code you suggested with the -split and the -join like this:

    $YorN = Read-Host -Prompt "Zero the space on these drives'?' (Y or N) " if ($YorN -eq "Y") { $zerolist = ($zerolist -split',' -join':,') + ':' <# Show me what sdelete should process #> Write-Host $zerolist <# Run sdelete -z on the requested drives #> sdelete -z $zerolist

    }

    The output of the Write-Host looks perfect when I enter the d, c at the prompt.  I get:

          d: c:

    When it hits the sdelete execution, sdelete tells me:

         Invalid drive letter: d

    I don't know why it drops the colons.  Again, maybe it is an sdelete issue.

    At the the command line of just a normal cmd, sdelete -z d: c: it what would be used.  I don't know why it is not as happy with the d: c: that the Write-Host is showing us.

    Alas, maybe I will just have to do this manually.  The whole idea was to have script to run via the Task Scheduler and to zero the empty space on some VMs which are affecting reported disk space on our PURE data store. One way to reclaim space and have it reported correctly after de-duplication runs is to zero the empty space.  In the script I would take out the questions (which are for testing only) and then have the script identify drivetype 3 and zero the empty space on them.

    Thank you so much for all you have done.  I've learned a lot.

    Wednesday, May 10, 2017 3:20 PM
  • jrv -  I just printed out your code.  I think I can hand-type it pretty easily vice downloading and transferring.
    Wednesday, May 10, 2017 3:34 PM