Category Archives: Script Sharing

A collection of helpful PowerShell scripts, functions, and modules.

Creating Multiple Credential Objects Part II

Download the updated function here: https://gist.github.com/tommymaynard/98031ccd5de67005bf3063db06a33851

Back in January 2015, I wrote a post and uploaded an advanced function to the TechNet Gallery that allows a user to create multiple credential objects. Edit: The TechNet Gallery no longer hosts scripts/modules, so use the GitHub Gist at the top and bottom of this page. The multiple part is up to the user, such as they might enter a command as in the below example. Due to the -Set 2 parameter and parameter value, they would get prompted twice, to enter a username and password combination. When the function was completed, they would have two credential objects, with the first stored in $CredSet1 and the second stored in $CredSet2.

New-TMMultiCred -Set 2

I had always wanted to make a couple of changes to the advanced function, and so I have. Now the function includes a -NoGui parameter, that will not require the username and password be entered into the Get-Credential GUI, and can instead be entered directly into the console. I should mention that if this was run in the ISE, the password would actually invoke a small GUI for the password, as is standard when using Read-Host‘s -AsSecureString parameter in that host.

The other addition I wanted to add is that the advanced function produces objects, instead of using the Write-Output cmdlet to display information. Now, instead of the function writing this:

SUCCESS: Credential Set 1 stored in $CredSet1
SUCCESS: Credential Set 2 stored in $CredSet2

the function writes this:

CredSet             Variable            UserName                                 Password
-------             --------            --------                                 --------
1                   $Credset1           mydomain\admin       System.Security.SecureString
2                   $Credset2           user1                System.Security.SecureString

Neat, right? So download it and try it out. I think it was a decent addition to an already helpful advanced function.

Download the updated function here: https://gist.github.com/tommymaynard/98031ccd5de67005bf3063db06a33851

Write-Output Gets Foreground and Background Colors and More

Every once in a while a forum post comes along that really captures my interest. Take this one for instance.

In this post, the creator wanted to build out a start up menu in the ConsoleHost that has a solid white line, another white line below that, with the words “PowerShell Project 1” in it, and a final white line beneath that. That might be difficult to imagine, so here’s a visual representation, and then what his/hers looked like. I had recommended to use a here-string to fix the problem, but unfortunately we didn’t have the same results.

write-output-gets-foreground-and-background-colors-and-more01
Note: While you can’t see them, in both this and the below image, there are spaces on the lines above, below, and before and after “PowerShell Project 1.” This is how we can ensure the white rectangle around the text.

write-output-gets-foreground-and-background-colors-and-more02

I can’t say for certain why theirs rendered differently, but I suspect version, or PSReadline, or possibly console font/size. That wasn’t important; what was, was trying to figure out a way around this problematic inconsistency. We have the option to change the background color of the area where we type, and so I wondered if I could temporarily do that inside the ConsoleHost. It turns out I could. With that new piece of knowledge, I set out to write a wrapper function around Write-Output. In my version — Write-TMOutput — it includes -ForegroundColor and -BackgroundColor parameters with an option to horizontally and vertically pad the text (object).

First, here’s a few images to show my new function in action. This first image shows the commands included in the TMOutput module.

write-output-gets-foreground-and-background-colors-and-more03

The next example image shows some basic, Write-Output type usage. One where we pipe to the function, and one where we don’t. Fairly standard.

write-output-gets-foreground-and-background-colors-and-more04

Now, the next example is where this starts to get fun: the incorporation of the -ForegroundColor and -BackgroundColor parameters. Prior to running these commands, and those in the last two examples, I removed the PSReadLine module so the colors would be easier to spot.

write-output-gets-foreground-and-background-colors-and-more05

Next is a demo of two additional parameters: -HorizontalPad and -VerticalPad. These will allow you to add spaces before and after the value supplied to the -InputObject parameter (the text), and add lines above and below the text. This is the part that gets back to the request in the Microsoft Technet forum post. I should mention that my solution in the forum post would be different now that I’ve spend some time writing this function — there are better ways to do things that I hadn’t considered at the time I replied to the post.

write-output-gets-foreground-and-background-colors-and-more06

The next example shows some usage with the Get-ADUser cmdlet. Keep in mind that if you combine this function with other cmdlets, that the -HorizontalPad and -VerticalPad parameters cannot be used. In my mind, they’re just a bonus to the option of using colors with Write-Output. I should mention it now, but this function was intentionally written to only work in the ConsoleHost. Perhaps I’ll add the option of using it in the ISE in the future.

write-output-gets-foreground-and-background-colors-and-more07

I’ve written an additional function that will allow you to quickly see the available colors from which you can choose. It’s called Show-TMOutputColor, and produces the results below. This might come in handy as you’re using the modified Write-Output.

write-output-gets-foreground-and-background-colors-and-more08

Now, on to the module. It’s the first time I’ve done it, but I’ve uploaded this to the PowerShell Gallery. I believe publishing to the PowerShell Gallery was one of my PowerShell New Year’s Resolutions for 2016, so there’s one down! You can use this direct link or, one better, download the module from your console, using this command:

Install-Module -Name TMOutput

Thanks for reading this post. Hopefully these function will be a useful way to get around the need for Write-Host’s foreground and background color options while working in the console. That, and maybe the TechNet thread creator can do whatever they wanted, too.

Multi-Level Menu System with a Back Option

It’s been said several times now, but while this site was designed to help people learn some Windows PowerShell, it’s also about posting things I’m going to want to find one day. Take for instance this menu system I started for someone on TechNet: https://social.technet.microsoft.com/Forums/en-US/30663446-4091-4a1c-9de0-407046ccc39f/powershell-script-with-submenus-how-to-go-back?forum=winserverpowershell.

It allows the user the ability to enter into menus and submenus with the option of backing out of them. You know, choose a number from the menu, or hit B to go back to the previous menu. Hopefully it’s helpful for the TechNet thread creator, and maybe it’s helpful for others someday, too. I’ve included both the code and an image of the code in action. Until next time.

Do {
@'

----------Software/Driver Installation----------
1. Toshiba 1
2. Acer 1
------------------------------------------------

'@

    $MainMenu = Read-Host -Prompt 'Enter 1 - 2 or Q to quit'
    Switch ($MainMenu) {
        1 {
            Do {
@'

---------Software/Driver Installation----------
1. Software
2. Drivers
------------------------------------------------

'@
                $1MainMenu = Read-Host -Prompt 'Enter 1 - 2 or B for Back'
                Switch ($1MainMenu) {
                    '1' {
                            Do {
@'

--------------Software Installation-------------
1. Package 1
2. Package 2
3. Package 3
------------------------------------------------

'@
                                $1InnerMenu = Read-Host -Prompt 'Enter 1 - 3 or B for Back'
                                Switch ($1InnerMenu) {
                                 '1' {Write-Output -InputObject '--> You chose to install package 1'; break}
                                 '2' {Write-Output -InputObject '--> You chose to install package 2'; break}
                                 '3' {Write-Output -InputObject '--> You chose to install package 3'}
                                }
                            } Until ($1InnerMenu -eq 'B')
                        }
                }
            } Until ($1MainMenu -eq 'B')
        }
    } # End Switch.
} Until (
    $MainMenu -eq 'Q'
)

multi-level-nested-menu-system-with-a-back-option01

View Current PowerShell.org Q&A Forum Topics

Note: Update added at the bottom on this post on August, 9, 2016. Please read.

Sometimes you don’t always have the time to finish something you’ve started. For me, it was this function. I pounded this out in a quick few minutes, and while I don’t see myself investing in it any further, I didn’t want to forget the function, and thought I would hang on to it somewhere. Well, that’s why it’s here, especially as someone may find it useful, or helpful.

The function, which I called Get-PowerShell.orgForumTopic, runs out to PowerShell.org and grabs the current topics (page one) from the PowerShell Q&A forum (http://powershell.org/wp/forums/forum/windows-powershell-qa). It only returns the Thread name and the URL, because, well, that’s what seemed useful and relevant at the time I wrote it (which was many months ago).

Function Get-PowerShell.orgForumTopic {
    [CmdletBinding()]
    Param ()

    Begin {
    } # End Begin.

    Process {
        (Invoke-WebRequest -Uri 'http://powershell.org/wp/forums/forum/windows-powershell-qa/' |
            Select-Object -ExpandProperty Links |
            Where-Object {$_.outerHTML -like '*http://powershell.org/wp/forums/topic*'} |
            Select-Object @{N='Thread';E={$_.innerHTML}},@{N='Url';E={$_.href}} |
            Select-Object -First 30)[(0..30 |
                ForEach-Object {
                    If (-not($_ % 2)) {
                        $_
                    }
                 }
            )]
    } # End Process.

    End {
    } # End End.
} # End Function: Get-PowerShell.orgForumTopic

Here’s what the results looked like in the ConsoleHost, near in time to when this post was published.

current-powershell.org-qa-forum-topics-01

While I never added any more to this function, I had some ideas: add the thread status, add the “started by user,” add the user that made the last post, add the number of posts per topic, and allow it to run against other PowerShell.org forum topics. It might’ve also been helpful to include additional pages, if requested by the user of the function, such as adding a -Pages parameter (-Pages 4).

Anyway, here it is. Beside being helpful to see the top PowerShell.org Q&A forum posts at a specific point in time, it’s an interesting example of reading from a webpage, of which I had minimal experience. So yeah, I probably learned something by doing this exercise.

If you want to do the same, then start by running the first command, Invoke-WebRequest -Uri ‘http://powershell.org/wp/forums/forum/windows-powershell-qa/’. Then add the pipe and first Select-Object command and run that. Then add the Where-Object command, and so on. This will allow you to see how I finally got to only returning the “Threads” and “Urls.” Take care.

Update: Since a site redesign at PowerShell.org, this function, no longer functions. I’m not sure that I’ll bother to update it — I don’t get the feeling that it was ever used by anyone — but I’ll keep this post up for anything else it may offer, that may be helpful in learning PowerShell.

Find the Account that Starts a Service

There was an email I wrote to a team member last week. The point behind it was to help the team member determine what service(s) might be running under a certain account. The Get-Service cmdlet has never provided this functionality, so I mentioned that they use the Win32_Service WMI class (with Windows PowerShell, of course).

This suggestion led to me write and send them a list of command examples to include local vs. remote computers, pulling computer’s from a text file and Csv file, and using Active Directory. It seemed like a fairly solid list, and so I thought it should be posted here. I won’t bother including any output, because it’s fairly easy to figure out what’s going to be returned — the name of the service, the account used to start/run the service, and the remote computer name, in some of the commands that run against remote computers.

This first example is how to run the command against the local computer. This will return all the services on the local computer to include the account that is used to start the listed service.

PS> Get-WmiObject -Class Win32_Service | Select-Object Name,StartName

This example shows how to run the same command above, against a single remote computer. The only difference is the addition of the -ComputerName parameter and the Server01 parameter value.

PS> Get-WmiObject -ComputerName Server01 -Class Win32_Service | Select-Object Name,StartName

In this example, we run the same command above, except we do run it against two computers. In order to know which computer returned which result, we include the PSComputerName property.

PS> Get-WmiObject -ComputerName Server01,Server02 -Class Win32_Service | Select-Object PSComputerName,Name,StartName

Here’s one way to use a text file. The Get-Content cmdlet executes first, because it’s in parenthesis. The results of this command are then provided to the -ComputerName parameter.

PS> Get-WmiObject -ComputerName (Get-Content -Path C:\computers.txt) -Class Win32_Service | Select-Object PSComputerName,Name,StartName

This example does the same thing as the command above; however, it does so by piping the results of the Get-Content cmdlet to the ForEach-Object cmdlet. Within each iteration of the foreach loop, it runs the Get-WmiObject command. In testing, there wasn’t much different in the time it took to complete this example when compared to the last one.

PS> Get-Content -Path C:\computers.txt | ForEach-Object {Get-WmiObject -ComputerName $_ -Class Win32_Service | Select-Object PSComputerName,Name,StartName}

This next example utilizes a Csv File. In a Csv file, we have (column) headers; therefore, we need to indicate to PowerShell the column we’d like to use. Let’s assume we have a Csv with three columns of data with the headers Location, NameOfComputer, and Year. We’ll need to make sure we’re instructing our command to only use the data in the NameOfComputer column.

PS> Get-WmiObject -ComputerName ((Import-Csv -Path C:\computers.csv).NameOfComputer) -Class Win32_Service | Select-Object PSComputerName,Name,StartName

Here’s the same example as above, but this one uses a pipeline and ForEach-Object cmdlet, much like we did with the text file. While there’s little difference in the time it takes to complete, I would recommend that we don’t use a pipe when it’s not necessary, or when it’s doesn’t give us an advantage.

PS> Import-Csv -Path C:\computers.csv | ForEach-Object {Get-WmiObject -ComputerName $_.NameOfComputer -Class Win32_Service | Select-Object PSComputerName,Name,StartName}

Let’s incorporate Active Directory (AD), since it’s another place where we can get computers. This first AD example returns all the computers from a specific Organization Unit (OU) and runs them through the Get-WmiObject cmdlet. As in previous examples, this command will return all the values before it provides them as the value to the -ComputerName parameter.

PS> Get-WmiObject -ComputerName ((Get-ADComputer -Filter * -SearchBase 'OU=Engineering,OU=Workstations,DC=mydomain,DC=com').Name) -Class Win32_Service | Select-Object PSComputerName,Name,StartName

In my coworker’s situation, one of the computers in the OU was down, so we needed a way to filter around that problem. Here’s two ways to do that; however, the second option is the better of the two. If you’ve never heard it before, hear it now: filter as close to the left of your commands as possible.

PS> Get-WmiObject -ComputerName ((Get-ADComputer -Filter * -SearchBase 'OU=Engineering,OU=Workstations,DC=mydomain,DC=com' | Where-Object {$_.Name -ne 'Server22'}).Name) -Class Win32_Service | Select-Object PSComputerName,Name,StartName

PS> Get-WmiObject -ComputerName ((Get-ADComputer -Filter {Name -ne 'Server22'} -SearchBase 'OU=Engineering,OU=Workstations,DC=mydomain,DC=com').Name) -Class Win32_Service | Select-Object PSComputerName,Name,StartName

 

Two Old HTAs: LoggedOnUser and Remote Desktop Assistant

There was a recent Windows PowerShell forum post that discussed HTAs. Due to that, I thought I would discuss a couple old HTAs I wrote and include their download links. Many people may not know it, but I was once a VBS aficionado. I had a task to set some registry settings back in 2005, or 6, and ended up staring some VBS examples right in the face. I was instantly hooked. I starting writing all kinds of things, and today I’m going to share two of my old HTAs — a couple favorites.

HTAs are HTML Applications. They allowed script writers, such as myself, the ability to create GUIs for their scripts. I suddenly had a way to hand over scripts in an easy to use fashion for users, and other IT personnel.

Funny story, but when Windows PowerShell — a.k.a Monad — was first introduced, I was excited at first, but then I was pissed (upset, not drunk). I had put so much time and effort into VBS, that moving to something else was upsetting. I’ve gotten over that now; I would need an extremely large pay day, to write and/or troubleshoot any VBS.

The first of the two HTAs I’ll share is called LoggedOnUser (1.6). Its original purpose was to determine who was logged on to a specific computer. Here’s what the HTA looks like when it’s first opened.

script-sharing-two-old-htas-loggedonuser-and-remote-desktop-assistant-2015-01

While you may not know what to do right away, there’s a tooltip that displays when you hover over the textbox, that reads, “Enter computer name, IP address, cmd or exit.” If someone entered “cmd” and pressed Enter, it would open the command prompt. I guess that seemed important at the time. If you entered “exit” and pressed Enter, then the HTA would close. Hopefully no one had a computer named cmd or exit! I wrote this for myself, so I assume I wasn’t worried about that possibility. If a computer name or IP is entered, it would attempt to connect over the network (using VBS and WMI), and populate three fields: Computer (as in the computer’s name), the currently logged on user as domain\user, and the full domain. Here’s an example:

script-sharing-two-old-htas-loggedonuser-and-remote-desktop-assistant-2015-02

After some time had passed, I decided to do more with this daily used HTA. I added a drop down menu that would perform different tasks, such as open C$, open Computer Management, and start a Remote Desktop Connection to the listed computer.

script-sharing-two-old-htas-loggedonuser-and-remote-desktop-assistant-2015-03

It was a fun project and the HTA was actively used from 2007 to probably 2013, by myself and at least one other IT shop. In my 1.5 version (one previous to this 1.6 version), there was a drop down option that opened up an inventory system to the listed computer’s inventory webpage. The inventory system had been built using a .vbs start up script deployed via Group Policy. It would collect computer information (including the logged on user), and write it to an Access database back end (yes, Access). Classic ASP was used for the web front (yes, classic ASP). Good times. I can say this: learning VBS made learning classic ASP extremely easy.

You can download this HTA here: LoggedOnUserv1.6 (6765 downloads )

The second HTA I’ll share was an amazing test of my patience. I’d like to thank Tool’s 10,000 Days for getting me through it.

I called this one Remote Desktop Assistant and its purpose was to store computer descriptions and matching IP addresses, or computer names. Choosing a computer from the list would allow a user to start a Remote Desktop Connection. This first screen shot shows the HTA when there are no stored computers. Let’s add one.

script-sharing-two-old-htas-loggedonuser-and-remote-desktop-assistant-2015-04

This image below, is what it looks like when it’s storing a computer for us. It stores this information in a computers.txt file in the same location as the HTA. Move the HTA and not the text file, and no computers will be listed, and the HTA will create a new computers.txt file. Yes, it’s creates this file if it can’t find one. With a single computer entered, such as we have below, the text file would contain one line that reads: Server01;10.10.10.35. It’s two strings with a semi-colon delimiter.

script-sharing-two-old-htas-loggedonuser-and-remote-desktop-assistant-2015-05

The server (Server01), in the image above was added by entering a description in the “Computer Description” textbox, and a corresponding computer name or IP address in the “IP Address or Computer” text box. When a user clicks on the computer in the left, it populates the the two textboxes and changes the “Choose Computer” button to a “Launch Remote Desktop” button. Do you see all this fanciness!?

script-sharing-two-old-htas-loggedonuser-and-remote-desktop-assistant-2015-06

If you press “Launch Remote Desktop” then it will do just that. The three bottom buttons: About…, Notes, and Feedback, offer some additional information about the HTA. It’s nothing monumental, but I was pleased with my ability to resize the form and replace the text in the lower area. The Hide button closes the lower, informational panel. Take a look below to see what I mean.

script-sharing-two-old-htas-loggedonuser-and-remote-desktop-assistant-2015-07

script-sharing-two-old-htas-loggedonuser-and-remote-desktop-assistant-2015-08

Well, that was a fun trip down memory lane. Who knows, these might actually be helpful for someone. One of the things I did, which I may share in a future post, was rewrite the LoggedOnUser VBS/HTA using PowerShell. There’s no GUI, but it does everything that HTA does, way faster, and with much less code. As you check these out, please keep in mind I wrote these around 2005 – 2007, or 8. Cheers!

You can download this HTA here: RDAssistantv2.1 (9295 downloads )

Update: Use PowerShell and Active Directory to create your computers.txt file: http://tommymaynard.com/quick-learn-prep-computers-txt-file-for-hta/.

Script Sharing – Remote Desktop Prompts for Multiple Computers

Yes, I still RDP* (occasionally). I am using it less and less, but there are still times when getting inside a system’s GUI is seems necessary. I’m into this Windows PowerShell thing, if you haven’t noticed, so you can rest assured that every time I RDP, I also do my best to figure out how to get the same information using PowerShell. In fact, this often leads to new functions and tools. I just remembered this, but in the earlier days of learning PowerShell I would try and replicate everything I did in the GUI, in PowerShell. If you’re wondering how to learn PowerShell, well then, there you go.

* RDP stands for Remote Desktop Protocol. While you can’t Remote Desktop Protocol into a server, the acronym is often used as a verb: “Hey, RDP over to bigserver1 and let me know if you see the same problem.”

Anyway, let me share a function that I occasionally use. Take a look at the code, and then I’ll briefly discuss it below.

Set-Alias -Name rdp -Value Connect-TMRDP
Set-Alias -Name rdc -Value Connect-TMRDP
Function Connect-TMRDP
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$true,Position=1,ValueFromPipeline=$true)]
        [Alias('cn')]
        [string[]]$ComputerName,

        [Parameter(Position=2)]
        [string]$DomainName
    )
    Begin {
    } #End Begin

    Process {
        If ($DomainName) {
            Foreach ($Computer in $ComputerName) {
                If ($DomainName -match '^\.') {
                    mstsc.exe /v "$Computer$DomainName"
                } Else {
                    mstsc.exe /v "$Computer.$DomainName"
                }
            }
        } Else {
            Foreach ($Computer in $ComputerName) {
                mstsc.exe /v $Computer
            }
        }
    }
}

This function allows me the ability to remote desktop into several systems at a time. While it won’t enter user names and passwords for me, it’ll present me the Windows Security logon dialog for each computer name supplied as a value to the -ComputerName parameter. That’s why I wrote it. If you’ve ever used mstsc.exe /v, and got tired of typing that over and over for each machine, now you can save time by typing something like rdp dc01,dc02,web01 and it’ll open a logon dialog for each. The rdp (and rdc) alias is created right before the function — a function I’ve named Connect-TMRDP.

Maybe this helps, may it doesn’t, but it sure speeds up the time it takes me to RDP to several servers at once. I know, I know — the simple fact that I need to RDP to several computers at once makes an even better case for PowerShell. Again, continuing to use RDP on occasion has led to some nice PowerShell tools, and I expect that this will continue.

I did want to mention one final thing about this function. It’s set up to handle the domain name being included in several different ways, if it’s included at all. Each of the examples below will work.

PS> rdp -ComputerName bigserver01
PS> rdp -ComputerName bigserver01.mydomain.com
PS> rdp -ComputerName bigserver01 -DomainName .mydomain.com
PS> rdp -ComputerName bigserver01 -DomainName mydomain.com

Script Sharing – Functions and Code from My Profile

Over the last couple of years, my profile ($PROFILE) has filled up with a bunch of little functions that I use to help shave seconds off my day. I’ve shared a few in other posts, but here’s a few more that I’ve yet to share, that might be interesting. As a forewarning, in many of these, I understand that there may be a better way to do things.

This first one uses Google to show me the definition of a word. It isn’t written to return results to the Windows PowerShell console, but instead will launch the definition in a web browser. It was good enough at the time, and still is on a occasion (when I don’t actually know what a word means ;)) .

Set-Alias -Name lookup -Value Get-Definition
Function Get-Definition {
    Param (
        [Parameter(Mandatory = $true)]
        [string]$Word
    )
        Start-Process "https://www.google.com/?gws_rd=ssl#q=define:$Word"
}

Here’s an example I just used today, when I read Don Jones’ post about Jeffrey Snover’s promotion to Technical Fellow: http://donjones.com/2015/09/02/congratulations-jsnover-a-well-earned-honor.

Functions and Code from my Profile ($PROFILE)01

And, because why not, here’s a photo of Jeffrey Snover and me. For those of you new to PowerShell, I’m on the right; Snover, PowerShell’s inventor, is on the left. Thanks to PowerShell.org and Will for the photo.

Me and Snover (front)

This next inclusion isn’t a function, but has turned out to be quite helpful. I recently posted it on Twitter. By entering the alias “snip” into the console, I’m able to quickly open the snipping tool. In fact, I just used the alias to grab the screen capture, for the Get-Definition function, above.

Set-Alias -Name snip -Value "$env:SystemRoot\system32\SnippingTool.exe"

Here’s a screen capture of the Snipping Tool program.

Functions-and-Code-from-my-Profile-PROFILE02

This next one is also not a function, but extremely helpful, and likely to be some of the oldest code in my profile. This, while quite small, saves me all the time. Here’s how it works: When the PowerShell console opens, it checks the title bar — the WindowsTitle — for any left or right square brackets: this [, or this ]. If it doesn’t find them, it then modifies the WindowsTitle to include my computer’s name inside square brackets. It is extremely handy to be able to quickly verify that I’m typing in to the console on my machine and not inside a console on a RDP session. Yes, I still RDP for some things, and yes, I will also, at times, open a PowerShell console inside the RDP session (as strange as that may be).

# Set Console Window Title
If (-not($Host.UI.RawUI.WindowTitle -like "*`[*`]*")) {
    $Host.UI.RawUI.WindowTitle += " [$($env:COMPUTERNAME)]"
}

Since I’ll occasionally take and upload screen captures (see the first example, above), I wanted a quick way to remove my edited WindowsTitle, so it didn’t show my computer’s name. That gave way to this micro function to return the WindowsTitle to its default (yes, it’s hard coded) — my console is always elevated (however, the log on to my computer is not). I suppose what I should do, is assign the default text, when the console is first opened, and before the WindowsTitle is changed, into a variable for later use in this function.

# Set Default Console Window Title
Function Set-WindowTitleDefault {
    $Host.UI.RawUI.WindowTitle = 'Administrator: Windows PowerShell'
}

The last function I’ll share today is called Get-PSRemotingSession and it allows me to see if anyone is actively using PowerShell Remoting on a specific computer, or computers. It’s basically a wrapper function for Get-WSManInstance (without having to remember the required parameters).

Function Get-PSRemotingSession([string[]]$ComputerName) {
    Foreach ($C in $ComputerName) {
        Get-WSManInstance -ComputerName $C -ResourceURI Shell -Enumerate | Select-Object -Property Owner,ClientIP
    }
}

That’s all I’ve got for today. I hope that some of these might have been helpful enough to incorporate into your profile. If there’s things you can’t live without in your profile, that you want to share, then comment below, or share them on Twitter.

Update: The last function I introduced, Get-PSRemotingSession, has been updated. Only returning the Owner and ClientIP was fine when I only ran it against a single computer. The problem, when I ran it against multiple computers, is that I didn’t know the name of the computer that had the remote session — it wasn’t included in the output. Therefore, I updated the function, as seen below, so that it’ll indicate the computer name. It can’t get the computer name as part of what’s returned from Get-WSManInstance (without resolving the ClientIP), but it can based on which computer it’s checking to begin with (the value in $C). Here’s the updated version:

Function Get-PSRemotingSession([string[]]$ComputerName) {
    Foreach ($C in $ComputerName) {
        Get-WSManInstance -ComputerName $C -ResourceURI Shell -Enumerate | Select-Object -Property @{N='ComputerName';E={$C}},Owner,ClientIP
    }
}

Script Sharing – Get Synonyms for Approved and Unapproved Verbs

Download link at bottom of post. Note: This post contains information that is necessary to know to use this function. Please read it if you think you’ll try using this function.

Update: The previous version of the function (1.0) required the user to register and obtain an API key, and place it inside the function’s code. I’ve only had some 40 downloads, so I’ve opted to include my API key to see if this function can get more usage. This really can be a great tool, and so it seems the best idea for now. If anyone ever hits an error using the API key, please let me know: <my1stname>@<thisdomain>.com. (6/10/2016)

I consider myself a best practice kind of guy; especially when it comes to Windows PowerShell. There’s been a time or two where I’m quite sure that I, politely, called someone out for using an unapproved verb. If you’re familiar with PowerShell, then you know that cmdlet and function names should use the verb-noun naming convention. Now, no one cares about the nouns you choose, but verbs need to be approved.

If you haven’t before, try running the Get-Verb cmdlet. This cmdlet, when used without any parameters, will return all the approved verbs. Even for me, there’s been a time or two when the verb I wanted to use wasn’t approved. In that case, I recommend still finding and using an approved verb, but also creating an alias that you can use to call your properly named, cmdlet or function. Here’s a modified example from one of my previous posts:

Set-Alias -Name Launch-InternetExplorer -Value Open-InternetExplorer
 
Function Open-InternetExplorer {
    # Do Stuff.
}

In this example, that was originally posted here: http://tommymaynard.com/quick-learn-create-a-function-to-open-internet-explorer-like-in-run-2015, I can use Launch as my verb, since I’ve made it part of an alias. The function name with the approved verb is Open-InternetExplorer and my alias, that will run this same function, is Launch-InternetExplorer.

So, where am I going with this: I’ve always wanted a function that would allow me to pull back synonyms for a verb, and today, I have just that. I considered walking though what I did to write this, but instead, because it ended up being somewhat lengthy, I posted it on TechNet for download.

Before I provide a download link, I should mentioned that you’re going to need to do a couple things to make this function work for you.

  1. Go to http://thesaurus.altervista.org/mykey and register for an API key.
  2. Download my function from the link at the bottom of the page.
  3. Open the function in the ISE, or your editor of preference, and replace [string]$Key with [string]$Key ='<Your API Key>’, replacing <Your API Key> with key you received from step 1.

Now when you use the function, it’ll use your API key. In addition, we won’t have to make the -Key parameter mandatory, forcing it to prompt us for the key, even when the $Key variable is being assigned a value inside the function. Thanks!

get-synonyms-for-approved-and-unapproved-verbs01

Update: The newest version is now available for download on the PowerShell Gallery.

Download the Get-TMVerbSynonym advanced function here: https://gallery.technet.microsoft.com/Get-Synonyms-for-Approved-f6625752

Copy Outlook Signature to Clipboard

As far as I am aware, the in-house built front end for our help desk ticketing system, doesn’t have a way to include a signature. This means that as I update and close tickets in the office, I often find myself opening a new, blank email, copying my signature, and pasting it in the notes field on the ticket. I know, I know — I’m embarrassed.

No more, am I going to consider this acceptable, especially for someone that uses PowerShell for as many things as I do: it’s. always. open. Today was the day I fixed this forever, and it took a whole two minutes.

I needed to first determine where Outlook (2013 on Windows 8.1) looks for my signature. I traced it down to C:\Users\tommymaynard\AppData\Roaming\Microsoft\Signatures. In that path there are three files named Standard — the same name used for my Signature in Outlook, when I open the Signatures and Stationary dialog. There is a .htm version, a .rtf version, and a .txt version of the signature. Simple decision: I decided I would make use of the text file.

Since I was going to use this in my profile, I didn’t include anything inside the function, but the simple command I wanted to run. Based on the function below, all I need to do is enter Get-Signature, or its alias, and my function will copy the contents of Standard.txt to my clipboard. From there, it’s a quick paste into the help desk ticketing system, and done.

Set-Alias -Name sig -Value Get-Signature
Function Get-Signature {
    $SigPath = 'C:\Users\tommymaynard\AppData\Roaming\Microsoft\Signatures\Standard.txt'
    Get-Content -Path $SigPath | Select-Object -First 4 | clip
}

If you’ve taken a look at the function, you’ll see that I only choose the first 4 lines of the signature file. This was because there was a blank line beneath the last line in my signature, that I wasn’t interested in copying (or manually removing from the file itself).