none
MDT 2013 - Concatenate command lines in an application? RRS feed

  • Question

  • Total noob to MDT. Have a few years experience with SCCM. My ongoing project is to create bootable media (DVD's only, no USB allowed...) to rebuild seats not attached to our network.

    I know one can concatenate command lines in SCCM task sequence steps... wondering if I can do so in applications too?

    Example:

    Create application BlahBlah

    Dir structure is:

    \BlahBlah

    \BlahBlah\A

    \BlahBlah\B

    The application will point to \BlahBlah as the source dir

    In the application command line, will this command work?

    "xcopy .\A\*.* c:\temp\BlahBlahA /E /Y & xcopy .\B\*.* c:\temp\BlahBlahB /E /Y"

    TIA,

    Lang

    Friday, April 3, 2015 2:36 PM

Answers

  • It depends on what your working directory is set to

    But I'd recommend using a script to handle installing applications, copying files, etc. You can then do far more advanced functions with the ability to log as well.

    For instance here's a script I wrote to install Firefox and copy over configuration files. It's one script that handles both x86 and x64 architectures.

    <job id="Install-MozillaFirefox">
    <script language="VBScript" src="..\..\scripts\ZTIUtility.vbs"/>
    <script language="VBScript"> 
    
    '//----------------------------------------------------------------------------
    '// Purpose: Used to install Flash Player
    '// Usage: cscript Install-MozillaFirefox.wsf [/debug:true]
    '// Version: 1.0 - September 29, 2014
    '// Version: 1.1 - February 6, 2015 - Corrected architecture detection
    '//
    '//
    '//----------------------------------------------------------------------------
    
    '//----------------------------------------------------------------------------
    '// 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() 
    
    
    	oLogging.CreateEntry "Install-MozillaFirefox: Starting Mozilla Firefox installation", LogTypeInfo	
    
    	' Disable Zone Checks
    	oEnv("SEE_MASK_NOZONECHECKS") = 1 
    
    	
    	' Install Mozilla Firefox
    	iRetVal = oUtility.RunWithHeartbeat(oUtility.ScriptDir & "\Installer\Setup.exe -ms")
    	
    	if (iRetVal = 0) or (iRetVal = 3010) then
    		ZTIProcess = Success 
    	Else 
    		ZTIProcess = Failure
    		oLogging.CreateEntry "Install-MozillaFirefox: Error installing Application Plugin. Check the log " & oUtility.LocalRootPath & "\SMSOSD\OSDLOGS\Install-MozillaFirefox-Plugin-App.log", LogTypeWarning
    	End If
    
    	
    	' Configure Mozilla Firefox
    	If oEnvironment.Item("Architecture") = "X86"  then 
    		oLogging.CreateEntry oUtility.ScriptName & ": Configuring for 32bit OS", LogTypeInfo
    		oFSO.CopyFile oUtility.ScriptDir & "\Installer\override.ini", oENV("ProgramFiles") & "\Mozilla Firefox\", True
    		oFSO.CopyFile oUtility.ScriptDir & "\Installer\mozilla.cfg", oENV("ProgramFiles") & "\Mozilla Firefox\", True
    		oFSO.CopyFile oUtility.ScriptDir & "\Installer\local-settings.js", oENV("ProgramFiles") & "\Mozilla Firefox\Defaults\Pref\", True
    
    	Else
    
    		oLogging.CreateEntry oUtility.ScriptName & ": Configuring for 64bit OS", LogTypeInfo
    		oFSO.CopyFile oUtility.ScriptDir & "\Installer\override.ini", oENV("ProgramFiles(x86)") & "\Mozilla Firefox\", True
    		oFSO.CopyFile oUtility.ScriptDir & "\Installer\mozilla.cfg", oENV("ProgramFiles(x86)") & "\Mozilla Firefox\", True
    		oFSO.CopyFile oUtility.ScriptDir & "\Installer\local-settings.js", oENV("ProgramFiles(x86)") & "\Mozilla Firefox\Defaults\Pref\", True
    
    	End If
    
    	' Enable Zone Checks
    	oEnv.Remove("SEE_MASK_NOZONECHECKS")
    
    	oLogging.CreateEntry "Install-MozillaFirefox: Return code from command = " & iRetVal, LogTypeInfo
    	oLogging.CreateEntry "Install-MozillaFirefox: Finished Mozilla Firefox installation", LogTypeInfo	
    	
    End Function 
    
    </script>
    </job>

    You can then use variables. Your code to copy files could be something like

    oFSO.CopyFile oUtility.ScriptDir & "\A\*.*", oENV("SystemDrive") & "\temp\BlahBlahA", True
    oFSO.CopyFile oUtility.ScriptDir & "\B\*.*", oENV("SystemDrive") & "\temp\BlahBlahB", True


    If this post is helpful please vote it as Helpful or click Mark for answer.

    Friday, April 3, 2015 3:06 PM

All replies

  • It depends on what your working directory is set to

    But I'd recommend using a script to handle installing applications, copying files, etc. You can then do far more advanced functions with the ability to log as well.

    For instance here's a script I wrote to install Firefox and copy over configuration files. It's one script that handles both x86 and x64 architectures.

    <job id="Install-MozillaFirefox">
    <script language="VBScript" src="..\..\scripts\ZTIUtility.vbs"/>
    <script language="VBScript"> 
    
    '//----------------------------------------------------------------------------
    '// Purpose: Used to install Flash Player
    '// Usage: cscript Install-MozillaFirefox.wsf [/debug:true]
    '// Version: 1.0 - September 29, 2014
    '// Version: 1.1 - February 6, 2015 - Corrected architecture detection
    '//
    '//
    '//----------------------------------------------------------------------------
    
    '//----------------------------------------------------------------------------
    '// 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() 
    
    
    	oLogging.CreateEntry "Install-MozillaFirefox: Starting Mozilla Firefox installation", LogTypeInfo	
    
    	' Disable Zone Checks
    	oEnv("SEE_MASK_NOZONECHECKS") = 1 
    
    	
    	' Install Mozilla Firefox
    	iRetVal = oUtility.RunWithHeartbeat(oUtility.ScriptDir & "\Installer\Setup.exe -ms")
    	
    	if (iRetVal = 0) or (iRetVal = 3010) then
    		ZTIProcess = Success 
    	Else 
    		ZTIProcess = Failure
    		oLogging.CreateEntry "Install-MozillaFirefox: Error installing Application Plugin. Check the log " & oUtility.LocalRootPath & "\SMSOSD\OSDLOGS\Install-MozillaFirefox-Plugin-App.log", LogTypeWarning
    	End If
    
    	
    	' Configure Mozilla Firefox
    	If oEnvironment.Item("Architecture") = "X86"  then 
    		oLogging.CreateEntry oUtility.ScriptName & ": Configuring for 32bit OS", LogTypeInfo
    		oFSO.CopyFile oUtility.ScriptDir & "\Installer\override.ini", oENV("ProgramFiles") & "\Mozilla Firefox\", True
    		oFSO.CopyFile oUtility.ScriptDir & "\Installer\mozilla.cfg", oENV("ProgramFiles") & "\Mozilla Firefox\", True
    		oFSO.CopyFile oUtility.ScriptDir & "\Installer\local-settings.js", oENV("ProgramFiles") & "\Mozilla Firefox\Defaults\Pref\", True
    
    	Else
    
    		oLogging.CreateEntry oUtility.ScriptName & ": Configuring for 64bit OS", LogTypeInfo
    		oFSO.CopyFile oUtility.ScriptDir & "\Installer\override.ini", oENV("ProgramFiles(x86)") & "\Mozilla Firefox\", True
    		oFSO.CopyFile oUtility.ScriptDir & "\Installer\mozilla.cfg", oENV("ProgramFiles(x86)") & "\Mozilla Firefox\", True
    		oFSO.CopyFile oUtility.ScriptDir & "\Installer\local-settings.js", oENV("ProgramFiles(x86)") & "\Mozilla Firefox\Defaults\Pref\", True
    
    	End If
    
    	' Enable Zone Checks
    	oEnv.Remove("SEE_MASK_NOZONECHECKS")
    
    	oLogging.CreateEntry "Install-MozillaFirefox: Return code from command = " & iRetVal, LogTypeInfo
    	oLogging.CreateEntry "Install-MozillaFirefox: Finished Mozilla Firefox installation", LogTypeInfo	
    	
    End Function 
    
    </script>
    </job>

    You can then use variables. Your code to copy files could be something like

    oFSO.CopyFile oUtility.ScriptDir & "\A\*.*", oENV("SystemDrive") & "\temp\BlahBlahA", True
    oFSO.CopyFile oUtility.ScriptDir & "\B\*.*", oENV("SystemDrive") & "\temp\BlahBlahB", True


    If this post is helpful please vote it as Helpful or click Mark for answer.

    Friday, April 3, 2015 3:06 PM
  • Dan,

    Thanks for the script. Always like to expand my limited scripting with new options.

    Most of the apps that I need to install are installed by an in-house utility that creates install logs. The app installs have been certified prior to me laying my hands on them, so I don't like to add any scripting to the installs that might add another layer to troubleshooting "known good" installs and why they might be failing in my project.

    In SCCM, I would create a single software distribution package for the app BlahBlah. Then have separate steps in the task sequence for copying the BlahBlah\A\*.* files and then the BlahBlah\B\*.* files. (To make it easier for others to see what steps were occurring, rather than concatenating the two commands in one step.)

    But now, with MDT, I'm thinking concatenation might be better than having separate MDT applications for doing what could be accomplished in SCCM with one software distro pkg and a few steps.

    In fact, after posting this and seeing your response, I'm wondering if I should try concatenating more commands into one MDT application. Most of my SCCM steps for installing an app consist of four separate commands:

    Create target dir A, B exists already (rather do this than rely on xcopy to create target dir during file copy...)

    xCopy .\A\*.* files

    xCopy .\B\*.* files

    Install app

    So now I'm thinking maybe I can put all those commands into the command line for one MDT application, something like:

    cmd /c mkdir c:\temp\A\ & xcopy .\A\*.* c:\temp\A\ /E /Y & xcopy .\B\*.* c:\temp\B\ /E /Y & InstallBlahBlahCommand

    Believe me, I know the power of scripting and it's value. Just trying to keep this as simple as possible for anyone that might have to pick it up on short notice who isn't a programmer. (I've written HTA, vb scripts and one powershell script... don't consider myself a programmer, though. Although my boss thinks I'm a Powershell SME because I wrote one script!)



    Friday, April 3, 2015 6:00 PM
  • I'm no programmer, but I was able to write my own scripts by just looking at a few others out there and poking around in Microsoft's Script center. I then looked over the ZTIUtility file to see what variables existed that I could make use of. From there I just made a template and use that for everything. I only need to make an adjustment or two to add logic for checking if the application is already installed for example, perhaps to install multiple apps in one script or to simply copy files.

    I do that since most of what I deploy are in the form of MSI installers and logging is built-in. Plus I can use oUtility.RunWithHeartbeat which can be helpful for various reasons.

    You can certainly concatenate those commands into one line. The advantage to scripts is you can leave commented lines to explain what it does and you can troubleshoot a script without having to run a full task sequence to see what breaks.


    If this post is helpful please vote it as Helpful or click Mark for answer.

    Friday, April 3, 2015 6:42 PM
  • Dan,

    Sounds like we're kindred spirits, scripting wise... when I'm faced with a new scripting task, I start poking around too. 

    When you say ZTIUtility file, do you mean the vbs file? If yes, a voyage of discovery for me.

    Our in-house utility that installs apps calls an app-specific xml file that has the install command, which in most cases is an msi. So those are the two copies: A for source files, B for the xml.

    Since I am just dipping my toes into MDT, I have to weigh options on how I'm going to build my task sequence. (I'm a team of one...)

    I will take a deeper look at your script and consider the possibilities.

    Thanks,

    Lang

    Friday, April 3, 2015 8:02 PM
  • Yes, I meant the ZTIUtility.vbs file.

    I get where you are coming from since I too am a team of one who builds the images and maintains MDT, while having to do my main job of Tier 1-3 support. I'd recommend bookmarking this site http://deploymentresearch.com/ and I'd really recommend looking over the driver management in the video section as well.


    If this post is helpful please vote it as Helpful or click Mark for answer.

    Monday, April 6, 2015 1:29 PM