Migrating from ZENworks 7 to ZCM



When we decided to migrate from ZENworks 7 to ZCM we took a look at the ZCM migration tools and while good, wouldn't work for us. We wanted to do a direct move from (the majority of applications being) distribution script based, and file server holding installation files, to the content repository model available in ZCM. So how did we do it without mass reinstallations of applications?


To give an overview of our setup, we have multiple ZENworks 7 servers spread throughout New Zealand, one at each of our major sites in Bream Bay, Auckland, Hamilton, Rotorua, Wellington, Nelson, Alexandra, Christchurch, and Dunedin. We have a number of other sites which have no NetWare/OES server and these also have no ZENworks server either.

The majority of applications are deployed via their native silent installation scripts, and these are done in pre- and post- distribution scripts in application objects. The applications that aren't built like this are either file-copy or MSI installations. Each site has a %zenapps% environment variable which is referenced by the distribution scripts so that installations are done from local sources.

Note: This isn't an article about ZCM installation, so I'll not touch on that at all except to say we now have 3 Primary servers, 1 Oracle DB server and many satellite servers for our small sites

First step: Application migration

This involved using the ZENworks migration tools for the file and MSI based applications, and a lot of manual labour for the distribution script based application installs – it was a good 4-5 weeks of migration and testing.

Second step: Script creation and deployment

Obviously, if we were using the ZCM migration tools there is a way to mark the bundles associated to a user/workstation as installed. I spent a lot of time investigating registry keys and playing around with the APPSTATE files in %programfiles%\ Novell\ZENworks\cache\zmd and not getting anywhere before I contacted Novell technical support and they pointed me towards the BundleMigrate.xml file, with ZCM installed, if you delete the folder

C:\Program Files\Novell\ZENworks\cache\zmd\migratedAppInfo

And prime the BundleMigrate.xml file in C:\Program Files\Novell\ZENworks\cache\zmd\BundleMigrate.xml, then on the next ZENworks refresh it will mark that bundle as available/installed. How is the BundleMigrate.xml file made up? Here's small example"

<?xml version="1.0"?>
<BundleList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://novell.com/zenworks/bundle/MigrateZEN7">
<Bundle ID="de9d7a00a6cd49a6b47a4db132e6d472" Version="0" Installed="true" />
<Bundle ID="fe07b2546d974c57bff05b0c989ce794" Version="0" Installed="true" />
<Bundle ID="b05186b5079a4ac0b23515c647dff63a" Version="0" Installed="true" />
<Bundle ID="96963720c4c64626b6a3c38403781657" Version="0" Installed="true" />

So all we need to do is populate that file with the Bundle ID of each application installed on the machine and mark it as installed. To get the bundle GUIDs of all my applications (these are the GUIDs of the new ZCM bundles, not old ZENworks 7 applications) I used a combination of:

Zman bundle-list (bl)
Zman object-get-GUID (ogg)

And notepad /Excel/ to massage the results into script files that I could use to get my bundle ID numbers. While there might be a zman command that would do it, I could not find one that would output the version number of my bundles, this wasn't such a problem as this is displayed on the main Bundles screen in the ZCC. Note that both the bl and ogg commands output there results in the same order as they are displayed in the ZCC so you can dump each output to a file then copy/paste them into different excel rows to match them up – watch out for folders though, as these get GUID numbers as well but obviously aren't required!!

So now that I have my bundle GUIDs and version numbers how do you know what applications are marked installed? I used the registry keys here:


This has a list of both the user and workstation associated applications. I didn't bother checking to see if the applications were actually installed, if they were in there then I marked them installed in ZCM – the worst thing that would happen would be the user would need to verify the application to get it.

I used autoit to create a script that takes all of the above and creates a BundleMigrate.xml file. Here is a cutdown version of the script:

;Script to set bundle install state to "installed"

; Export NAL registry
; Gives us the list of Zen7 associated applications

$windir = EnvGet("WINDIR")
$userprofile = EnvGet("USERPROFILE")

ShellExecuteWait($windir & "\system32\reg.exe", "export HKCU\Software\NetWare\NAL\1.0\Associations C:\temp\nal_associated.reg")

$file = FileOpen("C:\temp\nal_associated.reg", 0)
$filebundle = FileOpen("C:\temp\BundleMigrate.xml", 1)

;Check if file opened for reading OK
If $file = -1 Then
MsgBox(0, "Error", "Unable to open file.")

; make the top of the BundleMigrate.xml

FileWrite($filebundle, '<?xml version="1.0"?>' & @CRLF)
FileWrite($filebundle, '<BundleList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://novell.com/zenworks/bundle/MigrateZEN7">' & @CRLF)

; Read in lines of text until the EOF is reached
While 1
$line = FileReadLine($file)
If @error = -1 Then ExitLoop
;MsgBox(0, "Line read:", $line)
if $line == '"@Risk45.ZenApps.Hamilton.NIWA"="NIWA"' then FileWrite($filebundle, '<Bundle ID="899a347b252b2764d9c0d7374f5aa4a2" Version="0" Installed="true" />' & @CRLF)
; 7zip
if $line == '"7zip v4-57.zenapps.NIWA"="NIWA"' then FileWrite($filebundle, '<Bundle ID="746585b5e606d174f6c4200a9c811519" Version="0" Installed="true" />' & @CRLF)
; activesync
if $line == '"ActiveSync v45.zenapps.NIWA"="NIWA"' then FileWrite($filebundle, '<Bundle ID="b8007c6e4dd578ca082ea06ea7c19a57" Version="0" Installed="true" />' & @CRLF)
; adobe photoshop elements

; set install states for some apps I want "installed" no matter what
; ms office
FileWrite($filebundle, '<Bundle ID="de9d7a00a6cd49a6b47a4db132e6d472" Version="0" Installed="true" />' & @CRLF)
; excel icon
FileWrite($filebundle, '<Bundle ID="fe07b2546d974c57bff05b0c989ce794" Version="0" Installed="true" />' & @CRLF)
; word icon
FileWrite($filebundle, '<Bundle ID="b05186b5079a4ac0b23515c647dff63a" Version="0" Installed="true" />' & @CRLF)
; powerpoint icon
FileWrite($filebundle, '<Bundle ID="96963720c4c64626b6a3c38403781657" Version="0" Installed="true" />' & @CRLF)

; write the bottom of BundleMigrate.xml

FileWrite($filebundle, '</BundleList>')


; Install ZCM agent
; Set user
Local $sUserName = "administrator"
Local $sPassword = “removed"

; Run the installation
;RunAsWait('"C:\temp\PreAgentPkg_AgentComplete.exe" -x -q')
RunAsWait($sUserName, @ComputerName, $sPassword, 1, '"C:\temp\PreAgentPkg_AgentComplete.exe" -x -q', @SystemDir)
; Need to pause execution of script until installation completes

; after installation, copy BundleMigrate.xml into place
RunAsWait($sUserName, @ComputerName, $sPassword, 1, @ComSpec & ' /c copy /Y "C:\temp\BundleMigrate.xml" "C:\Program Files\Novell\ZENworks\cache\zmd"', @SystemDir)

; Clean up

; prompt for reboot
$answer = MsgBox(4, "Reboot required", "A reboot is required to complete the ZENworks upgrade - reboot now?")
If $answer = 6 Then
RunAs($sUserName, @ComputerName, $sPassword, 1, @ComSpec & " /c " & 'shutdown -r -t 05 -c "Rebooting due to ZENworks upgrade"', @SystemDir)
elseif $answer = 7 Then
Msgbox(0, "Reboot required", "Please reboot as soon as possible - the ZENworks upgrade will not complete until you do so")

So let's go through what's happening:

First I export the NAL registry key, which gives me a registry file with a list of all the ZENworks 7 associated applications. I then open this file for reading, and open another file (C:\temp\BundleMigrate.xml) for writing to. I then write the top of the file, which writes:

<?xml version="1.0"?>
<BundleList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://novell.com/zenworks/bundle/MigrateZEN7">

I then loop through the exported registry file, comparing each line in the file to a known line (I had to associate myself to ALL applications we had in ZENworks 7 and then take a dump of the registry key to get all the applications easily). Obviously in the above example I've cut the number of if statements way down, otherwise there would be pages of text!! At the end of my while loop I set a few applications to installed that I want marked that way even if they are not really installed (via zenworks – Microsoft Office was installed via imaging with ZENworks 7, but with the move to ZCM we have taken it out of the image, this is just to avoid it being reinstalled for those machines that have it already)

Next up I write the bottom of the file:

FileWrite($filebundle, '</BundleList>')

And close it. After this I'm all set to install ZCM. Here I'll touch on how I do the actual migration from ZENworks 7 to ZCM – I used a ZENworks 7 application. This app simple runs the below pre-distribution script

REM copy zenagent to C: drive
copy /Y "%zenapps%\zcm deployment\PreAgentPkg_AgentComplete.exe" "C:\Temp"

REM Make some directories
mkdir C:\Zenworks\zenapps
"%zenapps%\Windows Tools\xcacls" "C:\Zenworks\zenapps" /P users:F /Y /E

Which copies the ZCM installation package into place (the Windows runas command that autoit calls to install the agent can only see local drives easily, so it's a simple task to copy this over instead of mucking around with trying to map drives) and creates a folder C:\Zenworks\zenapps – this is used by a lot of my ZCM applications as a temporary storage location (referred to as ${zenapps}). After the pre-distribution script has run, I then run (under Run Options > Application) my autoit script which sits in a network location.

So, back to the autoit script – as all machines at my company have the same local administrator username and password I set this and run the ZCM install:

; Install ZCM agent
; Set user
Local $sUserName = "administrator"
Local $sPassword = “removed"

; Run the installation
;RunAsWait('"C:\temp\PreAgentPkg_AgentComplete.exe" -x -q')
RunAsWait($sUserName, @ComputerName, $sPassword, 1, '"C:\temp\PreAgentPkg_AgentComplete.exe" -x -q', @SystemDir)
; Need to pause execution of script until installation completes

There are few things to note here:

  • The PreAgentPkg_AgentComplete.exe actual exits quite fast – spawning ZENPreAgent.exe that does the install, to stop Autoit carrying on through the script I first wait for the process to exist (ProcessWait)

  • and then wait for it to exit (ProcessWaitClose) before continuing the script.

  • The package install quits silently at the end without rebooting

I then copy the BundleMigirate.xml created in C:\temp into the correct location so that when the PC reboots and registers with my ZCM primary server this file gets read and the agent sets the user and workstation associated applications as installed.

After that's all complete I clean up some files and prompt the user to reboot.

Wrap up

This is my no means the best way to migrate to ZCM, it certainly was a lot of manual labour getting the the script ready for deployment. However, it worked for us and hopefully it can help a few others out there!


How To-Best Practice
Comment List