Deleting a single entry in a REG_MULTI_SZ value

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
 
M

Mark V

Ritchie wrote in
Robert Strom said:
So sorry for the LONG post, but couldn't describe the situation
without all the details.

To delete the "QIP DHCP Server" value, create a .reg file
containing the three line below:-

REGEDIT4

[HKEY_CURRENT_USER\Software\Lucent Technologies, Inc.\Services
Controller] "QIP DHCP Server"=-

Then apply it with this commandline:-

regedit /s yourfile.reg

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.

There is another thread of the same name in ...win2000.registry
 
T

Torgeir Bakken (MVP)

Robert said:
I'm trying to delete one entry from a REG_MULTI_SZ registry entry.

Hi

Not exactly command line, but 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
 
R

Robert Strom

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
 
R

Ritchie

Mark V said:
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".
 
T

Torgeir Bakken (MVP)

Robert said:
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 :-(

Hi

Well, you posted in a Win2000 group, and didn't mention NT4, so I didn't take
this into consideration ;-)
 
M

Mark V

Ritchie wrote in
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".

! I just knew someone would take the time to work it out in batch.
Except, he's on NT4... FOR does or doesn't there?

And in another post he implies _no_ tools not shipped (like reg.exe v
2 on NT4). If that restricition, ... I'm stumped.
 
R

Ritchie

Mark V said:
! I just knew someone would take the time to work it out in batch.
Except, he's on NT4... FOR does or doesn't there?

It does when I use it! Are you referring to the comparison operators
and delims bugs? If so, they're easily circumvented.

Anyway, I tested it on both NT4 and 2000.
And in another post he implies _no_ tools not shipped (like reg.exe v
2 on NT4). If that restricition, ... I'm stumped.

I wonder why he's already using REGDMP? Thats multi-posters for ya.

BTW, its quite possible to do using ONLY built-in tools. If he pays me,
I'll post a script for NT4/2000.
 
M

Mark V

Ritchie wrote in
It does when I use it! Are you referring to the comparison
operators and delims bugs? If so, they're easily circumvented.

Anyway, I tested it on both NT4 and 2000.


I wonder why he's already using REGDMP? Thats multi-posters for
ya.

BTW, its quite possible to do using ONLY built-in tools. If he
pays me, I'll post a script for NT4/2000.


Could not recall the limitations in NT4... been awhile and only W2K
here now. He has (my mistake) already used reg.exe (alone) on the
system.

I think your solution will solve it for the OP (and in fewer lines
than a REXX script I was playing with!) Nice work.
 
R

Robert Strom

Ritchie,

I applaud you on your creativity, but I'm sorry to report that it doesn't
quite work. Close, but not quite.

Here's what I get when I do a reg query prior to running the script

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

C:\DHCPup>reg query "HKCU\Software\Lucent Technologies, Inc.\Services
Controller
"

! REG.EXE VERSION 2.0

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

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Here's what I get after running the script

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

C:\DHCPup>reg query "HKCU\Software\Lucent Technologies, Inc.\Services
Controller
"

! REG.EXE VERSION 2.0

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

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Note that the "VitalQIP Active" portion of the "VitalQIP Active Lease
Service" is missing from the first ServiceName value. That's a BAD thing :-(

I've been playing with the script trying to get it to work, but I'm not
getting any closer. I'm trying to understand exactly what you're doing in
these two lines

set "d=%d:QIP DHCP Server\0=%"
set "d=%d:\0\0=%"

I know that %d% is supposed to be previously set to equal all of the
ServiceName registry values. I'm trying to figure out exactly what is going
on after this. I see what the end results are, I'm just trying to follow how
you're getting rid of the "QIP DHCP Server" value and not setting %d% to QIP
DHCP Server\0 ?

I'll keep playing and looking for the answer to my question. If you are
inclined to explain and have a solution I'd very much appreciate it.

Thanks,

Robert
 
R

Robert Strom

I don't think, I may be wrong, that I said NO tools. I believe that I said
minimum dependencies. REG.EXE is a simple command line tool which doesn't
seem to have any nasty DLL dependencies. I can include it with the script
distribution, dump it in the same temp dir as the script and it will work
great.

Thanks,

Robert
 
R

Robert Strom

Sorry,

Didn't mean to be misleading. I faulted by not considering that a solution
that would be provided would be NT OS dependent.

Thanks,

Robert
 
M

Mark V

Robert Strom wrote in
Ritchie,

I applaud you on your creativity, but I'm sorry to report that it
doesn't quite work. Close, but not quite.

Here's what I get when I do a reg query prior to running the
script

Not Richie but I see
Error: Invalid command-line parameters
returned from reg.exe v 2.0. I'll try to find out why...

[ ]
 
M

Mark V

Mark V wrote in
Robert Strom wrote in

Not Richie but I see
Error: Invalid command-line parameters
returned from reg.exe v 2.0. I'll try to find out why...

The last "\0" chokes reg add it would appear. That can be stripped
off, but something more is odd. Still looking.
 
R

Ritchie

Works under 2000, but not NT eh? It's that pesky NT delims bug:

@echo off & setlocal ENABLEEXTENSIONS
set k="HKCU\Software\Lucent Technologies, Inc.\Services Controller"

for %%v in ("ServiceName" "DisplayName") do call :Doit %%v
goto :EOF

:Doit
:: YOU MUST EDIT THE DELIMS STATEMENT. IT SHOULD BE delims=<TAB><SPACE>
for /f "tokens=2* delims= " %%a in ('reg query %k% /v %1') do (
set "d=%%b"
)
set "d=%d:QIP DHCP Server\0=%"
set "d=%d:\0\0=%"
reg add %k% /v %1 /t REG_MULTI_SZ /d "%d%" /f
goto :EOF
 
R

Ritchie

Ritchie said:
:: YOU MUST EDIT THE DELIMS STATEMENT. IT SHOULD BE delims=<TAB><SPACE>

And to do it without a TAB in sight:-

01. @echo off & setlocal ENABLEEXTENSIONS
02. set k="HKCU\Software\Lucent Technologies, Inc.\Services Controller"
03.
04. for %%v in ("ServiceName" "DisplayName") do call :Doit %%v
05. goto :EOF
06.
07. :Doit
08. for /f "delims=" %%a in ('reg query %k% /v %1') do set "d=%%a"
09. set "d=%d: =¬%"
10. for %%a in (%d%) do set d=%%a
11. set "d=%d:¬= %"
12. set "d=%d:QIP DHCP Server\0=%"
13. set "d=%d:\0\0=%"
14. reg add %k% /v %1 /t REG_MULTI_SZ /d "%d%" /f
15. goto :EOF
 
M

Mark V

Mark V wrote in
Mark V wrote in news:[email protected]: [ ]
Not Richie but I see
Error: Invalid command-line parameters
returned from reg.exe v 2.0. I'll try to find out why...

The last "\0" chokes reg add it would appear. That can be

Stripping "\0\0" tends to leave a trailing "\0" that chokes reg.exe so
using "\0\0\0" looks good. However in the case where the target string
happened to match all components of the multi-string this would leave
the string to write as "\0\0" which will Error reg.exe. This seems to
be a fairly low probability. And you can/should Errorlevel test
reg.exe add

So (if I am correct of course) change the line:
set "d=%d:\0\0=%"
to
set "d=%d:\0\0\0=%"
and try it again.

This seems to be working for "ServiceName" and "DisplayName" here on
W2k with reg.exe v. 2.0. I am concerned that a commandline
length limitation could come into the picture at some point. My
tests done on W2K and with a shorter registry path (HKEY_CURRENT_USER
\_TEST\Services Controller\).


-----------
As to the usage of SET options, it can be difficult to get a
conceptual handle on it just from the syntax listed with SET /?
You should do some tests and observe the results.

This is my description. Others may state it better.
set "d=%d:QIP DHCP Server\0=%"
This is a "search and remove" method. IOW look for exact string "QIP
DHCP Server\0" in the data stored in %d% and remove it, storing the
revised data in %d%. Any single or multiple exact-string matches
removed.
 
R

Robert Strom

Ritchie,

Awesome job!!

It worked fantastically. I've never seen the SET command used like this. I
put echo's for the variables and pauses into the script so I could see what
was happening during the execution. I see what's going on and basically
understand, now I just need to figure out exactly what the set commands
you're using are doing (I'm not finding anything that looks like it
describes what you're doing when I execute SET /? or look at SET.EXE in the
WinXP help).

Can you point me to somewhere that has descriptions of what you're doing
here?

One last thing ... what the heck is the character in this command that you
used twice?
09. set "d=%d: =¬%"
11. set "d=%d:¬= %"


Thanks TONS!!

Robert
 
R

Robert Strom

Ritchie,

The script works great. Thanks VERY much for your time and efforts!!!

Robert Strom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top