Titlebar Script Error

I use the following script to generate a custom titlebar:

function OnInit(initData)
{
	initData.name = "Custom Title Bar";
	initData.version = "1.3";
	initData.copyright = "(c) 2019 cwfrizzell";
	initData.url = "https://resource.dopus.com/t/set-listertitle-to-include-file-display-view-mode/31991";
	initData.desc = "This script enables users to customize the Title Bar to reflect user-selected DOpus data.";
	initData.default_enable = true;
	initData.min_version = "12.0";
	
	//Get User and Machine names
	var objWSH = new ActiveXObject("WScript.Shell");
	var objEnv = objWSH.Environment("Process");
	DOpus.vars.set("ListerTitleUser",objEnv("USERNAME"));
	DOpus.vars.set("ListerTitleDomain",objEnv("USERDOMAIN"));
	var objcfg = initData.config;
	objcfg.Debug = true;
}

//Global Variables
var cmd = DOpus.create.command;
var version = DOpus.version.product;
var tab, tabs, dual, viewMode, activeDisplay, globalFilterFlag, quickFilterSet, quickFilterFlag, title;
var hideHiddenFlag, hideSystemFlag;
var filterSet = DOpus.filters.enable;

function OnOpenLister(OpenListerData)
{
	tab = OpenListerData.lister.activetab;
	cmd.SetSourceTab(tab);
	tabs = tab.right; 
	
	//Determine layout type and identify active display on Lister open
	dual = tab.source;
	
	if (dual == "1" && tabs == true)//check for dual vertical, active right display
	{
		activeDisplay = "Right"
	} else if (dual == "1" && tabs == false)//check for dual vertical, active left display
	{
		activeDisplay = "Left"	
	} else if (dual == "2" && tabs == true)//check for dual horizontal, active bottom display
	{
		activeDisplay = "Bottom"
	} else if (dual == "2" && tabs == false)//check for dual horizontal, active top display
	{
		activeDisplay = "Top"
	} else//if not dual vertical or horizontal, must be a single display
	{
		activeDisplay = "Display"
	}
	
	//Determine view mode status on Lister open
	viewMode = tab.format.view;
	viewMode = viewMode.substring(0,1).toUpperCase() + viewMode.substring(1);

	//Determine global filter status on Lister open
	if (filterSet== true)
	{
		globalFilterFlag = "ON"
	} else
	{
		globalFilterFlag = "OFF"
	}		

	//Determine quickfilter status on Lister open
	quickFilterSet = tab.quickfilter.filter;
	 
	if (quickFilterSet === '')
	{
		quickFilterFlag = "OFF"
	} else
	{
		quickFilterFlag = "[ " + quickFilterSet + " ]"
	}
	
	//Determine if hide hidden files set to true
	if (cmd.IsSet("GLOBALHIDEHIDDEN=Toggle"))
	{
		hideHiddenFlag = "ON"
	} else
	{
		hideHiddenFlag = "OFF"
	}
	
	//Determine if hide system files set to true
	if (cmd.IsSet("HIDESYSTEMFILES=Toggle"))
	{
		hideSystemFlag = "OFF"
	} else
	{
		hideSystemFlag = "ON"
	}
	
	//Build Lister Title
	title = "notoggle:Directory Opus " + version + " Pro (64-bit)   |   LAYOUT:  %L   |   STYLE:  %S   |   ACTIVE:  " + activeDisplay + "   |   VIEW:  " + viewMode + "   |   FILTERS:  Q - " + quickFilterFlag + "   G - " + globalFilterFlag + "   H - " + hideHiddenFlag + "   S - " + hideSystemFlag
	
	var id = tab.path.def_value;
	if (tab.path.test_root == 0) //Check if at root drive  
	{
		if (id.substr(id.length - 1) == "\\")
		{
			title = title + "   |   FOLDER:  %R\\"; //Ensures root drive displayed properly
		} else
		{
			title = title + "   |   FOLDER:  %R";
		}
	} else
	{
		title = title + "   |   FOLDER:  %R\\...\\%N";
	}
	
	DOpus.Output(title);

	cmd.RunCommand('Set LISTERTITLE="' + title + '"');
}

function UpdateTitleFilter(ScriptCommandData)
{
	//update title after quickfilter applied
	cmdname = UpdateTitleFilter;
	UpdateTitle(lister);
}

function UpdateTitle(lister)
//update title bar based on user changes to lister, layout, view, etc.
{
	tab = lister.activetab;
	cmd.SetSourceTab(tab);
	tabs = tab.right;
	
	//Determine layout type change and identify active display
	dual = lister.dual;
	
	if (dual == "1" && tabs == true)//check for dual vertical, active right display
	{
		activeDisplay = "Right"
	} else if (dual == "1" && tabs == false)//check for dual vertical, active left display
	{
		activeDisplay = "Left"	
	} else if (dual == "2" && tabs == true)//check for dual horizontal, active bottom display
	{
		activeDisplay = "Bottom"
	} else if (dual == "2" && tabs == false)//check for dual horizontal, active top display
	{
		activeDisplay = "Top"
	} else//if not dual vertical or horizontal, must be a single display
	{
		activeDisplay = "Display"
	}

	//Determine view mode status change
	viewMode = tab.format.view;
	viewMode = viewMode.substring(0,1).toUpperCase() + viewMode.substring(1);

	if (cmd.IsSet("VIEW=LargeIcons"))
	{
		viewMode = "Large Icons"
	} else if (cmd.IsSet("VIEW=SmallIcons"))
	{
		viewMode = "Small Icons"
	} else
	{
		viewMode = viewMode
	}
	
	if (cmd.IsSet("FLATVIEW=on,Grouped"))
	{
		viewMode += " (Flat-Grouped)"
	} else if (cmd.IsSet("FLATVIEW=on,Mixed"))
	{
		viewMode += " (Flat-Mixed)"
	} else if (cmd.IsSet("FLATVIEW=on,MixedNoFolders"))
	{
		viewMode += " (Flat-Mixed, No Folders)"
	} else if (cmd.IsSet("VIEW=Tiles"))
	{
		viewMode += "s"
	} else if ((cmd.IsSet("VIEW=Details")) && (cmd.IsSet("COLUMNSTOGGLE=thumbnail")))
	{
		viewMode += " + Thumbnails"
	} else
	{
		viewMode = viewMode
	}
	
	//Check for quickfilter status change
	quickFilterSet = tab.quickfilter.filter;
		
	if (quickFilterSet === '')
	{
		quickFilterFlag = "OFF"
	} else
	{
		quickFilterFlag = "[ " + quickFilterSet + " ]"
	}
	
	//Check for global filter status change
	if (filterSet == true)
	{
		globalFilterFlag = "ON"
	} else
	{
		globalFilterFlag = "OFF"
	}		
	
	//Determine if hide hidden files set to true
	if (cmd.IsSet("GLOBALHIDEHIDDEN=Toggle"))
	{
		hideHiddenFlag = "OFF"
	} else
	{
		hideHiddenFlag = "ON"
	}
	
	//Determine if hide system files set to true
	if (cmd.IsSet("HIDESYSTEMFILES=Toggle"))
	{
		hideSystemFlag = "OFF"
	} else
	{
		hideSystemFlag = "ON"
	}
	
	//Build Lister Title
	title = "notoggle:Directory Opus " + version + " Pro (64-bit)   |   LAYOUT:  %L   |   STYLE:  %S   |   ACTIVE:  " + activeDisplay + "   |   VIEW:  " + viewMode + "   |   FILTERS:  Q - " + quickFilterFlag + "   G - " + globalFilterFlag + "   H - " + hideHiddenFlag + "   S - " + hideSystemFlag
	
	var id = tab.path.def_value;
	var binid = DOpus.FSUtil.DisplayName(tab.path);
	if (tab.path.test_root == 0) //Check if at root drive  
	{
		if (id.substr(id.length - 1) == "\\")
		{
			title = title + "   |   FOLDER:  %R\\"; //Ensures root drive displayed properly
		} else
		{
			title = title + "   |   FOLDER:  %R";
		}
	} else
	{
		if (binid.substr(binid.length - 3) == "Bin")
		{
			title = title + "   |   FOLDER:  %R";
		} else
		{
		title = title + "   |   FOLDER:  %R\\...\\%N";
		}
	}		
	
	DOpus.Output(title);
	DOpus.Output(DOpus.FSUtil.DisplayName(tab.path));

	cmd.RunCommand('Set LISTERTITLE="' + title + '"');
}

//These functions update the lister title after specified events
function OnActivateTab(activateTabData)
{
	UpdateTitle(activateTabData.newtab.lister);
}

function OnSourceDestChange(sourceDestChangeData)
{
	UpdateTitle(sourceDestChangeData.tab.lister);
}

function OnAfterFolderChange(afterFolderChangeData)
{
	UpdateTitle(afterFolderChangeData.tab.lister);
}

function OnDisplayModeChange(displayModeChangeData)
{
	UpdateTitle(displayModeChangeData.tab.lister);
}

function OnFlatViewChange(flatViewChangeData)
{
	UpdateTitle(flatViewChangeData.tab.lister);
}

The script runs fine, regardless of the layout selected. However, it generates the following error when opening or switching to a single-pane layout:

Custom Title Bar: Error at line 229, position 2
Custom Title Bar: Invalid procedure call or argument (0x800a0005)

Line 229: var binid = DOpus.FSUtil.DisplayName(tab.path);

Any ideas how to revise the script to avoid this error?

Thanks in advance!

It's hard to guess what might be wrong with such a long script.

Have you tried adding some debugging to check what's in the variables you're using when the problem happens? e.g. What is in tab and tab.path when line 229 doesn't work?

Or have you tried simplifying things to the bare minimum to try to understand what's going wrong in that situation?

Those would be my first steps in working out why the error is happening.

This error very likely means that tab.path is empty. So you could just check for this and skip the instruction.

The underlying cause for this feels like a timing problem. Could it be that the skript gets called too often?

@Leo

Debugging returned expected values.

@lxp

Suspect you're right.

That said, tested by removing var binid and related code. Script still works as designed without issues. I will take a look at slimming the code down.

Thanks both of you for weighing in.

I am pretty sure it's a timing problem. Starting the UpdateTitle(lister) function with

DOpus.Delay(1000);

seems to work as a remedy.

Yes, not the most elegant fix :wink:

Even when the error occurs? If the path is empty or something else unusual then you should be able to see that via debugging. That or you'll get an error on the line outputting the debug info, which would be interesting and might point to a problem higher up the code.

The error occurred at this part of the code:

var id = tab.path.def_value;
var binid = DOpus.FSUtil.DisplayName(tab.path);

I checked the output as follows:

var id = tab.path.def_value;
DOpus.Output(id);
var binid = DOpus.FSUtil.DisplayName(tab.path); //line 230
DOpus.Output(binid);

The log returned this:

Custom Title Bar:  Error at line 230, position 2
Custom Title Bar:  Invalid procedure call or argument (0x800a0005)
Custom Title Bar:  C:\Users\Chuck\Pictures
Custom Title Bar:  C:\Users\Chuck\Pictures

I'm not smart enough on scripting to troubleshoot past that.

That said, it may be a timing thing as @lxp noted.

I tried running the script but I wasn't able to trigger this error. What's the exact steps required to get it to fail?

I can generate it on my system two ways:

  1. Open a single pane layout from the desktop via right-click menu to select saved single pane layout
  2. Switch from dual pane layout to single pane layout

Coming back to this issue, I now use a cut-down version of the script that still encountered the error when switching from a dual to single pane. I used a delay, as suggested by lxp, to resolve the issue. The error occurred at line 63. Here's the script for those interested:

function OnInit(initData)
{
	initData.name = "Title Bar";
	initData.version = "1.6";
	initData.copyright = "(c) 2021 cwfrizzell";
	initData.url = "https://resource.dopus.com/t/set-listertitle-to-include-file-display-view-mode/31991";
	initData.desc = "This script enables users to customize the Title Bar to reflect user-selected DOpus data.";
	initData.default_enable = true;
	initData.min_version = "12.25";
}

//Global Variables
var cmd = DOpus.create.command;
var version = DOpus.version.product;
var tab;

function OnOpenLister(OpenListerData)
{
	tab = OpenListerData.lister.activetab;
	cmd.SetSourceTab(tab);

	//Build Lister Title
	title = "notoggle:Directory Opus " + version + " Pro"
	
	var id = tab.path.def_value;
	if (tab.path.test_root == 0) //Check if at root drive  
	{
		if (id.substr(id.length - 1) == "\\")
		{
			title = title + "   |   %R\\"; //Ensures root drive displayed properly
		} else
		{
			title = title + "   |   %R";
		}
	} else
	{
		title = title + "   |   %R\\...\\%N";
	}
	
	DOpus.Output(title);

	cmd.RunCommand('Set LISTERTITLE="' + title + '"');
}

function UpdateTitleFilter(ScriptCommandData)
{
	//update title after quickfilter applied
	cmdname = UpdateTitleFilter;
	UpdateTitle(lister);
}

function UpdateTitle(lister)
//update title bar based on user changes to lister, layout, view, etc.
{
	DOpus.Delay(250);
	tab = lister.activetab;
	cmd.SetSourceTab(tab);

	//Build Lister Title
	title = "notoggle:Directory Opus " + version + " Pro"
	
	var id = tab.path.def_value;
	var binid = DOpus.FSUtil.DisplayName(tab.path);
	if (tab.path.test_root == 0) //Check if at root drive  
	{
		if (id.substr(id.length - 1) == "\\")
		{
			title = title + "   |   %R\\"; //Ensures root drive displayed properly
		} else
		{
			title = title + "   |   %R";
		}
	} else
	{
		if (binid.substr(binid.length - 3) == "Bin")
		{
			title = title + "   |   %R";
		} else
		{
		title = title + "   |   %R\\...\\%N";
		}
	}		
	
	DOpus.Output(title);
	DOpus.Output(DOpus.FSUtil.DisplayName(tab.path));

	cmd.RunCommand('Set LISTERTITLE="' + title + '"');
}

//These functions update the lister title after specified events
function OnActivateTab(activateTabData)
{
	UpdateTitle(activateTabData.newtab.lister);
}

function OnSourceDestChange(sourceDestChangeData)
{
	UpdateTitle(sourceDestChangeData.tab.lister);
}

function OnAfterFolderChange(afterFolderChangeData)
{
	UpdateTitle(afterFolderChangeData.tab.lister);
}

function OnDisplayModeChange(displayModeChangeData)
{
	UpdateTitle(displayModeChangeData.tab.lister);
}

function OnFlatViewChange(flatViewChangeData)
{
	UpdateTitle(flatViewChangeData.tab.lister);
}