Deleting a single entry in a REG_MULTI_SZ value

  • Thread starter Thread starter Robert Strom
  • Start date Start date
R

Robert Strom

So sorry for the LONG post, but couldn't describe the situation without all
the details.

Here's the issue (hopefully this all makes sense)

I'm trying to delete one entry from a REG_MULTI_SZ registry entry. Here is a
sample REGDMP of the registry key:

BEGIN REGDMP
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

C:\temp>REGDMP.EXE "HKEY_CURRENT_USER\Software\Lucent Technologies,
Inc.\Services Controller"

HKEY_CURRENT_USER\Software\Lucent Technologies, Inc.\Services Controller
DisplayName = REG_MULTI_SZ "VitalQIP Active Lease Service" \
"VitalQIP Message Service" \
"VitalQIP Remote Service" \
"QIP DHCP Server" \
"QIP DomainNameService"
ServiceName = REG_MULTI_SZ "VitalQIP Active Lease Service" \
"VitalQIP Message Service" \
"VitalQIP Remote Service" \
"QIP DHCP Server" \
"QIP DomainNameService"
Editor =

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
END REGDMP


I came up with this solution and it worked on some systems but not others
(using findstr /v to remove the line that I didn't want).


BEGIN REGDMP 2
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

C:\temp>REGDMP.EXE "HKEY_CURRENT_USER\Software\Lucent Technologies,
Inc.\Services Controller" | findstr /v /c:"QIP DHCP Server"

HKEY_CURRENT_USER\Software\Lucent Technologies, Inc.\Services Controller
DisplayName = REG_MULTI_SZ "VitalQIP Active Lease Service" \
"VitalQIP Message Service" \
"VitalQIP Remote Service" \
"QIP DomainNameService"
ServiceName = REG_MULTI_SZ "VitalQIP Active Lease Service" \
"VitalQIP Message Service" \
"VitalQIP Remote Service" \
"QIP DomainNameService"
Editor =

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
END REGDMP 2


I redirected the results to a text file, then deleted the registry key using
REG DELETE, then imported the REGDMP text file using REGINI. This all worked
great until you come across a machine where the original registry REGDMP
looks like this


BEGIN REGDMP 3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

C:\temp\Dhcpup>REGDMP.EXE "HKEY_CURRENT_USER\Software\Lucent Technologies,
Inc.\Services Controller"

HKEY_CURRENT_USER\Software\Lucent Technologies, Inc.\Services Controller
DisplayName = REG_MULTI_SZ "QIP DHCP Server" \
"QIP DomainNameService" \
"VitalQIP Active Lease Service" \
"VitalQIP Message Service" \
"VitalQIP Remote Service"
ServiceName = REG_MULTI_SZ "QIP DHCP Server" \
"QIP DomainNameService" \
"VitalQIP Active Lease Service" \
"VitalQIP Message Service" \
"VitalQIP Remote Service"
Editor =

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
END REGDMP 3


As you can see the QIP DHCP Server entry is on located on the key lines of
the REGDMP file which specify the registry entry value. Once this line is
deleted the REGDMP file is trash ... here's what it looks like


BEGIN REGDMP 4
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

C:\temp\Dhcpup>REGDMP.EXE "HKEY_CURRENT_USER\Software\Lucent Technologies,
Inc.\Services Controller" | findstr /v /c:"QIP DHCP Server"

HKEY_CURRENT_USER\Software\Lucent Technologies, Inc.\Services Controller
"QIP DomainNameService" \
"VitalQIP Active Lease Service" \
"VitalQIP Message Service" \
"VitalQIP Remote Service"
"QIP DomainNameService" \
"VitalQIP Active Lease Service" \
"VitalQIP Message Service" \
"VitalQIP Remote Service"
Editor =

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
END REGDMP 4


So, on some machines it works just fine, and on others it fails miserably.
It all depends on what order the entries are placed in the registry
(obviously it isn't consistent for some reason).

Now faced with the fact that the REGDMP / findstr method isn't fool proof, I
thought that there may be a way to use an .inf file to delete a single entry
from a REG_MULTI_SZ value (since I knew that you could append REG_MULTI-SZ
entries with an INF file). I've played with this and have not been
successful in doing anything but deleting the entire value.


Then I found this:

INF DelReg Directive
http://msdn.microsoft.com/library/d.../en-us/install/hh/install/inf-format_21de.asp

Clip from the MSDN page ......

flags

(Windows XP and later.) This optional hexadecimal value, expressed as an
ORed bitmask of system-defined low word and high word flag values, defines
the data type for a value entry, or controls the delete-registry operation.
If flags is not specified, the value-entry-name (if specified) or subkey
will be deleted.

Bitmask values for each of these flags are as follows:

0x00002000 (FLG_DELREG_KEYONLY_COMMON)
Delete the entire subkey.

0x00004000 (FLG_DELREG_32BITKEY)
Make the specified change in the 32-bit registry. If not specified, the
change is made to the native registry.

0x00018002 (FLG_DELREG_MULTI_SZ_DELSTRING)
Within a multistring registry entry, delete all strings matching a string
value specified by value. Case is ignored.


With this information I was able to create an INF file which removed just
the entry I desired from the REG_MULTI_SZ entry, leaving the remaining
entries as desired.


Unfortunately, as stated in the MSDN doc, this will only work on WinXP and
higher. On Win2k the entire registry value is deleted.


Has anyone out there been able to delete a single REG_MULTI_SZ value, while
preserving all of the existing values? Looking for any and all methods that
you might have devised.

Anyone interested in seeing the INF files which append to REG_MULTI_SZ and
delete from REG_MULTI_SZ values just drop me an e-mail and I'll send them to
you.

TIA,

Robert Strom
robert_strom at cox dot net
 
Robert Strom wrote in
So sorry for the LONG post, but couldn't describe the situation
without all the details.

Here's the issue (hopefully this all makes sense)

I'm trying to delete one entry from a REG_MULTI_SZ registry entry.
Here is a sample REGDMP of the registry key:
[ ]

Has anyone out there been able to delete a single REG_MULTI_SZ
value, while preserving all of the existing values? Looking for
any and all methods that you might have devised.

I've never yet had to do that from a command-line. If I did I'd
likely approach it by exporting to REGEDIT4 format then process the
..REG file with a scripting language. REXX in my case. Search and
delete on a given substring in the comma-separated decimal values.
Case might be rather bothersome. Or better, output from reg.exe
query (text) then process and re-add with reg.exe add after a
reg.exe del of the valuename... Curious to see other scripted
solutions.
 
How about creating the ideal config on one workstation, export that reg file
(deleting any keys you don't want to overwrite)
import the new reg file into the machines you want to change. The new values
will overwrite the old.
 
That would be a piece of cake if you could always count on only certain
specific entries, that no additional and no fewer entries would ever exist
in the key. When it comes to RE_MULTI_SZ entries one can never assume this.

So, one must make sure to either only delete the entry, or entries, that
needs to be deleted, or capture all entries that exist, get rid of the one
that you don't want, delete the key, and re-import the remaining entries.

That is the trick with REG_MULTI_SZ entries. Obviously Microsoft realized
that they needed to provide a reasonable way to do this otherwise they would
not have made it possible by using the INF DelReg Directive. Unfortunately
this function only works on WinXP and higher.

Hope this explains the situation a bit more.

Robert Strom
 
Mark V wrote in
Robert Strom wrote in news:#[email protected]: [ ]
Has anyone out there been able to delete a single REG_MULTI_SZ
value, while preserving all of the existing values? Looking for
any and all methods that you might have devised.

I've never yet had to do that from a command-line. If I did I'd
likely approach it by exporting to REGEDIT4 format then process the
.REG file with a scripting language. REXX in my case. Search and
delete on a given substring in the comma-separated decimal values.
Case might be rather bothersome. Or better, output from reg.exe
query (text) then process and re-add with reg.exe add after a
reg.exe del of the valuename... Curious to see other scripted
solutions.

Did a demo script. Works fine. Not a "packaged" solution though.
 
Robert said:
I'm trying to delete one entry from a REG_MULTI_SZ registry entry.

Hi

It is easily done with VBScript/WMI:


Const HKCU = &H80000001
sComputer = "."
Set oReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" _
& sComputer & "\root\default:StdRegProv")

sKeyPath = "Software\Lucent Technologies, Inc.\Services Controller"

RemoveQIPDHCPServerLine("DisplayName")
RemoveQIPDHCPServerLine("ServiceName")


Sub RemoveQIPDHCPServerLine(sValueName)

iRC = oReg.GetMultiStringValue(HKCU, sKeyPath, sValueName, aValues)

If iRC <> 0 Then
' registry value not found
Exit Sub ' ------------>
End If

bWriteValue = False
i = 0

For Each sValue In aValues
If sValue = "QIP DHCP Server" Then
bWriteValue = True
Else
ReDim Preserve aNewValues(i)
aNewValues(i) = sValue
i = i + 1
End If
Next

If bWriteValue Then
oReg.SetMultiStringValue HKCU, sKeyPath, sValueName, aNewValues
End If

End Sub


References:

Script Center - Registry
http://www.microsoft.com/technet/scriptcenter/registry/default.asp


WMI Class StdRegProv (Standard Registry Provider):
http://msdn.microsoft.com/library/en-us/wmisdk/wmi/stdregprov.asp
 
Torgeir Bakken (MVP) wrote in
Hi

It is easily done with VBScript/WMI:

[ ]

Not up on VBScript/WMI. Is
If sValue = "QIP DHCP Server" Then
case sensitive?
I presume it is and the OP may have exact known strings only to deal
with of course.

[ ]
 
Mark said:
Torgeir Bakken (MVP) wrote in news:[email protected]:


Not up on VBScript/WMI. Is
If sValue = "QIP DHCP Server" Then
case sensitive?
I presume it is and the OP may have exact known strings only to deal
with of course.

Hi

Yes, 'If sValue = "QIP DHCP Server" Then' is case sensitive.

I assumed that the OP had an exact string, based on his registry dump and his
findstr line in the batch file (findstr /v /c:"QIP DHCP Server").

An case insensitive version would be

If LCase(sValue) = "qip dhcp server" Then
 
Torgeir,

Thanks for the code, I've been trying to learn more about VBS and WMI. This
works great in Win2k, but does not work in WinNT :-(

The reason that I was going for a command line / shell solution was that I
wanted it to be sure and work across all versions of NT and have the
absolute least amount of possible dependencies. From what I've read this
could probably be done on NT if the core WMI components are installed.
Obviously these were not installed on my test WinNT system and I can't rely
on them being installed in the field.

Any further command line ideas?

Thanks,

Robert
 
Robert Strom wrote in
Torgeir,

Thanks for the code, I've been trying to learn more about VBS and
WMI. This works great in Win2k, but does not work in WinNT :-(

The reason that I was going for a command line / shell solution
was that I wanted it to be sure and work across all versions of NT
and have the absolute least amount of possible dependencies. From
what I've read this could probably be done on NT if the core WMI
components are installed. Obviously these were not installed on my
test WinNT system and I can't rely on them being installed in the
field.

Any further command line ideas?

Only as stated earlier. A scripted solution that may or may not
require something to be installed (eg: WinMgmt/WMI) or present (eg:
rexx.exe and reg.exe) for example. Or perhaps a compiled program
utilizing Win32 APIs. I (just personally) can't think of any native
commands solution across OSs. (Doesn't mean there isn't one of
course).

I don't think NT's FOR command is capable enough to do a "parsing"
operation on the output line from regedit /e. I could be wrong. I
think it would be messy if even possible.
 
REG.EXE doesn't work - I've tried every iteration of REG DELETE that I could
think of.

REGEDIT gives you a HEX dump of the REG_MULTI_SZ

Neither of these seem to be the solution.

Thanks,

Robert
 
Robert said:
REG.EXE doesn't work - I've tried every iteration of REG DELETE that I could
think of.

REGEDIT gives you a HEX dump of the REG_MULTI_SZ

Neither of these seem to be the solution.

Hi

It looks like Ritchie posted a solution for NT4/2000+ in your other thread in
the microsoft.public.win2000.cmdprompt.admin group (as long as you use REG.EXE
version 2.0):


From: "Ritchie" <[email protected]>
Newsgroups: microsoft.public.win2000.cmdprompt.admin
Subject: Re: Deleting a single entry in a REG_MULTI_SZ value
Date: Wed, 24 Sep 2003 08:36:04 +0100
Message-ID: <[email protected]>

He doesn't want to delete a valuename/data, but rather a nul-
terminated string in the multi-string data of a REG_MULTI_SZ
valuename as I understand it.

Oops, I see what you mean.

Here's a solution for NT4/2000+

@echo off & setlocal ENABLEEXTENSIONS
set k="HKCU\Software\Lucent Technologies, Inc.\Services Controller"
set v="ServiceName"
for /f "tokens=2*" %%a in ('reg query %k% /v %v%') do (
set "d=%%b"
)
set "d=%d:QIP DHCP Server\0=%"
set "d=%d:\0\0=%"
reg add %k% /v %v% /t REG_MULTI_SZ /d "%d%" /f

You must use REG.EXE version 2.0 (not version 1.0). Just repeat it for
"DisplayName".
 
Robert Strom wrote in
REG.EXE doesn't work - I've tried every iteration of REG DELETE
that I could think of.

Not alone.
Use reg's output (text) which is manipulated externally and then
written back with reg.exe again. Look/try "Richie"'s batch file
solution. If that will work, you're in.
REGEDIT gives you a HEX dump of the REG_MULTI_SZ'

That too could be processed by script. It's just another string of
comma-separated decimal values once you export it. But would be
harder than dealing with the TEXT output of reg.exe though.
 
Robert Strom wrote in
So sorry for the LONG post, but couldn't describe the situation
without all the details.

Just FYI to readers.
This issue was resolved in a Batch and using reg.exe

See "Deleting a single entry in a REG_MULTI_SZ value"
In microsoft.public.win2000.commandprompt.admin
Thread started 2003 SEP 20
 
Back
Top