Showing posts with label PowerShell. Show all posts
Showing posts with label PowerShell. Show all posts

4/25/2020

PowerShell: When does zero equal one? (Length property of a Directory)


You learn the most interesting things when teaching a class, especially when an off the cuff demo goes wrong.

During a simple demo of a calculated or derived column I did this:

For files, the output was as expected:


But for directories it returned this:


While the FileInfo object does have a Length property, the DirectoryInfo object does not. So what should we expect when both files and directories are in the same pipeline? Directories usually display a blank column for Length. Is this a Null? Is this an empty or one space string? Or is it just skipped because DirectoryInfo objects don't have a Length property?

Noting that 9.53674E-07 is 1 / 1MB, PowerShell is returning a 1 for the missing Length property, and not a zero or null as I was expecting.

Turns out that Length is both a property of FileInfo objects, and also a property of all PowerShell objects. In my example, DirectoryInfo objects did not have a Length property so $_.Length returns the underlying object's Length property.

Here's an example of a new "Object". Note that PowerShell thinks it has a length of 1 even though Length is not one of its properties. If it's not a defined property, where does it come from? PowerShell seems to treat all objects as collections, even if it is a single item. Collections have both a Count and a Length property. So, $x has a Length (and a Count) of 1.


There's a hint in the PowerShell help files about this. https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_properties?view=powershell-7  (or in PowerShell help about_Properties)



And, as the Help file says, it was different in PowerShell 2.0. If I launch PowerShell with the -Version 2.0 option, I actually get the result I expected in the original demo!





.

2/15/2018

Run SharePoint 2013 and 2016 Search Reports from PowerShell


Updated to include IDs for SharePoint 2016!   Original article here.


Update! Need these reports for every site collection in the farm? See Part 2: http://techtrainingnotes.blogspot.com/2015/04/run-sharepoint-2013-search-reports-from_21.html


In my Search Administration class I stress that admins should dump the search reports on a regular basis as the data is only kept in detail for 14 days and in summary form for 35 months. But who wants to both run these reports at least once every 14 days, even they can remember to do so. So, PowerShell to the rescue… Schedule this script to run each weekend and your work is done.

The following script works for on premise SharePoint 2013. To work with Office 365 you will have to figure out how to include your credentials. The example included here works on premises by using "UseDefaultCredentials = $true".

After lots of hacking, detective work (see below) and just plain trial and error, here's the script:

# This is the URL from YOUR Central Admin Search Service Usage Reports page:
#
# The script will not work unless this is correct!
# $url = "http://yourCentralAdminURL/_layouts/15/reporting.aspx?Category=AnalyticsSearch&appid=ed39c68b%2D7276%2D46f7%2Db94a%2D4ae7125cf567" # This is the path to write the reports to (must exist, but can be anywhere): $path = "c:\SearchReports\" function Get-SPSearchReports ($farmurl, $searchreport, $path, $version) { # TechTrainingNotes.blogspot.com
if ($version -eq "2013")
{ # Report names and IDs $Number_of_Queries = "
21be5dff-c853-4259-ab01-ee8b2f6590c7" $Top_Queries_by_Day = "56928342-6e3b-4382-a14d-3f5f4f8b6979" $Top_Queries_by_Month = "a0a26a8c-bf99-48f4-a679-c283de58a0c4" $Abandoned_Queries_by_Day = "e628cb24-27f3-4331-a683-669b5d9b37f0" $Abandoned_Queries_by_Month = "fbc9e2c1-49c9-44e7-8b6d-80d21c23f612" $No_Result_Queries_by_Day = "5e97860f-0595-4a07-b6c2-222e784dc3a8" $No_Result_Queries_by_Month = "318556b1-cabc-4fad-bbd5-c1bf8ed97ab1" $Query_Rule_Usage_by_Day = "22a16ae2-ded9-499d-934a-d2ddc00d406a" $Query_Rule_Usage_by_Month = "f1d70093-6fa0-4701-909d-c0ed502e3df8" }
else # 2016
{
$Number_of_Queries          = "df46e7fb-8ab0-4ce8-8851-6868a7d986ab"
$Top_Queries_by_Day         = "06dbb459-b6ef-46d1-9bfc-deae4b2bda2d"
$Top_Queries_by_Month       = "8cf96ee8-c905-4301-bdc4-8fdcb557a3d3"
$Abandoned_Queries_by_Day   = "5dd1c2fb-6048-440c-a60f-53b292e26cac"
$Abandoned_Queries_by_Month = "73bd0b5a-08d9-4cd8-ad5b-eb49754a8949"
$No_Result_Queries_by_Day   = "6bfd13f3-048f-474f-a155-d799848be4f1"
$No_Result_Queries_by_Month = "6ae835fa-3c64-40a7-9e90-4f24453f2dfe"
$Query_Rule_Usage_by_Day    = "8b28f21c-4bdb-44b3-adbe-01fdbe96e901"
$Query_Rule_Usage_by_Month  = "95ac3aea-0564-4a7e-a0fc-f8fdfab333f6"
} $filename = $path + (Get-Variable $searchreport).Name + " " + (Get-Date -Format "yyyy-mm-dd") + "
.xlsx" $reportid = (Get-Variable $searchreport).Value $TTNcontent = "&__EVENTTARGET=__Page&__EVENTARGUMENT=ReportId%3D" + $reportid # setup the WebRequest $webRequest = [System.Net.WebRequest]::Create($farmurl) $webRequest.UseDefaultCredentials = $true $webRequest.Accept = "image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, */*" $webRequest.ContentType = "application/x-www-form-urlencoded" $webRequest.Method = "POST" $encodedContent = [System.Text.Encoding]::UTF8.GetBytes($TTNcontent) $webRequest.ContentLength = $encodedContent.length $requestStream = $webRequest.GetRequestStream() $requestStream.Write($encodedContent, 0, $encodedContent.length) $requestStream.Close() # get the data [System.Net.WebResponse] $resp = $webRequest.GetResponse(); $rs = $resp.GetResponseStream(); #[System.IO.StreamReader] $sr = New-Object System.IO.StreamReader -argumentList $rs; #[byte[]]$results = $sr.ReadToEnd(); [System.IO.BinaryReader] $sr = New-Object System.IO.BinaryReader -argumentList $rs; [byte[]]$results = $sr.ReadBytes(10000000); # write the file Set-Content $filename $results -enc byte } # Note: Change the version to 2013 or 2016
Get-SPSearchReports $url "
Number_of_Queries" $path "2013" Get-SPSearchReports $url "Top_Queries_by_Day" $path "2013" Get-SPSearchReports $url "Top_Queries_by_Month" $path "2013" Get-SPSearchReports $url "Abandoned_Queries_by_Day" $path "2013" Get-SPSearchReports $url "Abandoned_Queries_by_Month" $path "2013" Get-SPSearchReports $url "No_Result_Queries_by_Day" $path "2013" Get-SPSearchReports $url "No_Result_Queries_by_Month" $path "2013" Get-SPSearchReports $url "Query_Rule_Usage_by_Day" $path "2013" Get-SPSearchReports $url "Query_Rule_Usage_by_Month" $path "2013"


The Detective Work…

I could not find anything documented on how the reports are called or details on things like the report GUIDs. So here's how I got there:

  • Go the search reports page in Central Admin and press F12 to open the Internet Explorer F12 Developer Tools then:
    • Click the Network tab and click the play button to start recording.
    • Click one of the report links.
    • Double-click the link generated for the report in the F12 pane to open up the details.
    • Make note of the URL (It's the same as the report page!)
    • Note the Accept, and Content-Type Request Headers.
    • Click the Request Body tab.
    • Stare at 3000 characters in that string until your head really hurts, or until you recognize most of what is there is the normal page postback stuff like VIEWSTATE. So we need to find what's unique in the string. (It's the Report IDs.)
    • Click on each of the nine reports and copy out the report IDs.
    • With a lot of trial and error figure out what the minimum string needed is to generate the reports. (It's ""&__EVENTTARGET=__Page&__EVENTARGUMENT=ReportId" plus the report id.)
    • Find out how to do an HTTP POST using PowerShell. (Steal most of it from here: http://www.codeproject.com/Articles/846061/PowerShell-Http-Get-Post.)
    • Find some other needed .Net code and convert the C# to PowerShell.
    • Fill in some gaps with PowerShell putty …….


.

        1/01/2018

        PowerShell to Bulk Add Lists and Libraries to SharePoint’s Quick Launch


        Someone created a bunch of lists and libraries in a new site, and then a few days later wondered why they were no longer in Quick Launch. They had seen them there the day before in the “Recent” section.

        I told them the steps to edit the properties of each list to add them to Quick Launch, and then they told me that there are over 30 lists. So… PowerShell to the rescue!  Here’s the on-prem version:

        $site = Get-SPSite http://sp2016/sites/calcdemo

        $web = $site.RootWeb     #or which ever web is needed

        $lists = $web.Lists

        $lists | where {-not $_.Hidden -and $_.Created -gt (Get-Date 12/21/2017)} |
                   foreach { $_.OnQuickLaunch = $true; $_.Update() }

         

        All done!

        I filtered by date so that I would not change any lists that existed before their new work, and filtered by Hidden to exclude the SharePoint auto-generated lists.

        11/26/2017

        Working with PowerShell’s -ExpandProperty (or… messing with the pipeline)


        One of the great things about PowerShell is how easy and clear much of it is. But then there’s the other things that seem like magic. One of those is when you are dealing with objects that have properties that are collections of other objects.

        Here will look at three solutions for dealing with properties that are collections of other objects:

        • Using -ExpandProperty (and a custom column or two)
        • Using ForEach (and a couple variables)
        • Using ForEach (and a customized object)


        Get-DependentServices

        Sorry, there’s not such a cmdlet. Get-Service does return service objects that have a dependent services property. The only problem is that it returns a summary of the dependent services, and only a partial list. While you could pipe this to Format-List -Wrap, that will not give you any details about the dependent services.

        image


        Using -ExpandProperty

        You can use -ExpandProperty to expand any single property.

        image

        While the above works nicely for a single service, it creates a mess for a collection of services. Which DependentService belongs to which service?

        image

        Your first attempt to solve this will probably fail. In this case, it fails as both the Service object has a Name property and the DependentServices objects have a Name property.

        image

        Your second attempt may run without error, but we still can’t see which Service belongs with which DependentService. Adding a custom column seems to be ignored here:

        image

        This didn’t work as expected because a Service object has a default list of Select properties defined in an XML file somewhere. ( :-) )  Your custom column was passed through the pipeline, but as a NoteProperty (a PowerShell added custom property).

        image

        You will need to pipe the last attempt to another Select to see your NoteProperty.

        image

        So the steps are:

        • Create a custom column with the data to pass on down the pipeline.
             @{n="ParentServiceName";e={$_.Name}}
        • Expand the property with the collection of child objects.
             -ExpandProperty DependentServices
        • Pipe the child object and its new NoteProperty to a final Select.
             select ParentServiceName, Status, Name


        Using ForEach with Variables

        ExpandProperty works great when you need to expand a single property. When you need to futher manipulate the data before sending it on down the pipeline you may want to use ForEach, formally ForEach-Object.

            Get-Service | ForEach { some code } | Select ….

        As a simple ForEach, let’s list Services in color based on Status.

           Get-Service | foreach { 
              if ($_.Status -eq "Running") 
                 { Write-Host $_.Name -ForegroundColor Green } else
                 { Write-Host $_.Name -ForegroundColor Red }
           }

        image

        Write-Host does not add its content to the pipeline, so that’s the end of the line for this one.

        Using ForEach to solve our Service and DependentServices problem, we will create and then reuse a variable that contains the name of the service. (I call this “Store and Forward”.) The ForEach code block can contain one or many statements seperated by semicolons. The last object returned in the code block is forwarded into the pipeline.

           Get-Service | ForEach { $parent = $_.Name; $_.DependentServices } |
                                 Select {$parent}, Status, Name

        This collects one or more pieces of data from the parent object (the Service) as variables, and then passes the DependentServices object on through the pipeline. On the other side of the pipeline you can continute expanding objects and using the variables as needed. Here’s the Service and DependentServices solution using “Store and Forward”.

        image


        Using ForEach with Custom Objects

        You can customize objects by adding “NoteProperties” to the object. You saw one form of this when we used the -ExpandProperty while listing other properties.

           image


        As a fun example, lets create a custom object that looks like a Service object, but has two properties named RunningDependentProperties and NonRunningDependentProperties.

        We will need:

        • A variable for the parent Service
        • Two variables to store the child services (Empty arrays created as $r=@().)
        • The Add-Member cmdlet to add a new NoteProperty to the Service object

        Get-Service |
             foreach {
               # initialize the arrays
               $r = @();
               $nr = @();
               # process all of the DependentServices
               ($_.DependentServices |
                  foreach { if ($_.status -eq "Running") { $r += $_ } else {$nr += $_ } }
               );  `
               # attach the results to the original service
               Add-Member -InputObject $_ -name RunningDependentServices -Value $r -MemberType NoteProperty;
               Add-Member -InputObject $_ -name NonRunningDependentServices -Value $nr -MemberType NoteProperty;
               $_
             } |
        Select name, RunningDependentServices, NonRunningDependentServices


        So what’s it good for?

        How about a list of only services with running dependent services? Just add a WHERE before the SELECT:

            where { $_.RunningDependentServices.Count -gt 0 }

           image

        Or, how about a list of all of the services where the DependentService “applockerfltr” is not running? Just add a WHERE before the SELECT:

           where { "applockerfltr" -in $_.NonRunningDependentServices.Name }


        (If you are not reading this at http://TechTrainingNotes.blogspot.com… you are reading stolen content!)


        Tip:

        In addition to the expansion of properties that are collections, -ExpandProperty can also be used to return a simple datatype like a string or a number. By default, a Select returns a collection. In the example below note that a basic Select Status returns a property named “Status” that contains the value “Running”. If you pipe that to Get-Member you will see that it is still a ServiceController object. If you expand the property Status you will then get the simple string value of the property.

        image


        .

        11/16/2016

        Using PATCH with PowerShell’s Invoke-RestMethod

         

        A story about a bug, an inconsistency and a solution…

         

        I recently did a demo of using PowerShell's Invoke-RestMethod to create, read, update and delete (CRUD) data to a REST service written using ASP.NET's WEBAPI project template and ODATA controllers. Everything worked pretty much as expected except for using the PATCH method to change an existing item.

        My GET worked as expected:

          Invoke-RestMethod 'http://localhost:41613/odata/Courses' | select -ExpandProperty value

        image_thumb[21]

         

        My DELETE worked as expected:

          Invoke-RestMethod 'http://localhost:41613/odata/Courses(33)' -Method DELETE

         

        My POST (create) worked as expected:

          $bodynew = @{ CourseCode='aa111'; Description='test'; Category='test'; Title='Test Course'}
          invoke-restmethod 'http://localhost:41613/odata/Courses' -Method POST -Body $bodynew

        image_thumb[22]

         

        My PATCH (and MERGE) failed!

          $bodyupdate = @{ Title='Updated Title!'}
          invoke-restmethod 'http://localhost:41613/odata/Courses(34)' -Method POST -Body $bodyupdate

        image_thumb[23]

        At least that gave me two hints… "no body" and "The inferred media type 'application/octet-stream' is not supported for this resource." The second one was probably the easiest to fix… tell it that I'm sending JSON.

           $headerJSON = @{ "content-type" = "application/json;odata=verbose"}

        image_thumb[24]

        This got past the Invoke-RestMethod error when using PowerShell 4, but got a new error when using PowerShell 3! "Invoke-RestMethod : The 'content-type' header must be modified using the appropriate property or method." (it's a bug!) But now my ASP.NET WebApi application threw an error, "NullReferenceException". No data was received! (Remember the "no data" error?) So, maybe it was not in the expected format. When using the jQuery AJAX method you serialize your object into JSON before sending. Maybe that would work here:

          $bodyupdateAsJSON = @{ Title='Updated Title!'} | ConvertTo-Json
          Invoke-RestMethod 'http://localhost:41613/odata/Courses(34)' -Method PATCH -Body $bodyupdateAsJSON
              -Headers $headerJSON

        image_thumb[25]

          Bingo!

         

        The Question then is…

        Why can I pass a -Body for a create (POST) without any additional work, but when I pass a -Body with an update (PATCH or MERGE), I have to pass the data as JSON and add a header to state that I'm sending JSON?

         

        Will POST work with those two changes?

        Actually it will! Invoke-RestMethod will do a POST using default PowerShell objects for -Body as long has you don't add a -Header that specifies JSON as the format. Invoke-RestMethod will also do a POST using JSON data as long as you do supply the right -Header. It's probably a best practice to be consistent and explicitly use JSON for both.

        image_thumb[26]

         

        Live and learn…

         

         

        Details:

        Tested with PowerShell 3.0 and 4.0. PowerShell 3.0 fails when trying to set a header for JSON with "Invoke-RestMethod : The 'content-type' header must be modified using the appropriate property or method." (It's a bug!)

        The .NET application:

        • Visual Studio 2015 ASP.NET Web API project with ODATA controllers
        • .NET Framework 4.5.2
        • Entity Framework 6.0
        • SQL Server in Azure
        • Test project hosted in Azure.

        .

        8/15/2016

        Get the Version Number of a PowerShell Module

         

        When a PowerShell script works for one person, but not for another, sometimes it's because the PowerShell module is a different version.

        To find the version number:

        Get-Module -ListAvailable "Microsoft.Online.SharePoint.PowerShell" | 
        select name, version

         

        If you need to deal with multiple versions in your scripts:

        if ( (Get-Module -ListAvailable "Microsoft.Online.SharePoint.PowerShell").
          Version.ToString() -eq "16.0.4915.0")
          { … do this }
        else
          { … do this }

        or maybe

        if ( (Get-Module -ListAvailable "Microsoft.Online.SharePoint.PowerShell").
           Version.ToString() –lt "16.0.4915.0")
           { "Must have 16.0.4915.0 or later"; Return; }
        .

        8/02/2016

        PowerShell to Find SharePoint Views Configured for More Than 5000 Items

         

        Have any of your site owners been trying to create views with more than 5000 items? Have you changed the row limit to more than 5000 and have decided to set it back? Here’s some PowerShell to find all Views with a RowLimit set to more than 5000.

        Here’s some PowerShell to find those views in an on premise SharePoint.

        Get-SPSite -Limit All | 
           Select -ExpandProperty AllWebs |
           Select -ExpandProperty Lists |
           Select -ExpandProperty Views |
           Where {$_.RowLimit -gt 5000} |
           Select {$_.ParentList.ParentWebUrl}, {$_.ParentList.Title}, {$_.ParentList.ItemCount}, {$_.paged}, {$_.RowLimit} | ft -autosize
        

         

        There are two properties of interest in the View object:

        • Paged – Boolean – is paging enabled for the view.
        • RowLimit – integer – number of items to display per page.

        If you wanted to only include views without paging then change the Where line to:

            Where { ($_Paged –eq $false) –AND ($_.RowLimit -gt 5000) } |

         

        .

        7/19/2016

        Use the Visual Basic Financial Functions from PowerShell

         

        You may already know that you can access the core .NET libraries like System.Math from PowerShell:

          image

        As “System” is the default namespace, you could just type [Math]::Sqrt(2).

        But what if you wanted to do a quick financial calculation from PowerShell? Maybe calculate the monthly payment for the classic Mustang you just just have to have? Just use the Visual Basic financial library. In the example below, at 5% (.05/12 per month), over five years (5*12 payments) and an amount of 20,000, your payment would be 377.42 per month. (The minus sign is what it will do to your checking account.)

          image

        Find the available methods…

        While you could search MSDN for a list of methods available from these libraries, you could also just ask the library! Just call the GetMethods() method!

          image

        As the Math library includes both Methods and Fields (constants in this case) you would use GetMembers() instead.

           image

         

        What else is in the VB library?

        Do some browsing by typing “[Microsoft.VisualBasic.” and pressing Tab. When you find something interesting then add the closing square bracket and add .GetMembers() and see what’s there. For example, [Microsoft.VisualBasic.Constants] provides a list of constants like vbOK and vbCancel.

         

        .

        5/16/2016

        Ed Wilson, the Microsoft Scripting Guy, Cincinnati June 15th!

         

        Ed Wilson, the Microsoft Scripting Guy, will be presenting at the Cincinnati PowerShell User Group meeting on June 15th at MAX Technical Training.

        Topic: Configuration Management with Azure Automation DSC - Cloud & On-Prem, Windows & Linux

        Info and regestration here: http://www.meetup.com/TechLife-Cincinnati/events/230743256/

        See you there!

        3/08/2016

        SharePoint PowerShell Training for Auditing and Site Content Administration

         

        image

        If you have followed this blog, you know that I’m kind of a SharePoint nut who’s also a PowerShell nut. Over the years I have created a lot of PowerShell scripts while working with SharePoint and answering questions in my classes and in the TechNet forums. There’s plenty of resources for installing and configuring SharePoint using PowerShell, but there’s little on dealing with all of the daily questions on premise admins get that can be quickly answered using PowerShell. I was just going to take my 100+ scripts and create something like a “cookbook”, but instead created a class. The class handout kind of ended up as the cookbook… 85 pages and 175 sample scripts, or maybe more like a giant PowerShell cheatsheet for SharePoint.

        This class is for on-premise SharePoint 2010, 2013 and 2016 administrators. A SharePoint Online version is in the works, but not available yet.

        If you would like to attend this class, delivered by the author (your’s turely!), we are offering it next Monday, March 14th, at MAX Technical Training in Cincinnati, Ohio. You can attend this class at MAX or remotely from anywhere. If you can’t attend this class, it is available from trainging centers all over the world.

        March 14th class at MAX: SharePoint 2010 and 2013 Auditing and Site Content Administration using PowerShell

        Search for this class at other training centers: https://www.bing.com/search?q=55095%20powershell

        If you would like to see some of the other courses and books I’ve written, then click here.

         

        55095 SharePoint 2010 and 2013 Auditing and Site Content Administration using PowerShell

        This one day instructor-led class is designed for SharePoint 2010 and 2013 server administrators and auditors who need to query just about anything in SharePoint. The class handout is effectively a cheat sheet with over 175 PowerShell scripts plus the general patterns to create your own scripts. These scripts cover:

        • using the SharePoint Management Shell and the ISE
        • general tips for counting, reformatting and exporting results;
        • drilling up and down the SharePoint object model
        • getting lists / inventories of servers, services web applications, sites, webs, lists, libraries, items, fields, content types, users and much more
        • finding lists by template type, content type and types of content
        • finding files by user, content type, file extension, checked out status, size and age
        • finding inactive sites
        • finding and changing SharePoint Designer settings and finding and resetting customized pages
        • inventorying and managing features
        • deleting and recycling files and list items
        • inventorying users and user permissions and finding out “who can access what”
        • creating sites, lists and libraries
        • uploading and downloading files
        • and much more…

        At Course Completion

        After completing this course, students will be able to:

        • Use PowerShell to query just about anything inside of SharePoint.
        • Understand the core SharePoint object model and object hierarchy as seen from PowerShell.
        • Format PowerShell output in to reports.
        • Manage resources to limit the impact on production servers.
        • Create and delete Site Collections, subsites, lists, libraries and content.

        Prerequisites

        Before attending this course, students must:

        • Very good knowledge of SharePoint and its features.
        • Good experience using PowerShell 2 or later or recent completion of a PowerShell class such as 10961 or 50414.

        Course Outline

        Module 1:  SharePoint and PowerShell

        This module provides an introduction to the topics covered in the class, introduces SharePoint PowerShell terminology and provides a review of important PowerShell features.

        Lessons:

        • History of PowerShell in SharePoint
        • PowerShell vs. Search
        • PowerShell, SharePoint Management Shell and cmdlets
        • Security and Permissions Needed
        • Getting Started with PowerShell: Counting Items, Custom Columns, Reformatting Numbers, Saving Results to a File
        • Changing and Updating Content: Creating SharePoint Objects, Changing Objects

        Lab:

        • Using PowerShell with SharePoint

        After completing this module, students will be able to:

        • Get started using PowerShell to inventory and update SharePoint.

        Module 2: Working with SharePoint CMDLETs and Objects

        This module introduces the SharePoint object model and some important terminology.

        Lessons:

        • GUIDs
        • Sites vs. Webs
        • The SharePoint Object Hierarchy

        Lab:

        • Get a list of all Site Collections and their GUIDs
        • Get a list of all Webs in all Site Collections
        • Given a web’s URL get its parent web and web application

        After completing this module, students will be able to:

        • Explore sites and webs using PowerShell.
        • Retrieve important properties of common SharePoint objects

        Module 3: Managing Memory and Limiting Performance Impact

        This explores limiting impact on server memory usage and performance.

        Lessons:

        • Memory Management and Disposing Objects
        • Limiting Impact on Production Servers

        Lab:

        • Exploring PowerShell’s use of system memory.
        • Testing the impact of scripts on server performance

        After completing this module, students will be able to:

        • Recognize and manage the impact of PowerShell on a SharePoint server.

        Module 4: Working with Content

        This module explores SharePoint using PowerShell from the Farm down to individual list items.

        Lessons:

        • Getting Farm Information: version, services, services, features
        • Getting Web Application information
        • Exploring Site Collections: retrieve Site Collections, Site Collection Administrators, quotas
        • Working with the Recycle Bins: finding items, getting file counts and bytes, deleted sites
        • Exploring Webs: web templates, finding webs, finding webs based on template, Quick Launch and Top Link Bar navigation
        • Exploring Lists and Libraries: finding all lists, lists by type, lists by Content Type, columns/fields, document count by web or library
        • Exploring Content Types
        • Finding documents: by a word in the title, file type, content type, size, date age, checked out status, approval status and many more…
        • Deleting content
        • Downloading and uploading files

        Lab:

        • Explore the farm.
        • Inventory site collections.
        • Create a recycle bin report.
        • Finding all blog sites.
        • Find all picture libraries.
        • Find all PDF files over 5 MB.
        • Delete all videos in a site collection.

        After completing this module, students will be able to:

        • Explorer, inventory and maintain SharePoint content using PowerShell.

        Module 5: Users and Security

        This module covers the use of PowerShell to explore and document SharePoint permissions.

        Lessons:

        • Users: find a user, get a list of all users, working with Active Directory groups
        • SharePoint groups: Get lists of groups, get the members of a group, find all groups a user belongs to, find the groups associated with a web
        • Expanding users lists that include Active Directory groups
        • Documenting Broken Inheritance / Unique Permissions: webs, lists, libraries, folders, items
        • Working with Role Assignments

        Lab:

        • Get a list of all users who have access to a Site Collection.
        • Get a list of all groups in a Site Collection.
        • Get a list of all groups a user belongs to.
        • List all users who may have access to a SharePoint securable.
        • Get a list of all securables with broken inheritance.

        After completing this module, students will be able to:

        • Explore and document users and user permissions.
        • Explore and document SharePoint groups.
        • Explore and document broken inheritance.

        Module 6: Managing Sites

        This module explorers Site Collection and Web management from PowerShell.

        Lessons:

        • Finding Inactive Webs
        • Creating and Deleting Site Collections
        • Getting Site Collection Data
        • Creating and Deleting Subsites
        • Working With SharePoint Designer Settings

        Lab:

        • Create a report for inactive sites.
        • Create a site collection and subsites.
        • Delete a site.
        • Delete a site collection.
        • Disable SharePoint Designer in all site collections.

        After completing this module, students will be able to:

        • Manage SharePoint Site Collections and webs from PowerShell.

        Audience

        • SharePoint server administrators.
        • SharePoint auditors.
        • Also valuable for SharePoint developers.

        2/08/2016

        Azure PowerShell: New-AzureRmAutomationCredential : Input string was not in a correct format.

         

        Not an obvious error message:

        New-AzurermAutomationCredential -AutomationAccountName "PStest" -Name "myPsredential"

        New-AzurermAutomationCredential : Input string was not in a correct format.

        image

        Turns out it means you already have an Azure Automation credential with that name (“myPsCredential” in this example).

         

        Wasted some time google/binging that one!

        .

        1/14/2016

        Azure: PowerShell to List All Blobs in Storage

         

        I have an Azure account for development and testing purposes that I want to keep as clean as possible. Part of my routine is clearing out unneeded blobs in the Storage Accounts. To do this using the Portal UI would take a long time… so PowerShell to the rescue.

        I thought there would be a quick like piped command something like this:
        Get-AzureStorageAccount | Get-AzureStorageContainer | Get-AzureStorageBlob

        But no such luck. There’s extra steps to access the Storage Key and to create an Azure Storage Context object needed.

        # optional!
        $PreviousVerbosePreference = $VerbosePreference
        $PreviousWarningPreference = $WarningPreference
        $VerbosePreference = "SilentlyContinue"
        $WarningPreference = "SilentlyContinue"


        # if not alreay logged in to your Azure account...
        # Add-AzureAccount
        # if more than one subscription
        # Select-AzureSubscription -SubscriptionName ????

        Get-AzureStorageAccount |
          foreach {

            $acct = $_.label; $storageKey = (Get-AzureStorageKey -StorageAccountName $acct ).Primary;

            $ctx = New-AzureStorageContext -StorageAccountName $acct
        -StorageAccountKey $storageKey;

            Get-AzureStorageContainer -Container * -Context $ctx } |

          foreach { $container = $_.Name; $_ } |

          Get-AzureStorageBlob |

          Select {$_.context.StorageAccountName}, {$container}, name,blobtype,length |

          Format-Table -autosize

        # optional!
        $VerbosePreference = $PreviousVerbosePreference

        Select @{label="Storage Account";expression={$_.context.StorageAccountName}},
               @{label="Container";expression={$container}},
               name,
               blobtype,
               @{label="Bytes";expression={"{0,20:N0}" -f $_.length}} |

        $WarningPreference = $PreviousWarningPreference

         

        And if you like pretty columns then replace the Select line with this:

        Select @{label="Storage Account";expression={$_.context.StorageAccountName}},
               @{label="Container";expression={$container}},
               name,
               blobtype,
               @{label="Bytes";expression={"{0,20:N0}" -f $_.length}} |

         

        There’s got to be a better way to do this. So post any better solution as a comment!

         

        Total storage?

        Replace the Format-Table line with “Measure-Object -Property length -Sum” and you can get a file count and total bytes. (Don’t combine this with the “pretty columns” change!)

        .

        Note to spammers!

        Spammers, don't waste your time... all posts are moderated. If your comment includes unrelated links, is advertising, or just pure spam, it will never be seen.