Windows Tech Support

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Wednesday, 21 November 2012

Windows 8 / Server 2012 Shutdown Safety Tip

Posted on 16:33 by Unknown
I really don't want to try to reinvent the many articles out there on how to make your own "Shutdown" and "Logoff" shortcuts on Windows 8 and Windows Server 2012, but I feel I need to add just a little bit more.

In case you aren't aware of what I'm talking about, I will describe it, sans screen captures.  The issue is how the Windows 8 "Metro" UI makes it feel like you have to click-click-click-click-click to the stupid "Charms" bar in order to Shutdown or Restart your computer.  Let's digress...

The Dilemma

Finding the Shutdown and Restart links in Windows 8 (and Windows Server 2012) for the first time can be a little confusing. I say "little", but that's like saying rednecks are a "little" upset that Obama won the election. Basically, you move the mouse cursor (or your finger or other body part, if you have a touch-screen) to the bottom right corner of the screen.  This brings up the transparent sidebar menu which contains five (5) icons, called "Charms".  You can also press WINKEY+C to do the same.

In case you expect this sidebar thing to be called a "Charms Bar", stop right there!  Microsoft has told some people, including Paul Thurrott, that this is not what it's called.  But in let's move on...

Then you click the bottom icon, which looks like a gear.  This is the "Settings" link.  Because we've gotten used to going through "Settings" to do "Shutdown" and "Restart", right?  This makes NO sense to me, nor to most other people I've talked with, but Redmond knows what we want.  So when you open the Settings panel, you click "Power" and then you get options for "Sleep", "Shutdown" and "Restart".  I'm sure this is because three gestures/clicks is faster than two.  Geez, I'm a real smart-ass tonight.

Band-aid Workaround

The easiest workaround to avoid all this crazy finger-straining is to make your own Desktop or Taskbar shortcuts to "shutdown.exe" with various options (for shutting down immediately, doing a restart, etc.):

"shutdown -s -f -t 0" (shutdown immediately)
"shutdown -r -f -t 0" (restart immediately)

Careful!  Let's add a Safety Button

The danger to using the above commands is the "-t 0" part.  Yes, it means "do it now!!!" (say that with your best Arnold Schwarzenegger impression).  I prefer t use "-t 10" (delay ten seconds), for both of those commands.

But Wait! There's More!

(My respects to Billy Mays)  This is especially relevant to Windows Server 2012:  In addition to adding a delay time, you might want to add one more shortcut:

"shutdown.exe -a" and label it "Abort Shutdown!"

If I really need to explain why this could be helpful, well, I'll let you ponder this for a few more minutes. I'm giving you the benefit of the doubt.  Okay, I'll tell you:  It's like cutting the green wire when the bomb is about to detonate in a few seconds.  It's your safety abort switch.  From here you can right-click on these shortcuts and Pin them to Start or the Taskbar, or both.

Read More
Posted in network administration, windows server 2012, windows8 | No comments

Monday, 19 November 2012

Why "Coming Soon" Can Be a Bad Idea

Posted on 16:18 by Unknown
I'm not sure what drives some companies to want to show their hand early, while others play them close to the vest. Especially in the field of computer hardware and software.

I've read dozens of articles comparing the marketing philosophies of companies like Apple, Microsoft, Sony, Nintendo and Samsung. But the one in this list in a unique situation is Microsoft. They earn a major portion of their revenue from enterprise business sales and subscriptions. Enterprise customers, unlike consumers, live on quarterly and annual budget cycles.

When Sony or Nintendo announces a major product is "coming soon" in the consumer market space, it doesn't have the same effect on their market as what happens when Microsoft announces a new version of Windows is coming in six months.  Enterprise customers hear that and do the following:  Hold off on buying and upgrading.  Even if the pricing is tweaked to offer a "free jump" to the new version when buying the current version within X months of the release, that's not the real challenge.  The real challenge is dealing with another round of planning, preparation, testing, and deploying.  Then there's the user learning curve issue and training.  Even when many organizations opt out of training budget, they have to contend with the communications and hand-holding aspects.  Intranet posts, e-mails, meetings, meetings and more meetings.  It all adds up to pain.

Sure, it's not always practical to suddenly announce a major new release of Windows or Office, when enterprise customers, partners, OEMs, and developers need lead-time to get familiar with the new versions.  But there needs to be a better/happier medium than announcing a new release coming "next year".  Practical or not, my gut feeling is somewhere between three (3) and four (4) months is about right.  Thoughts?

Read More
Posted in apple, business, marketing, microsoft, society, sony | No comments

Sunday, 11 November 2012

A Little Humor for Monday morning

Posted on 20:59 by Unknown
I dusted this off from the original I did in 2003.  I updated the logos and added Amazon, but otherwise it's pretty relevant to today I think...

Read More
Posted in advertising, amazon, apple, fun, google, humor, marketing, microsoft, stupidity, ubuntu | No comments

Crude But Effective: Part 2, the Electric Boogaloo

Posted on 10:32 by Unknown
In my previous article I described a system for replicating some of the functionality of the ConfigMgr Right-Click Tools (aka "SCCM Right-Click Tools"), through a web interface (intranet web portal application) using a combination of HTML, ASP, and a database back-end   What I planned to do was provide a little more detail of each of the pieces in follow-on articles.  This way, if you really cared enough, you could build your own setup (and probably do a better job of it than I have).

In this article I'm going to expand on the part of the process which involves the database back-end  and the script that runs on a schedule to query, process and update the database table.

The Database Table

To bring all of the processing into one central "hub", I chose to use a Microsoft SQL Server database, and create a table to capture the incoming requests from the portal.   My database server is named "DB1" and is running on SQL Server 2012, but it doesn't matter what version you use really.  I've tested this setup on 2005, 2008 and 2008 R2 with equal results.  The name of my database is "AMS" (for Asset Management Services), but you can call it whatever you want, just modify the names below to suit your needs.  The table I created is named "ClientToolsLog", but again, that's not required, so you could name it "DogPoo" and it won't matter.

USE [AMS]

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[ClientToolsLog](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ActionName] [varchar](50) NOT NULL,
[Network] [varchar](50) NOT NULL,
[Comment] [varchar](255) NULL,
[AddedBy] [varchar](50) NOT NULL,
[DateAdded] [smalldatetime] NOT NULL,
[DateProcessed] [smalldatetime] NULL,
[ResultData] [varchar] (50) NULL,
)
GO

GRANT SELECT, INSERT, UPDATE, DELETE on ClientToolsLog TO amsManager
GO

GRANT SELECT on ClientToolsLog TO amsReadOnlyUser
GO


The Table Structure

Each of the columns has a purpose, so I'll explain them each below:
  • ID - This is used to identify the specific row in the table.  Because it's an integer value, and auto-incremented by 1, you don't specify a value for this field when inserting a new row. You only need it if you want to query, modify, or delete a specific row.
  • ActionName - (required) This is where the specific action name is entered.  I use my own abbreviated codenames to save on space (this log can easily grow very quickly with multiple users!).  For example, I use "MACHINE_POLICY" to indicate "Machine Policy Retrieval and Evaluation", and "HWINV" to indicate "Hardware Inventory Cycle", and so on. (see image below for the list of default available actions for ConfigMgr 2012 clients)
  • Network - (required) This is for storing the AD domain name or the CM site name, the choice is yours and it really doesn't matter, but I made it mandatory so you can modify "NOT NULL" to "NULL" if you prefer.  It's just there to enable filtering on specific environments when needed.
  • Comment - (optional) This is for entering a comment if desired. I had initially intended this to be a [textarea] field on the web form, but decided to skip it to avoid unnecessary data.
  • AddedBy - (required) This stores the username of the person who submitted the request from the web site form.  For this to work, you MUST enable "Windows Authentication" in IIS for the web site or the virtual folder.  If you leave it on "Anonymous" there won't be any way to track who the user was unless you build in forms-based authentication (yuck!)
  • DateAdded - (required) This stores the date and time when the request was submitted
  • DateProcessed - This is initially NULL until the script comes along and processes the request, at which time it enters the date and time it was completed.
  • ResultData - This is also initially NULL until the script updates the row when the request has been processed.

Security

I chose SQL accounts for this setup, but you could use mixed-mode.  I do a lot of things by force of habit, so SQL accounts are pretty common for my work, so I tend to use mixed-mode setups.  In any case, I have two user accounts for this system:
  • amsManager - This account has rights to SELECT, INSERT, UPDATE and DELETE data and rows in the table.  I use this account from within the web application to insert new records, and it's used in the script (discussed later) to update the rows when requests are processed.
  • amsReadOnlyUser - This account only has SELECT rights, and is used for any applications/scripts/processes where someone needs to be able to consume (read) the data but not have the ability to modify or delete anything.

The Script

Now that the database is created, the table created and the permissions applied to the table, the next step is getting a script to work with it to do the heavy-lifting.  You can do this with almost any language, including PowerShell, VBscript, KiXtart, Perl, Python or whatever.  As long as the language you choose can do the following things it should work fine:
  • Open a database connection to query (read) and update data in the rows.
  • Execute shell operations to call external .exe applications (SendSchedule.exe), as well as invoke COM interfaces such as WMI and SWBEM requests.
Again, out of habit, I chose VBScript.  I was going to do it with PowerShell, but I got lazy.  Here's the code, but I have to mention that one key "action" is left out for now, and that's the "Re-Run Advertisement" option.  The reason is that I'm still working on this part and having some challenges.  When I get it working reliably and consistently I will post an update:

'****************************************************************
' Filename..: ams_client_tools.vbs
' Author....: David M. Stein
' Date......: 11/11/2012
' Purpose...: invoke ConfigMgr Agent "client actions" on remote clients
' using a SQL table and WMI invocation
' SQL.......: DB1\AMS
' Comment...: Beware of line-wrapping!  If I wrap it I used [& _]
'****************************************************************

Dim query, conn, cmd, rs, objShell, scriptPath, recID, objFSO

' controls DebugPrint output
Const verbose = True

' database connection
Const dsn = "DRIVER=SQL Server;SERVER=DB1;database=AMS;UID=amsManager;PWD=P@ssw0rd$123;"

' database table name
Const strTable = "dbo.ClientToolsLog"

'------------------------------------------------------------
scriptPath = Replace(wscript.ScriptFullName, "\" & wscript.ScriptName, "")
'------------------------------------------------------------
' constants used by this script (abridged format)
'------------------------------------------------------------
Const adOpenDynamic = 2 Const adOpenStatic = 3 Const adLockReadOnly = 1 Const adLockPessimistic = 2 Const adLockOptimistic = 3 Const adUseServer = 2 Const adUseClient = 3 Const adCmdText = &H0001 Const adStateClosed = &H00000000 Const adStateOpen = &H00000001 Const ForReading = 1 Const ForWriting = 2 Const ForAppend = 8 Const TristateUseDefault = -2 Const TriStateTrue = -1 Const TriStateFalse = 0 '------------------------------------------------------------ DebugPrint "info: begin processing..." Set objShell = CreateObject("Wscript.Shell") query = "SELECT * FROM " & strTable & _ " WHERE DateProcessed IS NULL ORDER BY ID" Set conn = CreateObject("ADODB.Connection") Set cmd = CreateObject("ADODB.Command") Set rs = CreateObject("ADODB.Recordset") On Error Resume Next conn.ConnectionTimeOut = 5 conn.Open dsn If err.Number <> 0 Then wscript.echo "fail: database connection failed" wscript.quit(err.Number) Else On Error GoTo 0 End If rs.CursorLocation = adUseClient rs.CursorType = adOpenStatic rs.LockType = adLockReadOnly Set cmd.ActiveConnection = conn cmd.CommandType = adCmdText cmd.CommandText = query rs.Open cmd If Not(rs.BOF And rs.EOF) Then xrows = rs.RecordCount counter = 0 Do Until rs.EOF recID = rs.Fields("ID").value compName = rs.Fields("ClientName").value actName = rs.Fields("ActionName").value actCode = ClientActionCode(actName) addBy = rs.Fields("AddedBy").value DebugPrint "record id...... " & rs.Fields("ID").value DebugPrint "client name.... " & compName DebugPrint "action name.... " & actName DebugPrint "action code.... " & actCode DebugPrint "requestor...... " & addBy DebugPrint "request date... " & rs.Fields("DateAdded").value DebugPrint "network........ " & rs.Fields("Network").value If IsOnline(compName) Then retval = ExecAction(compName, actName, actCode, addBy) Else DebugPrint "result......... offline!" retval = 100 End If DebugPrint "result......... " & retval MarkRecord recID, retval DebugPrint "-------------------------------------------" rs.MoveNext Loop DebugPrint "info: " & counter & " processed" Else DebugPrint "info: no records found" End If rs.Close conn.Close Set rs = Nothing Set cmd = Nothing Set conn = Nothing '------------------------------------------------------------ ' function: return datestamp formatted for log file use '------------------------------------------------------------ Function LogTime() LogTime = FormatDateTime(Now, vbShortDate) & " " & _ FormatDateTime(Now, vbLongTime) End Function '------------------------------------------------------------ ' function: return TRUE if computer responds to a PING request
' note: this features can be impacted by firewall settings!
'------------------------------------------------------------

Function IsOnline(strComputer)
Dim objPing, query, objStatus, retval
If strComputer <> "" Then
    query = "SELECT * FROM Win32_PingStatus WHERE Address='" & strComputer & "'" 
Set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}")._
ExecQuery(query)
For Each objStatus in objPing
If Not(IsNull(objStatus.StatusCode)) And objStatus.StatusCode = 0 Then
IsOnline = True
End If
Next
End If
End Function

'------------------------------------------------------------
' function:
'------------------------------------------------------------

Function ClientActionCode(actionName)
Select Case actionName
Case "MACHINE_POLICY":
' Machine Policy Retrieval and Evaluation Cycle
ClientActionCode = "{00000000-0000-0000-0000-000000000021}"
Case "HWINV":
' Hardware Inventory Cycle
ClientActionCode = "{00000000-0000-0000-0000-000000000001}"
Case "SWINV":
' Software Inventory Cycle
ClientActionCode = "{00000000-0000-0000-0000-000000000002}"
Case "DISCOVERY":
' Discover Data Collection Cycle
ClientActionCode = "{00000000-0000-0000-0000-000000000003}"
Case "RERUN_ADV":
' Re-Run Advertisement
ClientActionCode = "RERUNADV"
Case "INST_SOURCE":
' Windows Installer Source List Update Cycle
ClientActionCode = "{00000000-0000-0000-0000-000000000032}"
Case "UPDATE_SCAN":
' Software Updates Scan Cycle
ClientActionCode = "{00000000-0000-0000-0000-000000000113}"
Case "AMT_PROV":
' AMT Auto Provisioning Policy / Out-of-Band Mgt Scheduled Event
ClientActionCode = "{00000000-0000-0000-0000-000000000120}"
Case "BRANCH_DP":
' Branch Distribution Point Maintenance Task
ClientActionCode = "{00000000-0000-0000-0000-000000000062}"
Case "UPDATE_DEP":
' Software Updates Deployment Evaluation Cycle
ClientActionCode = "{00000000-0000-0000-0000-000000000108}"
Case "SW_METERING":
' Software Metering Usage Report Cycle
ClientActionCode = "{00000000-0000-0000-0000-000000000031}"
Case "USER_POLICY":
ClientActionCode = "{00000000-0000-0000-0000-000000000027}"
Case Else:
ClientActionCode = ""
End Select

' list of codes for future inclusion...
'
'{00000000-0000-0000-0000-000000000010} File Collection
'{00000000-0000-0000-0000-000000000021} Request machine assignments
'{00000000-0000-0000-0000-000000000023} Refresh default MP
'{00000000-0000-0000-0000-000000000024} Refresh location services
'{00000000-0000-0000-0000-000000000025} Request timeout value for tasks
'{00000000-0000-0000-0000-000000000026} Request user assignments
'{00000000-0000-0000-0000-000000000032} Request software update source
'{00000000-0000-0000-0000-000000000061} DP: Peer DP status report
'{00000000-0000-0000-0000-000000000062} DP: Peer DP pending status check
'{00000000-0000-0000-0000-000000000111} Send unset state messages
'{00000000-0000-0000-0000-000000000112} Clean state message cache
'{00000000-0000-0000-0000-000000000114} Refresh update status

End Function

'--------------------------------------------------------
' function:
'--------------------------------------------------------


Function ExecAction(clientName, actionName, actionCode, userID)
Dim strCmd, result

DebugPrint "info: executing action request for " & clientName

If actionCode = "RERUNADV" Then
' result = RerunAdv(compName, advID)
    ' [[ I will cover this in part 4 of this article ]]
    result = 200 ' denotes request was ignored (for now)
Else
strCmd = scriptPath & "\SendSchedule.exe " & actionCode & " " & clientName
wscript.echo "info: command = " & strCmd
result = objShell.Run(strCmd, 1, True)
End If

'--------------------------------------------------------

ExecAction = result

End Function

'------------------------------------------------------------
' function:
'------------------------------------------------------------

Sub MarkRecord(recID, pVal)
Dim query, conn, cmd, rs

wscript.echo "info: marking record completed..."

DebugPrint "info: id = " & recID & " / result = " & pval

query = "SELECT * FROM " & strTable & " WHERE id=" & recID

Set conn = CreateObject("ADODB.Connection")
Set cmd = CreateObject("ADODB.Command")
Set rs = CreateObject("ADODB.Recordset")

On Error Resume Next
conn.ConnectionTimeOut = 5
conn.Open dsn
If err.Number <> 0 Then
wscript.echo "fail: connection failed"
wscript.quit(err.Number)
Else
On Error GoTo 0
End If

rs.CursorLocation = adUseClient
rs.CursorType = adOpenDynamic
rs.LockType = adLockPessimistic

Set cmd.ActiveConnection = conn

cmd.CommandType = adCmdText
cmd.CommandText = query
rs.Open cmd

If Not(rs.BOF And rs.EOF) Then
rs.Fields("DateProcessed").value = Now
rs.Fields("ResultData").value = pVal
rs.Update
Else
DebugPrint "error: no records found"
End If

rs.Close
conn.Close
Set rs = Nothing
Set cmd = Nothing
Set conn = Nothing

End Sub

'------------------------------------------------------------
' function: verbose echo printing
'------------------------------------------------------------


Sub DebugPrint(s)
If verbose = True Then
wscript.echo s
End If
End Sub


What The Script Does

As I mentioned before, each time the Scheduled Task runs, it calls the script.  The script performs the following actions in the order/sequence listed below:
  • Opens a Connection to the database using ADO (COM) with SQL user permissions
  • Submits a Query for all rows where the DateProcessed value is NULL (indicating the request has not been processed yet).  The results are obtained as an ADO RecordSet object.
  • Iterates the RecordSet rows to gets the remote Computer Name, and ActionName field to determine the specific things that need to be done for the requested action (for example: look up the Action Code GUID)
  • Initiates a WMI (Win32_Ping) request to determine if the remote computer is online.
    • If not online, the ResultData column is updated with a value to indicate the client was offline
    • If online, the Action is processed...
  • Executes the requested Action:
    • If a "Client Action" is requested: Open a Shell session using WScript Shell object (COM) and executes the SendSchedule.exe application with the appropriate GUID for the Action and the name of the remote computer.  Gets the result/exit code from the SendSchedule process.
    • If "Re-Run Advertisement" is requested:  (to be continued)
  • Updates the database table row by entering the appropriate result code (ResultData) and the timestamp of the completion (DateProcessed)
  • Exits
Not really complicated actually.  This is a pretty straightforward and common process for interacting with database tables with ADO.  You could separate the requests and the results into two tables if you prefer, but I'm not shooting for 3NF or 4NF here.  I'm too lazy for that much work.

The Scheduled Task

This is where the Security aspect comes into play.  You need to execute the script under a context which has permissions to invoke the Configuration Manager Agent on remote computers over your network from a WMI interface.  I created a special Domain user account for this and added to the local Administrators group on every desktop and laptop computer using Group Policy and Restricted Groups.

Before setting up the Scheduled Task, I highly recommend testing the script directly.  Open a session (interactive login or use RunAs to open a CMD console) under the credentials of the user account you intend to use for the Scheduled Task.  Test the script until you are satisfied it works correctly.

As a force of habit, I use a simple BAT script to wrap my calls to VBScript to I can pipe the output (wscript.echo or DebugPrint results) to a log file if I want.  Or you can do it from within the VBScript code using basic FileSystemObject (FSO) methods if you prefer.  Either way, it can be helpful to generate a log file to diagnose issues where the database is unavailable for some reason when the scheduled task is executed.

The Schedule you choose is entirely arbitrary.  I run mine at ten (10) minute intervals all day, every day.  It also doesn't matter how you choose to create the Scheduled Task.  You can obviously use the GUI, or do it from the command line using SchTasks.exe, or from a script or whatever.

Summary

All of this I've covered here is essentially the "back-end" of the process.  I hope it you find it useful and helpful.  Let me know by posting a comment below?  In the next part of this article I will delve into the web form and the user interaction aspects.
Read More
Posted in applications, automation, config manager, databases, group policy, network administration, process automation, projects, scheduling, scripting, software development, sql server, t-sql, tutorials, vbscript, wmi | No comments

Saturday, 10 November 2012

Blog News and Updates!

Posted on 17:26 by Unknown
It's been awhile since I've posted anything mildly interesting here (even if you include the article I just posted before this).  But I have an announcement to make...

I've accepted an offer to write for 4Sysops.com!

I will post an update here when my first article is published, so please stay tuned.  I'm putting a lot of time into it, so I hope you find them useful and entertaining (yeah, I will still insert my stupid humor where I can).


Read More
Posted in articles, blogs, publishing, technology, writing | No comments

Crude But Effective (ConfigMgr Right-Click Tools Trickery)

Posted on 17:21 by Unknown
Intro:  I just took the wraps of this particular "feature" within a web application project I've been working on for some time now.  So I figured it was a good time to share some thoughts about why I spent the time and effort to make it work.  I'm not going to say it's 100% complete yet, and I still have some features to fill-out, but it's walking on two legs and says "Daddy!" so I'm kind of proud of it.  I actually submitted this for another blog site but it was rejected as not being within the topic set they prefer, so I'm posting it here. 

A Little Background

Anyone who grew up watching the original Star Trek series on TV should recall a particularly famous line quoted by Spock, where he said "Crude, but effective".  The implication made was that a “solution” doesn't always have to be elegant or optimal in order to be sufficient.  Hence the name of this article for the mini-project I’m about to describe and bore you to death. So, let’s get started!

One of the most widely-used tools in the world of Microsoft enterprise systems management, is System Center Configuration Manager.  One of the most widely-used tools to extend the functionality of Configuration Manager is (or are) the "SCCM Right-Click Tools", developed and supported by Rick Houchins (link).
The tool-set installs a set of scripts, and some XML extensions to the MMC console snap-in for Configuration Manager.  The result is an additional set of pop-out menus when you right-click on resources in the MMC console.  They are grouped into "Tools", "Actions", "Log Files" and so on, each having a set of links to perform useful tasks, upon a single resource (computer) or all of the resources in a selected Collection. Some of the features it provides include:
●     Invoke ConfigMgr Agent actions such as:
○     Hardware (and Software) Inventory
○     Machine (and User) Policy Retrieval and Evaluation
○     Discovery Data Collection Cycle
○     More
●     Run Client Tools such as:
○     Restart ConfigMgr Agent service
○     Uninstall/Re-install ConfigMgr Client
○     Re-Run Advertisements
●     View Client Log Files
●     View Reports for selected Clients or Collections

There are quite a few versions of this out in the wild, and I've rarely seen, or heard of two IT shops using the same (or even latest) version.  Regardless, Rick's product has become so popular and widely-known, that's it’s hard to find a ConfigMgr Administrator anywhere in the world that hasn't heard of it, let alone one that doesn't use it every day.  It’s even spawned inspired projects such as Client Tools (link) and SCCM Client Actions Tool (link).  Some have taken off, while others have not.  Ultimately, it's a good thing to inspire others to try good things for the good of others, is it not?
One of the larger projects I've been working on for the past year is a web-based tool for integrating and managing multiple enterprise "islands" of information to achieve an holistic management tool.  This involves Configuration Manager, Active Directory, legacy inventory management systems, multiple databases, and rolls all of that into a Role-Based Access Control interface that maps the features to the discrete functional groups within their IT department, as well as specific features made available to end users.
Some of you might wonder if this has anything to do with my old "Windows Web Admin" project that I killed a while ago.  The answer to that is "yes".  WWA formed the basis of this project, but if WWA was 1.0, this project is approximately 5.0.  There’s a lot of change and scaling out in this one, but it's genesis was WWA.  Okay, enough of that. Let's move on...
One of the most daunting challenges that I've been trying to solve is how to incorporate my own set of "client tools" into the web interface.  Why is this so difficult?  Primarily, the biggest concern is security risk and exposure.  There are quite a few potential ways to approach this, but let’s break it down in the most basic terms:

The Goal

The goal of this particular subset of the project is to be able to directly invoke processes on remote computers over a network connection, and initiate this from within a web browser.  Some aspects of the Right-Click tools are easy to implement via a web interface, such as exploring the C: drive, opening the remote log or cache folder, and ping for connectivity testing.  But the features which require invoking a WMI or WBEM/SWBEM interface remotely are a little more complicated to achieve from within a local web browser session.  At least they are for my limited set of abilities.
In the simplest terms, WBEM, or Web-Based Enterprise Management, is the web interface for WMI services on a given computer.  WBEM is the mechanism by which you connect to, and interact with, the ConfigMgr client on a remote computer.  It’s also how you connect to, and interact with the site server, but that’s for another article.
WMI and WBEM can be a little complicated to describe, but that’s not necessary for this article.  But you do need at least a basic understanding of WBEM as it pertains to "what it is", so that you can appreciate what’s going on under the hood when you turn the key and start this beast up.
The good news is that you don’t have to roll up your sleeves and get dirty with programming code in order to leverage WBEM's benefits.  There are packaged utilities that can do the messy work for you, such as the SendSchedule.exe utility included with the Microsoft ConfigMgr Toolkit v2.
There are probably more potential "options" to solving this dilemma, but I've boiled it down to three:

Option 1 - Client-Side Code

It could be done with some JavaScript code with JSON or JQuery, or whatever, running as a client-side process (on the computer where the browser is active).  This makes it possible to run in the context of the logged on user.
The problem with the client-side script option is security context and "sand-boxing" with respect to invoking other local scripts, or an executable, under the logged-on user context.  There's also the challenge of maintaining centralized access control and logging. The security model in this scenario relies on individual user accounts having permissions to invoke remote interfaces like the ConfigMgr Client Agent service.  This isn't a bad thing however, but it does depend on diligent administration of an AD security group.

Option 2 - Server-Side Code

It could be done with server-side code, but that would involve forked or marshaled processes running under the context of a proxy account.  Or it could be run in the context of the IIS application pool, or even the IIS web site.
The biggest problem with the server-side code approach is the use of a proxy user account, and controlling access to the folders and files in which the user context can execute.  The security model in this scenario is a single "proxy" user account, with permissions granted to allow it to invoke remote interfaces on client computers.

Option 3 - A Real Developer

It could also be done with custom programming using .NET or Java and a compiled executable or even a browser add-in.
The security model in this scenario could be either of the two described in the first two options above, or even a hybrid of both of them.  However, the less obvious "problem" with this approach comes down to complexity, time and resources.  Very often the fourth issue is budget.  In our case, we don’t have this as a viable option at our disposal.  What we do have at our disposal is.... me. 
That’s right.  Simple. Basic. Me.  My skill set is not the most robust on Earth, big shock, I know, but it does contain enough database, and coding skills, and a fetish for application design, to be dangerous.  And if you (ok, I) add a pinch of stupidity, sarcasm and bad humor, and a teaspoon of caffeine to the mix, you have a concoction that get it done.  So this led me to option 4...

Option 4 - Duct Tape, Chewing Gum, and Bailing Wire

The old McGyver approach.  This is actually a very old method, but it's a tried-and-true method, that has stood the test of time and many, many projects.  It's the old "web-database-scheduler" approach.  Let me digress...
In the most basic terms possible:
There’s a web interface for submitting the requested "action" to be performed on a remote client.  This captures the basic information: the client (or collection) name, and the action to be performed.  Before you start flapping away about which language is "best" for this role, I’ll just gently close your lips with my greasy fingers, encased in old welding gloves, and whisper: "shhhhhhhh... it doesn’t really matter."  It's true. You could crank this out using PHP, ASP, ASP.NET, Ruby, Python, Mython, Yourthon, Therethon or Whateverthon.  As long as it can display a web form in a browser session, collect the input, and interact with a database to store the information, you’re good to go.
Next, there's a database table for storing the submitted requests entered from the web form.  This includes the client name, the action to be performed, as well as who requested it, and when (date and time), and task-related things like "is-completed" and when, along with other optional pieces of information.
Then there's a scheduled task, which reads the database table, on a frequent and recurring schedule, fetching only those rows which have not already been processed (completed), and executes the requested action on the specified remote computer.  After each task is completed, the corresponding row in the database table is updated to indicate it was completed and time-stamped.  This is what effectively prevents the entire process from melting down by re-running every row every time.
So, putting this all together, you get a process that works like this:
1      Authorized user of the web site opens a web page for a particular computer or Collection of computers, and clicks a button/link for "Client Tools".  This opens a web form with a list of available "actions" to perform on the computer(s) remotely.  User selects the desired action and clicks "Submit".  The information is then entered into a database table.  In my case, I'm using SQL Server 2008 R2.  But you could use Oracle, MySQL, Sybase, Informix, DB2, or just about anything that’s "robust" enough to support a business environment with multiple users.
2      The scheduled task, running under the context of a proxy account with permissions to invoke client agent actions remotely, executes a script on the next cycle.  The script reads all rows which are not yet marked as being completed.  Iterating through the set of rows, it reads the name of the computer to be acted upon, and the requested "action" to invoke.  The script checks for connectivity to the remote computer, and then executes the remote action using either SWBEM interface (via COM or .NET), or in the case of my lazy-ass approach: executes the SendSchedule.exe utility (included with the ConfigMgr Toolkit v2 download).  After running the task, it updates the row to set the "completed" field and enters a time-stamp to indicate when it was processed.
3      The remote client receives the request from the remote script execution, under the user context of the scheduled task/job that launched it.  It then verifies authentication and, if allowed, invokes the client action or other (possibly) custom task.
Clunky?  Yep.  Complicated?  Not really (I've seen things MUCH more complicated doing much less).  Could it be done more simply or more elegantly?  You betcha!  

Some Advantages

So, what additional benefits does this approach provide?  For starters, since the action is really based on a SQL database repository, and a job scheduler, I have a centralized model.  That means I have the means to log everything going on.  Now, instead of every console-user running a local task, with log files on their computer and the remote computers, everything is in one place, where it's easy to sort and manage and get useful reports out.  It's also easy to apply a security model to restrict access in one place at one time.  I'm not going to say web applications are a panacea, but they do offer some very attractive capabilities.

Here's a few screen shots of it.  The first image is the Resource details view, which is showing the general "Computer System" properties.  The "Client Tools" button is at the upper-right corner.


After clicking the "Client Tools" button, the pop-up form is shown (below).  Right now, I only have three of the Client Actions exposed, not because there's a problem with them, but because I'm working on role-based filtering of features. The user session for this example doesn't have access to the other actions.

The image below is the log report, which captures every submitted request and shows when it was processed and the result.


Conclusion Contusion

Could this all have been a different/better way?  I'm sure it could have, but I'm working against two huge constraints: time and skill set.  Time is very limited and my skill set is still mostly ASP/SQL.  I've done a lot with PHP also, but in this environment it didn't make sense to shoehorn it in.  I used to work with ASP.NET for a brief period, but that was a while ago and I haven't had the opportunity to brush up on the newer technologies.  I know: excuses-excuses.  Feh.
The third constraint is budget.  Budgets are awesome.  If only we had one.  For now, duct tape and chewing gum will do just fine.
Read More
Posted in asp, config manager, logging, network administration, sccm, sql server, system center, web development, wmi | No comments

Sunday, 4 November 2012

Why I'm Still Not 100% on PowerShell

Posted on 05:13 by Unknown
In the past, I have been somewhat critical of PowerShell.  Not because it is somehow technically inferior to alternatives, but because of environmental ramifications.  I was an early adopter actually, having joined up in the Monad testing program, and I was very excited about the potential it offered.  Today, I use PowerShell more than I ever have, but there are still many types of tasks that I don't use it for:

  • Deploying / Installing Software to Remote Computers
  • Maintaining Legacy Script Files
  • Heterogeneous Windows Versions and .NET versions
The main reason I don't use it for software deployments is the slower execution time.  Compared with basic Batch/CMD scripts, or even VBscript, it just takes longer to "spin-up" the .NET and PowerShell foundation goodies before it even parses the script code.  Multiply that by multiple installs per remote computer, and hundreds of remote computers, and the aggregate time difference can be significant.  This is especially true on older hardware and older operating systems, which brings up the point of "pervasiveness" of PowerShell in a mixed environment:  

Many environments I walk into (I'm a consultant after all) are not homogeneous when it comes to operating systems versions, or even "common applications".  It's not unusual to find multiple configurations of .NET, Java Runtime, DirectX, MSXML, Oracle client, and SQL Native Client installations.  One thing I rarely have to contend with is inconsistent support for Windows Scripting Host, let alone the ever-present CMD shell.  I can't say the same for PowerShell.  I wish it were as consistent and pervasive but it's just not.  I'm sure that it will be someday, but we all know how long it takes customers to upgrade to newer operating systems.

To be fair, the same was true for Windows Scripting Host back in the early days of Windows NT.  Microsoft cranked out several versions, until they finally stopped on 5.8 and let it sink in.  That had a nice impact on most shops since they were no longer worried that as soon as they deployed WSH they would have to follow up with another upgrade.  PowerShell is still evolving, so many IT managers aren't over-eager to deploy 3.0 when they seem to expect a 3.1 to come out any day.

I know it's not exactly logical to expect that PowerShell and .NET could be somehow combined and made to be more cohesive (for more streamlined deployment), it would help.  The size of such a deployment package would be excessive for many shops to deal with, and might be tough to deploy on legacy hardware when local disk storage is almost maxed out.  No, it seems Microsoft is betting on customers upgrading to Windows 8 and that would take care of everything as it pertains to achieving a ubiquitous PowerShell presence.  I don't think that's going to happen anytime soon however, for a variety of reasons.  So, for now, while I continue to expand my PowerShell scope, I am still dependent on VBScript and Batch scripts for many tasks.

I'm sure there are some of you out there that will shake your head in disbelief at all this, and that's fine.  I welcome constructive feedback.  So if you have some insights or ideas about how this can be managed more effectively, please let me know?
Read More
Posted in batch, cmd, network administration, powershell, scripting, software deployment, vbscript, windows8 | No comments
Newer Posts Older Posts Home
Subscribe to: Posts (Atom)

Popular Posts

  • Voting Time: Help Me Out?
    I need to get a better view of how I should manage this blog if I'm going to keep at it. I'd like to know how you typically discover...
  • A World Without Competition
    Try to imagine what things would be like today had there not been fierce competition in certain key parts of our world.  I’ll give you some ...
  • Book Update
    I posted some gibberish a few weeks ago about another book project.  Well, I'm getting close to wrapping it up, so I thought I'd go ...
  • Cost
    Software technology, like any technology, provides a means to solving problems.  Some big. Some small.  Some that help.  Some that hurt.  An...
  • Windows 7: Default User vs All Users
    A lot of confusion seems to occur with understanding the difference between the "Default User" profile, and the "All Users...
  • Time to Give Props
    With the ever-expanding volume and breadth of information on the Internet today, it's easy to focus on my own thoughts, experiences, ide...
  • Table of Contents (Preliminary)
    Here's the preliminary Table of Contents for my new book "The AutoCAD Network Administrator's Bible - 2013 Edition".  I...
  • The Nicest IT and IT Vendor Folks I Know
    I've ranted many times before how it's unfair to "hate" an entire company, without providing a rationale for it based on s...
  • Windows 8
    Two small, yet irritating things, that I hope Windows 8 addresses with respect to Windows 7: Being able to put the Recycle Bin in the S...
  • Stupid Assumptions
    After years of watching sci-fi TV shows, movies, etc. it's finally come to a point where even the so-called brightest of our authors and...

Categories

  • a
  • activation
  • active directory
  • advertising
  • agile
  • agility
  • amazon
  • american
  • apple
  • application virtualization
  • applications
  • art
  • articles
  • asp
  • augi
  • authors
  • autocad
  • AutoCAD Autodesk
  • autodesk
  • autolisp
  • automation
  • automotive
  • backups
  • batch
  • beer
  • beta
  • blackberry
  • blogs
  • bongloads
  • book
  • books
  • Books writing kindle amazon technology business projects
  • browsers
  • business
  • cad
  • career
  • certification
  • chrome
  • city government
  • civilization
  • cloud services
  • cmd
  • cmmi
  • comedy
  • command
  • community
  • computers
  • conferences
  • config manager
  • consultants
  • consulting
  • contracting
  • cranium drainium
  • crapware
  • culture
  • data center
  • data mining
  • databases
  • deployment
  • directx
  • DLL
  • domains
  • dumb
  • earth
  • economy
  • editor
  • education
  • election
  • elections
  • employment
  • engineering
  • entertainment
  • environment
  • error monitoring
  • events
  • exchange
  • facebook
  • family
  • firefox
  • flexnet
  • fud
  • fun
  • funny
  • games
  • gary vaynerchuk
  • gmail
  • google
  • government
  • group policy
  • hampton roads
  • health
  • history
  • holidays
  • home
  • html5
  • humor
  • hyper-v
  • iis
  • industry
  • infrastructure
  • installation
  • installshield
  • internet
  • internet explorer
  • interviews
  • jobs
  • jtbworld
  • kindle
  • kixtart
  • lab setup
  • languages
  • ldap
  • learning
  • legal
  • licensing
  • life
  • lifecycle
  • linux
  • lisp
  • logging
  • management
  • manufacturing
  • marketing
  • markets
  • mdop
  • mdt
  • medical
  • messaging
  • microsoft
  • microsoft access
  • military
  • mountains
  • movies
  • mozilla
  • music
  • nature
  • network administration
  • news
  • nook
  • nothing
  • office
  • open source
  • openoffice
  • opera
  • operating systems
  • oracle
  • osx
  • packaging
  • patches
  • people
  • photos
  • podcasts
  • policy
  • politics
  • powershell
  • predictions
  • process automation
  • products
  • programming
  • projects
  • psychology
  • publishing
  • rail
  • reading
  • registry
  • religion
  • reporting
  • reviews
  • rsat
  • rss
  • safari
  • safety
  • sales
  • satire
  • sccm
  • scheduling
  • science
  • scripting
  • search
  • security
  • servers
  • services
  • sharepoint
  • shopping
  • sms
  • social stuff
  • society
  • softgrid
  • software assurance
  • software deployment
  • software development
  • software packaging
  • sony
  • speaking
  • sports
  • sql express
  • sql server
  • statistics
  • Statistics news marketing
  • steve jobs
  • stories
  • stuff
  • stupidity
  • symantec
  • sysinternals
  • system center
  • systems architecture
  • t-sql
  • taxes
  • technet
  • technical support
  • technology
  • TED
  • ted talks
  • testing
  • textpad
  • thoughts
  • traffic
  • training
  • transportation
  • travel
  • troubleshooting
  • tutorials
  • twitter
  • ubuntu
  • unattend
  • unemployment
  • updates
  • upfront ezine
  • utilities
  • vacation
  • vba
  • vbscript
  • video
  • virginia
  • virginia beach
  • virtualization
  • visual lisp
  • vmware
  • vmware server
  • voting
  • war
  • weather
  • web
  • web browsers
  • web development
  • web sites
  • windows
  • windows 7
  • windows live
  • windows server
  • windows server 2012
  • windows8
  • winpe
  • wise
  • wmi
  • work
  • writing
  • ws08
  • wsus
  • wwa
  • x64
  • xml
  • ze frank

Blog Archive

  • ▼  2013 (37)
    • ▼  October (1)
      • 10 Questions: With Ralph Grabowski
    • ►  September (5)
    • ►  August (8)
    • ►  July (2)
    • ►  June (4)
    • ►  May (4)
    • ►  April (2)
    • ►  March (2)
    • ►  February (8)
    • ►  January (1)
  • ►  2012 (120)
    • ►  December (14)
    • ►  November (12)
    • ►  October (10)
    • ►  September (7)
    • ►  August (3)
    • ►  July (2)
    • ►  June (6)
    • ►  May (6)
    • ►  April (20)
    • ►  March (16)
    • ►  February (18)
    • ►  January (6)
  • ►  2011 (343)
    • ►  December (15)
    • ►  November (23)
    • ►  October (27)
    • ►  September (35)
    • ►  August (29)
    • ►  July (17)
    • ►  June (23)
    • ►  May (20)
    • ►  April (38)
    • ►  March (61)
    • ►  February (54)
    • ►  January (1)
Powered by Blogger.

About Me

Unknown
View my complete profile