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

PowerTip: Use PowerShell to Launch Item from Control Panel

$
0
0

Summary: Learn how to use Windows PowerShell to launch an item from the Control Panel.

Hey, Scripting Guy! Question How can I use Windows PowerShell to launch the Mail item on the Control Panel in Windows 8 or Windows Server 2012?

Hey, Scripting Guy! Answer Use the Get-ControlPanelItem with a wildcard character to retrieve the item, then pipe the results to the Show-ControlPanelItem cmdlet:

Get-ControlPanelItem *mail* | Show-ControlPanelItem


Use PowerShell to display Short File and Folder Names

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, shows how to use Windows PowerShell to display short file and folder names.

Hey, Scripting Guy! Question Hey, Scripting Guy! I need to be able to use Windows PowerShell to show short folder and file names. In the old days, I could see short file and folder names in the CMD prompt, but these days when I am using Windows PowerShell I do not find these things. I know they look strange, and I need a systematic way to display the file and folder names without permitting them to stretch on and on. Please help me—this is a hard stop for my current project.

—SH

Hey, Scripting Guy! Answer Hello SH,

Microsoft Scripting Guy, Ed Wilson, is here. WooHoo! Today is Thursday, and the excitement is buzzing around the Scripting House in Charlotte, North Carolina. No, it is not because we are one more day closer to the weekend. Today is a special Thursday. First, we have the Charlotte Windows PowerShell User Group meeting at 6:30 at the Microsoft Office in Charlotte. Then it will be followed with the PowerScripting Podcast. Yepper! It will be all PowerShell, all day—and that is always a good thing.

Note I want to give credit to Microsoft PFE, Chris Wu, who is responsible for much of what is in today’s post by answering a question on our internal Windows PowerShell alias.

Use the old-fashioned CMD prompt

One of my favorite things to do is to run the old-fashioned CMD interpreter that is inside of Windows PowerShell. I know. It is my weird sense of humor, but it does make my inner geek smile. This works because CMD.EXE is simply another application. And I can run executables inside of Windows PowerShell with no problems. Therefore, I open Windows PowerShell, and run CMD inside it.

This is actually a useful technique at times. I run CMD with the /c parameter. The /c parameter tells CMD to run a command and then exit. The command I want to run is dir /x. Dir, of course, obtains a directory listing, and /x provides for extension information. The command is shown here:

cmd /c dir /x

The command and the associated output from the command are shown in the following image.

Image of command output

Of course, if I want to be able to do anything with the output, I need to capture it, parse it, and convert it to an object. For me, that is too much trouble; especially when a method exists from an unlikely source.

Using the FileSystemObject to create short names

I used the Scripting.FileSystemObject object (yes, there really is an “object object” thing going here) back in the VBScript days. It is an extremely fast and powerful object. To see some of the things I can do with FileSystemObject, I pipe the object to the Get-Member cmdlet:

$fso = New-Object -com scripting.filesystemobject

$fso | gm -mem method

The resulting output from the command is shown here:

Image of command output

When I inspect the methods available from FileSystemObject, I notice that there is nothing that looks like it would produce a short file name or a short folder name. The reason is because FileSystemObject returns objects.

To find something that would create a short file or folder name, I need to examine either the file object or the folder object. The file object returns when I use the GetFile method. A folder object returns when I use GetFolder. To investigate this, I use the GetFolder method to retrieve a folder object and examine the members. This is shown in the following image:

Image of command output

Create the short paths

Now that I know how I can shorten the paths, I decide to create a little function to make using the technique a bit easier. The first thing I want to do is to create the FileSystemObject object. So that goes in the BEGIN statement script block as shown here:

Function Get-ShortName

{

 BEGIN { $fso = New-Object -ComObject Scripting.FileSystemObject }

Now I need to process the pipeline information. Is the input object a folder? If it is, I use the GetFolder method as shown here:

PROCESS {

  If ($_.psiscontainer)

   {$fso.getfolder($_.fullname).ShortName}

If it is not a folder, it is more than likely a file. So I use the GetFile method:

 ELSE {$fso.getfile($_.fullname).ShortName} } }

That’s all there is to it. Here is the complete Get-ShortName function:

Function Get-ShortName

{

 BEGIN { $fso = New-Object -ComObject Scripting.FileSystemObject }

 PROCESS {

  If ($_.psiscontainer)

   {$fso.getfolder($_.fullname).ShortName}

  ELSE {$fso.getfile($_.fullname).ShortName} } }

So, how does it work? Well, in my Windows PowerShell ISE, I run the Get-ShortName.ps1 file and load the Get-ShortName function. Now I use the Get-ChildItem cmdlet to pipe some files and folders to the Get-ShortName function. The command and the results are shown in the following image.

Image of command output

SH, that is all there is to using Windows PowerShell to display short file and folder names. 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: Use PowerShell to Show Network Adapter Status

$
0
0

Summary: Use a function in Windows 8 to show network adapter status information.

Hey, Scripting Guy! Question How can I use Windows PowerShell in Windows 8 to find network adapter status information, such as link speed and duplexing?

Hey, Scripting Guy! Answer Use the Get-NetAdapter function, and select the appropriate properties, for example:

Get-NetAdapter | SELECT name, status, speed, fullduplex | where status -eq 'up'

More Messing Around with Wireless Settings with PowerShell

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about messing around with wireless settings with Windows PowerShell.

Microsoft Scripting Guy, Ed Wilson, is here. OK, I will admit it (in case you did not know), I am a geek. I also love my job at Microsoft. I get to play around with Windows PowerShell all day. I have meetings with people who are working on Windows PowerShell, and I attend user groups for Windows PowerShell, and speak at conferences to people who love Windows PowerShell. So what is not to love? Nothing! It is great!

One of the real treats I have is being on our internal Windows PowerShell discussion alias. Of course, some of the entries on the alias are confidential, but most are not. The writers are a bunch of geeks like me, who love experimenting and pushing the limits of Windows PowerShell. In the early days of Windows PowerShell 1.0 (when it was in beta), I believe someone wrote a song called there must be 50 ways to kill a process. Because Windows PowerShell is so powerful, and because it can leverage so many different technologies, there are quite often many different ways of accomplishing the same task. Which one is best?

The standard consultant answer may very well apply, but it depends. In all likelihood your Windows PowerShell experience is completely different than mine. I do stuff because it is fun and because I want to learn new things. You are probably working with Windows PowerShell because you have a task to perform, and you are in search of a solution. In that case, the best solution is the one that is easiest, fastest, most powerful, or that uses a technology with which you are already familiar. As you can see, best is certainly relative.

A few weeks ago I wrote a couple of blog posts that talked about enumerating wireless network connection profiles and cleaning up wireless profiles that are not needed. Also a while back, there was an email on our internal Windows PowerShell discussion alias where one of our engineers mentioned the Windows.Networking.Connectivity.NetworkInformation .NET Framework class. He showed how to use it to get the wireless connection cost and the network cost type. “Hmmmm,” I thought…

Use the NetworkInformation class to get connection cost info

You can find information on MSDN about the NetworkInformation class. But in reality, the class methods are pretty straight forward, and they are discoverable via Get-Member. My static members are shown here:

PS C:\> [Windows.Networking.Connectivity.NetworkInformation]::GetConnectionProfiles()

 

NetworkAdapter                             NetworkSecuritySettings                    ProfileName                               

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

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... Bluetooth Network Connection              

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... MrEd                                     

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... NOKIA Lumia 920_3303                      

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... Hyatt_Wifi                               

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... A-MSFTWLAN                                

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... KFC Wifi                                 

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... Hyatt                                     

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... Free_WiFi                                

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... STARBUCKS                                

The trick to using this class in Windows PowerShell does not really show up in the class documentation. When calling the class, I need to specify that the Windows.ContentType is equal to WindowsRunTime. This loads the class, and permits me to easily call its methods. Following is where I do that (I cast it to void because I do not need any feedback from loading the assembly):

[void][Windows.Networking.Connectivity.NetworkInformation,Windows,ContentType=WindowsRuntime]

Now, I call the GetInternetConnectionProfile method, and I store the returned ConnectionProfile object in the $connectionProfile variable. I now call the GetConnectionCost method. This method returns a ConnectionCost object. From that, I get the NetworkCostType property. Here is the remainder of the script:

$connectionProfile = [Windows.Networking.Connectivity.NetworkInformation]::GetInternetConnectionProfile()

$connectionCost = $connectionProfile.GetConnectionCost()

$networkCostType = $connectionCost.NetworkCostType

echo $networkCostType

When I run the script, the following output displays and tells me that my Internet connection is unrestricted:

Image of command output

Exploring security settings or network adapter information

The properties from the ConnectionProfile object each return additional objects. This is shown here:

PS C:\> [Windows.Networking.Connectivity.NetworkInformation]::GetInternetConnectionProfile() | Get-Member -MemberType Property

 

   TypeName: Windows.Networking.Connectivity.ConnectionProfile

 

Name                    MemberType Definition                                                                           

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

NetworkAdapter          Property   Windows.Networking.Connectivity.NetworkAdapter NetworkAdapter {get;}                 

NetworkSecuritySettings Property   Windows.Networking.Connectivity.NetworkSecuritySettings NetworkSecuritySettings {get;}

ProfileName             Property   string ProfileName {get;}  

I can directly access each of the objects by using dotted notation after the method call. For example, I can get the NetworkAdapter information by placing NetworkAdapter at the end of the method call as shown here:

[Windows.Networking.Connectivity.NetworkInformation]::GetInternetConnectionProfile().NetworkAdapter

In the image that follows, I explore the NetworkSecuritySettings object and the NetworkAdapter object.  

Image of command output

Another way to find stored network connection profiles

OK, that is cool. But what I want to do is to look at stored network connection profiles. This is simple—tab expansion even works for this in the ISE. I call the GetConnectionProfiles static method. This technique is shown here: 

PS C:\> [Windows.Networking.Connectivity.NetworkInformation]::GetConnectionProfiles()

 

NetworkAdapter                             NetworkSecuritySettings                    ProfileName                               

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

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... Bluetooth Network Connection             

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... MrEd                                     

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... NOKIA Lumia 920_3303                     

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... Hyatt_Wifi                               

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... A-MSFTWLAN                               

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... KFC Wifi                                 

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... Hyatt                                    

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... Free_WiFi                                

Windows.Networking.Connectivity.Network... Windows.Networking.Connectivity.Network... STARBUCKS                               

That is all there is to using Windows PowerShell to mess around with wireless settings. 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 the Number of Variables In-Scope

$
0
0

Summary: Find the number of variables in-scope in your function.

Hey, Scripting Guy! Question How can I see how many variables are available in-scope and out-of-scope in my Windows PowerShell function?

Hey, Scripting Guy! Answer Use the Get-Variable cmdlet, the Count property, and the –Scope parameter:

All variables

PS C:\> function myvar {(Get-Variable).count}

PS C:\> myvar

49

Variables in-scope

PS C:\> function myvar {(Get-Variable -Scope 0).count}

PS C:\> myvar

25 

Weekend Scripter: Use PowerShell to Get Folder Sizes

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to get folder sizes.

Microsoft Scripting Guy, Ed Wilson, is here. I was talking via Lync to my friend Rolf in Munich, Germany the other day. He said the temperatures were approaching 100 degrees Fahrenheit. We have been lucky in Charlotte, North Carolina—we have not made it out of the 90s yet. Still, anything over 80 degrees Fahrenheit is hot in my mind. Oh well, every year it is the same down here. August rolls around, and the mercury rises.

In much the same way, certain Windows PowerShell questions keep coming around. Not exactly on a calendar type of schedule, but they do crop up again and again. These predictable questions are due to the fact that no great solution exists for the issue.

A perfect case-in-point is the issue of determining folder sizes. There is no Get-FolderSize cmdlet, and Get-ChildItem does not return a folder size on the DirectoryInfo object. For the same reason that Windows Explorer is slow when showing folder size information, there is no direct way of obtaining the information. It is not cached anywhere, and therefore, it must be calculated.

In previous Hey, Scripting Guy! Blog posts, I have enumerated all files in a folder, and returned the folder size information. I have also used the FileSystemObject. Today, I want to create a simple function that accepts pipelined input. This may prove useful for you.

The Scripting.FileSystemObject returns a folder size

One way to avoid enumerating files and adding up their sizes is to use a method that returns a folder size directly. This is where using the old-fashioned FileSystemObject comes into play. The reason I decided to create the function to accept pipelined input is so that I could use it directly from the command line. Here is the function:

Function Get-FolderSize

{

 BEGIN{$fso = New-Object -comobject Scripting.FileSystemObject}

 PROCESS{

    $path = $input.fullname

    $folder = $fso.GetFolder($path)

    $size = $folder.size

    [PSCustomObject]@{'Name' = $path;'Size' = ($size / 1gb) } } }

The first thing I did was create an instance of Scripting.FileSystemObject. I only need to do this one time, and so I place it in the BEGIN block.

In the PROCESS block, I will process the pipelined input. The path comes from the pipeline input from the Get-ChildItem cmdlet. I select the FullName property because it provides the complete path to the folder. Now, I use the GetFolder method to return a folder object. The folder object has a Size property, and I store that in the $size variable. Now I create a custom object and return the folder name and size in gigabytes. That is all there is to the script.

Using the function

First I run the function in the ISE. This loads the function into memory.

If I do not run the function with Admin rights, I will not have access to all folders, and errors arise. In fact, even if I do run the function with Admin rights, it is likely I will run into errors. So I use the ErrorAction parameter (EA) and set it to SilentlyContinue (0). I then sort by size. The command is shown here:

Get-ChildItem -Directory -Recurse -EA 0 | Get-FolderSize | sort size -Descending

The command and associated output are shown in the following image:

Image of command output

So how long does it take? I use the Measure-Command to see:

Measure-command {gci -Directory -Recurse -EA 0 | Get-FolderSize | sort size -Descending }

And following are the results. A little over 30 seconds to process my entire hard drive. Not too bad, really.

Days              : 0

Hours             : 0

Minutes           : 0

Seconds           : 30

Milliseconds      : 24

Ticks             : 300247135

TotalDays         : 0.000347508258101852

TotalHours        : 0.00834019819444444

TotalMinutes      : 0.500411891666667

TotalSeconds      : 30.0247135

TotalMilliseconds : 30024.7135

So where is the time spent? Is it getting the Directory listing? Let’s see…

The Directory listing only takes 5 and a half seconds as shown here:

PS C:\> Measure-command {gci -Directory -Recurse -EA 0}

 

Days              : 0

Hours             : 0

Minutes           : 0

Seconds           : 8

Milliseconds      : 547

Ticks             : 85470865

TotalDays         : 9.89246122685185E-05

TotalHours        : 0.00237419069444444

TotalMinutes      : 0.142451441666667

TotalSeconds      : 8.5470865

TotalMilliseconds : 8547.0865

Well, what about sorting? How long does that take? To figure out how long the sorting takes, I run the command without the Sort-Object command. I can then see the difference between the first command and the second. Without the sort, it takes a little over 29 seconds:

PS C:\> Measure-command {gci -Directory -Recurse -EA 0 | Get-FolderSize}

 

Days              : 0

Hours             : 0

Minutes           : 0

Seconds           : 29

Milliseconds      : 154

Ticks             : 291541682

TotalDays         : 0.000337432502314815

TotalHours        : 0.00809838005555556

TotalMinutes      : 0.485902803333333

TotalSeconds      : 29.1541682

TotalMilliseconds : 29154.1682

With the sort, it took a little over 30 seconds. So surprisingly enough, the sort only took about a second. So, most of the time, nearly 21 seconds, was spent in making the calculation to find the folder sizes.

Join me tomorrow for more cool Windows PowerShell stuff. Hope you have a great weekend.

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 Get Detailed Network Adapter Information

$
0
0

Summary: Use Windows PowerShell to get detailed network adapter information about Windows 8.

Hey, Scripting Guy! Question How can I use a function to get detailed network adapter information about my Windows 8 device?

Hey, Scripting Guy! Answer Use the Get-NetAdapterHardwareInfo function and pipe the results to Format-List:

Get-NetAdapterHardwareInfo | Format-List *

Weekend Scripter: Looking at PowerShell Aliases

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about looking at Windows PowerShell defined aliases.

Microsoft Scripting Guy, Ed Wilson, is here. I am constantly amazed by Windows PowerShell. It keeps getting better and better. There are so many improvements in each new version that it is hard to keep up with them. For example, this morning I was playing around with Windows PowerShell and sipping a cup of English Breakfast tea. Just basic tea, nothing extra. I was looking at aliases, and I got this idea. I would like to load all of the modules, look at each module, and see what aliases are exported. Groovy.

So first I loaded all of the modules. I actually used my IAM function to do this. (For more information, see the Hey, Scripting Guy! Blog, Add a Couple of Functions to PowerShell Profile.)

Get-Module -ListAvailable | Import-Module

Now, I decide to find the exported aliases from each of the modules. To do this, I again use Get-ModuleListAvailable and send it to the Foreach-Object cmdlet. Then I gather the exported aliases from each module (gmo is an alias for Get-Module, and % is an alias for Foreach-Object). The script is shown here:

gmo -l | % {(get-module $_.name).exportedAliases}

I look at the output, and I can see that the command returns a dictionary object with keys and values. The key and the value are exactly the same, as shown here:

Image of command output

Because I know that a dictionary object has a property named Keys that returns a collection of keys, I group my previous expression, and call the Keys property. This command is shown here:

(gmo -l | % {(get-module $_.name).exportedAliases}).keys

It works exactly as I planned. Now I can use the Foreach-Object cmdlet and retrieve the specific item from the Alias ps drive. This command is shown here:

(gmo -l | % {(get-module $_.name).exportedAliases}).keys | % {get-item alias:$_}

Following is the command and the output.

Image of command output

Hmmm. I look at the output, and it seems familiar. It looks like the standard output from the Get-Alias cmdlet. So I type the Get-Alias cmdlet into my Windows PowerShell console, and press ENTER. Yep, the output looks the same:

Get-Alias

Image of command output

Except, as I look over the output, I can see that there are some blanks. I was specifically looking for aliases defined in modules, and some of the aliases, such as Clear-Host and Clear-History, are not defined in a module, but rather, they are part of core Windows PowerShell. I verify this by storing the results into variables and looking at the count. The commands are shown here:

PS C:\> $a = Get-Alias | select name

PS C:\> $b = (gmo -l | % {(get-module $_.name).exportedAliases}).keys | % {get-item a

lias:$_} | select name

PS C:\> $a.count

259

PS C:\> $b.Count

145

So, there are 114 aliases that are canonical to Windows PowerShell. I decide to compare the objects and verify this as shown here:

Compare-Object -ReferenceObject $b -DifferenceObject $a

Here is the command and its associated output:

Image of command output

 I can also retrieve aliases that do not report a module name via Get-Alias. This technique is shown here:

Get-Alias | where {-not ($_.module)}

Well, that is enough playing around for one day. Join me tomorrow for more Windows PowerShell fun.

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: Add Commands to PowerShell History

$
0
0

Summary: Learn how to add commands to your Windows PowerShell command history.

Hey, Scripting Guy! Question I have been working in the Windows PowerShell console all day, and I have several commands I keep running. It requires a lot of up and down arrowing to retrieve them. How can I add them to the my command history?

Hey, Scripting Guy! Answer Use Get-History to retrieve a list of all the commands you have typed. Note the command numbers, then use Get-History, supply the specific command numbers, store the resulting object in a variable, and add the history via the variable:

$a = Get-History 11,12

Add-History $a

Use PowerShell to Test Remote Printers

$
0
0

Summary: Learn how to use Windows PowerShell to test remote printers. 

Hey, Scripting Guy! Question Hey, Scripting Guy! I don’t know what it is, but for some reason printing still seems to be a pain. I mean, we have been using the network for a long time, and something as basic as printing still seems to be a problem. Whatever happened to the paperless office of the future? All we do is kill trees faster by using high-speed printers to print massive amounts of useless junk that no one reads.

Anyway, for some reason, about half of our Help Desk calls are related to print issues. To be sure, some of it is user training issues—people trying to select the wrong feature for the wrong printer. But in all honesty, not all of the print problems are user related. For example, sometimes the print spooler seems to die, and we need to restart it. My Help Desk techs can open Computer management to stop and restart the spooler service, but I would like to do this via a script. Can you help?

—RM

Hey, Scripting Guy! Answer Hello RM,

Microsoft Scripting Guy, Ed Wilson, is here. We continue to get lots of rain here in Charlotte, North Carolina. Lots and lots of rain. The solar heaters for our pool are not doing much good these days. Oh well, maybe the sun will come out tomorrow.

The print management module

RM, you did not say if you are using Windows 8, so I am going to assume that you are. In Windows 8 (and in Surface RT, Surface Pro, and Windows Server 2012), there is a print management module called PrintManagement. It exposes the following commands:

PS C:\> Get-Command -Module PrintManagement

 

CommandType     Name                                               ModuleName

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

Function        Add-Printer                                        PrintManagement

Function        Add-PrinterDriver                                  PrintManagement

Function        Add-PrinterPort                                    PrintManagement

Function        Get-PrintConfiguration                             PrintManagement

Function        Get-Printer                                        PrintManagement

Function        Get-PrinterDriver                                  PrintManagement

Function        Get-PrinterPort                                    PrintManagement

Function        Get-PrinterProperty                                PrintManagement

Function        Get-PrintJob                                       PrintManagement

Function        Remove-Printer                                     PrintManagement

Function        Remove-PrinterDriver                               PrintManagement

Function        Remove-PrinterPort                                 PrintManagement

Function        Remove-PrintJob                                    PrintManagement

Function        Rename-Printer                                     PrintManagement

Function        Restart-PrintJob                                   PrintManagement

Function        Resume-PrintJob                                    PrintManagement

Function        Set-PrintConfiguration                             PrintManagement

Function        Set-Printer                                        PrintManagement

Function        Set-PrinterProperty                                PrintManagement

Function        Suspend-PrintJob                                   PrintManagement

Inspecting a network printer connection

From a client workstation (one defined with a network printer), I can use the Get-Printer function. This function returns detailed information about every printer that is defined on the local system. This includes what I consider to be real printers and what I consider to be virtual printers. In the system that follows, only one real printer is defined, and it happens to not be able to connect to the server.

PS C:\> Get-Printer | select printerstatus, name, computername

 

               PrinterStatus name                        computername

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

                      Normal Snagit 11

                      Normal Send To OneNote 2013

                      Normal Microsoft XPS Document W...

                      Normal Fax

               ServerOffline \\dc1.iammred.net\HP Las... dc1.iammred.net

Because the server is reported as offline, there are a couple of possibilities. It may be that the server is actually down, or it may be that the spooler service is not responding. If the spooler is hung, I can restart the service. If the server is down, or not responding to remote queries, I need to restart the server.

This is exactly what the RestartSpoolerService.ps1 script does. If the server is up and responding to a ping, but the PrinterStatus is not normal, the script restarts the spooler service. This script does not use credentials, but it would be easy to modify it to do so by first soliciting credentials via Get-Credential and storing the returned credential object in a variable. Then supply the credential object to the Invoke-Command cmdlet. This script is shown here:

 get-printer |

 select printerstatus, name, computername  |

 Foreach {

    If ($_.PrinterStatus -ne 'normal')

      {

        if(Test-Connection -ComputerName $_.ComputerName -Quiet)

          {Invoke-Command -ComputerName $_.ComputerName -ScriptBlock {Restart-Service -Name Spooler} } }}

RM, that is all there is to using Windows PowerShell to test printer servers. Printer Week will continue tomorrow when I will talk about creating printer ports.

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 Secure Boot Policy

$
0
0

Summary: Use Windows PowerShell to verify your Secure Boot policy in Windows 8. 

Hey, Scripting Guy! Question How can I verify that the Secure Boot policy is enabled in my computers running Windows 8?

 Hey, Scripting Guy! Answer Use the Get-SecureBootPolicy cmdlet:

 Get-SecureBootPolicy

Use PowerShell to Create New Printer Ports

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell 3.0 to create new printer ports in Windows 8.

Microsoft Scripting Guy, Ed Wilson, is here. One of the exciting things that is happening around the Scripting House is the appearance of new Windows PowerShell Saturday events. We have new events coming up in Atlanta, Singapore, and Charlotte. For information about these and other events, check out my site, Scripting Community. If you do not know what Windows PowerShell is, check out my blog post, Community: All about PowerShell Saturday.

To programmatically create a working printer, there are at least three steps:

  1. Create the printer port.
  2. Install the printer driver.
  3. Install the printer (by using the printer port and the printer driver).

Today I am talking about creating the printer port.

Using PowerShell to work with printer ports

Before I create anything, I like to know what I have going on with my computer. I can use the Get-PrinterPort function to list existing printer ports on my local computer:

Get-PrinterPort

I can also use this function to retrieve printer port information from a remote server running Windows Server 2008 and Windows PowerShell 3.0 as shown here:

Get-PrinterPort -ComputerName dc1

The commands and the output from the commands are shown in the following image.

Image of command output

Adding a new printer port

To add a new printer port, I use the Add-PrinterPort function in Windows 8 or Windows Server 2012. By using the Add-PrinterPort function, I can add a local printer port, a TCP printer port, or an LPR printer port.

Most of the time, if I am creating a local printer port, I want to print directly to a printer on the network. Doing this bypasses a print server. Therefore, in the case of large print jobs, I lose flexibility because my laptop must remain on to manage the large print job. But for short documents, it is fast. Also by printing directly to the printer, I can configure things the way that I want.

By using Windows PowerShell, it is easy to create a TCP printer port. I use the Add-PrinterPort function, create a name for the port (the name does not matter, but it is best to use something that makes sense in the printing context). The IP address of the printer itself becomes the value for the PrinterHostAddress parameter. Here is the command I used:

Add-PrinterPort -Name 'HP_Direct:' -PrinterHostAddress '192.168.1.88'

I do not need to specify a value for the port number unless the printer is configured to use a different value than the default. The Add-PrinterPort function has four parameter sets, and I use the third one to create a TCP printer port. Here are the optional parameters for this parameter set:

Add-PrinterPort [-Name] <String> [-PrinterHostAddress] <String> [-AsJob

 [<SwitchParameter>]] [-CimSession <CimSession>] [-ComputerName <String>]

 [-PortNumber <UInt32>] [-SNMP <UInt32>] [-SNMPCommunity <String>]

 [-ThrottleLimit <Int32>] [-Confirm [<SwitchParameter>]] [-WhatIf

 [<SwitchParameter>]] [<CommonParameters>]

I have SNMP turned off on my network, so I do not need to specify a community string or any of that stuff.

When I add a printer port, I do not need an elevated Windows PowerShell console. In Windows 8, I can do this without additional rights. In addition, Windows PowerShell does not make any checks. Therefore, if the IP address is wrong or inaccessible, no warnings generate. This is shown here:

Add-PrinterPort -Name 'bogus:' -PrinterHostAddress '10.10.10.10'

The command and the output from Get-PrinterPort are shown in the following image.

Image of command output

Deleting the printer port

When I create something via Windows PowerShell, I also always like to know how to clean it up. To delete a printer port, I use the Remove-PrinterPort function. The use of the Remove-PrinterPort function is shown here:

Get-PrinterPort | Where name -eq 'bogus:' | Remove-PrinterPort

The following image shows the command and its associated output.

Image of command output

That is all there is to using Windows PowerShell to create new printer ports. Printer Week will continue tomorrow when I will talk about installing printer drivers.

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 Get Printer Configuration

$
0
0

Summary: Use Windows PowerShell in Windows 8 to find your printer configurations.

Hey, Scripting Guy! Question How can I use Windows PowerShell in Windows 8 to get the printer configuration of all printers?

Hey, Scripting Guy! Answer Use the Get-Printer function, and  pipe it to Foreach-Object and the Get-PrinterConfiguration cmdlet:

Get-Printer | ForEach {Get-PrintConfiguration $_.name}

Install Printer Drivers with PowerShell in Windows 8

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell in Windows 8 to install printer drivers.

Microsoft Scripting Guy, Ed Wilson, is here. This morning, it is rainy and overcast here in Charlotte, North Carolina, but it is pleasantly cool. The Scripting Wife migrated to the lanai and is sitting on her swing and checking Facebook on her Windows RT Surface. I am in my office checking email sent to scripter@microsoft.com. I am sipping a cup of English Breakfast tea with a cinnamon stick, lemon grass, hibiscus blossom, orange peel, and a bit of spearmint. It is a very refreshing cup of tea.

When it comes to using Windows PowerShell to install print drivers, there is the long way and the short way. The long way is…well…long and rather complicated. The short way is easy. The difference in the two methods is not necessarily a conscious choice, but rather a function of the drivers already installed in Windows and the print device you intend to hook up.

For example, we all know that Windows ships with a whole bunch of printer drivers already on the disk. They reside in the Windows\inf folder, and they all begin with the letters prn. The following script lists the printer drivers that ship with Windows.

Get-ChildItem ((Get-Item Env:\systemroot).value+"\inf") -Exclude *.pnf -recurse |

Where-Object { $_.name -match "prn" } |

Sort-Object -Property name |

format-table -Property name, length, creationTime, lastWriteTime -AutoSize

Of course, one issue is a bit convoluted. The following image illustrates the output.

Image of command output

The issue is that the names, such as prnbrcl1.inf, do not make too much sense. I can go to the Windows/inf directory, and open the .inf file in Notepad, and I am greeting with something that looks like the following.

Image of file content

If I compare this output with the output from the advanced printer installation dialog box, I can see similarities. This is shown here.

Image of menu

If I select a printer driver from the previous list, and click Next, the driver installs. I can verify this via the Get-PrinterDriver function, as shown here:

Get-PrinterDriver

The following image shows the command and its output.

Image of command output

I can then use the Get-PrinterDriver function to retrieve the newly installed printer:

Get-PrinterDriver -Name "Brother *"

If I attempt to remove it, however, an error message appears, which states that it is being used by a printer. This command and the error message are shown here.

Image of error message

After I remove the printer that uses the driver, I can then remove the printer—but that is tomorrow’s blog post.

To add a printer driver that exists in the driver store, I need to use the actual driver name. I cannot use wildcard characters, or an error message appears. For example to install the "Brother Laser Leg Type1 Class Driver" that I found in the .inf files, I must use the complete name. This command is shown here:

Add-PrinterDriver -Name "Brother Laser Leg Type1 Class Driver"

If I attempt to use Brother *, an error occurs. This message is shown in the following image.

Image of error message

I can also use the Add-PrinterDriver function to install a print driver by specifying the name of the .inf file for that printer driver. One issue is that often printer drivers are “universal drivers,” and the .inf file contains information for dozens of printers. Therefore, Windows PowerShell will not know which driver to install.

That is all there is to using Windows PowerShell to install printer drivers. Printer week will continue tomorrow when I will talk about removing printers.

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 Display Help for Module Cmdlets

$
0
0

Summary: Use Windows PowerShell to display all Help for all cmdlets in a module.

Hey, Scripting Guy! Question How can I see all of the Help examples for cmdlets from a specific module?

Hey, Scripting Guy! Answer After you have updated your Help in Windows PowerShell 3.0, use the Get-Command cmdlet to retrieve all cmdlets from a specific module, pipe the results to the Foreach-Object cmdlet, and use the Get-Help cmdlet inside the script block. Following is an example for the PrintManagement module:

Get-Command -Module PrintManagement| Foreach-Object {get-help $_.name -Examples}

Here is a shorter version of the same command:

gcm -mo *print* | % {get-help $_.name -ex}


Use PowerShell in Windows 8 to Remove Printers

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell 3.0 in Windows 8 to remove printers.

Microsoft Scripting Guy, Ed Wilson, is here. The Scripting Wife and I have been talking to various people from the Charlotte Windows PowerShell User Group all week about doing another Windows PowerShell Saturday. It is an awful lot of work, but I think we are going to do this again. The Windows PowerShell Saturday in Charlotte sold out within a few days, and there have been many positive comments about the event. That means that people found it to be a valuable experience. So we will have another Windows PowerShell Saturday. (By the way, if you want to have one where you live, let us know via scripter@microsoft.com.)

To remove a printer with Windows PowerShell, I use the Remove-Printer function from the PrinterManagement module. There are two ways to use the Remove-Printer function:

Remove-Printer [-Name] <String> [-AsJob [<SwitchParameter>]] [-CimSession

<CimSession>] [-ComputerName <String>] [-PassThru [<SwitchParameter>]]

[-ThrottleLimit <Int32>] [-Confirm [<SwitchParameter>]] [-WhatIf

[<SwitchParameter>]] [<CommonParameters>]

 

Remove-Printer [-AsJob [<SwitchParameter>]] [-CimSession <CimSession>]

[-PassThru [<SwitchParameter>]] [-ThrottleLimit <Int32>] -InputObject

<CimInstance> [-Confirm [<SwitchParameter>]] [-WhatIf [<SwitchParameter>]]

[<CommonParameters>]

What this means is that if I type the exact printer name, I can use the Remove-Printer function directly. It also tells me that I can pipe a printer object to the function. By pipelining a printer object, I can use wildcard characters.

Begin with Get-Printer

I usually begin things by using a Get type of command. So the first thing I do is use the Get-Printer function to see what printers are defined. The command is shown here:

Get-Printer

The command and its associated output are shown here:

Image of command output

I can use a wildcard character to avoid typing a complete printer name as shown here:

PS C:\> Get-Printer | where name -Like "my*"

 

Name                           ComputerName    Type         DriverName

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

myotherlaser                                   Local        Brother Laser Leg Typ...

Or, I can type the exact printer name and supply it directly to the –Name parameter as shown here:

PS C:\> Get-Printer -Name myotherlaser

 

Name                           ComputerName    Type         DriverName

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

myotherlaser                                   Local        Brother Laser Leg Typ...

Both of these commands return printer objects, and therefore, they can be piped to the Remove-Printer function. This is shown here:

Get-Printer -Name myotherlaser | Remove-Printer

Get-Printer | where name -like "my*" | Remove-Printer

Remember Whatif

Of course, before I add a Remove-Printer object, I want to use the –Whatif switch to ensure that I am doing exactly what I want to do. Here is an example of a near disaster:

PS C:\> Get-Printer | where name -match "my*" | Remove-Printer -WhatIf

What if: Deleting printer Microsoft XPS Document Writer

What if: Deleting printer \\dc1.iammred.net\HP LaserJet 2100 PCL6

What if: Deleting printer myotherlaser

PS C:\>

Luckily, I used –Whatif, so I did not delete a bunch of my printers.

Directly remove a printer

I can use the Remove-Printer function directly to remove a printer if I know the exact name. If I am unsure of the printer name, I use the Get-Printer function to list my printers, and I copy and paste the name. With quick edit mode turned on, I can highlight the printer name with my mouse, press ENTER to copy it to the clipboard, and then right-click to paste it. This is shown in the image that follows.

Image of command output

Here is the command:

Remove-Printer -Name myotherlaser

After I have deleted the printer, I may decide to delete the printer driver and the printer port (if necessary). To do that, I use the following functions:

PS C:\> Get-PrinterDriver -Name "Brother*"

 

Name                                PrinterEnvironment MajorVersion    Manufacturer

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

Brother Laser Leg Type1 Class Dr... Windows x64        4               Brother

 

PS C:\> Get-PrinterDriver -Name "Brother*" | Remove-PrinterDriver

I use the Get-PrinterPort function, and I decide that I do not need to remove any printer ports.

That is all there is to using Windows PowerShell to remove printers. This also concludes Printer Week. Join me tomorrow when I will talk about running scripts on remote file shares.

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 Rename Printers

$
0
0

Summary: Learn how to use Windows PowerShell 3.0 in Windows 8 to rename a printer.

Hey, Scripting Guy! Question How can I use Windows PowerShell 3.0 in Windows 8 to rename a printer?

Hey, Scripting Guy! Answer Use the Get-Printer function to retrieve the printer, and pipe it to the Rename-Printer function:

Get-Printer -Name 'mynewlaser' | Rename-Printer -NewName 'myotherlaser'

Running PowerShell Scripts from a Remote File Share

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about running Windows PowerShell scripts from a remote file share.

Microsoft Scripting Guy, Ed Wilson, is here. It is sort of official…

There are at least three Windows PowerShell Saturday events coming up. They are listed on the PowerShell Saturday website. Atlanta and Singapore are already planning (I know, because I will be speaking at both events). The Charlotte event is still early in the planning stages (I will be speaking there also). Of course, don’t just take my word for it. Bookmark the PowerShellSaturday website, so you can keep up to date on all the events.

First things first

Note  For good background info about running Windows PowerShell scripts from a remote file share, check out the guest blog post written by June Blender and Judith Herman: How to Run PowerShell Scripts from a Shared Directory.

So I have this shared folder on one of my servers. I can open Windows PowerShell and use the Net View command to see all of the shares. I can then use the Get-ChildItem command (dir is an alias) to view the files in the shared folder. This is shown here.

Image of command output

If I want to look at the files in a GUI, I can type the path into Internet Explorer, and view the files in the File Explorer as shown in the following image.

Image of menu

For a background, I happen to know that the remote server is running 32-bit Windows Server 2008. I also found out that the server is running Windows PowerShell 2.0. I did this by using the Invoke-Command cmdlet (icm is an alias) as shown here:

PS C:\> icm -ComputerName dc1 {$PSVersionTable}

Name                           Value

----                           -----

PSRemotingProtocolVersion      2.1

BuildVersion                   6.0.6002.18111

PSCompatibleVersions           {1.0, 2.0}

PSVersion                      2.0

CLRVersion                     2.0.50727.4241

WSManStackVersion              2.0

SerializationVersion           1.1.0.1

Open script in ISE

The cool thing is that I can open a Windows PowerShell script in the Windows PowerShell ISE on my 64-bit laptop (running Windows 8a and Windows PowerShell 3.0) from the remote file share. So I do the following:

  • I open the Windows PowerShell ISE.
  • I click File, then Open.
  • In the Open dialog box, I type the UNC path to the remote file share and I press ENTER. I am now viewing the files from the share, as shown in the following image.

Image of menu

I view (and edit if required) the script from the remote file share. When I am ready, I click the green triangle (or press F5) to run the script. At the top of the output pane, I see the UNC location to the script. On the subsequent lines, I see the output.

Keep in mind that the script resides on a remote file share, but the execution of the script takes place on my local computer, and the output that is displayed relates to my local computer. For instance, the remote server is a Dell device, but my local laptop is a Lenovo device. The remote server is named DC1, but my local laptop is named EDLT. The script and the output from the script are shown here.

Image of command output

Run directly in the Windows PowerShell console

But I do not need to open the script in the Windows PowerShell ISE; instead, I can run it directly from the Windows PowerShell console. Two ways to do this are to dot-source the script, or to use the Invocation operator.

PS C:\> . \\dc1\share\ServerNameBios.ps1

PS C:\> & \\dc1\share\ServerNameBios.ps1

The commands and the output from the commands are shown in the following image.

Image of command output

That is all there is to using a Windows PowerShell script from a remote file share. Join me tomorrow when I will talk about more stuff related to running a script from a remote file share.

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 Get DHCP Stats

$
0
0

Summary: Learn how to use Windows PowerShell 3.0 in Windows Server 2012 to get DHCP statistics.

Hey, Scripting Guy! Question How can I get an overview from my DHCP server running on Windows Server 2012?

Hey, Scripting Guy! Answer Use the Get-DHCPServerv4Statistics function:

Get-DhcpServerv4Statistics -ComputerName DHCP1

Weekend Scripter: Run PowerShell Scripts from Remote File Share: Part 2

$
0
0

Weekend Scripter: Run PowerShell Scripts from Remote File Share: Part 2

Summary: Microsoft Scripting Guy, Ed Wilson, continues his discussion about running scripts on a remote file share.

Microsoft Scripting Guy, Ed Wilson, is here. This week has been absolutely bizarre. I have been really busy working with a select group of Honorary Scripting Guys for upcoming blog posts. I must say, there is some absolutely way cool, knock-out stuff in the works. But of course, to make all of this streamlined, I had to set up a shared Office 365 SharePoint site, grant permissions, create views, test things out, and all of that. You know what? Dude, it was easy!!! As you may guess from the three exclamation points, I was surprised. I must say that I was dreading it. I will also say that it was so intuitive that I did not once have to use Help or search for How-To articles. It really makes sense, and it has actually been a fun project. As one twentieth-century philosopher said, “I love it when a plan comes together.”

Examining script execution policy

Note  This is the second in a multipart series of posts. The first post was Running Scripts from a Remote File Share.For good background info about running Windows PowerShell scripts from a remote file share, check out the guest blog post written by June Blender and Judith Herman: How to Run PowerShell Scripts from a Shared Directory.

By default when you open Windows PowerShell, the execution of scripts is disabled. This is because the default script execution policy in Windows PowerShell is restricted. To see the current script execution policy, use the Get-ExecutionPolicy cmdlet. For the current user, all you need to do is type the cmdlet name. This is shown here:

PS C:\> Get-ExecutionPolicy

RemoteSigned

To see all of the execution policies, use the –List switch as shown here:

PS C:\> Get-ExecutionPolicy -List

 

                             Scope                           ExecutionPolicy

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

                             MachinePolicy                   Undefined

                             UserPolicy                         Undefined

                             Process                             Undefined

                             CurrentUser                       RemoteSigned

                             LocalMachine                     Unrestricted

You can see that there are multiple levels to which the script execution policy can be set. An ordinary user can change the CurrentUser script execution policy (unless it is specified via Group Policy. In that case, it cannot be modified by a local user). When the execution policy is first checked, it is restricted; therefore, no scripts will run. In the following example, the execution policy is set to RemoteSigned for the current user, and a check verifies that the change works.

Image of command output

What is RemoteSigned, anyway?

A good setting to use in an enterprise situation is RemoteSigned. This means that a script from a remote location must be signed by a recognized Certification Authority (CA) with a code-signing certificate. There are specific trusted roots that are set up automatically. I can see them by using the Cert PS: drive and looking at CurrentUser\Root. The command is shown here:

dir Cert:\CurrentUser\Root

The following image shows the command and output from the command.

Image of command output

So, if a script runs from a remote location, it must be signed by one of the CAs with a root listed in the previous output. I can use Group Policy to add a trusted CA, so I can issue code-signing certificates on my local network. I can also purchase a code-signing certificate from the Internet and if it is trusted, everything will be groovy. But I only need to do that if the location is remote.

Note  Refer to the post listed earlier by Judith and by June for more information about this.

Because Windows PowerShell relies on the Internet Explorer definition of what is remote, a network share on my home domain is considered remote. Therefore, it needs to be signed. But more than that, even if I set my execution policy to Unrestricted, it STILL will prompt prior to running. This is by design, but it can be annoying. The best way to modify the Internet Explorer trusted sites setting is to use Group Policy. This is shown here:

Image of menu

In my mind, the best way to do this via Group Policy is to create a special Group Policy Object (GPO) with this setting and then apply it to appropriate scope within the domain. Give it a nice name so it makes it easy to keep up with.

After I have made my changes—even with RemoteSigned as the execution policy—I can run my scripts from network shares. This is because the network shares are not considered remote. This is shown here.

Image of command output

Well, that is about it for today. I am going to head out to my woodworking shop and work on my hand-cut dovetails. Join me tomorrow when I will continue this discussion about remotely running scripts from file shares.

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


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>