I did some AD cleanup yesterday, including removing some accounts that have been disabled for over a year. This is all part of our migration plans to move to integration1.
What I didn’t notice was one of those accounts was for an employee that hadn’t been with the company for several months, but was still live. It was still live, because the department was still actively using it. This is a bad thing™.
I didn’t know it was still in use, after having given them notice to move everything off of that account. So yesterday I removed it, today I found out the repercussions of doing so. My deletion of the AD account, made the jobs stop running. This was pretty obvious, what wasn’t so obvious was that losing the domain account, made it impossible to edit the job. It was generating an interesting error…
The attempt to retrieve account information for the specified task failed; therefore, the task did not run. Either an error occurred, or no account information existed for the task.
The specific error is:
0x80070534: No mapping between account names and security IDs was done.
Well that’s obvious, I deleted the account. So the task seemed pretty simple, all we had to do was edit the job2, and change who it was executing as. Unfortunately, when attempting to edit the job, all the fields relating to the application, and the execution user, were disabled.
This made things complicated. Either they had to recreated all 40+ jobs, or we had to figure out a way to edit the job, and reset the user. Neither seemed like a fun prospect.
However, there was light, somewhere. I vaguely remember reading some docs on WMI that mentioned it could create jobs. This was exactly what I wanted. I could just create a text file with the job info, and parse it in WMI to build the jobs. This drags into use the Win32_ScheduledJob class. This should do exactly what I wanted, until I started to read the fine print.
The Win32_ScheduledJob WMI class represents a job created with the AT command. The Win32_ScheduledJob class does not represent a job created with the Scheduled Task Wizard from the Control Panel. You cannot change a task created by WMI in the Scheduled Tasks UI.
Well that’s kind of useless. I needed to allow the end users manage them, and AT wouldn’t be the way to go. So I started rummaging some more, and stumbled across the documentation for AT. I’ve used this site before specifically for the RoboCopy documentation. Because I’m terrible at keeping my head going in one direction3, I ended up going back to the command list, and stumbled upon schtasks. This is exactly what I needed. Not only could it create jobs, but it could list them too.
From my laptop, I grabbed a copy of what was set to run on the server in question…
schtasts /query /S theserver
This didn’t output anything hugely useful, just the taskname, the next run time, and the last status. I needed more information, so I added the
/V for verbose, and got a whole bunch of extra useful information, like below…
HostName: theserver TaskName: SomeJobName Next Run Time: 02:42:00, 12/6/2007 Status: Could not start Last Run Time: 02:42:00, 12/4/2007 Last Result: 0 Creator: SomeCreator Schedule: At 2:42 AM every Mon, Tue, Wed, Thu, Fri of every week, starting 11/21/2006 Task To Run: \\server\e\apps\someapp.exe Start In: N/A Comment: N/A Scheduled Task State: Enabled Scheduled Type: Weekly Start Time: 02:42:00 Start Date: 11/21/2006 End Date: N/A Days: MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY Months: N/A Run As User: Could not be retrieved from the task scheduler database Delete Task If Not Rescheduled: Disabled Stop Task If Runs X Hours and X Mins: 0:10 Repeat: Every: Disabled Repeat: Until: Time: Disabled Repeat: Until: Duration: Disabled Repeat: Stop If Still Running: Disabled Idle Time: Disabled Power Management: No Start On Batteries, Stop On Battery Mode
I then forced the output of this to a text file. I could easily create a wrapper script to loop through the output of all the jobs, and build a new command line for
schtasks. I had the name, the server it was supposed to run on, the schedule, and the timings. The rest of the information was not very useful, as
schtasks didn’t support them as arguments. Armed with the above information, I wrote a quick PHP script which looped through the output, and built a .bat file which had a command to delete, and a command to reconstruct. The output ended up looking like this (each schtasks is on a single line, wrapping for easy readability):
schtasks /Delete /S theserver /TN sometask /F schtasks /Create /S theserver /RU serviceuser /RP servicepass /SC Weekly /D MON,TUE,WED,THU,FRI /ST 02:42 /TN sometask /TR "\\server\e\apps\someapp.exe"
When executed against all the failed tasks, I managed to rebuild 40+ jobs in about 15 minutes (this included script build time). PHP script is available here. I think that managed to save the new guy a few hours work. Hooray for scripts.
Integrate isn’t really the right word, we’re trashing our old AD domain, and moving to a tree in the corporate forest. The less I have to move, the better it’ll be for my sanity ↩
All 40+ jobs ↩
At the time I was doing this task, I was working on 4 active emails, 2 IRC windows, 2 MSN windows, and 4 browsers windows each working on something entirely different ↩