Posted in Editor, Powershell, Snippets, vscode

More Snippets but being Verbose

So this is another 101 level post. Most of my scripting has been for automation and I try to  debug enough that the code is ready to go. I have dabbled with Verbose messaging and normally it didn’t apply so I was easily distracted. I added a personal ToDo, learn to use this handy feature. Quick note, when I have written GUI’s for my scripts. Since they are written for other uses some messaging was in order to save me some helpdesk calls about it. In short I would add a StatusBar with text regions and I would basically add Verbose like messages there. Moving on…

TLDR; so guilty here as I started with If statements and check for Verbose and then change $VerbosePreference, write the message and then set the $VerbosePreference back to where it was. See, this is why I bailed. I also walked on kitten-shells around the write cmdlets with all of the back and forth about write-host and it killed kittens. Focused, let’s do this.

First step: remember the code you should always be adding to your Scripts and Functions

[CmdletBinding()]
Param ()

Again you should be preferencing your scripts and variables,  these  two lines of code make your code “Advanced”.

How does this help? Being an advanced Script or Function you immediately have access to “Common Parameters” and with that Verbose parameter is inherited. No let’s risk the ridicule and look at that Write-Verbose cmdlet.

BEGIN {
...
Write-Verbose -Message "Okay you are in the Begin block"
...
}

That was all it took. No need for If statements or sub-functions… just use that cmdlet.

Since the operator is running in Verbose mode I will be adding this line of code I will be adding this very often. I ran a few test runs and I wanted to include the Lifecycle Block the message is coming from so I started to format the message with [BlockName]Message text. like:

BEGIN {
...
Write-Verbose -Message "[BEGIN]Okay you are in the Begin block"
...
}

Admittedly I have seen this on petri and just saw it as a great practice. Lots of manual typing right. How do  we make that easier? 3.2.1 Snippets!!!!

I added the following to my PowerShell.json file:

<div>
<div>        // Adds verbose messaging in the BEGIN block</div>
<div>        "Add Verbose in Begin block": {</div>
<div>            "prefix": "verbBEGIN",</div>
<div>            "body": ["Write-Verbose -Message \"[BEGIN]${1:Message}\""],</div>
<div>            "description": "Add verbose messaging for activity in the BEGIN block"</div>
<div>        },</div>
<div>        // Adds verbose messaging in the PROCESS block</div>
<div>        "Add Verbose in Process block": {</div>
<div>            "prefix": "verbPROCESS",</div>
<div>            "body": ["Write-Verbose -Message \"[ROCESS]${1:Message}\""],</div>
<div>            "description": "Add verbose messaging for activity in the PROCESS block"</div>
<div>        },</div>
<div>        // Adds verbose messaging in the END block</div>
<div>        "Add Verbose in END": {</div>
<div>            "prefix": "verbEND",</div>
<div>            "body": ["Write-Verbose -Message \"[END]${1:Message}\""],</div>
<div>            "description": "Add verbose messaging for activity in the END section"</div>
<div>        }</div>
</div>

So while in VSCode, working on some code I can type verb and I will see the snippets for each LifeCycle Block. I select the appropriate one, the snippet text is inserted into the code and the message that follows the Block name is highlighted for editing and press tab and I am done.

Something like this:

VSCode - Verbose Message

 

Posted in Powershell, ActiveDirectory

Leaves or not – Removing an AD Computer Object

I read two posts  recently about removing computers from AD, specifically Computers with leaf objects. A computer can have leaf objects for several things, as an example a PrintServer has leaf objects for each Print Queue. I remember coming into the issue with leaf objects in the past. Blindly using Remove-ADObject can be problematic as was mentioned in one of the posts I was reading. If you have ever run a Remove-ADcomputer and received an error you may have just went into AD Computers and Users and just deleted … ugggh lots of mouse clicking.

I took this as a chance to just write a quick piece of PowerShell code that might provide  a better way to handle this. I took a chuck of code which was part of a ForEach loop just to provide a simple one-for-one you can use with which you can test and have some peace of mind.


$testCase = Get-ADComputer somecomputername
$leafObjects = get-ADObject -Filter * -SearchBase $testCase.DistinguishedName
If ($leafObjects.count -gt 0) {
# Leaf objects involved so Remove-ADObject
"Removing $(testCase.Name) with Remove-ADObject"
Remove-ADObject $testCase.DistinguishedName -Recursive -Confirm:$False -Force
}
Else {
# No leaf objects found so we can use the Computer specific method
"Removing $(testCase.Name) with Remove-ADComputer"
$testCase | Remove-ADComputer -Confirm:$False -Force
}

Again this was just some code I scratchpad-ed, any feedback is welcome.

Getting PowerShell Code into a WordPress.com post is just a pain…. where are my tabs? even if I precede indented text with four spaces

Posted in Editor, Powershell, Snippets, vscode

Easy Snippet – Small Tweaks

[These are pretty much 101 level posts]

Still distracted obviously, while on a conference call I was grazing through my VSCode PowerShell snippet file. I came across probably the most basic snippet and noticed it was not only lacking but missing some snippet magic:

        “Function”: {
            “prefix”: “func”,
            “body”: [
                “function $1() {“,
                “\t$0”,
                “}”
            ],
            “description”: “Function”
        },

Look at that mess. What is wrong?:

  1. When used it pastes the function shell but missing the closing curly bracket
  2. The $1() does nothing useful and we know the name of the function should be there.
  3. The $0 was right but again with no closing curly bracket why

So ashamed of myself, okay not really but a chance to improve with what I have learned

The revised version:

“Function”: {
            “prefix”: “func”,
            “body”: [
                “function $FunctionName {“,
                “\t$0# Code goes here\r”,
                “\\}”
            ],
            “description”: “Function”
        },
So what I have now performs the following when I call the Snippet now:
  1. Creates a basic function shell.
  2. The FunctionName term is highlighted first, so you enter the function name before beginning which just seems right.
  3. Once we give the function a name (Verb-Noun of course) we press Tab and we can start replacing “# Code goes here” with the contents of the function.
  4. The closing bracket is there and inline.

This is what it looks like in use.

Code_2018-04-26_16-29-48

 

 

 

Now to go back and fix up my other half-baked snippets and watch to see if I can discover new tricks as the community posts their snippets.

Posted in Editor, Powershell, Snippets, vscode

Distraction for Today – Snippets for VSCode

Current project for the PowerShell VSCode project is opening the Snippets up to the community and for the community. The was announced in the VSCode channel in the Slack group, a resource I strongly recommend.

I have taken the great base snippet file Keith Hill provided in the early days of using VSCode as my PowerShell editor and converted my ISE snippets from the XML file. I can’t complain as I had a useful collection of code snippets for ISE but looking at the format and capabilities that VSCode provided, I quickly started adding my snippets to the base collection Keith Hill provided.

I have one that I like to include in my End statement of a script. As it stood it was usable but was lacking. Watching the community post snippets I saw a chance to take this little nugget and make it better. The code simply starts a remove-variable so I can clean up variables before the script finishes and  then initiate a garbage collection via .Net. Below is what the snippet looked like when I used in my code:

 END {
    Remove-Variable -Name varA, varB, anotherVar
    [System.GC]::Collect()
}

I call the snippet and the code is added, including the tabs and carriage returns. The text area after the Name parameter is where the cursor goes because of  ${1:variablestoberemoved} but that is far as the Snippet automation would go. So I created an empty JSON file and started with the snippet as I had entered it. Then I progressed with fixing and adding some pieces to the snippet. I would then take the new version of just that snippet and replaced the one in the PowerShell.json file, then in a blank script file I would use the prefix and check the progress.

// Original
“Initiate Garbage Collection – Original”: {
            “prefix”: “freememory”,
            “body”:[
                “Remove-Variable -Name \\$variablestoberemoved\r”,
                “[System.GC]::Collect()\r”
            ],
            “description”: “Free up memory when script completes”
    },
    // Now let’s write that with a “tabable”
    “Initiate Garbage Collection – Next”: {
            “prefix”: “freememory”,
            “body”:[
                “Remove-Variable -Name \\${1:variablestoberemoved}\r”,
                “[System.GC]::Collect()\r”
            ],
            “description”: “Free up memory when script completes”
    // That sort of worked but after I enter the variables I want to table
    // tap out of the code because this is done
    },
    // What I finally came up with
    “Initiate Garbage Collection”: {
        “prefix”: “freememory”,
        “body”:[
            “Remove-Variable -Name ${1:variablestoberemoved}\r”,
            “[System.GC]::Collect()\r”,
            “$0”
        ],
        “description”: “Free up memory when script completes”
    }
}
So through the progression testing, I can call the snippet, it will take me to the “variablestoberemoved” enter the variables, comma seperated, that I know will still exist, then I can hit tab will take me to the line after my snippet text. Looks like:
2018-04-26_09-23-33
Quick use of a PowerShell snippet in Visual Studio Code
Posted in Powershell, CLI, ActiveDirectory

Get-ACL for a Computer Object

Just a quick post as I ran into something that really had me confused.  I have used get-acl and set-acl for folders and files, very frequently and easily actually.  Researching an SCCM issue, a scripting task presented itself.  A list of all computers and whether or not the “Windows Authorization Access Group” is listed in the Security for the object.  Using AD Users and Computers, you have to use View\Advanced Features, and then inspect the Security tab for the computer object.  I wrote a quick loop and on one machine it was producing verifiable results while on another machine the results were consistently negative results.

Versions of Powershell are the same, the ActiveDirectory module is the same… hmmmmm what is the difference?  “pwd” revealed the culprit.  What is odd, with my other ACL operations I did not specifiy that the current location is AD:\ but in order for get-acl $machine.DistinguishedName  to work and not return object not found I have to ensure get-location returns AD:\

Posted in Module, Plaster, Powershell

Plaster Baby Steps

Just a quick note… started to get addicted to plaster. One other thing I learned but not fully. I wanted to include the PowerShell Version to the plaster process. I made changes and the template started failing. It would appear there is some case sensitivity:

powerShellVersion='$PLASTER_PARAM_ModulePSVer'
The “p” in powerShellVersion appears to be lowercase only. I have to figure out the parameter names and case sensitivity. I found this by trial and error but I need to get more fluent with it.
Posted in Module, Plaster, Powershell

PowerShell Plaster Baby Steps

I have created modules, normally just for a demo showing how easy it would be to distribute PowerShell. They were simply a script I renamed to psm1 or a psm1 I created and threw some functions in it.

With the current role in, I see a greater need for a few modules. I could go with a bunch of functions in a script, or load scripts during runtime of my main script. I do not want to clutter my script with a large number of functions or even a few lines like:

. .\script1.ps1
. .\script2.ps1

Now I have to admit I have use Sapien’s PowerShell Studio to create a few modules. While I love the product I do not have access to it. That said it creates basic/static module files.

I saw the plaster module, read a few articles about it and at first my response was “meh” but hey it is prompting me for some interesting items so I must be missing something. I spent a day or two but just couldn’t figure something out like adding the Company Name at build time.

I was using Twitter to follow the news coming from the 2018 PowerShell summit. A post announced that there was going to be a presentation regarding Plaster. I liked the post and mentioned that I can’t wait to see the presentation when it was posted.

Two days later I received a link to the presentation. Major thanks to  for facilitating @rjpleau sending me a link to the presentation materials which can be found on github here.

Using this as a practical reference I was able to figure out what I was doing wrong with just get the company name as a runtime option. I know, nothing monumental but I write my own modules but at work I want to ensure I record my employers company name.

Sorry for the formatting of the XML is not great. Basically I copied an existing template (finding that folder is not easy (start looking in $env:userprofile either .vscode or .vscode-insiders then find the powershell module, then modules folder then plaster and then the templates folder). I copied the NewPowerShellScriptModule then renamed it. Then I edited the plastermanifest.xml to what you see below.

<?xml version="1.0" encoding="utf-8"?>
<plasterManifest
    schemaVersion="1.1"
    templateType="Project" xmlns="http://www.microsoft.com/schemas/PowerShell/Plaster/v1">
    <metadata>
        <name>JJK</name>
        <id>dd02bf66-9960-4014-a6fc-f09d5387c189</id>
        <version>1.0.0</version>
        <title>JJK Module Template</title>
        <description>Customized Manifest for creating Modules</description>
        <author>Kavanagh</author>
        <tags>Automation</tags>
    </metadata>
        <parameters>
                <parameter name="ModuleFullName" type="text" prompt="Module author's name" />
                <parameter name="ModuleName" type="text" prompt="Name of your module" />
                <parameter name="ModuleDesc" type="text" prompt="Brief description on this module" />
                <parameter name="Version" type="text" prompt="Initial module version" default="0.0.1" />
                <parameter name="ModuleCompanyName" type="text" prompt="Company name" default='N/A' />
                <parameter name="ModuleScripts" type="choice" prompt="Create a scripts folder for non function scripts?" default='1'>
                        <choice label="&amp;Yes" help="Creates a en-US folder within the module root" value="Yes" />
                        <choice label="&amp;No" help="Does not create a en-US folder within the module root" value="No" />
                </parameter>
        </parameters>
    <content>
        <message>

Scaffolding your PowerShell Module...


</message>
                <newModuleManifest destination='${PLASTER_PARAM_ModuleName}.psd1'
                                                     author = '$PLASTER_PARAM_ModuleFullName'
                                                     moduleVersion='$PLASTER_PARAM_Version'
                                                     rootModule='${PLASTER_PARAM_ModuleName}.psm1'
                                                     companyName='$PLASTER_PARAM_ModuleCompanyName'
                                                     encoding='UTF8-NoBOM'
                                                     openInEditor="true"/>
                <file source='Module.psm1'
                            destination='${PLASTER_PARAM_ModuleName}.psm1'
                            openInEditor="true"/>
                <message>Your new PowerShell module project '$PLASTER_PARAM_ModuleName' has been created.</message>
    </content>
</plasterManifest>

What I learned, and some of this is just take the example and following naming convenstions, in order to get something like a company name value in the resulting psd1 you have to create a parameter value and then include it in the newModuleManifest destination section To call the parameter which in this example is ModuleCompanyName you use $PLASTER_PARAM_ModuleCompanyName.

Cut to the end, in my resulting module’s psd1 you will find:

# Company or vendor of this module
CompanyName = 'KavanaghTech'

Which is the value I entered when I started the invoke-plaster (even easier in VSCode as it is simply availabe in the command palette) using my new template and during the initial process that is the value I entered for the Company Name.

Sorry for the rambling but I just wanted to share what was a major frustration for me. I also wanted to share the greatness that is the PowerShell community.