Silent Mobility NetMotion Installation

By | March 28, 2014
Share

Here is a breakdown on installing the Mobility XE client (NetMotion) silently.

Prep the install files:

1. Create a TXT file with the following name “options.inf” and save it in the same directory as the install files.

Contents of options.inf:

[version]
Signature="$CHICAGO$"
[DefaultInstall]
AddReg=NMsettings
[NMsettings]
HKLM,"System\CurrentControlSet\Services\NetMotion\Mobility Client","DhcpProvidesMmsAddress",0x00010001,0
HKLM,"System\CurrentControlSet\Services\NetMotion\Mobility Client","MmsAddress",0x00000000,"<ServerIP>"

 

2. Update the “options.inf” with your server address (replace the <ServerIP>).

3. Execute the netmotion..exe file, browse to the “%Temp%” directory, locate the netmotion..MSI and copy it over to where your install files exist.  You can now exit the installation.

Install Script:

1. Due to the network driver installation occuring during installation and potentially interferring with the installation, the first step is to copy the install file to a local temp directory.

xcopy "%~dp0*.*" "C:\Windows\Temp\NetMotion\" /heyi

2. Next we install the .MSI:

start /w "" msiexec.exe /qn /i "%~dp0netmotion_10.10_7x86.msi" NM_OPTIONS="%~dp0options.inf" EQSI="1" REBOOT=ReallySuppress

3. Lastly, delete our install files.

rd /S /Q "C:\Windows\Temp\NetMotion"

 

Entire script:

xcopy "%~dp0*.*" "C:\Windows\Temp\NetMotion\" /heyi
start /w "" msiexec.exe /qn /i "%~dp0netmotion_10.10_7x86.msi" NM_OPTIONS="%~dp0options.inf" EQSI="1" REBOOT=ReallySuppress
rd /S /Q "C:\Windows\Temp\NetMotion"

Source: http://www.netmotionwireless.com/support/docs/MobilityXE/923/help/wwhelp/wwhimpl/js/html/wwhelp.htm#href=setup.04.39.html#1300081

/BG

My MDT VBScript Template.

By | March 21, 2014
Share

The VBScript sample from Microsoft was a start, but here were the major limitations:

  1. Only meant to be used from within the “Scripts” folder, which is not useful when attempting to install applications.
  2. Does not include examples of actually using the ZTIUtility.vbs functions.

Template pulled from http://gallery.technet.microsoft.com/scriptcenter/84d18835-300a-42e3-b0e7-29cb7fc5aafc.
* Thanks Mr. Barnes!

GitHub Link: https://github.com/brianfgonzalez/Scripts/blob/master/Z-MyMDTTemplate.wsf

 

<job id="Z-Sample"> 
<script language="VBScript" src="..\..\Scripts\ZTIUtility.vbs"/> 
<script language="VBScript"> 

' //*************************************************************************** 
' // ***** Script Header ***** 
' // 
' // Solution: Solution Accelerator for Microsoft Deployment 
' // File: Z-MyMDTTemplate.wsf
' // 
' // Purpose: Template 
' // 
' // Usage: cscript Z-MyMDTTemplate.wsf [/debug:true] 
' // 
' // Customer Build Version: 1.0.0
' // Customer History: 
' // 
' // ***** End Header ***** 
' //*************************************************************************** 

'//---------------------------------------------------------------------------- 
'// 
'// Global constant and variable declarations 
'// 
'//---------------------------------------------------------------------------- 

Option Explicit 

Dim iRetVal 

'//---------------------------------------------------------------------------- 
'// End declarations 
'//---------------------------------------------------------------------------- 

'//---------------------------------------------------------------------------- 
'// Main routine 
'//---------------------------------------------------------------------------- 

On Error Resume Next 
iRetVal = ZTIProcess 
ProcessResults iRetVal 
On Error Goto 0 

'//--------------------------------------------------------------------------- 
'// 
'// Function: ZTIProcess() 
'// 
'// Input: None 
'// 
'// Return: Success - 0 
'// Failure - non-zero 
'// 
'// Purpose: Perform main ZTI processing 
'// 
'//--------------------------------------------------------------------------- 
Function ZTIProcess() 

     iRetVal = Success 

     ZTIProcess = iRetval 

     '!!!!!!!!!!!   INSERT YOUR CODE HERE   !!!!!!!!!!!!
     'Set a variable example
     'oEnvironment.Item("OSDComputerName") = "PC-01"

	'Read a variable example
	'If oEnvironment.Exists("_SMSTSORGNAME") then
	'       Wscript.Echo "The Property Value = " & oEnvironment.Item("_SMSTSORGNAME")
	'Else
	'       Wscript.Echo "The Property Value is not set!"
	'End if

	'Check if a variable is Null or Empty
	'If oEnvironment.isNullOrEmpty("_SMSTSORGNAME") then
	'       Wscript.Echo "The Property Value = " & oEnvironment.Item("_SMSTSORGNAME")
	'Else
	'       Wscript.Echo "The Property Value is not set!"
	'End if

	'Other oEnvironment methods
	'oEnvironment.Substitute(sVal)
	'Given a string, will expand any variables and/or functions within that string.
	'oEnvironment.ListItem(sName)
	'Read/Write a variable of type array to a persistent store.

	'Create a Log file with the name of the script file in the MININT\SMSOSD\OSDLOGS\ directory.
	'oLogging.CreateEntry "Logging: Beginning logging process", LogTypeInfo
	'wscript.echo "Hello world"
	'oLogging.CreateEntry "This is an Information Log Entry", LogTypeInfo
	'oLogging.CreateEntry "This is a Warning Log Entry", LogTypeWarning
	'oLogging.CreateEntry "This is an Error Log Entry", LogTypeError
	'oLogging.CreateEntry "Logging: End logging process", LogTypeInfo

	'oLogging.ReportFailure (sMessage,iError)
	'Used to perform a structured exit if an unrecoverable error is detected.

	'oLogging.CreateEvent(iEventID, iType, sMessage, arrParms)
	'Write a message to the log file, and post the event to a defined server.

	'Delete a file
	'Dim sTargetFile
	'sTargetFile = "C:\test.txt"
	'oFileHandling.DeleteFile sTargetFile

	'Move a file
	'Dim sFile, sDest
	'sFile = "C:\Folder1\test.txt"
	'sDest = "C:\Folder2\"
	'oFileHandling.MoveFile sFile, sDest

	'Copy a file
	'Dim sFile, sDest, bOverwrite
	'sFile = "C:\Folder1\test.txt"
	'sDest = "C:\Folder2\"
	'bOverwrite = True
	'oFileHandling.CopyFile sFile, sDest, bOverwrite

	'Copy a folder
	'Dim sSource, sDest, bOverwrite
	'sSource = "C:\Folder1"
	'sDest = "C:\Folder2"
	'bOverwrite = True
	'oFileHandling.CopyFolder sSource, sDest, bOverwrite

	'Move a folder
	'Dim sSource, sDest
	'sSource = "C:\Folder1"
	'sDest = "C:\Folder2\"
	'oFileHandling.MoveFolder sSource, sDest

	'Delete a folder incl. sub-folders
	'Dim sPath
	'sPath = "C:\Folder1"
	'oFileHandling.RemoveFolder sPath

	'Read a registry key
	'Dim sRegValue, sRegKey
	'sRegKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Version"
	'sRegValue=oUtility.regread(sregkey)
	'oLogging.CreateEntry "IE Version is " & sRegValue, LogTypeInfo

	'Write a registry key
	'Dim sRegValue, sRegKey, sNewRegValue
	'sRegKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\New Program"
	'sNewRegValue = "C:\Windows\Notepad.exe"
	'sRegValue=oUtility.regWrite(sregkey, sNewRegValue)

	'Pre-defined objects
    'oFSO – File System Object
    'oShell – Wscript Shell object
    'oEnv - Process Environment object
    'oNetwork - WScript Network object

	'Returns the full path of the script into the sScript variable
	'Dim sScriptName, sScript
	'sScriptName = "Set-Supervisor.wsf"
	'iRetVal = oUtility.FindFile(sScriptName, sScript)
	'If iRetVal <> Success then
	'	oLogging.CreateEntry "Unable to locate script " & sScriptName, LogTypeError
	'	Exit Function
	'End if

	'Script Directory and Name variables
	'oUtility.ScriptName
	'oUtility.ScriptDir
	'oUtility.LogPath

	'Sleep (Timeout) the script "safely"
	'oUtility.SafeSleep(miliSeconds)

	'sFile = oUtility.ScriptDir & "\WMI Provider GUI InstallShield Package 1.00L18.exe"
	'If not oFSO.FileExists(sFile) then
	'	oLogging.CreateEntry "Install Panasonic BIOS Provider: " & sFile & " was not found, unable to install.", LogTypeError
	'	ZTIProcess = Failure
	'	Exit Function
	'End if

	'sCmd = sFile & " -s -f1""" & _
	'	oUtility.ScriptDir & "\noui.iss"" -f2""" & _
	'	oUtility.LogPath & "\PanasonicBIOSProvider.log"""
	'oLogging.CreateEntry "Running: " & sCmd, LogTypeInfo
	'iRetVal = oUtility.RunWithHeartbeat(sCmd)

	'If (iRetVal = 0) or (iRetVal = 3010) then
	'	ZTIProcess = Success 
	'Else 
	'	ZTIProcess = Failure
	'End If
	'oLogging.CreateEntry "Install Panasonic BIOS Provider: Return code from command = " & iRetVal, LogTypeInfo
	'oLogging.CreateEntry "Install Panasonic BIOS Provider: Finished installation", LogTypeInfo

	'Pull OS Version from Win32_OperatingSystem WMI
	'Set oOperatingSystems = objWMI.ExecQuery ("Select * from Win32_OperatingSystem")
	'For Each oTmp in oOperatingSystems
	'	sOSCurrentVersion = oTmp.Version
	'Next

	'Run console command and hide window
	'RunWithConsoleLoggingAndHidden(sCmd)

	'Trim all white space from variable
	'oEnvironment.Item("_SMSTSORGNAME") = oUtility.TrimAllWS(oEnvironment.Item("_SMSTSORGNAME"))

	'Get random number/guid
	'oUtility.GenerateRandomGUID

	'Other File/Folder methods
	'oFileHandling.NormalizePath
	'oFileHandling.GetTempFolder
	'oFileHandling.GetTempFile
	'oFileHandling.GetTempFileEx("FileExtension")
	'oFileHandling.GetWindowsFolder

	'Check if the file is newer than a specified version
	'Dim sFileName, iMinVersion
	'sFileName = oUtility.ScriptDir & "\MyInstall.msi"
	'iMinVersion = 1.3
	'If oUtility.CheckFileVersion(sFileName, iMinVersion) Then
	'	Wscript.echo "File is new enough.."
	'End If

	'Regular Expression match
	'For Each Match in oRegEx.GetRegExMatchesFromFile( "\[([^\]]*)\]","c:\boot.ini" ) 
	'	Wscript.echo "Match: " & Match
	'Next

End Function 

</script> 
</job> 
	</script>
</job>

 

 

/BG

My MDT PowerShell Template

By | March 17, 2014
Share

I’ve recently come to really appreciate PowerShell as the most versatile and powerful language available natively in any/all Windows OS.

i.e. 2 lines of code to ensure laptop battery is plugged in and prompt the user.
If ((Get-WmiObject -Query “SELECT * From Win32_Battery”).BatteryStatus -ne 2)
{ Write-Host “Please plug in your laptop” }

An equivalent VBScript would easily run around 30 lines of code.

Running PowerShell via the Task Sequence has been around for a bit, which is simple enough.

This however, does NOT include any logging support and requires that your scripts exist in the “Scripts” Directory. Which in my opinion almost renders the feature useless.

Here is my Template, which can be used within an application:

GitHub Link: https://github.com/brianfgonzalez/Scripts/blob/master/Z-MyMDTTemplate.ps1

<#
Purpose: Replaces Windows 8/8.1 Start Screen Background image.
Version: 1.0 - March 14, 2013

Author - Brian Gonzalez
    Blog   : https://supportishere.com

ChangeLog:
    2014-03-17 BFG:
        - Updated LogHelper output strings to match MDT logging strings.
        - set LogHelper to also write to BDD.log.
#>

# Create Global Variables
$oInvocation = (Get-Variable MyInvocation).Value
$sScriptDirectory = Split-Path $oInvocation.MyCommand.Path
$sScriptNameExt = $oInvocation.MyCommand.Name
$sScriptName = $sScriptNameExt.Substring(0, $sScriptNameExt.Length - 4)

# Ensure script can attach to TS Environment
try
{
    $ErrorActionPreference = "Stop"
    $oTSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment 
    $sLogPath = $oTSEnv.Value("LogPath")

}
catch [System.Runtime.InteropServices.COMException]
{
    $sLogPath = "C:\Windows\Temp\DeploymentLogs" #Hardcode Logs Directory    
}
finally
{$ErrorActionPreference = "Continue"}

# Set Logging File Variables
$sLogFilePath = "$sLogPath\$sScriptName.log"
$sCmdLogFilePath = "$sLogPath\$sScriptName-Cmd.log"
$sBDDLogFilePath = "$sLogPath\BDD.log"
$sTZbias = (Get-WmiObject -Query “Select Bias from Win32_TimeZone”).Bias
$sTime = ((Get-Date -Format hh:mm:ss.fff) + $sTZbias) 
$sDate = Get-Date -Format MM-dd-yyyy

# Function to run processes and capture output
function RunWithLogging
{
    param([string]$cmd,
    [string]$params)
    $ps = new-object System.Diagnostics.Process
    $ps.StartInfo.Filename = $cmd
    $ps.StartInfo.Arguments = $params
    $ps.StartInfo.RedirectStandardOutput = $True
    $ps.StartInfo.UseShellExecute = $false
    $ps.start() | Out-Null
    $ps.WaitForExit()
    [string] $out = $ps.StandardOutput.ReadToEnd();
    $out | Out-File $sCmdLogFilePath -Append
    return $ps.ExitCode
}

function CopyFileWithLogging
{
    param([string]$sSrcFile,
       [string]$sDesFile)
    If (!(Test-Path $sSrcFile))
    {LogHelper "$sSrcFile not found." "Error"}

    try
    {
        $ErrorActionPreference = "stop"
        Copy-Item $sSrcFile $sDesFile -Force -Recurse
    }
    catch [System.Management.Automation.ItemNotFoundException]
    {
        LogHelper ("Could not find target location:  " + $sDesFile) "Error"
        return 1
    }
    catch [System.UnauthorizedAccessException]
    {
        LogHelper ("Access Error: Could not overwrite target file:  " + $sDesFile) "Error"
        return 2
    }
    finally {$ErrorActionPreference = "continue"}

    If (Test-Path $sDesFile)
    {
        LogHelper ($sDesFile + " was copied successfully.")
        return 0
    }
}

function LogHelper
{
    param([string] $sLogContent,
    [string] $sLogType = "Update")

    try
    {
        $ErrorActionPreference = "stop"
        If (!(Test-Path $sLogFilePath))
        {
            # Create Log File
            $sUpdateStringTest = ("<![LOG[Initial LOG Entry]LOG]!><time=""" + $sTime + """ date=""" + `
                $sDate + """ component=""" + $sScriptName + """ context="""" type=""1"" thread="""" file=""" + `
                $sScriptName + """>")
        }
    }
    catch [System.IO.DirectoryNotFoundException]
    {
        Write-Host (Split-Path $sLogFilePath),"folder does not exist"
        New-Item -ItemType Directory (Split-Path $sLogFilePath) | Out-Null
        $sUpdateStringTest = ("<![LOG[Created Logging Directory.]LOG]!><time=""" + $sTime + """ date=""" + `
            $sDate + """ component=""" + $sScriptName + """ context="""" type=""1"" thread="""" file=""" + `
            $sScriptName + """>")
        $sUpdateStringTest | Out-File $sLogFilePath -Append -NoClobber -Encoding Default
    }
    finally {$ErrorActionPreference = "continue"}

    If ($sLogType -eq "Update")
    {
        # Write to log named after script file.
        $sUpdateStringTest = ("<![LOG[" + $sLogContent + "]LOG]!><time=""" + $sTime + """ date=""" + `
            $sDate + """ component=""" + $sScriptName + """ context="""" type=""1"" thread="""" file=""" + `
            $sScriptName + """>")
        $sUpdateStringTest | Out-File $sLogFilePath -Append -NoClobber -Encoding Default
        # Write also to BDD.log
        If (Test-Path $sBDDLogFilePath)
        {$sUpdateStringTest | Out-File $sBDDLogFilePath -Append -NoClobber -Encoding Default}
    }
    ElseIf (($sLogType -eq "Error") -or ($sLogType -eq "Failure"))
    {
        # Write to log named after script file.
        <![LOG[FAILURE (Err):
        $sUpdateStringTest = ("<![LOG[FAILURE (Err):" + $sLogContent + "]LOG]!><time=""" + $sTime + """ date=""" + `
            $sDate + """ component=""" + $sScriptName + """ context="""" type=""1"" thread="""" file=""" + `
            $sScriptName + """>")
        $sUpdateStringTest | Out-File $sLogFilePath -Append -NoClobber -Encoding Default
        # Write also to BDD.log
        If (Test-Path $sBDDLogFilePath)
        {$sUpdateStringTest | Out-File $sBDDLogFilePath -Append -NoClobber -Encoding Default}
    }
}

# Start Main Code Here

# Examples
# Run a Command Line
#LogHelper "About to run a command."
#$sCmd = "$env:SystemDrive\Windows\System32\cmd.exe"
#$sParams = "/C IPCONFIG /ALL"
#$sReturn = RunWithLogging $sCmd $sParams
#LogHelper "Command Completed and Returned: $sReturn"

# Copy a File/Folder
#$sSourceFilePath = ($sScriptDirectory + "\SourceFile.txt")
#$sDestinationFilePath = "C:\Temp"
#LogHelper ("About to copy """ + $sSourceFilePath + """ to " + $sDestinationFilePath)
#$sReturn = CopyFileWithLogging $sSourceFilePath $sDestinationFilePath
#LogHelper ("Copy is complete and returned: $sReturn")

 

/BG

How to create Panasonic Driver Bundles from Scratch

By | March 4, 2014
Share

Here is a video I produced displaying the full process of building a driver bundle from scratch.  All needed files are provided via the video.

How to create a Panasonic Driver Bundle from scratch.

Files used in tutorial can be downloaded using the following link:

http://goo.gl/AOPz66

/BG

How to download Microsoft Office 2010/2013/2016 Updates the Easy Way *UPDATED*

By | February 7, 2014
Share

*UPDATE* Script update, thanks Andy! (CollectOfficeMSPs-2016.vbs)

UPDATE: This also works for Office 2010!

Since Office 2010, I’ve been using one of the MS Office’s installation hidden gems, the “Updates” folder. In previous versions, I’ve had to use WSUSOffline to grab the update files and convert them to .MSP, which wasn’t fun. With Office 2013, Microsoft finally empowered administrators to pull the update .MSPs themselves using the following script. See below:

Pulled from the following Technet article: http://technet.microsoft.com/en-us/library/cc178995.aspx

To extract the .msp files from a test computer and copy them to the Updates folder

On the test computer, install all Office 2013 applications that will be installed on users’ computers.

Run Microsoft Update to apply all the necessary Office 2013 updates on the test computer.

Verify that your applications are running as expected.

Save the following Visual Basic script as “CollectUpdates.vbs” Then run it to extract the update files that are installed on the test computer to a target folder. The script uses %Temp%\Updates as the target folder, where %Temp% is the Windows temporary folder.

Script Source(Gist Link):


Verify that all the required .msp files are in the target folder (%Temp%\Updates).

ExportedMSPUpdates

Copy all .msp files from %Temp%\Updates on the test computer to the Updates folder on the Office 2013 network installation point.

/BG