Quantcast
Channel: Scripting Blog
Viewing all 2129 articles
Browse latest View live

Use WMI and PowerShell to Work with Services

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell and WMI to work with services.

Microsoft Scripting Guy, Ed Wilson, is here. It is that time of the year. I just spent the last couple of hours uninstalling useless software from my laptop. This includes stuff that I intentionally installed and junk that becomes installed with other programs. I also spent a decent amount of time reviewing start-up programs and services. This is pretty much a stop gap measure – it is only a matter of time before I FDISK my machine and perform a complete reinstall.

It still seems necessary to reinstall every year, which is a lot better than it used to be. I can remember a time when I reinstalled twice a year. The Scripting Wife has been talking about reinstalling her laptop for a while. I was kind of hoping to avoid doing all that until Windows 10 ships, but now I am not so sure.

The problem is that although reinstallation is pretty easy these days, finding all the keys, original disks, and so on that seems to take forever. In my case, it seems that I continually find stuff that I am missing for weeks.

I am in the middle of a project now, so I want to avoid that huge time hit for as long as I can. But I did feel the need to do some maintenance and optimization. Luckily, I have Windows PowerShell to aid in the task.

Using native Windows PowerShell commands for services

Windows PowerShell has always had the Get-Service cmdlet. It is great for what it does—and that is to show basic service information. By default, it has an output such as the following:

Image of command output

As shown here, I can easily sort the output by piping it to the Sort-Object cmdlet:

Get-Service | sort status –Descending

To see the running processes first, I need to use the –Descending switch because R (for running) comes before S (for stopped).

I can also get an overview of how many started and stopped services I have by using the Group-Object cmdlet. This technique is shown here:

PS C:\> Get-Service | sort status -Descending | group status -NoElement

Count Name

----- ----

  101 Running

  109 Stopped

This is all based on the default output. What information is available via the Get-Service cmdlet? The best way to find out is to select a single service and send the output to the Format-List cmdlet. This is shown here:

Image of command output

Using WMI

If I want more information about the services, I need to use WMI. Here is the default output when I use the Get-CimInstance Win32_Service command:

Image of command output

To get a better look at what is available, I use the –Filter parameter to return only information about the Bits service:

Get-CimInstance Win32_Service -Filter "name = 'bits'" | fl *

The output is shown in the following image:

Image of command output

For the purposes of optimizing my laptop, I like the following properties:

  • Description
  • StartName
  • StartMode
  • PathName

This information tells me what the service does, what account it uses to start up, how the service starts, and even the executable it uses. This information helps me make the decisions I need. Lately, I have found that when I search for information about services on the Internet, I get pages of spam sites that are useless (at best).

This is why I am glad that I can get this kind of detailed information via Windows PowerShell. When I need additional information, I search TechNet or MSDN directly, and I can normally find good stuff there.

I use the following command to obtain the output from WMI:

$p = 'name', 'startname', 'startmode', 'pathname', 'description'

Get-CimInstance Win32_Service -Filter "state = 'running'" -Property $P | FL $P

The command and its output are shown here:

Image of command output

That is all there is to using WMI and Windows PowerShell to work with services. WMI Week will continue tomorrow when I will talk about more cool stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy


PowerTip: Compare Processes with PowerShell

$
0
0

Summary: Learn how to compare two processes with Windows PowerShell.

Hey, Scripting Guy! Question How can I use Windows PowerShell to find the differences between two instances of the same process
           running on my system?

Hey, Scripting Guy! Answer Use the Compare-Object cmdlet and specify specific properties to examine, such as cpuidvm, and ws.
            Here is an example that uses two instances of Notepad:

$a = Get-Process -Id 6208

$b = Get-Process -Id 10744

Compare-Object -ReferenceObject $a -DifferenceObject $b -Property cpu, ws, vm, id

Get Process Owner and Other Info with WMI and PowerShell

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell and WMI to retrieve process owner and other information.

Microsoft Scripting Guy, Ed Wilson, is here. We were supposed to receive seven inches of snow the other day. They closed schools and businesses, and the roads were swamped with people rushing to various stores in preparation for the snowstorm of the century. Of course, the century is still not all that old, and the storm was not that big of a deal.

In fact, as it turned out, it really was not a big deal at all. We received less than a half-inch of snow, and even that did not stick around. So the kids were outside trying to make snow persons, but they did not have enough snow to do so. Perhaps they could have bought some via the Internet. It was all a non-event.

Something that is not a non-event is using Windows PowerShell to retrieve cool information. As I have mentioned, for basic process information, nothing beats the Get-Process cmdlet. It is fast, works remotely, and is really easy to use. But there are times I need to know more information.

First up, what file is open?

I like the detailed command information that is available in Windows PowerShell via WMI when I query the Win32_Process cmdlet. For example, I can often find out what file is open by looking at the command line. I use the Get-CimInstance cmdlet, and pipe the output to the Format-List cmdlet so I can see all of the properties. This command is shown here:

Get-CimInstance Win32_Process -Filter "name = 'notepad.exe'" | fl *

In the following output, the CommandLine property shows me that I have a specific file open in Notepad.

Image of command output

By using a command like the following, I can find what process has a file locked or filter the results based on the file name:

PS C:\> Get-CimInstance Win32_Process | where commandline -match 'applog'

ProcessId            Name             HandleCount         WorkingSetSize      VirtualSize       

---------            ----             -----------         --------------      -----------        

10076                notepad.exe      114                 9093120             2199130263552      

After I have this information, I can stop the process if I need to do so. This is shown here:

PS C:\> $proc = Get-CimInstance Win32_Process | where commandline -match 'applog'

PS C:\> Invoke-CimMethod -InputObject $proc -MethodName Terminate

                                   ReturnValue PSComputerName                              

                                   ----------- --------------                               

                                             0                         

Get the owner of the process

To get the owner of the process, I use the GetOwner method from the Win32_Process class that I retrieve when I query for instances of Notepad. The first thing I do is use Get-CimInstance to retrieve instances of Notepad:

  Get-CimInstance Win32_Process -Filter "name = 'notepad.exe'"

Next, I store the returned object in a variable:

$proc = Get-CimInstance Win32_Process -Filter "name = 'notepad.exe'"

Now I call the GetOwner method from the Invoke-CimMethod cmdlet. The cool thing is that Tab completion works, so I can cycle through the available methods. The command is shown here:

Invoke-CimMethod -InputObject $proc -MethodName GetOwner

Here is the command and the output from the command:

Image of command output

That is all there is to using WMI methods and Windows PowerShell to retrieve information. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Fix Network Connection Profile with PowerShell

$
0
0

Summary: Use Windows PowerShell to fix the network connection profile on your laptop running Windows 8.1.

Hey, Scripting Guy! Question How can I use Windows PowerShell to fix the connection profile for my home network on my laptop
           running Windows 8.1?

Hey, Scripting Guy! Answer Use the Get-NetAdapter cmdlet to verify the interface index, and then use the 
           Set-NetConnectionProfile cmdlet to specify the network category, for example:

Set-NetConnectionProfile -InterfaceIndex 9 -NetworkCategory Private

PowerShell Spotlight: Windows PowerShell User Groups

$
0
0

Summary: Windows PowerShell MVP, Teresa Wilson, talks about Windows PowerShell user groups in this edition of PowerShell Spotlight.

Microsoft Scripting Guy, Ed Wilson, is here. Today is the last Saturday of the month, and that means it is PowerShell Spotlight time. Here is our guest blogger for the day, Teresa Wilson, with information about user groups...

Greetings everyone,

I hope you are off to a great start with your weekend, and thank-you for allowing me to be part of your day. I would like to shine the spotlight on user groups today. I realize that there are many places where attending a local user group meeting is not an option, but we have ways of dealing with that scenario. Stay tuned...

First, let me give you two webpages to look at to see if there is a user group near you or near a place you plan to visit:

Ed and I have attended user group meetings all over the world. Any time we plan to go out of town, we always check to see if there is a user group on our path. If possible, we contact the user group lead to verify the meeting. Whenever possible, we attend.

For example, I am headed to Philadelphia the last of March for an MVP event. I contacted the leaders of the Philadelphia user group and explained that I would be in Philadelphia. I asked if they would be conducting a meeting around that time. They changed their normal meeting date to coincide with the date I will be in town. The cool part is that MVPs, Jim Christopher and Steven Murawski, are also planning to attend.

If anyone is interested in attending the Philadelphia meeting with us, it is Thursday, March 26. The webpage to follow is Philadelphia PowerShell User Group. The meeting on March 26 is not their normal meeting date, so I am sure they will update their webpage after their normal meeting on March 5.

Speaking of March 5...

That is the next scheduled user group meeting in Charlotte. Ed and I will be there. Jason Walker will be talking about DSC here is a link to the meetup page: Charlotte PowerShell Users Group. At our last meeting, our guest speaker was Terri Donahue. She spoke about IIS. I did not get to hear it because I was sick and stayed home, but Ed liked it and asked her to write a guest blog. That blog is scheduled right here for tomorrow.

As I mentioned earlier, if you do not live in an area that has a user group, and your area is not populated enough to make it feasible to start one, you may want to get on board with one of the user groups that broadcast their meetings.

Obviously, the Virtual PowerShell Group is, well, virtual. It is led by MVP, Joel Bennett. The Mississippi user group is headed up by MVPs, Mike Robbins and Rohn Edwards, and it is virtual. Some user groups meet live and also broadcast their meetings. For example, the Arizona user group does this.

I am thrilled to say that I used to know more about the workings of each user group. But now we have broadened our horizons, and we have more than 40 user groups, so I cannot keep up with all the details for each group.

I am always available to help. Please let me know if you want to start a group or if you need any ideas or assistance. I had some IMs this week with @chri_tea. He is starting a group somewhere exciting! You may want to follow him on Twitter so you know the latest and greatest news.

I am out of time here, and that’s the most important info I have about user groups. See you next month.

~Teresa

I invite you to follow me on Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

PowerTip: Use PowerShell to Decrypt Files

$
0
0

Summary: Use Windows PowerShell to decrypt files.

Hey, Scripting Guy! Question How can I use Windows PowerShell to decrypt a file that it previously encrypted?

Hey, Scripting Guy! Answer Use the Decrypt static method from System.IO.File .NET Framework class, for example:

[io.file]::Decrypt("C:\fso\FileWithOutExtension")

Weekend Scripter: Use PowerShell to Update SSL Bindings

$
0
0

Summary: Microsoft IIS MVP, Terri Donahue, talks about using Windows PowerShell to update SSL bindings.

Microsoft Scripting Guy, Ed Wilson, is here. Today, please welcome back IIS MVP, Terri Donahue. Terri is an IIS MVP, but she also attends the Charlotte PowerShell User Group meetings and events. Take it away, Terri...

I recently spoke about IIS at the Charlotte PowerShell User Group monthly meeting. One of the questions that I was asked related to updating SSL bindings after a certificate is renewed. As anyone that manages SSL certificates across multiple servers knows, this can be a time consuming task. I found a great article by Jason Helmick, IIS: Manage multiple certificates on multiple Web servers, and I used that as the basis for this quick script to update the SSL bindings to a newly issued certificate.

Because all companies use different methods of SSL administration, there isn’t going to be a perfect answer to capture the most important piece of data that is needed for the script. The thumbprint is a unique identifier for a certificate that is located in the certificate store. This is the identifier that is used for completing the crucial piece of the script to actually bind the certificate to the IP.

If you want to script updating certificate bindings, I recommend adding a friendly name with a year designation to your certificates (if you do not already do that). For the purpose of this blog post, only one SSL certificate will be used. You can modify the script to include steps for as many certificates as needed.

Prep work

For this example, we are going to ensure that the friendly name is set and it has a unique identifier of the year the certificate was issued. To do this, open the Certificates add-in for the local computer in the MMC. Browse to Personal, and then click Certificates. You will see a list of the certificates that are installed on the computer, for example:

Image of menu

Right-click the certificate to which you want to add a friendly name and select Properties. Enter a distinguishable friendly name and click OK. For example, you can add the year to the end of the name. This will allow you to have multiple pieces of information available to ensure that you capture the correct certificate. Here is an example:

Image of menu

After you have assigned a friendly name, export the certificate to a .pfx file. Then create a text file named webservers.txt that contains the list of servers where this certificate will need to be installed and the IIS bindings updated.

Copy and install the .pfx file

Begin by creating the reference to the list of servers where this process should run and instantiating a Windows PowerShell remote session:

$servers = Get-Content d:\temp\webservers.txt

$session = New-PsSession –ComputerName $servers

The script copies the .pfx file from your computer to the servers where it will be installed:

$servers | foreach-Object{copy-item -Path d:\temp\*.pfx -Destination "\\$_\c$"}

CertUtil.exe is used to install the .pfx file into the certificate store:

Invoke-command -Session $session {certutil -p td -importpfx c:\testdomain.pfx}

The .pfx file is then deleted from the remote machine:

$servers | foreach-object {Remove-Item -Path "\\$_\c$\*.pfx"}

Update certificate bindings

You need to capture the thumbprint of the installed certificate:

Invoke-Command -session $session {$CertShop=Get-ChildItem -Path Cert:\LocalMachine\My |
where-Object {$_.subject -like "*testdomain*" -and $_.FriendlyName -like "*2015*"} |
Select-Object -ExpandProperty Thumbprint}

The WebAdministration module provides access to the IIS drive, which allows you to modify the SSL bindings:

Invoke-Command -session $session {Import-Module WebAdministration}

The next step is to remove the existing binding from the IP address:

Invoke-Command -Session $session {Get-Item IIS:\SslBindings\10.238.82.89!443 | Remove-Item}

And finally, update the SSL binding to use the new certificate:

Invoke-Command -Session $session {get-item -Path "cert:\LocalMachine\My\$certShop" |
new-item -path IIS:\SslBindings\10.238.82.89!443}

Hopefully, you will find this as useful as I have.

~Terri

Thanks, Terri—awesome as always.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

PowerTip: Use PowerShell to Return Directory Information

$
0
0

Summary: Use Windows PowerShell to return directory information.

Hey, Scripting Guy! Question How can I use Windows PowerShell to provide information about directories in a specific location?

Hey, Scripting Guy! Answer Use the Get-ChildItem cmdlet, specific the path and use the –Directory switch, for example:

Get-ChildItem e:\data -Directory


Write and Run PowerShell Script Without Scripting

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about writing and running a Windows PowerShell script without scripting.

Hey, Scripting Guy! Question Hey, Scripting Guy! I like using the Windows PowerShell ISE, but I do not have rights to run a script. I am stuck using a twenty year-old command prompt with Windows PowerShell inside. What’s up with that?

—DM

Hey, Scripting Guy! Answer Hello DM,

Microsoft Scripting Guy, Ed Wilson, is here. This afternoon I am sipping a cup of Gunpowder green tea, with a bit of fresh lemon juice in it. It is a nice refreshing treat for a midafternoon slump. Of course, the biscotti also helps. Anyway...

DM, welcome to Script Without Scripting Week. Because you use the Windows PowerShell ISE, does not necessarily mean that you are scripting. In fact, you can write a script and run a script, and still not be scripting.

I have pretty much quit my exclusive use of the Windows PowerShell console, and I do nearly all of my Windows PowerShell work inside the Windows PowerShell ISE. But unless I am doing something complex, I do not bother writing a script. I just use the Windows PowerShell ISE as a better, more modern console. If I choose to write in the upper-script pane or type directly in the interactive pane is more a function of whether my command will be one line or longer.

Even if have your script execution policy set to Restricted, you can still use the Windows PowerShell ISE. For Windows PowerShell purposes, a script is not a script until it reads from the disk. So all commands typed in the script pane and executed are simply Windows PowerShell commands, and they are not subject to the script execution policy. However, when you save the code to a file, the next time you run it, it will be a script. Here is an example:

Image of command output

When I save the script as a file, and then I attempt to run the script, the following error message appears to inform me that running scripts is disabled:

Image of error message

If I open the script in Notepad, copy the contents to the clipboard, and then paste the script into a new Windows PowerShell ISE pane, I can run the script as I did before. This is shown here:

Image of command output

Using bypass

There are many ways to run a Windows PowerShell script when the execution policy is set to Restricted. But the easiest way is to launch Windows PowerShell with the bypass execution policy. Here is the command:

powershell -executionpolicy bypass

As shown here, I type this command in the Run dialog box:

Image of dialog box

This command launches the Windows PowerShell console in bypass mode. But what about the Windows PowerShell ISE? Let's try to use the following command:

powershell_ise -executionpolicy bypass

I receive an error message that says there is no such parameter:

Image of error message

So what do I do? As shown here, I can use the simple ISE command inside the Windows PowerShell console that I launched in bypass mode:

Image of command

Now I go to my newly opened Windows PowerShell ISE, and I see that it is in bypass mode. I then open and run my Windows PowerShell script:

Image of command output

DM, that is all there is to using the ISE without scripting. Script Without Scripting Week will continue tomorrow when I will talk about more cool stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Use PowerShell to Show Illegal File Name Characters

$
0
0

Summary: Use Windows PowerShell to display illegal characters for a file name.

Hey, Scripting Guy! Question How can I use Windows PowerShell to easily obtain a list of characters that are not permitted in file names?

Hey, Scripting Guy! Answer Use the GetInvalidFileNameChars static method from the System.IO.Path .NET Framework class:

[System.IO.Path]::GetInvalidFileNameChars()

Avoid Scripting: Use PowerShell Command History

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about avoiding Windows PowerShell scripting by using command history.

Hey, Scripting Guy! Question Hey, Scripting Guy! I used to have a program that I could use to keep track of commands I typed at the command prompt. It permitted me to use macros to replay those commands or to select which commands I wanted to run. It was simple, elegant, and not complicated. It is a shame that “modern” programs are not that easy to use. I really don’t relish the thought of having to learning scripting to be able to run a few commands. I wish I could go back to my old command prompt. But I guess I cannot. No action required. I am just letting off steam today. Thanks for listening.

—LM

Hey, Scripting Guy! Answer Hello LM,

Microsoft Scripting Guy, Ed Wilson, is here. The Scripting Wife and I were out and about the other day, before the snow storm hit, and we ran across a little tea shop that had a very nice Lapsang Souchong tea. It is one of the few teas that I drink with milk. I find I need the milk to help cut the rather strong, unique flavor. If you haven’t had this tea, you may want to try it sometime—but don’t rush out and buy a pound of it just yet. It is a bit of an acquired taste, and you might not like it.

It is a good tea to try off a nice tea menu to see if you like it. I find it goes really well with Scottish butter cookies—but again, that may be me. I find the combination to be a bit “old school”;  but then, it may be that I fell in love with the combination a long time ago when we were in Australia for the first time.

Speaking of old school...

Yeah, I think I may remember using an old-fashioned command prompt a long time ago. It was simple—but I also remember some of the commands were pretty convoluted, and they all seemed to act differently. The good thing, LM, is that you can use the Windows PowerShell console in a similar fashion to how you used the command line. You do not have to learn scripting if you do not want to. All you need to do is to use the command history.

Windows PowerShell command history

There are a number of Windows PowerShell cmdlets that permit working with the command history. I can find them by using the Get-Command cmdlet, and then looking for a name that matches History and a command type that equals Cmdlet. Here is the command and the results:

PS C:\> Get-Command -Name *history* -CommandType cmdlet

CommandType     Name                                        ModuleName

-----------               ----                                               ----------

Cmdlet          Add-History                                        Microsoft.Powe...

Cmdlet          Clear-History                                     Microsoft.Powe...

Cmdlet          Get-History                                        Microsoft.Powe...

Cmdlet          Invoke-History                                    Microsoft.Powe...

To see the commands in my history, I use the Get-History cmdlet:

PS C:\> Get-History

  Id CommandLine

  --   -----------

   7 clhy

   8 cls

   9 h

  10 cls

  11 Get-Command -Noun history

  12 cls

  13 Get-Command -Noun history -CommandType cmdlet

  14 Get-Command -Noun history -CommandType Cmdlet

  15 Get-Command -Noun history

  16 Get-Command Get-Command -Syntax

  17 cls

  18 Get-Command -Name *history* -CommandType cmdlet

If I find myself using the Get-History cmdlet often, I can use an alias. Here is the Get-Alias command:

PS C:\> Get-Alias -Definition Get-History

CommandType     Name                                     ModuleName

-----------               ----                                            ----------

Alias           ghy -> Get-History

Alias           h -> Get-History

Alias           history -> Get-History

If I want to run a command from the history, I use the Invoke-History cmdlet. I generally use Get-History and Invoke-History together. I need to see what is in my history before I can execute a prior command. The easiest way to run something from the history is to specify the command ID. This technique is shown here:

PS C:\> Get-History

  Id CommandLine

  --     -----------

  21 clhy

  22 cls

  23 Get-History

  24 cls

  25 Get-Service bits

  26 Get-Process explorer

  27 cls

 

PS C:\> Invoke-History -Id 25

Get-Service bits

Status   Name               DisplayName

------        ----                   -----------

Running  bits               Background Intelligent Transfer Ser...

As shown here, I can specify an array of ID numbers for the Get-History cmdlet:

PS C:\> Get-History -Id 25, 26

  Id CommandLine

  --    -----------

  25 Get-Service bits

  26 Get-Process explorer

But when I attempt to use an array of IDs with the Invoke-History cmdlet, I get the following error message:

Image of error message

Hmmm…

Well, I can pipe the results from Get-History to Invoke-History:

PS C:\> Get-History 25 | Invoke-History

Get-Service bits

Status   Name               DisplayName

------       ----                   -----------

Running  bits               Background Intelligent Transfer Ser...

Because I can get multiple items from the history, can I also pipeline them? As shown in the following image, I still get an error message:

Image of error message

Bummer.

When I see an error message that says a cmdlet will not accept multiple items through the pipeline, I can usually substitute the command for one that includes Foreach-Object. This is because Foreach-Object interrupts the pipeline and deals with each item, one at a time. It ruins “streaming” the output, but it permits me to pipe the results from one command to another. I can also automate the output without having to resort to scripting. Here is the revised command:

Get-History -Id 25, 26 | foreach { Invoke-History -id $_.ID}

As shown in the following image, the command works:

Image of command output

LM, that is all there is to using the Windows PowerShell command history. Script Without Scripting Week will continue tomorrow when I will talk about more cool stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Use PowerShell to Generate Random File Name

$
0
0

Summary: Use Windows PowerShell to generate a random file name.

Hey, Scripting Guy! Question How can I use Windows PowerShell to generate a random file name so I can ensure that
           a file I create does not have a naming conflict?

Hey, Scripting Guy! Answer Use the GetRandomFileName static method from the System.IO.Path .NET Framework
           class, for example:

[System.IO.Path]::GetRandomFileName()

Don’t Script: Edit PowerShell Command History

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about editing the Windows PowerShell command history.

Hey, Scripting Guy! Question Hey, Scripting Guy! I liked your ideas in Avoid Scripting: Use PowerShell Command History. My problem is that I seldom (if ever) type commands perfectly the first time—often, not even the second time. This means that I end up with a lot of junk in my command history. I wish there was a way to clean up the command history so it would be more usable. Is there?

—AP

Hey, Scripting Guy! Answer Hello AP,

Microsoft Scripting Guy, Ed Wilson, is here. This afternoon, I am listening to a Canadian rock group and sipping some pomegranate tea. Of course, pomegranate is not really a tea, and a pomegranate tea is actually an herbal fruit kind of concoction. But hey—it is still nice and refreshing, and it doesn’t have any caffeine in it. Along with chocolate biscotti, it makes a great way to work.

AP, another great way to work is to use your Windows PowerShell command history. It is actually very flexible, and it is pretty easy to edit the history if you want to do so.

Editing the Windows PowerShell command history is perhaps a misnomer. I cannot really edit the command history, but I can delete items from it and add items to it. I cannot edit an actual entry from the command history—well actually, I could, but I would need to export the history to a file, edit the file, and then import the history back in, which is a bit more work than I want to do. (If this was a scenario that I found myself doing on a regular basis, I could write a function to make it more doable.)

How do I remove stuff from my Windows PowerShell command history? I use the Clear-History cmdlet. I will admit that when I first saw this cmdlet, I thought that it...well...cleared all of my history from Windows PowerShell. And it will do that, of course. Here is an example:

PS C:\> Clear-History

PS C:\>

I type the command, and nothing returns. If I want to see a bit more information, I can use the standard –Verbose Windows PowerShell parameter. This will tell me that the command is clearing my Windows PowerShell command history. This is shown here:

PS C:\> Clear-History -Verbose

VERBOSE: Performing the operation "Clear-History" on target "This command will clear all the entries from the session history."

As shown here, I can also use the –WhatIf parameter if I am unsure that I want to remove all items:

PS C:\> Clear-History -WhatIf

What if: Performing the operation "Clear-History" on target "This command will clear all the entries from the session history."

But the cmdlet is more flexible than simply emptying my Windows PowerShell history. I could remove specific items from my Windows PowerShell history. Before I remove a specific item from the Windows PowerShell command history, I like to look at the command. I can do this by using the Get-History cmdlet and specify a specific ID number. I then pipe the results to the Format-List cmdlet so I can see more information than the standard output. Here is the standard output:

PS C:\> Get-History 67

  Id CommandLine

  --   -----------

  67 srv

Here is the more detailed output:

PS C:\> Get-History 67 | fl *

Id                 : 67

CommandLine        : srv

ExecutionStatus    : Completed

StartExecutionTime : 3/2/2015 3:15:36 PM

EndExecutionTime   : 3/2/2015 3:15:36 PM

Because a command completed (as did the previous command), it does not mean that it completed successfully. Here is what happens when I try to use the Invoke-History cmdlet (r is an alias) to execute the command:

PS C:\> r 67

srv

srv : The term 'srv' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

At line:1 char:1

+ srv

+ ~~~

    + CategoryInfo          : ObjectNotFound: (srv:String) [], CommandNotFoundException

    + FullyQualifiedErrorId : CommandNotFoundException

Finding a specific command

So I have a command that doesn’t work in my Windows PowerShell command history. I can find all of these types of commands by using the Get-History command and piping the results to the Where-Object cmdlet. I already know that I have a property called CommandLine that contains my commands. Here is the command I use to find the commands:

PS C:\> Get-History | where commandline -eq 'srv'

  Id CommandLine

  --   -----------

  67 srv

  78 srv

  81 srv

Removing the bad commands from history

I thought I might need to pipe the results of my Get-History cmdlet to the Clear-History cmdet. But as it turns out, I don’t need to do that. I can use Clear-History to search for and remove my bad command:

Clear-History -CommandLine 'srv'

Sweet…no errors. Then I decide to use the Up arrow to recall my previous Get-History command. Bummer. I still have a couple of entries remaining:

PS C:\> Get-History | where commandline -eq 'srv'

  Id CommandLine

  --   -----------

  78 srv

  81 srv

I remember to use the count. I see that there are two instances of the bad command still in history, so I use the Up arrow and add the count. Here is my command:

Clear-History -CommandLine 'srv' -Count 2

Now when I use the Get-History command, nothing appears.

These commands and their associated output are shown in the following image:

Image of command output

AP, that is all there is to editing the Windows PowerShell command history. Script Without Scripting Week will continue tomorrow when I will talk about using code snippets.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Use PowerShell to Find Temp User Directory

$
0
0

Summary: Use Windows PowerShell to find the temporary user directory.

Hey, Scripting Guy! Question How can I use Windows PowerShell to find location of my temporary user directory?

 Hey, Scripting Guy! Answer Use the GetTempPath static method from the System.IO.Path .NET Framework class:

[System.IO.Path]::GetTempPath() 

Don’t Write Scripts: Use Snippets

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell snippets to avoid scripting demands.

Hey, Scripting Guy! Question Hey, Scripting Guy! One of the things that I find myself having to do from time-to-time is write scripts. I really don’t like to write scripts, but sometimes I cannot find what I need to, and I cannot avoid it. I really wish that when I do have to write a script, I could make it as painless as possible. Is painless possible?

—RA

Hey, Scripting Guy! Answer Hello RA,

Microsoft Scripting Guy, Ed Wilson, is here. Well tonight is the Charlotte PowerShell Users Group meeting. We will be having a guest presentation by Microsoft PFE, Jason Walker. Jason is a really cool dude, and he has written quite a few guest Hey, Scripting Guy! Blog posts (in fact, he is an Honorary Scripting Guy). So, the meeting tonight will be awesome. The Scripting Wife and I have been looking forward to it for a while.

RA, something else that is awesome is using Windows PowerShell ISE snippets to reduce the amount of scripting involved in creating a custom solution.

When I open the Windows PowerShell ISE, the first thing I need to do is start the snippets. To do this, I can type <CTRL +J>, or simply select Start Snippets from the Edit menu:

Image of menu

The snippet drop-down list appears and it shows me what snippets are available. The list is shown here:

Image of menu

If I hover my mouse over the snippet for a few seconds, the actual code that comprises the snippet appears. This will appear on the left if it is a long piece of code, such as the complete advanced function. It will appear on the right if it is relatively short, such as the comment block. Here is the comment-block snippet:

Image of script

If I want to insert the code snippet into my script, I highlight the snippet from the drop-down list, and press ENTER. The current insertion point in the script governs where the code snippet will appear. This means that I need to place my mouse cursor exactly where I want the snippet to appear in my script. So the following comment block appears at the beginning of my script because that is where my cursor is:

Image of command output

The cool thing about this snippet is that it moved my insertion point to the place where I would more than likely actually type. Of course, the fact that I have a comment in the middle of a comment block is a bit strange—but hey, it works, and it helps me avoid typing.

Now I decide to add a For loop. I move my insertion point after my comment block, and start the snippets again (I like to use <CTRL + J> because it keeps my hands on the keyboard). I select For from the drop-down list. The description tells me it is a For loop. I press ENTER, and voila! The For loop appears in my code.

The strange thing is that I am left on the For line, not in the code block. But I guess that makes sense because most of the time I am not going to loop 99 times. I add the output for $i into the script block, and I press the green triangle (or <F5>) to run my script. The output is shown here:

Image of command output

I place my insertion point after the $i that I added to the script, start the snippets again, and add an If statement to my script. I have to change the $x variable to $i, and set a condition that $i is equal to 5. I then add code in the script block so that the script will break when the $i condition matches. I then run the script again. The script and the output are shown here:

Image of command output

So I did very little typing, and in less than a minute, I had a script “that does something.” Windows PowerShell code snippets offer two advantages:

  1. They help if one cannot remember exact syntax. In this way, they often provide enough so that one can quickly get the code written without having to look up everything.
  2. They help an experienced scripter avoid a lot of typing. In this way, the snippets help save time.

RA, that is all there is to using Windows PowerShell ISE snippets. Script Without Scripting Week will continue tomorrow when I will talk about creating snippets.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy


PowerTip: Use PowerShell to Identify Files Without an Extension

$
0
0

Summary: Use Windows PowerShell to identify files that do not have an extension.

Hey, Scripting Guy! Question How can I use Windows PowerShell to easily identify files that do not have an extension?

Hey, Scripting Guy! Answer Use the HasExtension static method from the System.IO.Path .NET Framework class, for example:

[System.IO.Path]::hasExtension("C:\fso\FileWithOutExtension")

Don’t Script: Create PowerShell Snippets

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about creating custom Windows PowerShell snippets.

Hey, Scripting Guy! Question Hey, Scripting Guy! Thank you for yesterday's blog post, Don’t Write Scripts: Use Snippets. I like the idea of having access to Windows PowerShell script snippets. But I used to create my own snippets. It made it easier for me to work, and I could create a custom script based on my snippets in less than 30 seconds. I don’t see anything like that these days. Am I missing something? Please help me understand.

—JT

Hey, Scripting Guy! Answer Hello JT,

Microsoft Scripting Guy, Ed Wilson, is here. This morning, it is raining. It looks like spring time outside. It is almost warm, and it really is damp. So, as a result, I got soggy on my way to the gym for my morning workout. To me, it just seems wrong to drive to the gym, so I always walk or run there. Anyway, after drying off and changing, I got on the treadmill to finish warming up.

Luckily, the gym has WiFi, so I was able to check the email sent to scripter@microsoft.com when I finished my workout. JT, one of the cool things about Windows PowerShell ISE snippets, is that I can easily create my own snippets. I can even save them, and copy them to other devices. This makes them really great to use. One thing to keep in mind is that I cannot create a new snippet if the execution policy is set to AllSigned or Restricted. I will get an error message.

Anything that I type over and over again in my Windows PowerShell scripts becomes fair game for a script snippet. Of course, the things I have a tendency to type over and over again tend to depend on what sort of a script I am writing.

For example, if I am working with Word, I will obviously need to create an instance of the Word.Application object. If I am working on a script that connects to remote servers, I usually query Active Directory Domain Services to obtain a list of servers. So, I might need to create multiple snippets that cover the basic types of scripts I tend to write.

The cool thing is that there is a New-ISESnippet cmdlet I can use to create a new snippet. I can call the cmdlet directly, or I can write a script to create the snippet. I can even overwrite an existing snippet with the same name by using the –Force parameter. I specify the title, the description, author information, and the text. The text is the actual content of my snippet. The –CaretOffset parameter specifies how far over the insertion point moves. This parameter requires a bit of experimentation to get it right. Here is an example of a script that creates a new ISE snippet:

New-IseSnippet -Force -Title "Basic Heading" -Description "Basic script heading info" `

 -Author "ed wilson" -CaretOffset 18 -Text "

 # Script name:

 # Script description:

 # Script category:

 #

 # Date:

 # Version: 1.0

 # "

When I run the script, the newly created snippet appears in the snippet list. (I use <Ctrl+J> to start the snippets, but I can also click Start Snippets from the Edit menu.) The newly created snippet is shown here in the drop-down list:

Image of menu

I select the snippet, press ENTER, and it is inserted into my new blank script file. This is shown here:

Image of command output

One thing to keep in mind is that even if I use the –Force parameter to overwrite existing snippets, if I run the script multiple times, I will get multiple instances of the snippet appearing in the snippet drop-down list. To fix this issue, all I need to do is to close the Windows PowerShell ISE and open it. The extraneous entries no longer appear in the drop-down list.

To delete a snippet, I use the Get-ISESnippet cmdlet and pipe the results to the Remote-Item cmdlet. This technique is shown here:

PS C:\> Get-IseSnippet

    Directory: C:\Users\ed\Documents\WindowsPowerShell\Snippets

Mode             LastWriteTime     Length    Name                                                       

----                -------------                  ------    ----                                                       

-a---          3/3/2015  10:33 AM        783 Basic Heading.snippets.ps1xml                              

PS C:\> Get-IseSnippet | Remove-Item

JT, that is all there is to creating your own script snippets. Script Without Scripting Week will continue tomorrow when I will talk about saving scripts from applications.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Encrypt Files with PowerShell

$
0
0

Summary: Learn how to easily encrypt files by using Windows PowerShell.

Hey, Scripting Guy! Question How can I use Windows PowerShell to easily encrypt files?

Hey, Scripting Guy! Answer Use the Encrypt static method from the System.IO.File .NET Framework class, for example:

[io.file]::Encrypt("C:\fso\FileWithOutExtension")

Weekend Scripter: Avoid PowerShell Scripting—Use GUI Tools

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about exporting queries from the event log tool.

Microsoft Scripting Guy, Ed Wilson, is here. It has long been a truism (at least with things related to computers): powerful is opposite of simple. I can have a tool that is powerful, but with that power comes complexity. When that complexity is so complex as to render the tool ridiculously hard to use, the tool rapidly becomes useless.

What is awesome is when a tool is extremely powerful and also very easy to use. Of course, this usually means that the tool makes lots of default choices for me. If those default choices are intelligent, I really don’t care. Microsoft Word is sort of like that. I mean, the default document template makes tons of choices. Usually, I do not care about the exact spacing between paragraphs, the default Tab stop, column width, or page length. Usually…

Of course, when I have to modify those things, I know I am probably going to have to set aside all day.

The Windows PowerShell cmdlet Get-WinEvent is often perceived to be such a tool. It is way powerful—but it is also more complicated to use, than for example, the Get-EventLog cmdlet. The problem with Get-EventLog is that it only works for legacy event logs. For all the newer (new as in Windows Vista era—so not really all that new at all) types of logs, I need to use Get-WinEvent. Because Get-WinEvent also works with legacy event logs, I have completely quit using the Get-EventLog cmdlet. This forces me to learn how to use the Get-WinEvent cmdlet.

One problem with the Get-WinEvent cmdlet, is at first glance, it is hard to figure out how to filter the results. It is a truism, that for performance sake, I filter to the left of the pipeline character. So this means that I do not use Get-WinEvent to return everything and then pipe it to the Where-Object.

This is especially true with some logs that return thousands of records. But how do I filter, for example, on an Event ID? Here is the syntax that shows the various parameter sets (ways of using the cmdlet):

PS C:\> Get-Command Get-WinEvent -Syntax

 

Get-WinEvent [[-LogName] <string[]>] [-MaxEvents <long>] [-ComputerName <string>] [-Credential

<pscredential>] [-FilterXPath <string>] [-Force] [-Oldest] [<CommonParameters>]

 

Get-WinEvent [-ListLog] <string[]> [-ComputerName <string>] [-Credential <pscredential>] [-Force]

[<CommonParameters>]

 

Get-WinEvent [-ListProvider] <string[]> [-ComputerName <string>] [-Credential <pscredential>]

[<CommonParameters>]

 

Get-WinEvent [-ProviderName] <string[]> [-MaxEvents <long>] [-ComputerName <string>] [-Credential

<pscredential>] [-FilterXPath <string>] [-Force] [-Oldest] [<CommonParameters>]

 

Get-WinEvent [-Path] <string[]> [-MaxEvents <long>] [-Credential <pscredential>] [-FilterXPath

<string>] [-Oldest] [<CommonParameters>]

 

Get-WinEvent [-FilterXml] <xml> [-MaxEvents <long>] [-ComputerName <string>] [-Credential

<pscredential>] [-Oldest] [<CommonParameters>]

 

Get-WinEvent [-FilterHashtable] <hashtable[]> [-MaxEvents <long>] [-ComputerName <string>]

[-Credential <pscredential>] [-Force] [-Oldest] [<CommonParameters>]

From this, there are basically three ways of filtering:

  • Via XML
  • Via a hash table
  • Via XPath

Dude!!!

The easy way to an XPath query

Believe it or not, the easy way to filter the results of Get-WinEvent is with XPath. This is because I can use the Event Viewer to create my query for me. To do this, I open the Event Viewer, right-click the log, and choose Filter Current Log from the action menu. I then use the check boxes, drop-down lists, and text boxes to filter the content of the selected log. This is shown in the following image:

Image of menu

I then click the XML tab to look at the query. This is shown here:

Image of menu

Now I select the Edit query manually check box. This permits me to highlight the query. I always copy the query and paste it into Notepad. When I have the query in Notepad, I select the Path portion of the query:

Image of command

I open the Windows PowerShell ISE, create my query, and add a line for my Get-WinEvent cmdlet:

$xpath = "*[System[(Level=2) and (EventID=35)]]"

Get-WinEvent -LogName application -FilterXPath $xpath 

And that is the easy way to query a log by using the Get-WinEvent cmdlet.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Use PowerShell to Read the Content of a ZIP File

$
0
0

Summary: Learn how to use Windows PowerShell to read the content of a .zip file.

Hey, Scripting Guy! Question How can I read the content of a .zip file from within Windows PowerShell?

 Hey, Scripting Guy! Answer Use the OpenRead static method from the IO.Compression.ZipFile .NET Framework class.
            First, you will need to load the assembly that contains the class. Here is an example:

Add-Type -assembly "system.io.compression.filesystem"

[io.compression.zipfile]::OpenRead("E:\Ch10.zip").Entries.Name

Viewing all 2129 articles
Browse latest View live