Packaging a LaunchAgent Script with The Luggage

Previously, I showed how to install Luggage, and how to package a drag and drop app.  In this installment, we will look at how to package up a LaunchAgent script.

We will work with a simple script to mount a couple of file shares when a user logs into their computer.  To set it up as a LaunchAgent, we need two pieces.  First, the script itself ( needs to be copied to /Library/Scripts/Myorg and everyone should have read and execute permissions.  Second, a plist (com.myorg.connectshares.plist) file which controls the execution of the script needs to be copied to /Library/LaunchAgents and and everyone should have read permissions. Continue reading

Installing Novell ZCM Adaptive Agent in MDT 2012

The Novell ZCM Adaptive Agent is an example of an application that needs to be installed at deployment time and should not be included in the reference image.  In general, MDT Lite Touch handles installing applications at deployment time quite nicely.

The Adaptive agent, however is an example of an install process that does not play nice with MDT.  It really is a quite horrible installer.  First, lets take a look at the installer and what it does. Continue reading

HTA Script for Mapping Network Drives

I had a need for a user friendly Windows script to map network drives using credentials supplied by the user.  The script I endend up with is an HTA script that allows the user to enter their credentials and map a predefined set of network drives.  There is also a button to disconnect the mapped drives.

The script is here :

<!-- HTA script to allow machines that are not joined to a domain to access
     Windows file shares with domain credentials. It will atomatically prepend the
     domain to the username and then map several drives. If a drive is already
     mapped, it is disconnected and then mapped for the current user.
     Version 1.0.2
     Written by Vaughn Miller 7/20/2012
     Currently setup to map the following drives :
     M: = \\\dept
     O: = \\\users
     W: = \\mcweb\messiahweb

<TITLE>Connect Network Drives</title>


' *** Define Drive Mappings ***
dim arrDrives(2,2)
intMaxdrives = 2

arrDrives(0,0) = "M:"
arrDrives(0,1) = "\\\dept"
arrDrives(0,2) = "Dept"

arrDrives(1,0) = "O:"
arrDrives(1,1) = "\\\users"
arrDrives(1,2) = "Users"

arrDrives(2,0) = "W:"
arrDrives(2,1) = "\\mcweb\messiahweb"
arrDrives(2,2) = "messiahweb"
' *** End Drive Map Definitions ***

strDOMAIN = "messiah\" 'Domain to prepend to the username

Sub Window_Onload
  '# Size Window
  sHorizontal = 440
  sVertical = 175
  Window.resizeTo sHorizontal, sVertical
  '# Get Monitor Details
  Set objWMIService = GetObject _
  intHorizontal = sHorizontal *2
  intVertical = sVertical *2
  Set colItems = objWMIService.ExecQuery( _
    "Select ScreenWidth, ScreenHeight from" _
    & " Win32_DesktopMonitor", , 48)
  For Each objItem In colItems
    sWidth= objItem.ScreenWidth
    sHeight = objItem.ScreenHeight
    If sWidth > sHorizontal _
      then intHorizontal = sWidth
    If sHeight > sVertical _
      then intVertical = sHeight
  Set objWMIService = Nothing
  '# Center window on the screen
  intLeft = (intHorizontal - sHorizontal) /2
  intTop = (intVertical - sVertical) /2
  Window.moveTo intLeft, intTop
  '# default window content
End Sub

Sub RunScript
   on Error Resume Next

   minUSRnamelength = 2
   minPASSwrdlength = 3

   strUsr = UsrnameArea.Value
   strPas = PasswordArea.Value

   Set objNetwork = CreateObject("WScript.Network")
   Set oShell = CreateObject("Shell.Application")

   If Len(strUsr) >= minUSRnamelength then
      strUsr = strDOMAIN & UCase(strUsr) '<--- adds the domain before the username

      if Len(strPas) >= minPASSwrdlength Then
         Call ClearDrives ' Delete existing mappings if they exist
         '***** Begin Drive mapping *****
         For n = 0 To intMaxDrives 'Loop through our array of drives
            objNetwork.MapNetworkDrive arrDrives(n,0), arrDrives(n,1), False, strUsr, strPas
            If Err.Number = 0 Then
               oShell.NameSpace(arrDrives(n,0)).Self.Name = arrDrives(n,2)
            End If
         '***** End Drive Mapping *****
            Msgbox chr(34) & strPas & """ is an incorrect password !"
            Exit Sub
         End If
      Msgbox chr(34) & strUsr & """ is an incorrect Username !"
      Exit Sub
   End If
    ' Clean up the objects before exiting
   Set oShell = Nothing
   Set objNetwork = Nothing
End Sub

Sub ClearDrives ' Sub Routine to remove the drives if they are already mapped
  On Error Resume Next
  Set objNetwork = CreateObject("WScript.Network")

  '***** Begin section to delete drive mappings ***
  Set AllDrives = objNetwork.EnumNetworkDrives
  For n = 0 To intMaxDrives 'Loop through our array of drives
     For i = 0 To AllDrives.Count - 1 Step 2
        If AllDrives.Item(i) = arrDrives(n,0) Then AlreadyConnected = True
     If AlreadyConnected = True then
        objNetwork.RemoveNetworkDrive arrDrives(n,0), True, True
     End If
  '***** End section to delete drive mappings
End Sub

Sub DisconnectDrives ' Calls ClearDrives subroutine and then closes the window
Call ClearDrives
    Set oShell = Nothing
    Set objNetwork = Nothing
End Sub

Sub CancelScript
   Set oShell = Nothing
   Set objNetwork = Nothing
End Sub


<BODY STYLE="font:14 pt arial; color:white; filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=1, StartColorStr='#000000', EndColorStr='#0000FF')">
<a name="Top"></a><CENTER>
  <table border="0" cellpadding="0" cellspacing="0"><font size="2" color="black" face="Arial">
      <td height="30">
        <p align="right">Your Username</p>
      <td height="30">&nbsp;&nbsp; <input type="text" name="UsrnameArea" size="30"></td></tr>
      <td height="30">
        <p align="right">Password</p>
      <td height="30">&nbsp;&nbsp; <input type="password" name="PasswordArea" size="30"></td></tr>
<HR color="#0000FF">
 <Input id=runbutton class="button" type="button" value=" Map Drives " name="run_button" onClick="RunScript">
 <Input id=runbutton class="button" type="button" value=" Disconnect Drives " name="dis_button" onClick="DisconnectDrives">
 <Input id=runbutton class="button" type="button" value="Cancel" name="cancel_button" onClick="CancelScript">


The drive definitions are coded in an array so that the mapping and disconnecting subroutines can use a loop. To modify this for your own use, you need to modify strDomain (line 50) and the drive definitions (lines 33-48).

I think a nice revision of this script would be to design it to read a configuration file for the domain info and drive definitions. This was one motivation for implementing the array/loop structure.

Packaging a Drag and Drop Application

In a previous post, I showed how to get started by getting Luggage setup.  In this post we will create a simple package based on a .app bundle.

Drag and drop applications are really user friendly to install, the user simply needs to drag them to the Applications folder.  They are not as nice, however, for the system administrator who wishes to deploy the application via some automated tool.  In some cases it is desirable to repackage these application into an installer package.  Fortunately this is easy to do with the Luggage.

For this demonstration, I will use my favorite text editor  When we download TextWrangler it is downloaded as a disk image.  Mount the image file by double clicking on it, and we see that we have an app bundle and a link to the Applications folder.  The application bundles are actually a special directory, so our first step is to make a compressed tar of the app. Continue reading

Some new Features in MDT 2012

I’ve been working with MDT 2012 in my test environment, and here are three new features that I really like.

Dirty Environment Cleanup

Some times a deployment fails from some reason, and you just want to restart the process of a bare metal install.  In MDT 2010, the task sequence would read the logs written to the hard drive and realize that a deployment was still in progress.  At this point, MDT 2010 will halt the process with an error.  Pressing F8 and using diskpart to wipe the disk is my usual work around, but it is a bit clumsy for less experienced technicians.

Continue reading

Getting Started with The Luggage

When administering and or deploying Mac OS systems, it becomes very useful to be able to create packages.  This can be to repackage an app to automate deployment, or package up scripts or configuration files.  One such tool to do this is The Luggage.  Written by Joe Block, it is a command line tool that makes use of Apple’s Packagemaker as well as Make.  More information can be found here.

This post is intended to walk you through getting up and running with luggage from ground zero.  A future post will look at using The Luggage.  This tutorial is assuming you are running Mac OS 10.7. Continue reading

What the heck are Directory Junction Points?

So I recently fielded a question from someone new to Windows 7 about some “directories” that they were being denied access to.  This seemed odd, because it was under the user profile so they should not have been a permissions issue.

I inquired about some more specifics, and the list of problem directories were Application Data, Cookies, Local Settings, etc…  I recognized right away that these were Windows XP directories which should not normally show up for a user in Windows 7.  What these really are is Directory Junction points provided by Microsoft to maintain compatibility with software written for previous versions of Windows.  Starting with Windows Vista, Microsoft changed the structure of the user profile namespace.  The result of this is that Directory Junction points are needed to route files to the new locations even when the old style path is specified. Continue reading

Troubleshooting MDT Deployments

So, a colleague hands me two laptops that are going to be added to our loaner pool.  No problem…  just add the the computer’s information into the MDT database and image them.

Both machines were taking quite a long time for the wizard to come up, and when it did it was obvious that none of the values from the database were coming down.  Both machines were connecting to the deployment share, and had valid IP addresses.  I even booted up a Virtual Machine I use for testing and verified that it was connecting to the database properly.  So what the heck is up with the two problem machines? Continue reading

Added a Resources Page

My intent with this blog is to post information that is not readily available elsewhere.  I do not feel the need to duplicate a lot of the great information that is already available.  With that in mind, I have added a Resources page with links to a number of sites that I have found helpful.  Most of these are sites I find myself visiting frequently.