One Inch of Power: Bulk file relocation

September 30, 2014 FoxDeploy

Hi guys,

Back for another installment of One inch of Power. In this episode, I became sick of seeing my music folder full of folders for albums, each of which may only have a single file or two.

I wrote this one incher to grab all folders with less than three files and move them all into a single folder, for ease of sorting.

"$HOME\Music" | gci |
   ? PSIsContainer -eq $true | % {
       if ((gci $__.FullName -recurse).Count -le 3){
          gci $__ -recurse *.mp3 | move-item -Destination $HOME\\Music\\misc 
          }
      } 

Here’s the overall flow.

  1. Get Items from $HOME\Music
  2. Filter down to only ones where PSIsContainer equals True, which returns only folders
  3. If the number of items in the folder is less than or equal to three…
  4. …get a list of all files in the directory
  5. Move all of those items into $Home\Music\Misc

Pretty amazing what one line of PowerShell can do.

Continue Reading...

Slide Deck, photos and resources from my Session at ATLPUG

September 26, 2014 FoxDeploy

The Atlanta PowerShell User’s Group first meeting at iVision went off wonderfully! We had a solid turn out, plenty of pizza and soda, and talked a whole lot about PowerShell, what’s new, and whats coming.

Here’s the demo I worked through exploring features using the ISE  Props to Mike Robbins for showing me this technique!

#Check our Version, needs to be greater than 5.0. version 9814 is the most up to date version (September preview) 
Get-host | Select-Object -Property Version

#region Working with Archives Set-location C:\\Demo

#Something to do with Archives, so lets look for ZIP Get-Command \*-Zip

Get-Command \*-Archive

Compress-Archive -Path C:\\demo -DestinationPath c:\\demo\\Files.zip -CompressionLevel Optimal #mkdir Unzipped

#endregion

#region Modules #Find-module #xActiveDirectory, xJea,

Find-Module

#endregion

#region #ONEGET

#One-Get is Apt-Get come to Windows. It is awesome!

#Import the Module Import-Module OneGet

#List all commands for the module, will prompt to install nuget Get-Command -Module OneGet

#Search your repo's for packages available DONT RUN! $OriginalPackages = Find-Package

#Number of packages Find-Package | Measure-Object | Select -Property Sum

#Not that many apps, where'd they all go? Let's check our package Sources Get-PackageSource

#by default, we only have PSGallery and MSPSGallery as sources...let's add Chocolatey. Previously this was Add-PackageSource, it's changed! $PackageSourceLocation = "http://chocolatey.org/api/v2" Register-PackageSource -ProviderName PSModule -Name Chocolatey -Location $PackageSourceLocation -Trusted -VERBOSE

#After adding Chcolatey DONT RUN! $FullPackages = find-package

#Total count of packages now ~ Find-Package | Measure-Object | Select -Property Sum

find-package evernote

#Search for apps with a summary that mentions PDF find-package | Where Summary -like "\*pdf\*"

find-package evernote | install-package -force #endregion

#region Convert-FromString $TraceRT = tracert -h 6 -w 45 microsoft.com #hops 6, -waiting 45 milliseconds

$TraceRT\[(3..12)\] #Skip the first few lines

$TraceRT\[(3..12)\] -replace "^\\s+" | ConvertFrom-String -PropertyNames Hop,Latency1,Latency2,Latency3,ServerName,ServerIP #Props to Francois Xavier Cat for this regex and general idea

$TraceRT\[(3..10)\] -replace "^\\s+" -replace 'ms','' -replace '\[ \\t\]+$','' | ConvertFrom-String -PropertyNames Hop,Latency1,Latency2,Latency3,ServerName,ServerIP

#endregion

#region DSC Stuff #Remove-item $env:windir\\system32\\MonitoringSoftware -Confirm -Force

Configuration InstallXMLNotePad { param(\[string\[\]\]$MachineName="localhost")

Node $MachineName { File InstallFilesPresent { Ensure = "Present" SourcePath = "\\\\localhost\\Installer" DestinationPath = "C:\\Demo\\InstallFiles" Type = "Directory" Recurse=$true # can only use this guy on a Directory }

Package XMLNotePad { Ensure = "Present" # You can also set Ensure to "Absent" Path = "C:\\Demo\\InstallFiles\\XmlNotepad.msi" Name = "XML Notepad 2007" ProductId = "FC7BACF0-1FFA-4605-B3B4-A66AB382752D" DependsOn= "\[File\]InstallFilesPresent" }

}

}

InstallXMLNotePad

Start-DscConfiguration -Path InstallXMLNotePad -Wait -Verbose -Force #endregion

#Cleanup Demo Unregister-PackageSource -ProviderName PSModule -Name Chocolatey 

Here’s the function we created on stage, which recieves and parses output from Trace Route using Convert-FromString.

function Test-Route{ param( $ServerName='microsoft.com', $Hops=6, $Wait=45 )

Write-Host "Tracing Route from localhost to $Servername, capturing $Hops Hops and waiting $Wait MS" $TraceRT = tracert -h $Hops -w $Wait $ServerName #hops 6, -waiting 45 milliseconds

$TraceRT\[(3..10)\] -replace "^\\s+" -replace 'ms','' -replace '\[ \\t\]+$','' | ConvertFrom-String -PropertyNames Hop,Latency1,Latency2,Latency3,ServerName,ServerIP } 
Continue Reading...

Question Time : Why Won't My Script Run?

September 23, 2014 FoxDeploy

Accepting Scripts for Review!

I love it when people send me scripts that don’t run, or ask for help when they encounter issues.  For me, part of my own learning solidification process is trying to explain things to others.  If I can’t explain it to them, then I really don’t know the topic as well as I think I do.  If you, dead readers, ever have a script or function that just won’t run, never hesitate to send it to me.  I’ll do my best to answer your problem in an understandable and friendly way, and hopefully we’ll both be the wiser.  If you’re okay with it, I’ll post it here for others to enjoy too!

-Parameter Binding OMFG

I got an e-mail from a colleague today.  He said that this simple script kept failing:

$servers = get-content c:\\temp\\servers.txt Test-connection $servers -count 1 | export-csv C:\\temp\\Server.csv 

He sent me a copy of the file, which looked like this:

NoParam_01

Running the command would give him (And me too!) the same output!

Invalid parameter, TestConnectionException.Microsoft.PowerShell.Commands

 

I jumped into the machine, and then saw it for myself, typing out $servers would give me the contents of the file.I could separately ping each of the computers too.  But then when I attempted to run the full command, I’d get the same error!  Finally, I decided to take a look into the contents of $server, because something was going wrong here…

$servers.Count
>2 

Hmm…two items

$servers[1]                              

>ALBFX3

And the text looks good…what about the length, is something off?

$servers[1].Length          

>10

Wait…ALBFX3 is only five letters. So I jumped into the text file itself and…

With Spaces, no one can hear you scream

In the text file, ALBFX3 actually had some spaces in it!  PowerShell was getting the second item as ‘ALBFX3    ‘.

PowerShell interprets spaces as the delimiter between arguments and inputs.It thought the spaces were preceding input, and then not finding any, throwing up an ‘Invalid Parameter’ error for that reason.  If you run into a bizarro invalid parameter error in the future, remember to double check for trailing spaces.

Continue Reading...

Impractical One-liner Challenge

September 19, 2014 FoxDeploy

Update

My thanks to Mike F. Robbins and others on reddit who pointed out that the command should be ‘Select -ExpandProperty DistinguishedName’, and not organizationalUnit.

The Challenge

A colleague and I got into a competition earlier today. How could we display an Out-Gridview of all of a companies OU’s, and then move a computer to the selected one in a single line of code.

We condensed our code down to the following two lines:

$destinationOU =  Get-ADObject -Filter 'ObjectClass -eq "organizationalUnit"' | Select -ExpandProperty DistinguishedName -Unique | Out-Gridview -passthru

Get-Content .\\Computers.txt | Get-QADObject | Move-QADObject -NewParentContainer $destinationOU -whatif 

The goal? Make it into a one-liner.

GUIDELINES:

  • Maintain the steps if possible.  Minimally acceptable solution:
    • Get user input for which OU
    • Get a list of computers and move them to the OU
  • NO CHEATING WITH Semicolons or backticks Doing the below doesn’t count

      $ou = Out-Gridview;gc Computers.txt | Move-Computer $ou
    
  • Anything else goes!

Please comment here with your answers. I’ll post my own within a few days.  Also, if you have any ideas for a future impractical One-Liner Challenge, let me know here, Twitter, or Reddit!

Continue Reading...

Adding Autocomplete to your Textbox forms in PowerShell

September 18, 2014 FoxDeploy

Today I had a fun little challenge come-up: how do I go about adding Auto-completion records to my forms?

Turns out it is pretty easy! Let’s start very simply. The following will draw out a small box with an OK button, a textbox, and…thats it. Hitting OK will pass along the output of the box.

#Load the assemblies needed for drawing forms with PowerShell
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
 
#region to draw the background form
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "Autocompletion Tool"
$Form.Size = New-Object System.Drawing.Size(300,140)
$Form.StartPosition = "CenterScreen"
$Form.KeyPreview = $True
$Form.MaximumSize = $Form.Size
$Form.MinimumSize = $Form.Size
 
#begin to draw text box
$textbox = New-Object System.Windows.Forms.TextBox
$textbox.Location = New-Object System.Drawing.Size(10,40)
$textbox.Size = New-Object System.Drawing.Size(200,20)
$textbox.Height = 80
$textbox.Name = 'TextBox_UserName'
 
$Form.Controls.Add($textbox)
 
#begin to draw an OK button
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(220,38)
$OKButton.Size = New-Object System.Drawing.Size(40,25)
$OKButton.Text = "OK"
$OKButton.Add_Click({$xdept=$ListBox.SelectedItem;$xname=$TextBox.Text;$xfname=$TextBoxfName.Text;$Form.Close()})
$Form.Controls.Add($OKButton)
 
#Make our form topmost, then show it
$Form.Topmost = $True
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()
 
#Return the value
$textbox.Text

There we go, basic-basic.

The difference is simply adding the following lines starting on line 20:

$textbox.AutoCompleteSource = 'CustomSource' $textbox.AutoCompleteMode='SuggestAppend' $textbox.AutoCompleteCustomSource=$autocomplete 

And with that, you can now directly add entries to the AutoCompleteCustomSource using it’s method .AddRange()

autocomplete_02

You could Import from a file

#Importing from a file 
Get-content 'C:\\TEMP\\User Records.txt' | % {$textbox.AutoCompleteCustomSource.AddRange($\_) } 

Or you could add individual entries, or the output of a script

#Adding single entries to the inherited AutoCompleteSource object of the textbox 
"1","blam","foxdeploy","stephen.owen" | % {$textbox.AutoCompleteCustomSource.AddRange($\_) } 

autocomplete_03 Voila, Magnifique!

As always, feel free to modify for your own purposes, and I hope that this helps you in the future.

Continue Reading...

[PSCustomObject] Need not apply;How PowerShell 2.0 handles objects

September 12, 2014 FoxDeploy

Today at a client I had to export some Exchange Information from a one of their Exchange boxes. A simple task, but I kept experiencing some strange issues when I would run my script in PowerShell on the Exchange servers.

The only data I needed was RecipientType, LastLoggedOn and some other similar info, which is also easy to get. It needed to be extracted from Exchange and made ready for assimilation into a larger spreadsheet, so exporting as a Custom Object of some form would be the way to go.

I quickly came up which this script, which should have been more than up to the task. However, the output was very bizarre.

$Array = New-Object -TypeName System.Collections.ArrayList
 
Function Get-MarkInfo {
   ForEach ($user in $users){
      $mbx = Get-Mailbox $user
      $mbxstat = Get-MailboxStatistics $user
      [PSCustomObject]$obj=@{Name=$user;RecipientType=$mbx.RecipientType;LastLoggedOnUserAccount=$mbxstat.LastLoggedOnUserAccount;LastLogOffTime=$mbxstat.LastLogOffTime;LastLogonTime=$mbxstat.LastLogonTime}
      $Array.Add($obj) | Out-Null
   }
   $Array | export-csv C:\temp\EmailExport.Csv
}

This shouldn’t export these sorts of things

PSObjectWeirdness Oh no…why is my glorious [PSCustomObject] master race appearing as a hash table? No one asked for key:value pairs!

A hashtable? I never ordered a hashtable!  The CSV output was even worse

PSObjectWeirdness01 No properties? This is what happens when you export a hashtable and don’t enumerate

This was very puzzling. I tried everything under the sun to try and determine why my beautiful little PSCustomObject was coming out as an ugly hashtable. Surely there is an explanation somewhere!  I tried adding Format-Table commands everywhere you could think of, and sorts of craziness with using accelerators to try and force my PSCustomObject to be treated with the respect it deserves.

I ended up digging through old blogposts about ‘Whats New In PowerShell v2’ and v3, when finally I stumbled on these posts: http://stackoverflow.com/questions/14967920/powershell-3-pscustomobject-displays-in-stupid-mode-via-a-variable http://www.jonathanmedd.net/2011/09/powershell-v3-creating-objects-with-pscustomobject-its-fast.html

[PSCustomObject] casting is a new feature in PowerShell version 3.0!

A quick check…

PSObjectWeirdness02

There It was, right in front of me

I’d been working on a 2.0 version server all along! :(

I did some googling to try to refresh myself on the old way to do it, and even posted on PowerShell.org.

http://blogs.technet.com/b/heyscriptingguy/archive/2011/05/19/create-custom-objects-in-your-powershell-script.aspx

MikeFRobbins( http://mikefrobbins.com/, https://twitter.com/mikefrobbins) chimed in with a text-book perfect solution to my issue. So, I present to any of you who ever run into this same issue, the PowerShell 2.0 approach to creating and exporting a custom object.

$Array = New-Object -TypeName System.Collections.ArrayList
 
Function Get-MarkInfo {
   ForEach ($user in $users){
      $mbx = Get-Mailbox $user
      $mbxstat = Get-MailboxStatistics $user
 
      $ObjectProperties = @{
         Name = $user
         RecipientType=$mbx.RecipientType
         LastLoggedOnUserAccount=$mbxstat.LastLoggedOnUserAccount
         LastLogOffTime=$mbxstat.LastLogOffTime
         LastLogonTime=$mbxstat.LastLogonTime
         }
 
      $obj = New-Object PSObject -Property $ObjectProperties
      $obj | ft
      $Array.Add($obj) | Out-Null
      }
   $Array | ft
   }
Continue Reading...


Microsoft MVP

Five time Microsoft MVP, and now I work for the mothership


Need Help?

Get help much faster on our new dedicated Subreddit!

depicts a crowd of people in a night club with colored lights and says 'join the foxdeploy subrreddit today'


Blog Series
series_sml_IntroToDsc
series_sml_PowerShellGUI series_sml_IntroToRaspberryPi Programming series_sml_IntroToWindows Remote Management Series The Logo for System Center Configuration Manager is displayed here Depicts a road sign saying 'Learning PowerShell Autocomplete'




Blog Stats