Replace line breaks in PRE tags using RegEx in ASP/VBScript

This article discusses how to replace unnecessary line breaks (<br>, <br />) in HTML pre-formatted ‘PRE‘ tags using RegEx and ASP/VBScript.

The Problem

When I added a [code] tag to the HPC:Factor Community Forums markup some years ago. There was an obvious, but low-priority problem that had niggled at me. The BBS tag renders a pre-formatted ‘PRE‘ tag into the post HTML and styles it using a console font and fixed-size characters for improved legibility. The way that MegaBBS works however is that new lines (vbcrlf, vblf, \r\n, \n, chr(13) & chr(10), chr(10)) are replaced with ‘<br />‘ as a batch replace at the beginning of the forum sanitisation and rendering process.

This means that when the browser renders the <pre></pre> tag, it renders both the vblf and the <br />, leading to double line breaks.

For example

Dim i
i = 0
while (i < 1000)
  Response.Write i
  i = (i + 1)
loop

becomes

<pre><br />
Dim i<br />
i = 0<br />
while (i < 1000)<br />
  Response.Write i<br />
  i = (i + 1)<br />
loop<br />
</pre><br />

leading the browser to render

Dim i

i = 0

while (i < 1000)

Response.Write i

i = (i + 1)

loop

This wastes screen space and reduces legibility.

RegEx Fix

The solution is very simple, use RegEx to re-parse the [code] block after it has globally replaced the line breaks.

I added the following code at the bottom of the MBBS Code loop in the MBBSDecode function  in include.asp

if (vBBSDecodeArray(0, index) = "\[code\]") then	' This looks for the PRE tag for the code and then removes the <br />'s from it to return it to pure pre-formatted
	mBBSRegEx.pattern = "\<pre[^>]*\>((.|\n)*)\<\/pre\>"
	for each sNewText in mBBSRegEx.execute(MBBSDecode)
		MBBSDecode = Replace(MBBSDecode, sNewText.Value, (Replace(sNewText.Value, "<br />", "")))
	next
end if

To evaluate what this means line-by-line

  1. When it is parsing the [code] tag from the list of all BBS markup statements
  2. Set a RegEx pattern to search for the opening PRE tag with zero or more attributes e.g. <pre attribute1="one" attribute2="two"> ending with </pre>. The “((.|\n)*)” ensures that the search looks for all characters, including over new lines, for as many characters and new lines as is necessary to encounter the closing </pre> tag.
  3. For every positive match i.e. for every <pre>*</pre> match
  4.  In the matches string, replace <br /> with "", then replace the match in the original source string (MBBSDecode) with the fixed string
  5. Move to the next match until there are no more matches

 

To genericise the example

Dim strHtml
Dim match
Dim matches
Dim regEx

strHtml = "<body><p>hello</p><pre class="">line one" & vbcrlf & "<br />line two" & vbcrlf & "<br />line three" & vbcrlf & "<br /></pre><p>hello</p></body>"

set regEx = New RegExp
    regEx.Pattern = "\<pre[^>]*\>((.|\n)*)\<\/pre\>"
    regEx.IgnoreCase = true
    regEx.Global = true
set matches = regEx.Execute(strHtml)

For Each match in matches
    strHtml =  = Replace(strHtml, match.Value, (Replace(match.Value, "<br />", "")))
Next

' strHtml will now effectively be:
' "<body><p>hello</p><pre class="">line one" & vbcrlf & "line two" & vbcrlf & "line three" & vbcrlf & "</pre><p>hello</p></body>"

Fairly simple, but as with most things RegEx, a headache for most of us – unless you are using it all the time.

“TsManager.exe – Entry Point Not Found” error during MDT task sequence

This article discusses an error that you may receive performing a MDT Windows Client Upgrade Task Sequence. The error message “TsManager.exe – Entry Point Not Found” may halt, but not end your Task Sequence process or, my cause it to fail prematurely part-way through the task sequence.

Error Message Screenstor of TsManager.exe - Entry Point Not Found

TsManager.exe - Entry Point Not Found
The procedure entry point MDMIsExternallyManaged could not be located in the dynamic link library C:\WINDOWS\CCM\lsutilities.dll

Note: The above error is for “LSUtilities.dll” not “iSUtilities.dll”

The name of the entry point stated in the error may differ depending on

  1. The stage in the MDT Task Sequence where the error occurs
  2. The version of the SCCM Client installed on the computer. The above error is from SCCM Client version 5.00.8790.1025 (SCCM 1902 Update 1) at the end of the Post-Processing phase of the Task Sequence

 

More Info

“TsManager.exe – Entry Point Not Found” is caused by a mismatch between the MDT integration with SCCM and the SCCM Client LSUtilities.dll – which provides Location Services for the SCCM Client.

Microsoft have made the assumption that if you are using the SCCM client and MDT, that MDT has been integrated into SCCM. If you are running a stand-alone MDT LTI build process, you may encounter this problem. The issues occur because MDT integration modifies MDT to work with the task sequence and the SCCM client. Without the integration, the SCCM client’s MDT hooks still fire, but cannot function due to MDT not having been upgraded.

 

Check the Client Version

Ensure that the SCCM Client version you are deploying is an approximate match to the version to the one in General Availability at the time the MDT build was released.

For example, MDT version 8456 was released 25th January 2019. By using the SystemCentreDudes SCCM Client Version list, you can see that the active release of SCCM in January 2019 would have been SCCM 1810. Consequently you should ensure that the SCCM Client version deployed on the system/via the MDT Task Sequence is is a SCCM 1810 release.

This means that you should avoid using the SCCM 1902 client with a stand-alone MDT 8456 build server.

Ensuring client version parity will not prevent all Entry Point errors, however it will minimise the possible range of errors that can be encountered by the Client/MDT. SCCM will self-update the client to the current version as part of its client servicing activities post-install.

View: SystemCentreDudes “SCCM Version Numbers and Cumulative Update List”

 

Preventing an irrecoverable failure of the task sequence

You must uninstall the SCCM client from the workstation before the operating system upgrade commences. You can automate this as part of your task sequence. The only requirement is for it to have been uninstalled before the first reboot of the system by MDT.

  1. Open the “Task Sequence” tab in the properties of you Task Sequence
  2. In the “Preparation” section, after “Validate” add a new “Run Command Line”
  3. Name the task:
    Uninstall SCCM Client
  4. Enter the Command Line:
    cmd.exe /c ""C:\Windows\ccmsetup\ccmsetup.exe" /uninstall & RD /S /Q "C:\Windows\ccmsetup" & RD /S /Q "C:\Windows\CCM""

The first part of the command shuts down all SCCM client services and performs the uninstall:

"C:\Windows\ccmsetup\ccmsetup.exe" /uninstall

The second part of the command deletes the “C:\Windows\CCM” folder, ensuring that LSUtilities.dll cannot be present during the imaging process.

Note: Deleting this folder will delete all historic log data associated with the client.

 

Reinstall the SCCM Client

To reverse the removal and restore the SCCM client, you must introduce its re-installation later in the task sequence. To reinstall the SCCM Client add the SCCM client setup as a new application in the Applications section of your Deployment Share. The following example is for the SCCM 1902 client.

MDT Application Definition for SCCM ClientMDT Application SCCM Client Install Command

Note: Do not select “Reboot the computer after installing this application”. Doing so will force the SCCM client to interact with MDT.

An example of the install command would be:

ccmsetup.exe /service /mp:<management point FQDN> /forceinstall SMSSITECODE=<site code> DNSSUFFIX=<domain suffix> FSP=<server> SMSMP=<server FQDN>

Return to the Task Sequence tab in the properties of the task sequence.

Create an “Install Application” task as late as possible in the “Post-Processing” section of the Task Sequence. Select a single application and browse for the newly created SCCM Client package.

Note: Avoid running additional tasks after the reinstallation of the client as you increase the risk of experiencing an associated fault once the system has restarted.

Windows 10 Search not working after performing an in-place upgrade

This article discusses a fix for the Windows Search bar / Cortana not working after an in-place Windows 10 upgrade.

The Problem

Upgraded Windows 10 to find Windows Search Not Working? The symptoms may include:

  1. Clicking on the search bar in the task bar does not launch the search user interface pop-up
  2. Opening the Start menu and immediately typing does not launch the search user interface
  3. When you click on the search bar in the task bar, Cortana momentarily appears on the ‘Apps’ tab in Task Manager and then exists
  4. Clicking on the search bar causes SearchUI.exe to launch on the Details tab in Task Manager and then immediately exit
  5. The search bar on the taskbar flickers, flashes on and off or even vanishes completely; leaving a display artefact.
  6. The Events Viewer > Application log records the following event under Event ID 1000:
Faulting application name: SearchUI.exe, version 10.0.18362.1, time stamp: 0x5c90179d
Faulting module name: SearchUI.exe, version 10.0.18362.1, time stamp: 0x5c90179d
Exception code: 0xc000027b
Fault offset: 0x000000000015bf3e
Faulting process ID: 0xb50
Faulting application start time: 0x01d5229682a57780
Faulting application path: C:\Windows\SystemApps\Microsoft.Windows.Cortana_cw5n1h2txyewy\SearchUI.exe

In my case, the upgrade was from Windows 10 1703 to Windows 10 1903 and the user account was a Roaming profile (local profiles were all fine).

Am I the only person who is beyond fed-up with this nonsense? I digress…

Yes, no doubt you are equally frustrated with seeing Microsoft supports unhelpful and generic “run DISM’s Restore Health command followed by running SFC.exe /ScanNow[1]. Microsoft Product Support are just ignoring the problem and trying to encourage people for format the system by means of finding a zero-effort fix. This attitude helps no one.

The Windows shell is a mess. The Windows Modern App paradigm – while improved on 2015 – is still not in a fit state to be able to replace Win32. With these kinds of issues, is it any wonder that even in 2019 no one is writing Modern Apps? Microsoft themselves were forced to acknowledge this. Microsoft’s one success to encourage the use of Modern Apps has been to create a Win32 wrapper. Allowing Win32 programs to be released via the Windows Store. It says it all doesn’t it?

The Fix

As the search bar works fine for local users, the issue had to be profile, not system level (for anyone paying attention this rules out SFC /ScanNow and DISM).

Event Viewer tells us the application version involved as being “Microsoft.Windows.Cortana_cw5n1h2txyewy”. For a test user this happens to map within their profile to:

C:\Users\<username>\AppData\Local\Packages\Microsoft.Windows.Cortana_cw5n1h2txyewy

I then proceeded to delete data from within the directory until search worked. The culprit was the contents of the Settings folder. Clearly between version 1703 and 1903, Microsoft have changed a lot here. There has not been any settings migration through Windows Store auto-update as “Cortana” (Windows Search) is only upgraded during feature updates.

 

Automating the Fix

If you are experiencing the same problem. I have put together the following PowerShell scripts to solve the issue on both a per-user and per-system basis. The script does the following

  1. Searches for all Settings folders present beneath any version of Cortana on the system
  2. Attempts to kill the SearchUI process, if present
  3. Deletes the contents of the Settings folder and the Settings folder itself

The SearchUI process/deleted data will be restored the next time the search bar is clicked.

 

For the currently logged on user

$settings = dir $env:UserProfile\AppData\Local\Packages\Microsoft.Windows.Cortana*\Settings
$settings | % {Stop-Process -Name 'SearchUI' -Force; Remove-Item $_.FullName -Recurse -Force}

 

For a named user profile

$profile = ‘joe.bloggs’

$settings = dir C:\Users\$profile\AppData\Local\Packages\Microsoft.Windows.Cortana*\Settings
$settings | % {Stop-Process -Name 'SearchUI' -Force; Remove-Item $_.FullName -Recurse -Force}

 

For all users on the system

$settings = dir C:\Users\*\AppData\Local\Packages\Microsoft.Windows.Cortana*\Settings
$settings | % {Stop-Process -Name 'SearchUI' -Force; Remove-Item $_.FullName -Recurse -Force}

 

Things to note

Working search bars will have file locks on the Setting folder. If you do not wish to see file lock errors messages use:

Remove-Item $_.FullName -Recurse -Force -ErrorAction SilentlyContinue.

 

Deployment Options

Your options for deployment of the script(s) are:

  1. Inject the script into a HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce entry for the system
  2. Inject the script into a HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce entry for the user
  3. Process the script as part of a logon script
  4. Use SCCM to deploy the script as a SCCM Package to the system/user
  5. Fire the script as a one-off/recurring Task Scheduler script via Group Policy
  6. Execute the script at the end of your MDT upgrade task sequence

Netgear Switch 1Gbps port at 100Mbps, goes up and down several times before settling at 100Mbps

This article discusses a problem in which jacking cables on a switch cause two or more ports to drop in and out of a shutdown / no shutdown sequence. After a few moments of going up/down, one or both of the ports will settle at a low speed (e.g. 1Gbps port at 100Mbps).

After adding new cabling to a LAG group, I experienced an intermittent fault in which one (or occasionally both) of the new cables would drop down to 100Mbps. If I removed the relevant keystone modules from the patch panel, the problem would cease.

 

Troubleshooting 1Gbps port at 100Mbps

Firstly, you should test the cable ensuring that all 8 pairs are up and in the correct sequence. A network tester should be used to do this.

If you used a punch tool during the install. Use a watchmakers screwdriver or the flat headed probe/shim on your punch tool to ensure that each wire in each pair is correctly and firmly seated. Ensure that there are no arched cables across the termination pins.

The most likely cause of a fault like this is a patch panel short. On a keystone patch panel, the keystone modules sit very close together. If the exposed copper ends of one keystone module touch the copper of a neighbour, the electrical circuit will short.

Data intended for one network port will be (poorly) transmitted down another one, causing signal corruption. The switch will attempt to respond by disabling pairs until it can get a clean signal. In the case of a 1Gbps Ethernet connection, it will disable 4 pairs, rendering the port 100Mbps. If there is still a short, it will fail to 10Mbps or shutdown the port.

A simple check for an electrical short is to place something non conductive – for example paper or electrical insulation tape – between the two keystone modules.

Photo of patch panel
Insert something non-conductive between the two patch panel keystones to check for an electrical short

The switch port will not automatically recover from an electrical short. You must jack/un-jack or sh/no sh the port to force speed renegotiation to occur.

If the insulator corrects the problem use some clippers to better trim the excess copper from the keystone, or leave the insulation in place permanently.