Quantcast
Channel: Hey, Scripting Guy! Blog
Viewing all 3333 articles
Browse latest View live

PowerTip: Use PowerShell to Count Types of Images

$
0
0

Summary: Use Windows PowerShell to count different types of image files.

Hey, Scripting Guy! Question How can I use Windows PowerShell to see a count of the different types of image files on my computer?

Hey, Scripting Guy! Answer Use the Get-ChildItem cmdlet to find the image files and then pipe the results to the Group-Object cmdlet,
           for example:

dir -Recurse -ea 0 -File -path e:\data -include "*.gif","*.jpg", "*.png", "*.bmp" | 
group extension -NoElement

Note  Dir is an alias for Get-ChildItem and Group is an alias for Group-Object.


Weekend Scripter: Use PowerShell to Find Longest Cmdlet Name

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to find the longest cmdlet name.

Microsoft Scripting Guy, Ed Wilson, is here. This is an exciting time of the year, as we get ready for the PowerShell Summit in Charlotte and for the Microsoft Ignite conference in Chicago. I have been having numerous email conversations with various individuals the past week. One of the fun exchanges took place with Windows PowerShell MVP and Honorary Scripting Guy, Sean Kearney. We are planning something cool for Ignite, and we were bouncing ideas around, for example, "I wonder which Windows PowerShell cmdlet name is the longest?" I know there are some long ones, especially when it comes to the NetAdapter or TCP cmdlets, but which is longest? And of course, how long is it really?

I played around for a couple of minutes and came up with a Windows PowerShell script that provides the answer. Let’s take a look…

First I need to get the cmdlet names (and also the CIM-wrapped functions). So I use the Get-Command cmdlet to retrieve all of the cmdlets. I then pipe the CmdletInfo object to Select-Object where I create a custom object that provides the name and the length of each name. Let's take a look at the first part of that command:

Get-Command |

Select-Object @{label = 'name'; expression = {$_.name}}, 

I use Select-Object to create the custom object. The first property of that object is the name. I pick that up directly from the Name property of the CmdletInfo object that streams across the pipeline. To get the length of the name, I need to use the Measure-Object cmdlet.

The name of the second property of my custom object is Length. I take the name from the CmdletInfo object and pipe it to Measure-Object and tell it to count characters. I then grab the Character property. This portion of the command is shown here:

@{label = 'length'; expression = {($_.name |

  Measure-Object -Character).Characters}} |

Now I need to sort the custom object by the Length property. I tell it to sort in descending order:

Sort-Object length -Descending | 

Lastly, I use the Select-Object cmdlet again to return the first item from the sorted list:

Select-Object -First 1

The complete script is shown here:

Get-Command |

Select-Object @{label = 'name'; expression = {$_.name}},

@{label = 'length'; expression = {($_.name |

  Measure-Object -Character).Characters}} |

Sort-Object length -Descending |

Select-Object -First 1

As shown here, when I run the script, it tells me the name of the longest cmdlet:

Image of command output

Dude, 47 characters long! I am sure glad for Tab completion. There is one problem with the output, and that is that the cmdlet name is sooooooooooooooooooooooooooo long that it exceeds the screen size. If I reduce the size of the output, the cmdlet name fits. This is shown here:

Image of command output

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 Verify Hotfix

$
0
0

Summary: Use Windows PowerShell to verify if a hotfix is installed.

Hey, Scripting Guy! Question How can I use Windows PowerShell to verify that my workstation running Windows 8.1 has
           the November DSC rollup installed?

Hey, Scripting Guy! Answer Use the Get-Hotfix cmdlet and search for ID KB3000850:

Get-HotFix -Id kb3000850

Use PowerShell to Enable Wi-Fi

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to enable Wi-Fi if Ethernet is not connected.

Hey, Scripting Guy! Question Hey, Scripting Guy! Most of the time when I use my laptop running Windows 8.1, I am plugged in to the Ethernet network at work. Occasionally, I unplug the laptop and take it to meetings. I keep the Wi-Fi disabled when I am plugged in to the Ethernet because if I have it enabled, it seems that at random times, my laptop connects to Wi-Fi.

I only notice this when Outlook becomes really slow or I am trying to download something that ends up taking forever. I also think this is a security issue, because I should know what network I am connected to. But it seems to take me forever to make the change between enabling and disabling various network adapters. Can I script this?

—SC

Hey, Scripting Guy! Answer Hello SC,

Microsoft Scripting Guy, Ed Wilson, is here. This past weekend was pretty cool. The weather was wonderful and I was caught up on my book project, so the Scripting Wife and I headed out for a weekend excursion. Because we really did not have a set agenda, and because we had no specific timetable to adhere to, we sort of winged it. Armed with a couple of Windows Phones, a couple of Surfaces, and a couple of Zunes, we were ready for anything.

We ended up in a small town outside of Charlotte, and I found a highly recommended tea room on Yelp. So we detoured to go there. The tea selection was OK, but not great, so I opted for a triple shot espresso instead. Teresa, of course, had hot chocolate. Anyway, I like hand-crafted coffee if I don’t have to make it, and if there is not any good tea around. But like most things, if it becomes a regular thing, I want to automate it.

Your question gives me a perfect start for Hardware Week. One of the issues with my laptop is that it seems to keep growing new network adapters. Every time I update drivers or software, it seems that a new network adapter pops up. I can navigate to the network adapter folder. It is shown here:

Image of folders

But I can also use the Get-NetAdapter cmdlet to display the network adapters and their status. This is shown here:

Image of command output

I can use Get-NetAdapter and a wildcard configuration to find network adapters, or I can use the Name or InterfaceDescription properties. Each computer will have its own collection of adapters and names for those devices. Therefore, each script will need to be matched to the workstation that will run the script. It is possible to simplify this process by naming each adapter the same—but as I said, over time, my laptop seems to grow new network adapters, and these tend to take on default names.

For me, the best approach was to disable everything if I am not connected via the Ethernet cable, and then turn on the adapters I need. Because the command to disable the network adapters tends to be slow (or at least, take varying amounts of time), I decided to call the command as a job and wait for the job to complete. Because the cmdlet prompts by default, I set –Confirm to $False. This command is shown here:

If ( (Get-NetAdapter -Name 'Ethernet').Status -ne 'Connected' )

    {

      Get-NetAdapter | Disable-NetAdapter -Confirm:$false -AsJob | Wait-Job 

Now I need to enable the network adapters I want to use. Here is the command I use:

Enable-NetAdapter -Name 'Wi-Fi'-Confirm:$false

Enable-NetAdapter -Name 'Ethernet 3' -Confirm:$false

The complete script is shonw here:

If ( (Get-NetAdapter -Name 'Ethernet').Status -ne 'Connected' )

    {

      Get-NetAdapter | Disable-NetAdapter -Confirm:$false -AsJob | Wait-Job

      Enable-NetAdapter -Name 'Wi-Fi'-Confirm:$false

      Enable-NetAdapter -Name 'Ethernet 3' -Confirm:$false

      }

    Note  You need to run this script with admin rights. It also uses Windows 8.1, and therefore, it will not work on Windows 7.
    I talk about other approaches for performing this task in the Hey, Scripting Guy! Blog post called Enabling and Disabling Network Adapters.

SC, that is all there is to using Windows PowerShell to enable Wi-Fi if Ethernet is not connected. Hardware Week will continue tomorrow when I will talk about disabling Wi-Fi if Ethernet is connected.

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 Disable All Network Adapters

$
0
0

Summary: Use Windows PowerShell to disable all network adapters on your system.

Hey, Scripting Guy! Question I often work in offline situations, and I would like to disable all network adapters on my laptop for security reasons
           and to help to extend battery life. How can I use Windows PowerShell to do this easily?

Hey, Scripting Guy! Answer Use the Get-NetAdapter cmdlet to retrieve all network adapters and pipe the results to the 
           Disable-NetAdapter cmdlet. To suppress confirmation messages use the –Confirm parameter
           and set it to $false:

Get-NetAdapter | Disable-NetAdapter -Confirm:$false

Note  This command requires admin rights.

Use PowerShell to Disable Wi-Fi

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to disable Wi-Fi if Ethernet is connected.

Hey, Scripting Guy! Question Hey, Scripting Guy! When I have an Ethernet cable plugged in to my laptop and I am connected to a network, I want to ensure that everything else is disabled. How can I do that by using Windows PowerShell?

—DH

Hey, Scripting Guy! Answer Hello DH,

Microsoft Scripting Guy, Ed Wilson, is here. This morning is a bit cool, and definitely moist outside. It is not raining, but it seems like it could easily do so. It sort of reminds me of winter mornings in Florida, when it was cool and damp. I have not seen any seagulls, but I would not be surprised if a few appeared. The big thing is to be prepared, because the weather can change suddenly and dramatically.

DH, the thing I like to do when setting up my laptop, or when setting up servers, is to provide meaningful names for things. If I rely on Windows naming conventions, I end up not aware of what a lot of stuff actually is. But by naming them myself, I can confirm that I know what each device really does.

This is the way I found out what was going on with my laptop after I added the Hyper-V role because it changed, added, and modified the way the network adapters did things. So, the best way to know what is going on is to make sure that you name network adapters so you know what they are. Here is a screenshot of my network adapters:

Image of folder

I have named my Ethernet, my virtual Ethernet adapters, the Wi-Fi, and the virtual Wi-Fi. I also renamed my internal switch. I did not bother naming the other stuff. This enables me to easily separate the network adapters I am concerned with.

To write the script, the first thing I need to do is to find if the Ethernet wired network connection is actually connected. If it is connected, I want everything except my virtual Ethernet adapter disabled. Here is the code that I use to determine if I am connected via Ethernet:

If ( (Get-NetAdapter -Name 'Ethernet').MediaConnectionState -eq 'Connected' )

Now I need to find everything that is not “Ethernet.” This is actually easy to do because I name my network adapters “Ethernet” or something like that. So in this line of code, I simply look for all network adapters not named something like Ethernet:

  (Get-NetAdapter).where({$psitem.name -notmatch 'ethernet'}) |

I now pipeline the resulting network adapters to the Disable-NetAdapter cmdlet, and I specify that I do not want confirmation:

  Disable-NetAdapter -Confirm:$false

When I run the script, I can see the results in the Network Connections pane. I check there because there is no output from the script as it is written. Here are the resulting changes:

Image of folder

For those who were paying close attention to the images, there was an “Ethernet 3” adapter that appeared in the first image, but it is not present in the second. This is where naming stuff makes it easier to keep track of things. The “Ethernet 3” adapter seems to appear when wireless is enabled, and it disappears when it is disabled.

This is why I do not need to worry about it in my script. Based on yesterday's script (see Use PowerShell to Enable Wi-Fi), I can say when Ethernet 3 is not enabled, wireless on my laptop does not appear to work. Based on that, I know it is important, but I really do not know where it came from, where it goes, or why Windows seems to feel it needs it. Oh well, the script works, and it does what I want it to do.

DH, that is all there is to using Windows PowerShell to disable network adapters. Join me tomorrow when Hardware Week continues, and I will talk about more cool stuff. Now, I think I will go outside and look for seagulls.

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 See Who Can Access Folder

$
0
0

Summary: Use Windows PowerShell to see who has access to a folder.

Hey, Scripting Guy! Question How can I use Windows PowerShell to see who has access rights to a folder?

Hey, Scripting Guy! Answer Use the Get-Acl cmdlet, specify the folder, and look at the access property, for example:

(Get-Acl c:\fso).Access

 

Use PowerShell to Explore Old Windows VHDs

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to explore old Windows VHDs.

Hey, Scripting Guy! Question Hey, Scripting Guy! It is time for spring clean-up around our datacenter. I am not talking about chasing out dust bunnies, although that is part of it. What I am talking about is trying to determine what can be safely deleted without annoying the users too badly.

We have a lot of virtual machines that could have data on them, but I do not know the passwords, and I do not want to go to the trouble of creating virtual machines, mounting the drives, and launching the things to see if there is any user data on the virtual drive. How can I do this quickly and easily—and safely? To be honest I am a bit concerned about the safety of launching a virtual machine that may not have been updated in over a year. Any tips would be appreciated.

—JB

Hey, Scripting Guy! Answer Hello JB,

Microsoft Scripting Guy, Ed Wilson, is here. Today it is cold and rainy, but I guess that is a good thing. In fact, we even turned the heat on for a little while. I am sipping a nice cup of cinnamon tea that I made: a spoon of English Breakfast tea, two cinnamon sticks, and a splash of nutmeg for fun. It is great with a little bit of milk in it—kind of like drinking a cup of cinnamon toast, only not.

Anyway, JB, you need to approach your virtual hard disk (VHD) issue as a disk or folder issue, and not as a Windows issue. So it is like mounting a VHD, only not.

The trick is to mount the Windows image into a folder so that I can use normal Windows PowerShell cmdlets to peruse it for any data that might need to be archived. When I have the data archived, I can delete the VHD and reclaim my lost disk space. My laptop running Windows 8.1 has the necessary cmdlets. In fact, for my purposes, I need the following Windows PowerShell commands:

  • Get-ChildItem to find the Windows images
  • MD to create a folder that I will use to mount the Windows image
  • Mount-WindowsImage to actually mount the Windows image to the newly created folder
  • Dismount-WindowsImage to dismount the Windows image after I am finished looking at it
  • RD to delete the folder that I used to mount the Windows image

Here is how it all works...

The first thing I do is use the Get-ChildItem cmdlet to search for virtual hard disks that contain the name 2003. In my naming scheme, this will work because I tend to use the version of the operating system as part of the virtual hard disk name. I also use a wildcard character because I cannot remember if the virtual hard disks are VHD or VHDX.

It seems that at some time, Hyper-V changed the file extension, but to be honest, I do not remember when that change actually took place, so I use a wildcard character to ensure that I get the required files. In addition, even if I did actually create a VHD, it is possible that at some date, I may have upgraded the version to a VHDX, so it is always better to be safe than to be sorry. Here is my command:

$image = Get-ChildItem -Path e: -Filter *2003*.vhd* -Recurse -File

Now I create a folder that I will use to mount the Windows image. To do this, I use MD because it is quick. I store the returned directory info object so I can pick up my path. This command is shown here:

$path = md c:\image

I use the Mount-WindowImage cmdlet to mount the Windows image in the virtual hard disk to the C:\image folder. There are three required parameters:

  • ImagePath: The complete path to the virtual hard disk that contains the version of Windows to mount. It points to an actual file, not to a folder.
  • Path: The path to the folder that will hold the mounted Windows image.
  • Index: For a virtual hard disk type of file, it is always an index of 1. This can be different if mounting a WIM, but that is not what I am doing here, so Index is 1.

Here is the command:

Mount-WindowsImage -ImagePath $image.FullName -Path $path.FullName -Index 1

When I run the command, I see a progress bar appear, and then the output tells me the path to find my mounted image, if it is online, and if it needs to be restarted. The progress bar is shown here:

Image of command output

I can navigate to the C:\Image folder. It looks exactly like it would if I was to load Windows and navigate around. As shown here, I even see the page file:

Image of menu

If I click something, it might tell me that I do not have permission to the folder. I can click Continue to obtain permission, and then see what is there. Here is the message:

Image of command output

I can easily copy anything I need to from the VHD. When I am done, I dismount the installation of Windows, and remove my folder. Because I am not making any changes, I do not need to worry about saving changes or anything like that. Here is the script I wrote to dismount Windows:

$path = "C:\image"

Set-Location c:\

Dismount-WindowsImage -Path $path -Discard

RD $path -Force

This works a lot better than having to create a bunch of virtual machines for potentially obsolete versions of Windows that one finds laying around on miscellaneous virtual hard disks.

JB, that is all there is to using Windows PowerShell to explore old Windows VHDs. Join me tomorrow for more Hardware Week 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: Use PowerShell to Find Virtual Hard Disks

$
0
0

Summary: Use Windows PowerShell to find virtual hard disks on your system.

Hey, Scripting Guy! Question I notice that my disk space appears to be disappearing at a rapid rate, and I suspect someone is creating
           virtual hard disks (VHDs) and forgetting about them. How can I use Windows PowerShell to find all the
           VHDs on my system?

Hey, Scripting Guy! Answer Use the Get-ChildItem (LSDirgci are aliases), use a filter like *.vhd*, and specify the Recurse switched
           parameter. To simply report on the path to the VHDs, select the FullName parameter. Here is an example:

Get-ChildItem -Path e: -Filter *.vhd* -Recurse -File | select fullname

Use PowerShell to Add Files to Offline Windows Image

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to add files to an offline Windows image.

Hey, Scripting Guy! Question Hey, Scripting Guy! I have a number of VHDs that I need to add files to. I know that I can use File Manager to mount the VHD and then copy the files, but I am hoping that I can use Windows PowerShell to do this. The VHDs are for virtual machines that I run in my lab. Can you help?

—AM

Hey, Scripting Guy! Answer Hello AM,

Microsoft Scripting Guy, Ed Wilson, is here. Today I am a bit sore. I finally made it back into the gym yesterday, and my trainer seemed to have it in for me. Anyway, I am listening to Alan Parsons on my Zune, sipping a nice cup of Earl Grey tea, and going through my email to scripter@microsoft.com. I am thinking that later tonight I might make it back to the gym to work out the soreness.

Speaking of sore...

AM, just reading about all that mousing around makes my wrist hurt. The good thing is that Windows PowerShell can indeed mount and service offline Windows images. (This functionality was introduced in Windows 8 and Windows Server 2012.)

One of the things I like to do is to put things back where I found them—this includes my current working directory. So, I love to use Push and Pop. Push-Location stores the current working location. I use it before I set my location using Set-Location. I do not need to use a variable and Get-Location because Windows PowerShell already knows about a “location stack.” All I need to do is call Push-Location, and Windows PowerShell will automatically remember where I start from. Here is the code:

Push-Location

Set-Location c:\

Because I want things to occur in a specific order, I create a simple workflow—and I do mean simple. It is no more complicated than a very basic Windows PowerShell function. I use the Workflow keyword, specify a name, and create some variables. This is shown here:

WorkFlow Service-Image

{

 $image = "E:\vms\vhd\c1\c1.vhdx"

 $path = "c:\image"

 $scripts = 'C:\PoshScripts'

Now I create the folder that will hold my mounted image, and I use the Sequence keyword to specify that I want commands to appear in a certain order:

MD $path

  Sequence {

I want to first mount my Windows image, then I want to copy some Windows PowerShell scripts to a folder, then I want to dismount my Windows image and remove the folder that I created. All this is shown here:

Mount-WindowsImage -ImagePath $image -Path $path -Index 1

   Copy-Item -Path $scripts -Destination "C:\image\poshScripts" -Recurse

   Dismount-WindowsImage -Path $path -Save

   RD $path -Force

 } }

The last things I do is call my workflow and pop back to my original working directory. This is shown here:

Service-Image

Pop-Location

Here is the complete script:

Push-Location

Set-Location c:\

WorkFlow Service-Image

{

 $image = "E:\vms\vhd\c1\c1.vhdx"

 $path = "c:\image"

 $scripts = 'C:\PoshScripts'

 MD $path

  Sequence {

   Mount-WindowsImage -ImagePath $image -Path $path -Index 1

   Copy-Item -Path $scripts -Destination "C:\image\poshScripts" -Recurse

   Dismount-WindowsImage -Path $path -Save

   RD $path -Force

 } }

Service-Image

Pop-Location

As shown in the following image, when I run the script, I see a few things in the output:

Image of command output

One thing I see is a path to the DISM log. So I go there and open the log in Notepad. The log is shown here:

Image of files

One thing to note is that the DISM log appends to the end. So I need to go all the way to the end of the log to see what happened during my Windows PowerShell script. I see that it said everything was successful. Cool. I decide to mount the image via the Windows Files Explorer so that I can check to ensure that my Windows PowerShell scripts were indeed copied. As shown in the following image, it was a success:

Image of menu

AM, that is all there is to using Windows PowerShell to add files to a Windows image. 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: Find DISM-Related PowerShell Cmdlets

$
0
0

Summary: Learn how to find all Windows PowerShell cmdlets that work with DISM.

Hey, Scripting Guy! Question How can I find all Windows PowerShell cmdlets that work with Deployment Image Servicing and Management (DISM)?

Hey, Scripting Guy! Answer Use the Get-Command cmdlet and specify the DISM module:

Get-Command -Module dism

Use PowerShell to Remove Optional Features from Windows VHD

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to remove optional features from Windows virtual hard disks.

Hey, Scripting Guy! Question Hey, Scripting Guy! I have a number of virtual machines that have optional features that they do not need, such as Windows Media Player. In fact, the virtual machines are set up with no audio, so having Windows Media Player is sort of a waste. How can I easily remove this feature?

—CG

Hey, Scripting Guy! Answer Hello CG,

Microsoft Scripting Guy, Ed Wilson, is here. This morning started off early. IIS MVP, Teri Donahue, stopped by to pick up Teresa’s Surface Pro 2. Teri and Teresa are meeting at an MVP conference in Philly. I had to get a new SIM card for the Surface because the dial-up adapter quit working, and Teri is taking it to Teresa, who is pretty much going through withdraw without her device.

Not that she is completely deviceless, she had my Surface Pro 2 and her original Surface RT with her, not to mention her Windows Phone, but still she was jonesing without her favorite device. Thanks Teri! Anyway, I took the early morning wake up to head to the gym to get my workout over so I could get back to work answering email sent to scripter@microsoft.com.

CG, speaking of withdrawl…

It is actually pretty easy to use Windows PowerShell to remove unneeded features from your VHDs. (This technique also works for WIM images.)

One of the cool things about using the DISM cmdlets is that it permits me to work with optional features in a supportable and reliable method. In the old days, I had to worry about dependencies and hope that I did not break things when I used tools that were designed to shrink Windows images, but that is no longer the case.

The first thing I do is mount an image that I want to work with to a folder. Here is the code I use:

$image = "E:\vms\vhd\c1\c1.vhdx"

$path = "c:\image"

 MD $path

 Mount-WindowsImage -ImagePath $image -Path $path -Index 1

After I have my virtual machine mounted to a folder, I use the Get-WindowsOptionalFeature to look at the optional features:

Get-WindowsOptionalFeature -Path $path

The following image shows the output from this command:

Image of command output

To find related features, use wildcard characters. The following command illustrates finding media-related features:

PS C:\> Get-WindowsOptionalFeature -Path C:\image -FeatureName *media*

Feature Name      : MediaPlayback

Display Name      : Media Features

Description       : Controls media features such as Windows Media Player and Windows Media Center.

Restart Required  : Possible

State             : Enabled

Custom Properties :

                    \SoftBlockLink : http://go.microsoft.com/fwlink?LinkID=153156        

Feature Name      : WindowsMediaPlayer

Display Name      : Windows Media Player

Description       : Windows Media Player

Restart Required  : Possible

State             : Enabled

Custom Properties :

                    \SoftBlockLink : http://go.microsoft.com/fwlink?LinkID=140092

To remove an optional Windows feature, I pipe the results of the Get-WindowsOptionalFeature cmdlet to the Disable-WindowsOptionalFeature cmdlet. I also use the –Remove switch to actually remove the feature and not simply disable the feature. This command is shown here (this is a single-line command that wraps at the pipe character for readability):

Get-WindowsOptionalFeature -Path C:\image -FeatureName *media* |

Disable-WindowsOptionalFeature -Remove

Now, I put everything together into a script:

Push-Location

Set-Location c:\

WorkFlow Service-Image

{

 $image = "E:\vms\vhd\c1\c1.vhdx"

 $path = "c:\image"

 MD $path

  Sequence {

   Mount-WindowsImage -ImagePath $image -Path $path -Index 1

   Get-WindowsOptionalFeature -Path C:\image -FeatureName *media* |

   Disable-WindowsOptionalFeature -Remove

   Dismount-WindowsImage -Path $path -Save

   RD $path -Force

 } }

Service-Image

Pop-Location

When I run the script, the following output appears:

Image of command output

CG, that is all there is to using Windows PowerShell to remove optional features from virtual machines. Join me tomorrow when I will have a guest blog post by Windows PowerShell MVP, Teresa Wilson. She will talk about plans for the Scripting Guys Ignite booth.

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 Installed Optional Features

$
0
0

Summary: Learn how to use Windows PowerShell to find installed optional features in Windows.

Hey, Scripting Guy! Question How can I use Windows PowerShell to see what optional features are installed in a copy of Windows?

Hey, Scripting Guy! Answer Use the Get-WindowsOptionalFeature cmdlet, and if you are looking at a version of Windows
           that is running, use the –Online switch:

Get-WindowsOptionalFeature -Online

PowerShell Spotlight: Scripting Guys at Ignite

$
0
0

Summary: Microsoft PowerShell MVP, Teresa Wilson, talks about plans for the Scripting Guys booth at Ignite in Chicago.

Microsoft Scripting Guy, Ed Wilson, is here. Today we have Windows PowerShell MVP, Teresa Wilson (aka The Scripting Wife) with another edition of PowerShell Spotlight...

It is almost April which means conference season is about to begin. I am so excited. The first conference is the PowerShell Summit in Charlotte April 20-22. This event is sold out. It is going to be an awesome three days. If you are in the Charlotte area and did not get tickets to the Summit (or even if you did and are going to be around on the last day), the Charlotte Windows PowerShell User Group is hosting Lee Holmes. There are still tickets for that free event, so you will want to sign up for that if you can: Everyday PowerShell – My Favorite PowerShell Hacks with Lee Holmes. Lee is an awesome speaker, and he will be talking about totally bodacious Windows PowerShell tricks.

Next up will be the Microsoft Ignite in Chicago, May 4-8, 2015. There is still time to register, and I would definitely sign up before it is too late: Microsoft Ignite Registration.

Ed and I will be on hand at the Scripting Guys booth in the Microsoft on Microsoft area. When the exact floor plan is available, I am sure Ed will post it in a blog. Meanwhile, I can tell you we have three of the most awesome guys I know staffing the booth with us. This year it is Microsoft PFEs, Jason Walker, Gary Siepser, and Brian Wilhite. All three have written awesome blog posts for the Hey, Scripting Guy! Blog, and all three are also accomplished speakers. Having so much Windows PowerShell knowledge all in one spot will be impressive. If you are at Ignite, you will want to stop by and talk to these guys.

Of course, The Microsoft Scripting Guy and I will also be at the booth. I am putting together a schedule, so you will always know who will be around and when. By the way, Ed says if you have one (or more) of his Windows PowerShell books you can bring them by, and he will be glad to autograph them. Brian was the tech reviewer for the last book, and so he will also be glad to autograph the book. I guess if you have the electronic version on your Kindle, they will be willing to autograph your Kindle...if you wish.

Speaking of so much awesome knowledge in one spot...

Don't forget all our special guests, which has become a tradition at our booth. So far we have Windows PowerShell founder, Jeffrey Snover, Don Jones, Todd Klindt, Steve Murawski, Yuri Diogenes, Jason Helmick, and Boe Prox promising to visit. There will be many, many more. I am working on the schedule for that now and will post it soon.

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: Find PowerShell Sessions at Ignite

$
0
0

Summary: See the scheduled Windows PowerShell sessions for Microsoft Ignite.

Hey, Scripting Guy! Question I am planning to attend the Microsoft Ignite conference in Chicago this year! How can I find what Windows PowerShell
           sessions are on the schedule?

Hey, Scripting Guy! Answer Go to the Microsoft Ignite page, and filter on Windows PowerShell: Windows PowerShell Sessions.
           Also keep in mind that many other sessions may have a heavy Windows PowerShell content,
           but they are not specifically keyed as Windows PowerShell sessions.


Weekend Scripter: Special Charlotte PowerShell User Group Meeting

$
0
0

Summary: On April 22, the Charlotte Windows PowerShell User Group will host Lee Holmes and Paul Higginbotham.

Microsoft Scripting Guy, Ed Wilson, is here. Sometimes things just work out. The other day, I received an email from Lee Holmes. He is speaking at the Windows PowerShell Summit, which will be hosted in Charlotte, NC, on April 20 – 22. This event sold out in just a few days, and when additional tickets were added, it sold out again.

It would probably be easier to get tickets to the NCAA basketball tournament, than it is to get tickets to this event. After all, after basketball teams lose, many people seem to want to leave town, so there are always people reselling their tickets. However, I have not seen anyone wanting to part with their Windows PowerShell Summit tickets…just sayin'.

Anyway, Lee emailed me, and asked about the Windows PowerShell User Group that meets in Charlotte. I told him that it meets the first Thursday of every month. He says, "Bummer." He was thinking about staying over one night (Wednesday night), and he would be available to speak at the user group meeting.

Now, here is the thing...

Simply because the Windows PowerShell Summit is being held in Charlotte does not mean that everyone who attends the Windows PowerShell User Group gets to go to the Summit. I mean, the last Windows PowerShell Saturday we held in Charlotte also sold out. There are a lot of very enthusiastic Windows PowerShell users in the Charlotte area, so space is always at a premium.

Then the Scripting Wife said, “Why don’t we see if we can move the Windows PowerShell User Group meeting from Thursday to Wednesday, April 22?” Hmmm…great idea!

So Lee Holmes, will be presenting “Everyday PowerShell–My Favorite PowerShell Hacks.” I have seen Lee talk about some of his favorite Windows PowerShell hacks, tips, and tricks (he basically wrote the book about this), and he is awesome. Here is an abstract I put together:

A highly interactive session in which principle Windows PowerShell developer, Lee Holmes, shares some of his favorite Windows PowerShell tips and tricks. In this session, attendees are also encouraged to share their favorite Windows PowerShell tricks, so the session should be fun and educational. This will be a unique opportunity. Take advantage of it if at all possible. Tickets are available now, and they are expected to go quickly. So if you didn’t get tickets to the Windows PowerShell Summit, here is a chance for a “mini-summit.” I mean, a really mini-summit. Oh well, at least you get to meet and hear Lee. He is awesome!

RSVP now via the Charlotte Windows PowerShell User Group meetup page: Everyday PowerShell–My Favorite PowerShell Hacks with Lee Holmes

PS: We may have even more special guests. Stay tuned, but get your tickets anyway before they are all gone.

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: How to Find PowerShell User Groups

$
0
0

Summary: Learn how to find Windows PowerShell user groups.

Hey, Scripting Guy! Question Where do I begin a search to find if there is a Windows PowerShell user group in my area?

Hey, Scripting Guy! Answer There are two primary places for finding Windows PowerShell user group information:

Use PowerShell to Detect if Hypervisor is Present

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to determine if a hypervisor is present

Hey, Scripting Guy! Question Hey, Scripting Guy! I have been trying to use WMI to determine if a server has the hypervisor present. I found the WMI class, and even the properties I need. But alas, the WMI class seems to be broken, and it is causing my Windows PowerShell script to fail. For your information, I have been using the Win32_Processor WMI class because it seems to have the properties I need. I know there are various tools I can download that provide this information, but I prefer to use something native if I can. Can you help me save my script? I have been working on this for days, and if I cannot get this to work, I will look really bad with my boss.

—AZ

Hey, Scripting Guy! Answer Hello AZ,

Microsoft Scripting Guy, Ed Wilson, is here. I can certainly understand how your boss might not be too pleased if after you have spent a couple of days on a script, and you do not have something working to show for the time. Unfortunately, it seems that WMI is often a hit or miss proposition. I mean, for one thing, there is an awful lot of it—like thousands of WMI classes in dozens of WMI namespaces. For another thing, just because I find the perfect WMI class, with the perfect WMI properties, it does not mean that it will actually work for me.

This is especially true when talking about hardware because often hardware must be specifically instrumented to provide certain types of information—and that is often driver dependent. Many times, various hardware makers will include a WMI management (or support) pack that must be specifically downloaded and installed on certain makes and models of equipment. At times, this actually creates additional WMI namespaces related to your specific hardware. This looks like a great opportunity to begin  Troubleshooting Week.

Looking at processor information

The Win32_Processor WMI class (depending on what version of the operating system you have installed) provides good general information about processors. I like to use the Get-Ciminstance cmdlet because I get Tab completion with my WMI classes. Here is the basic command:

Get-CimInstance win32_processor | fl *

I can get the same information by using the Get-WmiObject cmdlet:

Get-WmiObject win32_processor | fl *

I can shorten the commands by using aliases, such as this:

gcim Win32_Processor | fl *

     or

gwmi Win32_Processor | fl *

The output from the basic WMI query is shown here:

Image of command output

The properties that you are probably looking for appear to be:

VirtualizationFirmwareEnabled           : False

VMMonitorModeExtensions                 : False

But because I am running Hyper-V on my laptop, I imagine that this is the WMI class and properties you were complaining about.

Interestingly enough, there is a WMI class that provides Hypervisor information. It is the Win32_ComputerSystem WMI class. This command is shown here:

gcim Win32_ComputerSystem | fl *

As you can see in the following image, there are some properties that do not report back.

Image of command output

But, there is an interesting property, HypervisorPresent, that does appear to report correctly. Here is the command I like to use:

PS C:\> (gcim Win32_ComputerSystem).HypervisorPresent

True

So, AZ, all you need to do is to modify your Windows PowerShell script to use the Win32_ComputerSystem WMI class and to query the HypervisorPresent property.

AZ, that is all there is to using WMI and Windows PowerShell to find out if a hypervisor is present. Troubleshooting 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 See if Media Center is Installed

$
0
0

Summary: Use Windows PowerShell to determine if a Windows 8.1 has Media Center installed.

Hey, Scripting Guy! Question How can I use Windows PowerShell to determine if a version of Windows 8.1 has Media Center installed?

Hey, Scripting Guy! Answer Use WMI and look at the Caption property of the Win32_OperatingSystem WMI class, for example:

(Get-CimInstance Win32_OperatingSystem).caption

Note  You can also use the alias GCIM, or use Get-WmiObject (alias GWMI).

Help Comparing Objects in PowerShell

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, helps a reader compare two objects in Windows PowerShell.

Hey, Scripting Guy! Question Hey, Scripting Guy! I am having a problem with a script. I wrote a function to compare virtual machines with virtual drives that I have on my hard drive, and it works just fine. But when I try to put the thing into a larger script, and get the path from those drives, well, it just won’t work. In fact, all I get is gibberish. I am pasting my code into a different email. I hope you can help me.

—RL

Hey, Scripting Guy! Answer Hello RL,

Microsoft Scripting Guy, Ed Wilson, is here. This morning I am sipping a wonderful cup of Gunpowder green tea, with a hint of lemon, cinnamon, and a single bit of raw sugar. It is a great tea to drink in the morning.

You know RL, there are some things one should never do: never brew green tea with water that is hotter than 175 degrees Fahrenheit, never feed a gremlin after midnight, and never ever use a Format* type of Windows PowerShell cmdlet inside of a function. The first two admonitions are probably self-evident, so let's spend a bit of time talking about the nature of Format* type of cmdlets and functions in Windows PowerShell.

What happens in a function…

What happens in a function does not really stay in a function. Instead, Windows PowerShell functions automatically return stuff. Your first function appears to work because it simply permits the Format-Table cmdlet to output data. That data appears to go to the output screen, and so you think it is working OK. Here is your function:

Function CompareHVHD{

Compare-Object (get-vm) (Get-ChildItem -Path e:\) |

ft -Property InputObject -HideTableHeaders }

CompareHVHD

The following is an aimage of your function and the output:

Image of command output

In your revised script, you attempt to pick up the paths to your virtual machines. It does not appear to work. Here is your second script:

Function CompareHVHD{

Compare-Object (get-vm) (Get-ChildItem -Path e:\) |

ft -Property InputObject -HideTableHeaders

}

$diff = CompareHVHD

foreach ($path in $diff) {

write-host "e:\$path" }

And here is the output associated with your revised script:

Image of command output

The difference between your first function and the second script is that in the first function, you send the output of the Format-Table directly from your function, and it appears in the output pane of the Windows PowerShell ISE. In the second script, you are capturing that output, and then attempting to manipulate the data.

What is confusing is that in the first function, it looks like you are doing what you want, and in the second script, it is not working. This is because you are displaying the output in the first function, and in your second script, you are capturing the output and trying to manipulate it.

The key to understanding this is that a Windows PowerShell function always returns objects. If you capture that object, you can do stuff with it; otherwise, it goes to the default output, which in this case, is your Windows PowerShell ISE output pane. Perhaps an easier example will illustrate this point better.

Understanding function output

The following function is basically the same as the one you wrote. It adds two numbers together, and then sends the output to the Format-Table. Here is the function:

Function add

 {

  (1 + 1)| ft

 }

 add

When I run the function, it appears to work great. Here is the output:

Image of command output

Suppose I want to add additional numbers to it. I modify my script so that I call the function, and then I add 5 to the output. I expect to see 7 as my result. However, what I really see is an error message. This is shown here:

Image of error message

The reason for the error is that I convert the object in the function from being an integer to being a table. The error message says I cannot add a number to FormatEntryData, which is one of the objects Windows PowerShell uses to create a table. Interestingly enough, if I look back up at the second picture, in the output, I will also find this FormatEntryData object in the output.

So, what do I need to do? Well, I need to remove the Format-Table cmdlet from the function. Here is the revised code, and it works just fine:

Function add

 {

  (1 + 1)

 }

 (add) + 5

How would I revise your original function? I would remove the Format-Table cmdlet from your function. Then I would look at what I was really trying to compare. I assume that you are comparing your virtual machine names with the disks associated with them. In addition, I assume that your disks contain the name of your virtual machines. Based on this assumption, here is what I might be inclined to do:

Function CompareHVHD{

Compare-Object (get-vm).name (Get-ChildItem -Path e:\vms -Recurse -Filter *.vhd*).basename }

CompareHVHD 

RL, that is all there is to using Windows PowerShell to compare objects and avoid using Format* type cmdlets in a function. Troubleshooting 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 

Viewing all 3333 articles
Browse latest View live




Latest Images