Skip to content
⌘ NSIS Forum Archive

Parse cmd.exe output in ini file for each item to RichEdit

11 posts

meoit#

Parse cmd.exe output in ini file for each item to RichEdit

I run batch file with command:


ExecShellWait 'open' '"$SYSDIR\cmd.exe"' '/c "D:\MyDisks.cmd"' SW_HIDE
Content batch MyDisks.cmd file:


@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
SET "InputFile=MyDisks.ini"
IF EXIST "%InputFile%" (DEL /f /q "%InputFile%")
FOR /F "skip=2 tokens=*" %%G IN ('
"WMIC PATH Win32_DiskDrive GET Caption,Index,Size /format:csv 2>NUL"
') DO (
@FOR /F "tokens=2,3,4 delims=," %%H IN ("%%G") DO (
SET "strCaption=%%H"
SET "strIndex=%%I"
SET "strSize=%%J"
>>"%InputFile%" CALL ECHO [Disk%%strIndex%%]
>>"%InputFile%" CALL ECHO Item=Index%%strIndex%% - %%strCaption%% (%%strSize%%^)
)
)
pause
Result MyDisks.ini :


[Disk0]
Item=Index0 - Samsung EVO (232536803840)
[Disk1]
Item=Index1 - Adata USB Device (35718510080)
But I do not know how to parse MyDisks.ini file for each item to the RichEdit control.

I tried

ReadINIStr $0 'D:\MyDisks.ini' 'DiskZZZ' 'Item'

but not success 🙁

I need content in the RichEdit control same as:


Index0 - Samsung EVO (232536803840)
Index1 - Adata USB Device (35718510080)
Please help me. 🙂

Thanks.
meoit#
Yes Anders.

I put MyDisks.cmd in D:\ location.
And the output of MyDisks.cmd which MyDisks.ini also in D:\ location
Anders#
Your batch-file and ReadINIStr ... "Disk0" work just fine for me when I use full paths.

ExecShellWait '"$SYSDIR\cmd.exe"' should just be '$SYSDIR\cmd.exe' but I assume this is not the real issue.
meoit#edited
There are computers with 2 storage devices, 3 storage devices, 4 storage devices, ... So, How do we know how many devices that the computer has ?.

Index0 - Samsung EVO (232536803840)

Index1 - Adata USB Device (35718510080)

Index2 - Samsung EVO 2 (232536803840)

Index3 - Adata USB Device 2 (35718510080)

Index4 - Samsung EVO 3 (232536803840)

Index5 - Adata USB Device 3 (35718510080)

.....
.....
......
.....

IndexN - Samsung EVO N (232536803840)

IndexN - Adata USB Device N (35718510080)
Nutzzz#
Originally Posted by meoit View Post
There are computers with 2 devices, 3 devices, 4 devices, ... how do we know how many devices that the computer has ?.
If you could assume that the disk numbers are contiguous, you could just loop through them until the Errors flag is set. Though that's usually true, it's not always a safe assumption. Assuming this ini file isn't used for any other purpose, I would personally make the section name in square brackets use the %%G number instead of the disk number, and then contiguity would be guaranteed.

Spoiler:
rem			...
SET "strCount=%%G"

SET "strCaption=%%H"

SET "strIndex=%%I"

SET "strSize=%%J"

>>"%InputFile%" CALL ECHO [Disk%%strCount%%]

>>"%InputFile%" CALL ECHO Item=Index%%strIndex%% - %%strCaption%% (%%strSize%%^)
rem ...


Assuming you've done that, you'd loop through them, e.g.:

Spoiler:
!include LogicLib.nsh
# ...
StrCpy $R0 0
ClearErrors
${DoUntil} ${Errors}
ReadINIStr $0 'D:\MyDisks.ini' 'Disk$R0' 'Item'
${IfNot} ${Errors}
${AndIfNot} $0 == ""
# ...
${EndIf}
IntOp $R0 $R0 + 1
${Loop}
ClearErrors


* * * * *

If you need to keep the index as is for some reason, then you'd have to come up with a maximum number beyond which the number of drives is unreasonable. 16, maybe, for a consumer system, but if you might be installing on a server, even though usually you'd expect to find lots of drives hidden behind a RAID pool, theoretically you could have hundreds of disks in a bunch of JBODs, so let's say, 200?

e.g.:

!include LogicLib.nsh
!define MAX_DRIVES 200
# ...
ClearErrors
${For} $R0 0 ${MAX_DRIVES}
ReadINIStr $0 'D:\MyDisks.ini' 'Disk$R0' 'Item'
${IfNot} ${Errors}
${AndIfNot} $0 == ""
# ...
${EndIf}
${Next}
ClearErrors
meoit#
Thanks Nutzzz.

I edited MyDisks.cmd to count devices as you told.

@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
SET "InputFile=MyDisks.ini"
IF EXIST "%InputFile%" (DEL /f /q "%InputFile%")
SET /A "Total_Devices=0"
SET /A "Index=0"
@FOR /F "skip=2 tokens=*" %%G IN ('
"WMIC PATH Win32_DiskDrive GET Index /format:csv 2>NUL"
') DO (
SET /A "Total_Devices=Total_Devices+1"
SET /A "Index=Index+1"
>>"%InputFile%" CALL ECHO [Disk%%Index%%]
@FOR /F Tokens^=* %%A IN ('
"WMIC PATH Win32_DiskDrive GET Caption,Size /value 2>NUL"
') DO (
@FOR /F Tokens^=* %%H IN ("%%A") DO (>>"%InputFile%" CALL ECHO %%H)
)
)
>>"%InputFile%" CALL ECHO [Total Devices]
>>"%InputFile%" CALL ECHO Value=%%Total_Devices%%
PAUSE
Then, read MyDisks.ini

ReadINIStr $R1 'D:\MyDisks.ini' 'Total Devices' 'Value'
ClearErrors
${For} $R0 0 $R1
ReadINIStr $0 'D:\MyDisks.ini' 'Disk$R0' 'Item'
${IfNot} ${Errors}
${AndIfNot} $0 == ""
MessageBox MB_OK|MB_USERICON '$0'
${EndIf}
${Next}
ClearErrors
But when open MyDisks.ini, I see it double result devices.

[Disk1]
Caption=Samsung EVO
Size=232536803840
Caption=Adata USB Device
Size=35718510080
[Disk2]
Caption=Samsung EVO
Size=232536803840
Caption=Adata USB Device
Size=35718510080
[Total Devices]
Value=2
How to fix this?.
Nutzzz#
Originally Posted by meoit View Post
But when open MyDisks.ini, I see it double result devices.
As I said, you can't assume the Index value is contiguous, and your new method doesn't resolve that issue. Even if the method was valid, you're missing a where clause to match up the current index with the appropriate caption and size.

Did the replacement section I gave you not work, or are you required to use the Index value for your sections?
meoit#
Yes, I need to use Index value and count devices. And I want to read the size, to converte to MB, GB in NSIS, don't handle size in MyDisks.cmd.
meoit#
Thanks Nutzz.

I fixed code for myself.

ReadINIStr $0 'D:\MyDisks.ini' 'Total Devices' 'Value'
IntOp $R1 $0 + 1
ClearErrors
${For} $R0 0 $R1
ReadINIStr $1 'D:\MyDisks.ini' 'Disk$R0' 'Index'
${If} $R0 != $1
ReadINIStr $2 'D:\MyDisks.ini' 'Disk$R0' 'Item'
MessageBox MB_OK|MB_USERICON '$0'
${EndIf}
${Next}
ClearErrors
Now, it is working so good. 🙂
Nutzzz#
Originally Posted by meoit View Post
Thanks Nutzz.

I fixed code for myself.
We are still not communicating. The user could pull a drive and end up with a gap in the index values, e.g.:
Disk 0
Disk 1
Disk 3