Search code examples
powershellcmdregistry

Strip CMD output to just show directories


I'm currently trying to replace a powershell script with a cmd script as it's more suitable for what is trying to be done.

In Powershell I'm using this bit of code to return a list of personal folder directories on the computer

$Name = [Environment]::UserName
get-item HKCU:\software\Microsoft\Office\15.0\Outlook\Search\Catalog - ErrorAction SilentlyContinue | select -expandProperty property | Out-File Z:\global\pst\PowershellOutput\$Name.txt -append

This does what I want and outputs a list of directories like so

H:\PST\My Outlook Data File 1.pst
H:\PST\My Outlook Data File 2.pst
C:\PST\My Outlook Data File 3.pst

However when I run this line to extract the registry key

regedit.exe /e Z:\global\battest\%username%.txt "HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Outlook\Search\Catalog"

I get an output with lots of unnecessary data

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Outlook\Search\Catalog]
"H:\\PST\\My Outlook Data File 1.pst"=hex:0c,01,00,00,00,00,00,00
"H:\\PST\\My Outlook Data File 2.pst"=hex:f8,00,00,00,00,00,00,00
"C:\\PST\\My Outlook Data File 3.pst"=hex:ac,02,00,00,00,00,00,00

This data is passed onto another program* so a work-around could be to use data within the "" marks however it also has the double backslashes which makes the data awkward to pass on.

Is there a better way to grab these values within CMD or perhaps a parameter which I've missed which just shows the directories?

  • -Sorry for not including this before however this program is not a CMD program, it's visual basic

Solution

  • While I don't have Office installed to test, this should get the work done

    @echo off
        setlocal enableextensions disabledelayedexpansion
    
        set "HKCU=&H80000001"
        set "subKey=software\Microsoft\Office\15.0\Outlook\Search\Catalog"
    
        >> "Z:\global\pst\PowershellOutput\%username%.txt" (
            for /f "tokens=2 delims={" %%a in ('
                wmic 
                    /NameSpace:\\root\default 
                    Class StdRegProv 
                    Call EnumValues 
                         hDefKey^="%HKCU%" 
                         sSubKeyName^="%subkey%"
                2^>nul 
                ^| find "sNames = {"
            ') do for %%b in (%%a) do (
                for /f delims^=^" %%c in ("%%~b") do echo(%%~fc
            )
        )
    

    It uses wmic to retrieve the list of values defined under the indicated key and filter the output to only retrieve the line with the names of those values in the form sNames = {"v1", "v2", "v3"}.

    The { is used to separate the start of the line from the list of values (%%a) , and this list is iterated (%%b) to get each value. The last element in the list includes an ending } that needs to be removed, this is handled by %%c using the quotes in the value as delimiters.

    The equivalent vbs version could be

    Option Explicit
    
    Const HKEY_CURRENT_USER = &H80000001
    Const ForAppending = 8
    
    Const SUB_KEY = "software\Microsoft\Office\15.0\Outlook\Search\Catalog"
    Const OUTPUT_PATH = "Z:\global\pst\PowershellOutput"
    
    Dim fso, shell
        Set fso = WScript.CreateObject("Scripting.FileSystemObject")
        Set shell = WScript.CreateObject("WScript.Shell")
    
    Dim values
        Call GetObject( _ 
            "winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv" _ 
        ).EnumValues( _ 
            HKEY_CURRENT_USER, SUB_KEY, values _ 
        )
    
    Dim outputFile
        Set outputFile = fso.OpenTextFile( _ 
            fso.BuildPath( _ 
                OUTPUT_PATH, shell.ExpandEnvironmentStrings("%username%")  & ".txt" _ 
            ) _ 
            , ForAppending _
            , True _
        )
    
    Dim value    
        If Not IsNull(values) Then 
            For Each value In values
                Call outputFile.WriteLine(fso.GetAbsolutePathName( value ))
            Next 
        End If
    
        Call outputFile.Close()