Tag Archives: Hacks

Scheduled tasks, PowerShell’s -file parameter, and array values

I wrote a script that accepts a comma-separated list of values, and the script worked just fine from the command-line. However, when I tried to configure a scheduled task to run the script, it always failed.

Why? Well, I started a cmd.exe session and then launched the script in the same way that the scheduled task did, using PowerShell’s -file parameter. And when I did that, the error message that I emit from the script showed me that the list was being parsed as a single string argument.

To confirm and experiment, I wrote a short little test script:

<# Cast-WizardSpell.ps1 
Simple script to test parameter parsing when using -file invocation e.g.: 
powershell.exe -file .\Cast-WizardSpell -Spell 'Light','Magic Missile' 
process {

    foreach ($spell in $spells ) {
        "Casting $spell"

When run from within a PowerShell session, it works as expected:

PS C:\> .\Cast-WizardSpell.ps1 -SpellList 'Ray of Frost','Light','Detect Magic'
Casting Ray of Frost
Casting Light
Casting Detect Magic

When invoked using the PowerShell -file parameter, the comma-separated list is parsed as a single parameter (note: cmd.exe doesn’t like single quotes):

C:\>powershell -file .\Cast-WizardSpell.ps1 -SpellList "Ray of Frost","Light","Detect Magic"
Casting Ray of Frost,Light,Detect Magic

# Trying explicit array syntax, but no luck

C:\>powershell -file .\Cast-WizardSpell.ps1 -SpellList @("Ray of Frost","Light","Detect Magic")
Casting @(Ray of Frost,Light,Detect Magic)

What does work is to use the old-style -command syntax:

C:\>powershell -command "& .\Cast-WizardSpell.ps1 -SpellList 'Ray of Frost','Light','Detect Magic'"
Casting Ray of Frost
Casting Light
Casting Detect Magic

Alternatively, one can adjust the parameter syntax, adding the ValueFromRemainingArguments attribute. However, for this to work, you can’t specifiy the parameter name.

C:\>powershell -file .\Cast-WizardSpell.ps1  "Ray of Frost" "Light" "Detect Magic"
Casting Ray of Frost
Casting Light
Casting Detect Magic

C:\local\scripts>powershell -file .\Cast-WizardSpell.ps1 -SpellList "Ray of Frost" "Light" "Detect Magic"
C:\local\scripts\Cast-WizardSpell.ps1 : A positional parameter cannot be found that accepts argument 'Light'.
+ CategoryInfo          : InvalidArgument: (:) [Cast-WizardSpell.ps1], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Cast-WizardSpell.ps1

I’m not thrilled with either of these options, because some person like me may come along and, in an effort to be helpful, may twiddle the command line, thinking we’re normalizing or updating the syntax, when we’re really breaking things. However, I think using the -Command invocation is the least surprising, most consistent implementation. I’ll just make notes in the script help and in the description of the scheduled task about the reason I’ve used that method.




Robocopy file classes

This information comes from the Robocopy.exe documentation PDF file for Windows XP version, but it’s the best description I’ve been able to find. From page 15 of that document:

Using Robocopy File Classes

For each directory processed, Robocopy constructs a list of files in both the source
and destination directories. This list matches the files specified on the command line
for copying.

Robocopy then cross-references the lists, determining where files exist and comparing
file times and sizes. The program places each selected file in one of the following

File Class In source In destination Source/Dest file times Source/dest file sizes Source/dest attributes
Lonely Yes No n/a n/a n/a
Tweaked Yes Yes Equal Equal Different
Same Yes Yes Equal Equal Equal
Changed Yes Yes Equal Different n/a
Newer Yes Yes Source > Destination n/a n/a
Older Yes Yes Source < Destination n/a n/a
Extra No Yes n/a n/a n/a
Mismatched Yes (file) Yes (directory) n/a n/a n/a

By default, Changed, Newer, and Older files are candidates for copying (subject to
further filtering, as described later). Same files are not copied. Extra and Mismatched
files and directories are only reported in the output log.

Normally, Tweaked files are neither identified nor copied – they are usually identified
as Same files by default. Only when /IT is used will the distinction between Same and
Tweaked files be made, and only then will Tweaked files be copied.

Readable System Event logs

I think I’m not alone in finding the Service Control Manager logs so many informational events as to make it hard to read the important events in the System Event logs on modern Windows systems.

I’ve used custom XPath queries of Event logs before, and decided to define a Custom view of the System event log that suppresses the events generated by the Service Control Manager that are in the Informational or Verbose catergories. Here’s the XML that defines this custom view:

 <Query Id="0" Path="System">
 <Select Path="System">*</Select>
 <Suppress Path="System">*[System[Provider[@Name='Service Control Manager']
 and (Level=4 or Level=0 or Level=5)]]</Suppress>


Quick tip – Human readable folder sizes in Excel

From the school of There’s Probably a Better Way, But…

I was taking the output of SysInternals’ du.exe utility and wanted to email it to a colleague, but the folder sizes were in KB. Since most of them were many Gigabytes in size, I wanted a quick way to convert them to the appropriate size in GB, MB, or KB.

I copied the du.exe size column and pasted it into Excel. Then I created the following formula:

=IF(E6>(2^20),TEXT(E6/(2^20),"0.0") & " GB","smaller")

…where E6 is the cell reference. Also note that du.exe’s output was in KB, so my test is one order of magnitude smaller than it would need to be if I was formatting a size in bytes. (i.e., 2^20 is 1 MB).

I then nested another similar if() function with a final formatting option to get my final formula:

=IF(E6>(2^20),TEXT(E6/(2^20),"0.0") & " GB",IF(E6>(2^10),TEXT(E6/(2^10),"0.0") & " MB",TEXT(E6,"0.0") & " KB"))

Adding VMware Tools to WinPE 4.0

I’m trying to augment the Bare Metal Recovery boot image provided by EMC as part of the NetWorker Client to support recovery in our VMware vSphere environment. The BMR .ISOs include a sources\boot.wim file that I should be able to modify.

I started with these somewhat date instructions in the VMware knowledgebase. I copied the contents of the .ISO file to a temporary directory on my PE Build system (Windows 8 guest). Using the Windows ADK, I mounted the sources\boot.wim file.

C:\Temp>dism /mount-image /imagefile:c:\temp\NW-MBR-ISO\sources\boot.wim /index:1 /mountdir:c:\temp\mount

I downloaded the latest VMware Tools, then used the /A switch (administrative install) on the setup file to extract the contents to a local folder. The driver files are contained within Program Files\VMware\VMware Tools\VMware\Drivers. I copied that directory to my working location, then added the drivers to the WIM files.

dism /image:c:\temp\mount /add-driver /driver:c:\temp\drivers /recurse

DISM reported success, so I committed the changes and umounted the WIM file.

dism /unmount-image /mountdir:c:\temp\mount /commit

The files I copied off of the EMC-provided ISO were not sufficient to create a new bootable image. So I used the CopyPE command to create a new base image, which included a file source for the PE image as well as the appropriate boot sector files. Since the image source files were identical to the file in the EMC disk image (because this is how they created the image), I just copied my customized boot.wim over the default boot.wim. Then I was able to use the makewinpemedia command to create a new .ISO image.

I’ve been able to boot the image, and it loaded the VMXNET3 like a champ. We’ll see how the Bare Metal Recover process goes. Thankfully, this is a test and not a crisis.

Custom event log queries

I really like the newer event log model on Windows 2008 family, and the flexibility of the XML events and the queries that makes possible.

Recently, I started noticing a quiet failure of a scheduled task. The Task Scheduler thinks that the task completed successfully, though the executable called by the task action returned an error code of 3:

Task Scheduler successfully completed task “\ShareVol_Sync” , instance “{92ac3257-f52d-47eb-9a3a-ce02c5196bbd}” , action “diskshadow.exe” with return code 3.

I wanted to see how long this have been going on, so I switched from the Task Scheduler console to Eventlog Viewer, and navigated to the Operational log under “Applications and Services Logs”- Microsoft – Windows – TaskScheduler.

I started by using the using the Filter Current log dialog to select events with Event ID 201, but this included all “Action completed” events for all tasks. So I looked at the XML view for one of the events for the task I was researching. The event includes a data value named “ActionName” with the value “diskshadow.exe” that should allow me to find all the relevant events.


Next, I needed to refine my filter to look for this value in the events. I opened the Filter Current log dialog again, and switched to the XML tab, then checked the Edit query manually option. You get a scary warning about not being able to use the GUI again, but that only applies to the current filter. Be bold: click OK.

Next, I edited the query, following examples from this excellent Ask the Directory Services Team blog post. The query is junk the between the select tags. Originally, the query was simply:


To that, I added the following:

*[EventData[Data[@Name=’ActionName’] and (Data=’diskshadow.exe’)]]

So that the whole query looks like this:

  <Query Id="0" Path="Microsoft-Windows-TaskScheduler/Operational">
    <Select Path="Microsoft-Windows-TaskScheduler/Operational">
      *[EventData[Data[@Name='ActionName'] and (Data='diskshadow.exe')]]

Now event viewer shows me only the “Action Completed” events for the diskshadow.exe command, and I can see exactly when the behavior changed.

Note that you can save use the query XML with PowerShell’s Get-WinEvent commandlet’s -filterXML parameter [See an example]. You can also use the Save Filter to Custom View option to make this view persistent.

I routinely review Windows’ Event logs during diagnostics and troubleshooting. I find the ability to query those logs for specific data is an indispensable technique. No more dumping to CSV and running findstr! I hope you find it helpful, too.

Use it up – Brother HL-3070CW Toner

Use it up, Wear it out, Make it do, or Do without.

There are some things that we can’t really do without. But good old Yankee thrift pains me every time I have to replace printer consumables.

I have a Brother HL-3070CW color laser printer at home, which I really like. I selected it specifically because it has an optional straight-through printing path, to reduce curl on heavier stock.

I’ve also discovered that it reports being out of toner based on page count or something, rather than a measure of actual toner remaining. I found two ways to make sure I get the most from my toner cartridges.

First, I found that there’s a menu for resetting the state of toner in the printer.

  1. Open the top cover
  2. Press the Cancel and Secure Print buttons together to bring up the toner menu
  3. Use the + and – buttons to select the toner cartridge to reset, and press OK (twice). Each color (CMYK) has two options, one each for standard and high capacity cartridges.
  4. When finished, closed the top cover.

In addition, it’s very easy to reset the physical switch on the toner cartridge, as shown in this short video:

Very easy to do.

(Both procedures from http://www.fixyourownprinter.com/forums/laser/39806 )

I’ve used the menu reset option several times, and I haven’t seen any problems with toner coverage on my printed pages.

When I do need to replace the cartridge, I have found the best prices on Amazon and NewEgg.

Webmail on a Netbook

Amid the praise for and complaints about the newer version of webmail, we received a plea from a netbook user. She pointed out that the new layout made it very difficult to navigate among her mail folders. I use a netbook myself, and I thought I’d share some things that we can do to improve our browsing from a netbook. Specifically, we’re going to take webmail from this:

Webmail on a netbook - before

to this:

Webmail on a netbook - after

Continue reading

Elevated ShellRunAs

Back in the day, I was a good Windows admin and did my administration using the Windows Server admin tools from my workstation, logged in with a non-admin user, using the RunAs shell feature (shift+right-click) to start the admin tool with administrator credentials.

Vista’s “Run as administrator”  feature will run a program with elevated (i.e., administrator) rights, but with the credentials of the current user. The runas.exe shell command provides a way to execute a command with different credentials, but they aren’t elevated.

Now, granted that it is rare that I need to run a tool both as a different users and have elevated rights on the local system. It can happen, though.

Sysinternals provides a handy utility called ShellRunAs, which provides the RunAs feature, and I found a forum post suggesting a method for getting “Run elevated as a different user” functionality.

I haven’t tried it, yet, but I wanted to share the solution.

Worklog – Wednesday, Feb 25

Service restarts on some hosts.

Looked into automating some periodic restarts. One app vendor suggests using SQL Agent. I don’t really like the idea of using SQL Agent for non-database tasks. Found an interesting exercise in CMD batch file writing in a Microsoft script to restart IIS services. Powershell is another possibility.

Problems with SharePoint search service.

Greg worked on the problem, but emailed me on his day off that the problem continues. Given that the message indicates “access denied,” it seems worthwhile to verify that the gatherer is running with sufficient credentials. But starting with a google search, I found:


I checked SharePoint Central Administration, App Management, and “Manage Search Service,” but I receive an error indicating that the search service isn’t running. I have verified that the “Windows SharePoint Services Search” service is running, and checked the account under which it is running.

Checking logs at C:Program FilesCommon FilesMicrosoft Sharedweb server extensions12LOGS. Looking at the log file corresponding to the warning event time, SHAREPOINT1-20090225-1002.log. Looks like a search process kicked off at 10:16:38.

There are some errors indicating “No administration site found for SSP SharedServices.” But later, the gather is committing changes to the admin site. Nothing leaps out at me, here. Except a ton of errors like this:

02/25/2009 11:32:55.43     w3wp.exe (0x0E58)                           0x0AF4    Windows SharePoint Services       General                           8e1f    High        Failed to find the XML file at location ’12TemplateFeaturesBatchSiteManagerLinksfeature.xml’

I also see a message about the Search Service being disabled. It now makes sense to me that the normal windows indexing service is disabled, and thus the “Manage Search Service” option is disabled. I found the Microsoft Search Server program group, but when I launch the Administrator app, I see an icon appear briefly on the task bar, and then it vanishes. Checking the command-line, I see it runs a STSADM.EXE command. Perhaps I can run that command from a command prompt.

Z:>”C:Program FilesCommon FilesMicrosoft Sharedweb server extensions12BINSTSADM.EXE” -o osearch -action showdefaultsspadmin

‘showdefaultsspadmin’ action failed. Additional information: The site with the id [GUI] could not be found.

So maybe there really is a problem with the administration site. I tried stopping and restarting the Windows SharePoint Services Search service, but that didn’t appear to change anything.

However, it is clear that I don’t know much about Microsoft Search Service and the way it has been deployed.

Getting started with Search Server 2008



File locked issue

Examining a reported locked file, I see that it is held open by sa_ss_srchserv. Related to our search problem above?

Problem with Canon Printer Job codes

Printer is installed correctly, and “Get Device Status” successfully returns information, including Job Code setting. Created footprint 43362 from email thread.

Back to restarting services

A one-line powershell script:

restart-servce PncPrintSpooler*

Run as a scheduled task in the early morning. Found some good pointers on starting a powershell script.