2

我试过问这个,但我觉得有些混乱,所以我要试试这个新鲜的。这是代码:

set regVar=HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
set excluded=Microsoft MDOP Dell 
set count=0
for /f "tokens=2,*" %%a in ('Reg Query %regVar% /S^|find " DisplayName" ^| findstr /v "%excluded%"') do (
    set /a count+=1
    setlocal EnableDelayedExpansion
    for %%n in (!count!) do (
        endlocal
        set product[%%n]=%%b
        echo  %%n.%tab%%%b
        echo  %%a
    )   
)

这样做是遍历所有卸载注册表,然后将每个 DisplayName 键添加到名为 product[] 的数组中,然后将其在循环中的当前编号的结果打印到屏幕上以获取菜单。然后你可以做的是输入数字,它会返回该数组中的显示名称:

因此,就目前而言,它过滤掉了所有 microsoft、mdop 和 dell

我想要它做的是还查看那个 DisplayName 的键并返回另一个名为 UninstallString 的键,并将其分配给具有相同关联索引的数组 uninstallprod[]。我遇到的问题是我无法弄清楚如何使用 sql 中的语句进行查询

Select UninstallString from REGISTRY where DisplayName="Program name"

程序名称是从您选择的 DisplayName 返回的字符串,或者有一个 SINGLE 查询,这将允许我像您在上面看到的那样过滤掉 DisplayNames,并在同一语句中包含 UninstallString 值。以任何其他方式尝试它的问题是我无法过滤并执行两个数组而没有它以完全错误的索引结束(它会跳过显示名称但仍然分配卸载字符串,因为它不允许我过滤两者)

更新:

在这一点上,我让它拉回了 DisplayName 和 Uninstall 字符串,但它没有正确推进计数器。在当前状态下,它分配了 2 个变量,用于分配和比较键是什么的键的名称 (%%a),以及作为程序名称的键的值 (%%c)或稍后在脚本中用于卸载的卸载路径(字符串)。所以最终发生的事情是我最终得到了一个跳过的数字列表,因为即使没有显示名称被打印到列表中,计数器也在前进。这是我现在正在使用的代码。

@echo off
set tab=    
set regVar=HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
set excluded=Microsoft MDOP Dell 
set count=1
for /f "tokens=1,2,*" %%a in ('Reg Query %regVar% /S^|findstr "DisplayName UninstallString" ^| findstr /v "%excluded%"') do (
    setlocal EnableDelayedExpansion
    for %%n in (!count!) do (
        endlocal
        if "%%a"=="DisplayName" set product[%%n]=%%c&echo %%n.%tab%%%c
        if "%%a"=="UninstallString" if defined product[%%n] set uninstall[%%n]==%%c&set/a count+=1
    )
)

举个例子,我的列表中有 Sublime Text 2.0.1 和 64 位 HP CIO Components Installer。最终发生的是我得到一个这样的列表:

1.  Sublime Text 2.0.1
3.  64 bit HP CIO Components Installer

因此,由于某种原因,即使没有定义产品 [2],计数器也会超过 2。在 32 位版本中,我显示了 5 个条目,其中一个是空白的,打印如下:

1.  Adobe Flash Player 11 ActiveX
2.  Google Chrome
3.  TeamViewer 8
4.  
4.  Google Update Helper.
4

1 回答 1

2

你需要让“UninstallString”和“Displayname”都通过初始门,所以改变

for /f "tokens=2,*" %%a in ('Reg Query %regVar% /S^|find " DisplayName" "...

for /f "tokens=1,2,*" %%a in ('Reg Query %regVar% /S^|FINDSTR "Displayname UninstallString"...

这将设置%%aDisplaynameUninstallString%%c所需的数据值。

那么你必须处理序列

显示名称 x
显示名称 y
卸载 y

或者

显示名称 y
卸载 y
卸载 z

这实际上并不是特别难。

您已经在设置 ​​Product[n] - 您需要为每个%%a==Displayname 执行此操作。对 Uninstall[n] 重复 - 仅在定义 Product[n] 时对每个%%a==UninstallString 执行此操作。

IF "%%a"=="UninstallString" if defined Product[%%n] set uninstall[%%n]=%%c&set/a count+=1

在 SETLOCAL 之前取出计数增量,因为只有当您有一对匹配的 PRODUCT 和 UNINSTALL 时才需要这样做;将初始值更改为 1(除非您喜欢从零开始计数)

并祈祷你没有得到一个序列

显示名称 y
卸载 z

现在,如果你确实得到了这个序列,只需找到一个方便的字符串来让通过门 - 比如,也许是“HKEY_”,如果%%a开始“HKEY_”然后set "Product[%%n]="清除任何没有卸载字符串出现的显示名称。

你甚至可能想稍微改变一下。

如果你设置

  • 针对第一个显示名称的产品
  • 根据第一个卸载字符串卸载(即仅if not defined unistall[%%n]
  • 当 HKEY_ 出现时,如果 product[%%n] 和 uninstall[%%n] 都定义了,则递增计数器,否则将 product[%%n] 和 uninstall[%%n] 设置为 [nothing]

那么卸载和显示名称的顺序不相关,尽管您需要在循环后重复 HKEY_ 测试以处理最后一个实例......


解决部分问题的附录

@ECHO OFF
setlocal
set regVar=HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
set excluded=/c:" Microsoft" /c:"MDOP" /c:"Dell" 
set count=1
for /f "tokens=1,2,*" %%a in ('Reg Query %regVar% /S^|findstr "DisplayName HKEY_ UninstallString" ^| findstr /v %excluded%') do (
    setlocal EnableDelayedExpansion
    for %%n in (!count!) do (
        ENDLOCAL
        SET HKEY=Y
        IF "%%a"=="DisplayName" SET "HKEY="&set product[%%n]=%%c
        IF "%%a"=="UninstallString" SET "HKEY="&IF NOT DEFINED uninstall[%%n] set uninstall[%%n]=%%c
        IF "%%a"=="QuietUninstallString" SET "HKEY="&IF NOT DEFINED uninstall[%%n] set uninstall[%%n]=%%c
    IF DEFINED hkey IF DEFINED product[%%n] IF defined uninstall[%%n] SET /a count+=1&SET "hkey="
    IF DEFINED hkey set "product[%%n]="&SET "uninstall[%%n]="
    )   
)

::
:: Last entry may not be complete
::
IF NOT DEFINED product[%count%] SET "uninstall[%count%]="&SET /a count-=1
IF NOT DEFINED uninstall[%count%] SET "product[%count%]="&SET /a count-=1

ECHO %count% entries found
SET prod
SET unins

请注意,既然HKEY现在允许通过门,但测试起来很痛苦line beginning HKEY,如果它不是字符串“Displayname”、“UninstallString”或“QuietUninstallString”之一,那么它被假定为 HKEY。IF DEFINED适用于允许更容易 - er,koff - 编程的变量的 RUN-TIME 存在/不存在。


显示来自“数组”的数据

FOR /l %%i IN (1,1,%count%) DO (
CALL ECHO %%i. %%product[%%i]%%
)

附加数据 20130419-1756Z

@echo OFF
setlocal
set tab=    
set regVar=HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
set excluded=Microsoft MDOP Dell 
FOR /f "delims=" %%i IN ('Reg Query %regVar% /S^|find "HKEY_"') DO (
 FOR %%s IN (dn us qu pu dn ut) DO SET "%%s="
 FOR /f "tokens=1,2,*delims= " %%s IN ('Reg Query "%%i" /S') DO (
  if /i "%%s"=="Displayname" SET /a dn+=1&SET dn=%%u
  if /i "%%s"=="Uninstallstring" SET /a us+=1&SET ut=%%u
  if /i "%%s"=="quietUninstallstring" SET /a qu+=1
  if /i "%%s"=="publisher" SET pu=%%u
 )
 FOR %%s IN (dn us qu) DO SET /a %%s+=0
 CALL :report
)

GOTO :eof

:report
SET /a tus=us+qu
ECHO %dn%   %us%   %qu%   %tus%   %pu% %dn% %ut%
GOTO :eof

这个过程应该显示有趣的细节。

报告栏是

  1. 找到的“显示名称”数
  2. 找到的“卸载字符串”的数量
  3. 找到的 'quiteuninstallstring' 的数量
  4. 总共前 2 列
  5. 发布者字符串 - 如果找到
  6. 显示名称 - 如果找到
  7. 卸载文本 - 如果找到

我建议您使用这些数据进行过滤和分配给您的数组 - 内部循环正在处理单个卸载项。选择所需的部分并将它们添加或不添加到您的阵列中。

于 2013-04-12T21:03:23.733 回答