-1

I've looked at the similar questions but they dont seem to work for me, hopefully something simple....(for an expert)…

Here is a config file I'm trying to edit as part of a batch file...

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <userSettings>
        <Accenda.ICG.EndPoint.Properties.Settings>
            <setting name="SiteURL" serializeAs="String">
                <value>https://nww.rss.scarboroughryedaleccg.nhs.uk/_vti_bin/Accenda.ICG.EndPoint.WCF</value>
            </setting>
            <setting name="FilePathToDelete" serializeAs="String">
                <value />
            </setting>
            <setting name="WatchPath" serializeAs="String">
                <value />
            </setting>
            <setting name="MonitorFolderChoice" serializeAs="String">
                <value>True</value>
            </setting>
            <setting name="UserName" serializeAs="String">
                <value />
            </setting>
            <setting name="Password" serializeAs="String">
                <value />
            </setting>
            <setting name="AutoLogin" serializeAs="String">
                <value>True</value>
            </setting>
            <setting name="PollingIntervalMinutes" serializeAs="String">
                <value>5</value>
            </setting>
            <setting name="RegistrySettingsImportedToAppConfig" serializeAs="String">
                <value>True</value>
            </setting>
        </Accenda.ICG.EndPoint.Properties.Settings>
    </userSettings>
</configuration>

For this line (or 2) here...

    <setting name="WatchPath" serializeAs="String">
        <value />

whether empty, or populated with a path to 'any folder'

I only ever want it to contain the following:-

        <setting name="WatchPath" serializeAs="String">
            <value>C:\Users\Public\Desktop\RSS Referrals</value>

If the value contains a path I can use findstr & FART.exe in combination fine, but if its empty I'm stuck, many thanks in advance ;-)

code snippet if the line contains a path :-

for /f "tokens=3 delims=>;<" %%a in ('findstr /C:"C:\Users" "C:\Users\%usr%\AppData\Local\Accenda_Limited\Accenda.ICG.EndPoint.exe_Url_m5l4ujc5t22f3qw0q5uz1dwlfcnrdaoh\1.0.0.15\user.config"') do (
fart -i -c "C:\Users\%usr%\AppData\Local\Accenda_Limited\Accenda.ICG.EndPoint.exe_Url_m5l4ujc5t22f3qw0q5uz1dwlfcnrdaoh\1.0.0.15\user.config" "%%a" "C:\Users\Public\Desktop\RSS Referrals"
)

However if empty, as mentioned, I'm stuck - thanks peeps!!!

Compo
  • 36,585
  • 5
  • 27
  • 39
Tika9o9
  • 405
  • 4
  • 22
  • 1
    Stop tring to parse XML files with native batch file commands. Your system should have PowerShell, which has built in support for XML and Unicode. It also should perform the replacement without the need for using a third party `f`ind `a`nd `r`eplace `t`ool. – Compo Oct 31 '20 at 16:06
  • I've asked in batch because there is already a lot of work going into a script previous, this being the final part to be added. Powershell is no good here since it's blocked on many of the domains I am working on. – Tika9o9 Oct 31 '20 at 16:15
  • Getting the `user.config` paths will be easier using PowerShell too, but that's beside the point. Your XML is clearly encoded as UTF-8, and your batch file will invariably break it. You can run powershell code directly from a batch file, so you can treat it like a normal exe file, just as you are with FART. – Compo Oct 31 '20 at 16:19
  • It doesn’t , I use it all the time to replace a path, just need help to replace the line when it’s empty. – Tika9o9 Oct 31 '20 at 16:21
  • 1
    Why don't you just determine the line number containing your target setting name and then completely replace that line number + 1 with `C:\Users\Public\Desktop\RSS Referrals`? *Oh and it would be nice to get positive feedback when I help you with something, instead of just providing the opposite.* – Compo Oct 31 '20 at 16:50
  • I spent hours trying to do it but couldn’t, why I’m asking for help. I said thanks but seems never came. I’ll thank you if you show me how to +1 swap the line ;) – Tika9o9 Oct 31 '20 at 17:17
  • This would also be simple to do in the windows scripting host using jscript or vbs. – Señor CMasMas Oct 31 '20 at 17:23
  • `Find`, and your already used command utility, `FindStr`, can both return the line number of a matched string. Please open up a Command Prompt window, type `findstr /?`, press the `[ENTER]` key, and read its usage information. To increment the returned line number, you could use `set` with its arithmetic option. Please open up a Command Prompt window, type `set /?`, press the `[ENTER]` key, and read its usage information. – Compo Oct 31 '20 at 17:27
  • I'm well aware of these, and have tried but see no option for replace line 12 in a text file with a given string. I'll go back to google. Thanks for everything so far. – Tika9o9 Oct 31 '20 at 17:42

1 Answers1

1

Windows command processor cmd.exe processing a batch file is not designed for file contents modification tasks, especially not for UTF-8 encoded XML files. There are other script interpreters installed by default on Windows like Windows Script Host interpreting Visual Basic and JScript scripts and PowerShell which are much better for such a task.

However, here is a batch file for this task.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ConfigFile=%LOCALAPPDATA%\Accenda_Limited\Accenda.ICG.EndPoint.exe_Url_m5l4ujc5t22f3qw0q5uz1dwlfcnrdaoh\1.0.0.15\user.config"
if exist "%ConfigFile%" goto ScanForConfig
echo ERROR: File "%ConfigFile%" not found.
exit /B 4

:ScanForConfig
set "LineNumber="
for /F "delims=:" %%I in ('%SystemRoot%\System32\findstr.exe /L /N /C:"<setting name=\"WatchPath\" serializeAs=\"String\">" "%ConfigFile%" 2^>nul') do set /A LineNumber=%%I + 1
if defined LineNumber goto DesktopFolder
echo ERROR: Could not find ^<setting name="WatchPath" serializeAs="String"^>
echo        in file "%ConfigFile%".
exit /B 3

:DesktopFolder
rem Determine the common desktop folder directly from Windows registry.
rem The first FOR loop is usually enough to get the common desktop folder.
set "CommonDesktop="
for /F "skip=1 tokens=1-3*" %%I in ('%SystemRoot%\System32\reg.exe QUERY "HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "Common Desktop" 2^>nul') do if /I "%%I %%J" == "Common Desktop" if not "%%~L" == "" if "%%K" == "REG_SZ" (set "CommonDesktop=%%~L") else if "%%K" == "REG_EXPAND_SZ" call set "CommonDesktop=%%~L"
if not defined CommonDesktop for /F "skip=1 tokens=1-3*" %%I in ('%SystemRoot%\System32\reg.exe QUERY "HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "Common Desktop" 2^>nul') do if /I "%%I %%J" == "Common Desktop" if not "%%~L" == "" if "%%K" == "REG_SZ" (set "CommonDesktop=%%~L") else if "%%K" == "REG_EXPAND_SZ" call set "CommonDesktop=%%~L"
if not defined CommonDesktop set "CommonDesktop=\"
if "%CommonDesktop:~-1%" == "\" set "CommonDesktop=%CommonDesktop:~0,-1%"
if defined CommonDesktop if exist "%CommonDesktop%\" goto ScanForValue
if defined PUBLIC if exist "%PUBLIC%\Desktop\" set "CommonDesktop=%PUBLIC%\Desktop" & goto ScanForValue
if exist "%SystemDrive%\Users\Public\Desktop\" set "CommonDesktop=%SystemDrive%\Users\Public\Desktop" & goto ScanForValue
if defined ALLUSERSPROFILE if exist "%ALLUSERSPROFILE%\Desktop\" set "CommonDesktop=%ALLUSERSPROFILE%\Desktop" & goto ScanForValue
echo ERROR: Cannot determine the all users desktop folder.
exit /B 2

:ScanForValue
set "NewValue=<value>%CommonDesktop%\RSS Referrals</value>"
for /F "delims=:" %%I in ('%SystemRoot%\System32\findstr.exe /L /N /C:"%NewValue%" "%ConfigFile%" 2^>nul') do if %LineNumber% == %%I goto NoUpdate

rem It is really necessary to update the value in the configuration file.
set "TempFile=%ConfigFile%.tmp"
(for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /N "^" "%ConfigFile%" 2^>nul') do (
    set "Line=%%I"
    setlocal EnableDelayedExpansion
    for /F "tokens=1,2 delims=:<>/" %%J in ("!Line!") do if not %%J == %LineNumber% (
        echo(!Line:*:=!
    ) else if "%%K" == "value " (
        echo(!NewValue!
    ) else if "%%K" == "value" (
        echo(!NewValue!
    ) else echo(%%K!NewValue!
    endlocal
))>"%TempFile%"
move /Y "%TempFile%" "%ConfigFile%"
if not exist "%TempFile%" goto UpdateDone

del "%TempFile%"
echo ERROR: Failed to modify file "%ConfigFile%".
exit /B 1

:NoUpdate
echo There is nothing to update.
exit /B 0

:UpdateDone
echo Configuration update done successfully.
endlocal

ATTENTION:
This batch file works only if the XML file user.config is as posted with always having a line with tag value below the line with <setting name="WatchPath" serializeAs="String">. Any other variant of XML file contents results could result in a damaged XML file after execution of the batch file.

Please read my answer on How to read and print contents of text file line by line? for information on how the line replacement is done.

I recommend to read also the Wikipedia article which describes the predefined Windows Environment Variables.

My answer on Making a directory not in the current directory describes the command lines uses to get the desktop folder whereby in this case the code is modified to get the common desktop folder for all users instead of the user's desktop folder.

The batch file does not modify the configuration file if the value to modify is already present in the line below the line with <setting name="WatchPath" serializeAs="String">.

I recommend once again coding a PowerShell script for this task instead of using a batch file as it would be safer and much faster. I cannot be made responsible on an XML file damage caused by using this batch script on changed XML file contents.

To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.

  • del /?
  • echo /?
  • endlocal /?
  • exit /?
  • findstr /?
  • for /?
  • goto /?
  • if /?
  • move /?
  • rem /?
  • set /?
  • setlocal /?

PS: This batch file works even on Windows XP as long as the file to update is found which is not the case by default with %LOCALAPPDATA% because of the environment variable LOCALAPPDATA is not defined by default on Windows XP, just on Windows Vista and newer Windows versions.

Mofi
  • 46,139
  • 17
  • 80
  • 143