01-23-2019 04:34 PM
Hi All,
Seeking your help if anyone have any script for Windows Master Server to get the Image listing follow like
Client name, Primary copy, copy #2.
We are running on Windows Master Server which is connected to Data Domain (as staging disk) and a Tape library.
Our backups are Backups -----> Data Domin (staging disk) -------> Tape (longer retention)
Backup job completed successfully on Disk (Primary Copy)
Backup job duplicated to Tape on Tape (Copy 2)
As of now we are getting this info from Catalog, but very tedious task on daily basis to get this info for 200-250 clients.
Expected output
Client name, Primary copy/Copy #1, copy #2.
Would really appreciate if some can guide me on this request to make this task automate for daily basis.
With Warm Regards
Harpreet Singh
01-24-2019 03:31 AM
A hint:
I think opscenter is the tool you are looking for - is it included in Netbackup. OpsCenter allow you to make customized reports if the built-in doesn't work.
01-24-2019 06:42 AM
First thing to note is that primary copy is not necessarily always copy 1.
And, the first copy number is not always copy number 1.
What I mean is, this is entirely valid:
imageA, copy #9 exists, copy #10 exists, copy #10 is primary
01-24-2019 06:43 AM - edited 01-24-2019 06:49 AM
Save this as: list-copies.bat
@echo off setlocal enabledelayedexpansion set z_path=%~dp0 set z_name=%~n0 set z_sts=1 set z_file_csv=!z_path!!z_name!.csv set z_file_ima=!z_path!!z_name!.ima set z_file_log=!z_path!!z_name!.log set z_file_sts=!z_path!!z_name!.sts set z_file_stv=!z_path!!z_name!.stv set z_file_tmp=!z_path!!z_name!.tmp set z_file_typ=!z_path!!z_name!.typ set z_file_vbs=!z_path!!z_name!.vbs if exist "!z_file_csv!" del "!z_file_csv!" if exist "!z_file_ima!" del "!z_file_ima!" if exist "!z_file_log!" del "!z_file_log!" if exist "!z_file_sts!" del "!z_file_sts!" if exist "!z_file_stv!" del "!z_file_stv!" if exist "!z_file_tmp!" del "!z_file_tmp!" if exist "!z_file_typ!" del "!z_file_typ!" call :log "" call :log "collecting storage server list..." nbdevquery -liststs -l >"!z_file_sts!" set /a z_total=0 for /f "tokens=1,2,3" %%a in ('type "!z_file_sts!"') do ( set z_type=%%c if not "!z_type!"=="BasicDisk" ( find /i "!z_type!" "!z_file_typ!" >nul 2>&1 if !errorlevel!==1 ( echo !z_type! >>"!z_file_typ!" nbdevquery -listdv -stype !z_type! -l >>"!z_file_stv!" ) ) ) call :log "...done..." call :log "" call :log "collecting image list..." bpimagelist -d 01/01/1970 00:00:00 -l > "!z_file_ima!" set z_sts=!errorlevel! if not !z_sts!==0 ( call :log "...failed to collect image list, status `!z_sts!`, script aborting..." goto :end ) call :log "...done..." call :log "" call :log "processing images..." cscript //nologo "!z_file_vbs!" set z_sts=!errorlevel! if not !z_sts!==0 ( call :log "...failed to process image list, status `!z_sts!`, script aborting..." goto :end ) call :log "...done..." if not exist "!z_file_csv!" ( set z_sts=911 call :log "unable to locate output CSV file, script aborting..." goto :end ) REM put your "blat" command here to email the CSV file. :end call :log "" call :log "Script exiting..." exit /b !z_sts! :log (echo !date! !time:~0,8! %~1) (echo !date! !time:~0,8! %~1)>>"!z_file_log!" goto :eof
01-24-2019 06:43 AM - edited 01-24-2019 06:50 AM
Save this as : list-copies.vbs
Option Explicit '****************************************************************************************************** '* File: list-copies.vbs '* Use: Simple list of images and where the copy numbers are. '* '* Vers Date Who Description '* ---- ---- --- ----------- '* v0.01 24-Jan-2019 sdo First draft. '****************************************************************************************************** '* Notes '* ----- '* 1) Tested on Windows Server 2016, and NetBackup v7.7.3. '****************************************************************************************************** '* Ideas for future enhancement '* ---------------------------- '* 1) If present then this script will read a file named "scriptname.ign", e.g. "list-copies.ign". '* This file is a list of elements to ignore from candidate SLP cancellation. The text in the file '* is case insensitive. Any "<value>" elements from: '* <item>:<value> '* ...will partial match, e.g.: '* client:mycli '* policy:mypol '* slp:myslp '* ...i.e. there are three items that can be checked for, client, policy, and slp. This script '* searches for "values" in strings, and so will match partial string "mycli" with full client name '* of "thisismyclient.mydom", and this render any client containing thr string "mycli" ineligible '* for SLP cancellation. All matches are Case insensitive. '****************************************************************************************************** Const ci_for_reading = 1 Const ci_for_writing = 2 Dim go_fso Dim gs_script_spec, gs_script_path, gs_script_name Dim gd_ignore_policy, gd_ignore_client, gd_ignore_slp Call s_init() Call s_main() WScript.Quit(0) Sub s_init() Dim ls_ignore, ls_recs, ll_rec, ls_rec, ls_items Set go_fso = CreateObject( "Scripting.FileSystemObject" ) gs_script_spec = WScript.ScriptFullName gs_script_path = go_fso.GetParentFolderName( gs_script_spec ) gs_script_name = go_fso.GetBaseName( gs_script_spec ) Set gd_ignore_client = CreateObject( "Scripting.Dictionary" ) Set gd_ignore_policy = CreateObject( "Scripting.Dictionary" ) Set gd_ignore_slp = CreateObject( "Scripting.Dictionary" ) ls_ignore = gs_script_name & ".ign" If go_fso.FileExists( ls_ignore ) Then Call s_log( "...loading ignore list..." ) ls_recs = Split( go_fso.OpenTextFile( ls_ignore, ci_for_reading ).ReadAll, vbcrlf ) For ll_rec = LBound( ls_recs ) To UBound( ls_recs ) ls_rec = fs_clean( ls_recs( ll_rec ) ) ls_rec = Replace( ls_rec, " ", "" ) ls_rec = LCase( ls_rec ) Select Case Left( ls_rec, 1 ) Case "", "#" Case Else Call s_log( "...ignore: " & ls_rec ) ls_items = Split( ls_rec, ":" ) Select Case ls_items( 0 ) Case "client" : gd_ignore_client.Add ls_items( 1 ), "" Case "policy" : gd_ignore_policy.Add ls_items( 1 ), "" Case "slp" : gd_ignore_slp.Add ls_items( 1 ), "" Case Else Call s_quit( "...bad keyword in `" & ls_rec & "`..." ) End Select End Select Next Call s_log( "...done..." ) Else Call s_log( "...no ignore list to load..." ) End If End Sub Sub s_main() Dim la_dvs, ll_dv, la_data, ls_dv, ld_dv_name Dim la_recs, ll_rec, ll_images, ls_client, ls_image, ls_policy, ls_schedule, ls_ctime, ls_primary, ls_copies, ls_yyyy_mm_dd Dim ls_copy, ll_copy, ls_frag, ls_media, lo_chan, ls_csv, ls_image_copy Dim ld_image_client, ld_image_primary, ld_image_copies, ld_imagecopy_media, ld_image_policy, ld_image_schedule Set ld_dv_name = CreateObject( "Scripting.Dictionary" ) Set ld_image_client = CreateObject( "Scripting.Dictionary" ) Set ld_image_policy = CreateObject( "Scripting.Dictionary" ) Set ld_image_schedule = CreateObject( "Scripting.Dictionary" ) Set ld_image_primary = CreateObject( "Scripting.Dictionary" ) Set ld_image_copies = CreateObject( "Scripting.Dictionary" ) Set ld_imagecopy_media = CreateObject( "Scripting.Dictionary" ) Call s_log( "" ) Call s_log( "reading disk volumes..." ) la_dvs = Split( go_fso.OpenTextFile( gs_script_name & ".stv", ci_for_reading ).ReadAll, vbCrlf ) For ll_dv = LBound( la_dvs ) To UBound( la_dvs ) - 1 la_data = Split( la_dvs( ll_dv ), " " ) ls_dv = la_data( 4 ) ld_dv_name.Add ls_dv, la_data( 1 ) Next Call s_log( "...done..." ) Call s_log( "" ) Call s_log( "reading image list..." ) la_recs = Split( go_fso.OpenTextFile( gs_script_name & ".ima", ci_for_reading ).ReadAll, vbCrlf ) For ll_rec = LBound( la_recs ) To UBound( la_recs ) - 1 la_data = Split( la_recs( ll_rec ), " " ) Select Case la_data( 0 ) Case "IMAGE" ll_images = ll_images + 1 ls_client = la_data( 1 ) ls_image = la_data( 5 ) ls_policy = la_data( 6 ) ls_schedule = la_data( 10 ) ls_ctime = la_data( 13 ) ls_copies = la_data( 20 ) ls_primary = la_data( 27 ) ld_image_client.Add ls_image, ls_client ld_image_primary.Add ls_image, ls_primary ld_image_policy.Add ls_image, ls_policy ld_image_schedule.Add ls_image, ls_schedule ld_image_copies.Add ls_image, ls_copies Case "HISTO" Case "FRAG" ls_copy = la_data( 1 ) ls_frag = la_data( 2 ) ls_media = la_data( 8 ) If Left( ls_media, 1 ) = "@" Then If Not ld_dv_name.Exists( ls_dv ) Then Call s_abort( "...unexpected, DV id `" & ls_media & "` for image `" & ls_image & "` not found in DV list..." ) End If End If ll_copy = CLng( ls_copy ) If ( ll_copy < 1 ) Or ( ll_copy > 10 ) Then Call s_abort( "...unexpected copy number `" & ls_copy & "` for image `" & ls_image & "`..." ) End If Select Case ls_frag Case "-1" ld_imagecopy_media.Add ls_image & "|" & ls_copy, ls_media End Select Case Else Call s_quit( "...bad record type `" & la_data( 1 ) & "`, at record `" & ll_rec & "`..." ) End Select Next Set la_recs = Nothing Call s_log( "...images: " & ll_images ) Call s_log( "...done..." ) Call s_log( "" ) Call s_log( "sorting..." ) Call s_sort( ld_image_client, "key" ) Call s_log( "...done..." ) Call s_log( "" ) Call s_log( "reporting..." ) Set lo_chan = go_fso.OpenTextFile( gs_script_name & ".csv", ci_for_writing, True ) lo_chan.WriteLine "Client,Image,Policy,Schedule,Copies,Primary,Copy1,Copy2,Copy3,Copy4,Copy5,Copy6,Copy7,Copy8,Copy9,Copy10" For Each ls_image In ld_image_client.Keys ls_client = ld_image_client.Item( ls_image ) ls_policy = ld_image_policy.Item( ls_image ) ls_schedule = ld_image_schedule.Item( ls_image ) ls_primary = ld_image_primary.Item( ls_image ) ls_copies = ld_image_copies.Item( ls_image ) ls_csv = ls_client & "," & ls_image & "," & ls_policy & "," & ls_schedule & "," & ls_copies & "," & ls_primary For ll_copy = 1 To 10 ls_image_copy = ls_image & "|" & ll_copy If ld_imagecopy_media.Exists( ls_image_copy ) Then ls_csv = ls_csv & "," & ld_dv_name.Item( ld_imagecopy_media.Item( ls_image_copy ) ) Else ls_csv = ls_csv & "," End If Next lo_chan.WriteLine ls_csv Next lo_chan.Close Call s_log( "...done..." ) End Sub Sub s_log( ps_text ) Dim ld_now, ls_now ld_now = Now() ls_now = FormatDateTime( ld_now, vbShortdate ) & " " & FormatDateTime( ld_now, vbLongtime ) WScript.Echo ls_now & " " & ps_text End Sub Sub s_sort( pd_tab, ps_what ) Dim ll_count, ll_i, ll_j, ls_key, ls_item, lb_swap, lb_swapped, ll_compares, ll_swaps ll_count = pd_tab.Count If ll_count < 2 Then Exit Sub Redim ls_keys( ll_count ) Redim ls_items( ll_count ) ll_count = 0 For Each ls_key In pd_tab.Keys ll_count = ll_count + 1 ls_keys( ll_count ) = ls_key ls_items( ll_count ) = pd_tab.Item( ls_key ) pd_tab.Remove ls_key Next If pd_tab.Count <> 0 Then Call s_quit( "...sort not empty after unload..." ) ll_compares = 0 ll_swaps = 0 For ll_i = ( ll_count - 1 ) To 1 Step -1 lb_swapped = False For ll_j = 1 To ll_i lb_swap = False Select Case ps_what Case "key" If ls_keys( ll_j ) > ls_keys( ll_j + 1 ) Then lb_swap = True Case "item" If ls_items( ll_j ) > ls_items( ll_j + 1 ) Then lb_swap = True Case Else Call s_quit( "...sort, bad p2 `" & ps_what & "`..." ) End Select ll_compares = ll_compares + 1 If lb_swap Then ll_swaps = ll_swaps + 1 ls_key = ls_keys( ll_j ) ls_keys( ll_j ) = ls_keys( ll_j + 1 ) ls_keys( ll_j + 1 ) = ls_key ls_item = ls_items( ll_j ) ls_items( ll_j ) = ls_items( ll_j + 1 ) ls_items( ll_j + 1 ) = ls_item lb_swapped = True End If Next If Not lb_swapped Then Exit For Next For ll_i = 1 To ll_count pd_tab.Add ls_keys( ll_i ), ls_items( ll_i ) Next Call s_log( "...compares:" & ll_compares & ", swaps:" & ll_swaps ) End Sub Sub s_add( pd_tab, ps_key, px_val ) Dim lx_val If pd_tab.Exists( ps_key ) Then lx_val = pd_tab.Item( ps_key ) + px_val pd_tab.Remove ps_key Else lx_val = px_val End If pd_tab.Add ps_key, lx_val End Sub Sub s_quit( ps_text ) Call s_log( ps_text ) WScript.Quit( 1 ) End Sub Function fs_left( ps_text, pl_len ) fs_left = Left( ps_text & Space( pl_len ), pl_len ) End Function Function fs_right( ps_text, pl_len ) fs_right = Right( Space( pl_len ) & ps_text, pl_len ) End Function Function fs_num( px_num, pl_len ) Dim ll_num ll_num = Int( px_num ) fs_num = Right( Space( pl_len ) & FormatNumber( ll_num, 0 ), pl_len ) End Function Function fs_ctime_to_yyyy_mm_dd( ps_ctime ) Dim ls_res, ld_date ld_date = DateAdd( "s", ps_ctime, "01-Jan-1970 00:00:00" ) ls_res = DatePart( "yyyy", ld_date ) ls_res = ls_res & "-" & fs_zero( DatePart( "m", ld_date ), 2 ) ls_res = ls_res & "-" & fs_zero( DatePart( "d", ld_date ), 2 ) ls_res = ls_res & " " & WeekDayName( WeekDay( ld_date ), True ) fs_ctime_to_yyyy_mm_dd = ls_res End Function Function fs_zero( ps_num, pl_len ) fs_zero = Right( String( pl_len, "0" ) & ps_num, pl_len ) End Function Function fs_clean( ps_rec ) Dim ls_old, ls_new ls_new = ps_rec ls_new = Replace( ls_new, vbtab, " " ) Do ls_old = ls_new ls_new = Replace( ls_new, " ", " " ) ls_new = Trim( ls_new ) Loop Until ls_new = ls_old fs_clean = ls_new End Function Function fd_ctime2date( ps_ctime ) fd_ctime2date = DateAdd( "s", ps_ctime, CDate( "01-Jan-1970 00:00:00" ) ) End Function
01-24-2019 06:46 AM
Save the two scripts in the same folder. Take the ".txt" file extension off the name. Run the .bat script.
The scripts assume that the NetBackup binaries are in the system/process wide "path" definition.
01-24-2019 06:48 AM
apologies but this platform will not let me upload a file named "list-copies.bat.txt"
so you'll have to select/copy that from a posting above
watch out for line wrap
01-29-2019 02:11 AM
...an improved version of the main script :
Option Explicit '****************************************************************************************************** '* File: list-copies.vbs '* Use: Simple list of images and where the copy numbers are. '* '* Vers Date Who Description '* ---- ---- --- ----------- '* v0.01 24-Jan-2019 sdo First draft. '* v0.02 29-Jan-2019 sdo Handle if there are no disk volumes, i.e. only tape, DSU, DSSU. '* v0.03 29-Jan-2019 sdo Only attempt DV lookup if copy ref begins with "@". '* v0.04 29-Jan-2019 sdo Use fragment '1' as basis for picking up media ID. '* v0.05 29-Jan-2019 sdo If "/" or "\" present in media id then just capture left-most part. '* v0.06 29-Jan-2019 sdo Collect and report media type. '****************************************************************************************************** '* Notes '* ----- '* 1) Tested on Windows Server 2016, and NetBackup v7.7.3. '* 2) Tested on Windows Server 2016, and NetBackup v8.1.1. '****************************************************************************************************** '* Ideas for future enhancement '* ---------------------------- '* 1) If present then this script will read a file named "scriptname.ign", e.g. "list-copies.ign". '* This file is a list of elements to ignore from candidate SLP cancellation. The text in the file '* is case insensitive. Any "<value>" elements from: '* <item>:<value> '* ...will partial match, e.g.: '* client:mycli '* policy:mypol '* slp:myslp '* ...i.e. there are three items that can be checked for, client, policy, and slp. This script '* searches for "values" in strings, and so will match partial string "mycli" with full client name '* of "thisismyclient.mydom", and this render any client containing thr string "mycli" ineligible '* for SLP cancellation. All matches are Case insensitive. '****************************************************************************************************** Const ci_for_reading = 1 Const ci_for_writing = 2 Const cs_bs = "\" Const cs_fs = "/" Dim go_fso Dim gs_script_spec, gs_script_path, gs_script_name Dim gd_ignore_policy, gd_ignore_client, gd_ignore_slp Call s_init() Call s_main() WScript.Quit(0) Sub s_init() Dim ls_ignore, ls_recs, ll_rec, ls_rec, ls_items Set go_fso = CreateObject( "Scripting.FileSystemObject" ) gs_script_spec = WScript.ScriptFullName gs_script_path = go_fso.GetParentFolderName( gs_script_spec ) gs_script_name = go_fso.GetBaseName( gs_script_spec ) Set gd_ignore_client = CreateObject( "Scripting.Dictionary" ) Set gd_ignore_policy = CreateObject( "Scripting.Dictionary" ) Set gd_ignore_slp = CreateObject( "Scripting.Dictionary" ) ls_ignore = gs_script_name & ".ign" If go_fso.FileExists( ls_ignore ) Then Call s_log( "...loading ignore list..." ) ls_recs = Split( go_fso.OpenTextFile( ls_ignore, ci_for_reading ).ReadAll, vbcrlf ) For ll_rec = LBound( ls_recs ) To UBound( ls_recs ) ls_rec = fs_clean( ls_recs( ll_rec ) ) ls_rec = Replace( ls_rec, " ", "" ) ls_rec = LCase( ls_rec ) Select Case Left( ls_rec, 1 ) Case "", "#" Case Else Call s_log( "...ignore: " & ls_rec ) ls_items = Split( ls_rec, ":" ) Select Case ls_items( 0 ) Case "client" : gd_ignore_client.Add ls_items( 1 ), "" Case "policy" : gd_ignore_policy.Add ls_items( 1 ), "" Case "slp" : gd_ignore_slp.Add ls_items( 1 ), "" Case Else Call s_quit( "...bad keyword in `" & ls_rec & "`..." ) End Select End Select Next Call s_log( "...done..." ) Else Call s_log( "...no ignore list to load..." ) End If End Sub Sub s_main() Dim la_dvs, ll_dv, la_data, ls_dv, ld_dv_name Dim la_recs, ll_rec, ll_images, ls_client, ls_image, ls_policy, ls_schedule, ls_ctime, ls_primary, ls_copies, ls_yyyy_mm_dd Dim ls_copy, ll_copy, ls_frag, ls_mtype, ls_media, lo_chan, ls_csv, ls_image_copy Dim ld_image_client, ld_image_primary, ld_image_copies, ld_imagecopy_media, ld_imagecopy_mtype Dim ld_image_policy, ld_image_schedule Dim ls_sep, ll_pos1, ll_pos2 Set ld_dv_name = CreateObject( "Scripting.Dictionary" ) Set ld_image_client = CreateObject( "Scripting.Dictionary" ) Set ld_image_policy = CreateObject( "Scripting.Dictionary" ) Set ld_image_schedule = CreateObject( "Scripting.Dictionary" ) Set ld_image_primary = CreateObject( "Scripting.Dictionary" ) Set ld_image_copies = CreateObject( "Scripting.Dictionary" ) Set ld_imagecopy_mtype = CreateObject( "Scripting.Dictionary" ) Set ld_imagecopy_media = CreateObject( "Scripting.Dictionary" ) Call s_log( "" ) Call s_log( "reading disk volumes..." ) If go_fso.FileExists( gs_script_name & ".stv" ) Then la_dvs = Split( go_fso.OpenTextFile( gs_script_name & ".stv", ci_for_reading ).ReadAll, vbCrlf ) For ll_dv = LBound( la_dvs ) To UBound( la_dvs ) - 1 la_data = Split( la_dvs( ll_dv ), " " ) ls_dv = la_data( 4 ) ld_dv_name.Add ls_dv, la_data( 1 ) Next End If Call s_log( "...done..." ) Call s_log( "" ) Call s_log( "reading image list..." ) la_recs = Split( go_fso.OpenTextFile( gs_script_name & ".ima", ci_for_reading ).ReadAll, vbCrlf ) For ll_rec = LBound( la_recs ) To UBound( la_recs ) - 1 la_data = Split( la_recs( ll_rec ), " " ) Select Case la_data( 0 ) Case "IMAGE" ll_images = ll_images + 1 ls_client = la_data( 1 ) ls_image = la_data( 5 ) ls_policy = la_data( 6 ) ls_schedule = la_data( 10 ) ls_ctime = la_data( 13 ) ls_copies = la_data( 20 ) ls_primary = la_data( 27 ) ld_image_client.Add ls_image, ls_client ld_image_primary.Add ls_image, ls_primary ld_image_policy.Add ls_image, ls_policy ld_image_schedule.Add ls_image, ls_schedule ld_image_copies.Add ls_image, ls_copies Case "HISTO" Case "FRAG" ls_copy = la_data( 1 ) ls_frag = la_data( 2 ) ls_mtype = la_data( 5 ) ls_media = la_data( 8 ) Select Case ls_frag Case "1" If Left( ls_media, 1 ) = "@" Then If Not ld_dv_name.Exists( ls_dv ) Then Call s_abort( "...unexpected, DV id `" & ls_media & "` for image `" & ls_image & "` not found in DV list..." ) End If End If ll_copy = CLng( ls_copy ) If ( ll_copy < 1 ) Or ( ll_copy > 10 ) Then Call s_abort( "...unexpected copy number `" & ls_copy & "` for image `" & ls_image & "`..." ) End If Select Case ls_mtype Case "0" : ls_mtype = "disk" case "1" : ls_mtype = "unitree" Case "2" : ls_mtype = "tape" Case "3" : ls_mtype = "ndmp" Case "5" : ls_mtype = "checkpoint" case "6" : ls_mtype = "staging" Case Else : ls_mtype = ls_mtype & "_unknown" End Select If Left( ls_media, 1 ) <> "@" Then If ls_mtype = "disk" Then ls_sep = "" If Instr( 1, ls_media, cs_bs ) Then ls_sep = cs_bs '...probably a Windows path... If Instr( 1, ls_media, cs_fs ) Then ls_sep = cs_fs '...probably a Linux/Unix path... If ls_sep <> "" Then ll_pos1 = Instr( 1, ls_media, ls_sep ) ll_pos2 = Instr( ll_pos1 + 1, ls_media, ls_sep ) If ll_pos2 > ll_pos1 Then ls_media = Mid( ls_media, 1, ll_pos2 ) Else ls_media = Mid( ls_media, 1, ll_pos1 ) End If End If End If End If ld_imagecopy_mtype.Add ls_image & "|" & ls_copy, ls_mtype ld_imagecopy_media.Add ls_image & "|" & ls_copy, ls_media End Select Case Else Call s_quit( "...bad record type `" & la_data( 1 ) & "`, at record `" & ll_rec & "`..." ) End Select Next Set la_recs = Nothing Call s_log( "...images: " & ll_images ) Call s_log( "...done..." ) Call s_log( "" ) Call s_log( "sorting..." ) Call s_sort( ld_image_client, "key" ) Call s_log( "...done..." ) Call s_log( "" ) Call s_log( "reporting..." ) Set lo_chan = go_fso.OpenTextFile( gs_script_name & ".csv", ci_for_writing, True ) lo_chan.WriteLine "Client,Image,Policy,Schedule,Copies,Primary,Copy1,Copy2,Copy3,Copy4,Copy5,Copy6,Copy7,Copy8,Copy9,Copy10" For Each ls_image In ld_image_client.Keys ls_client = ld_image_client.Item( ls_image ) ls_policy = ld_image_policy.Item( ls_image ) ls_schedule = ld_image_schedule.Item( ls_image ) ls_primary = ld_image_primary.Item( ls_image ) ls_copies = ld_image_copies.Item( ls_image ) ls_csv = ls_client & "," & ls_image & "," & ls_policy & "," & ls_schedule & "," & ls_copies & "," & ls_primary For ll_copy = 1 To 10 ls_image_copy = ls_image & "|" & ll_copy If ld_imagecopy_media.Exists( ls_image_copy ) Then If Left( ls_image_copy, 1 ) = "@" Then ls_csv = ls_csv & "," & ld_imagecopy_mtype.Item( ls_image_copy ) & "-" & ld_dv_name.Item( ld_imagecopy_media.Item( ls_image_copy ) ) Else ls_csv = ls_csv & "," & ld_imagecopy_mtype.Item( ls_image_copy ) & "-" & ld_imagecopy_media.Item( ls_image_copy ) End If Else ls_csv = ls_csv & "," End If Next lo_chan.WriteLine ls_csv Next lo_chan.Close Call s_log( "...done..." ) End Sub Sub s_log( ps_text ) Dim ld_now, ls_now ld_now = Now() ls_now = FormatDateTime( ld_now, vbShortdate ) & " " & FormatDateTime( ld_now, vbLongtime ) WScript.Echo ls_now & " " & ps_text End Sub Sub s_sort( pd_tab, ps_what ) Dim ll_count, ll_i, ll_j, ls_key, ls_item, lb_swap, lb_swapped, ll_compares, ll_swaps ll_count = pd_tab.Count If ll_count < 2 Then Exit Sub Redim ls_keys( ll_count ) Redim ls_items( ll_count ) ll_count = 0 For Each ls_key In pd_tab.Keys ll_count = ll_count + 1 ls_keys( ll_count ) = ls_key ls_items( ll_count ) = pd_tab.Item( ls_key ) pd_tab.Remove ls_key Next If pd_tab.Count <> 0 Then Call s_quit( "...sort not empty after unload..." ) ll_compares = 0 ll_swaps = 0 For ll_i = ( ll_count - 1 ) To 1 Step -1 lb_swapped = False For ll_j = 1 To ll_i lb_swap = False Select Case ps_what Case "key" If ls_keys( ll_j ) > ls_keys( ll_j + 1 ) Then lb_swap = True Case "item" If ls_items( ll_j ) > ls_items( ll_j + 1 ) Then lb_swap = True Case Else Call s_quit( "...sort, bad p2 `" & ps_what & "`..." ) End Select ll_compares = ll_compares + 1 If lb_swap Then ll_swaps = ll_swaps + 1 ls_key = ls_keys( ll_j ) ls_keys( ll_j ) = ls_keys( ll_j + 1 ) ls_keys( ll_j + 1 ) = ls_key ls_item = ls_items( ll_j ) ls_items( ll_j ) = ls_items( ll_j + 1 ) ls_items( ll_j + 1 ) = ls_item lb_swapped = True End If Next If Not lb_swapped Then Exit For Next For ll_i = 1 To ll_count pd_tab.Add ls_keys( ll_i ), ls_items( ll_i ) Next Call s_log( "...compares:" & ll_compares & ", swaps:" & ll_swaps ) End Sub Sub s_quit( ps_text ) Call s_log( ps_text ) WScript.Quit( 1 ) End Sub