retrieving drive details into variables

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Yanta
Posts: 48
Joined: 01 Sep 2019 07:08

retrieving drive details into variables

#1 Post by Yanta » 01 Sep 2019 07:28

I am writing a script to automate my windows installation.

So, from a batch script

After Windows is installed I need to reassign drive letters on several drives (Both removable and local).
I then run another script which does a multitude of things, but needs to have the drive letters in the right sequence for it to work.
There are 10 PCs I manage. There are a variable number of drives in each PC. On those drives there may be a variable number of partitions.

I can get the drive details using wmic logicaldisk where "drivetype =2" get value1,value2,value3...

Where drivetype; 2=Removable, 5=Optical

What I need to do is to locate optical drives. Reassign the drive letters based on how many optical drives are detected
Then I need to reassign the drive letter of the USB from which I did the install.
By default Windows will give the UEFI install USB a drive letter for the UEFI partition, which I need to remove.
I then need to create additional partitions on the boot drive (Only part of it is used for the Windows partition). After that, the second script will restore files to those partitions

I can pipe commands into diskpart with /s - I believe that's how I will have to reassign the drive letters. It'd be better if I could use wmic to do it though.

So, my boggle is that (a). I'm not sure how to get a variable number of drive letters into a variable for each optical drive and (b) As the USB will also present with two drive letters, the same applies.

I gather this is going to be a FOR loop, which I'm not real good with.

Would appreciate some help.

thanks

aGerman
Expert
Posts: 4654
Joined: 22 Jan 2010 18:01
Location: Germany

Re: retrieving drive details into variables

#2 Post by aGerman » 01 Sep 2019 08:18

I'm not sure how to get a variable number of drive letters into a variable for each optical drive

Code: Select all

@echo off
setlocal EnableDelayedExpansion

set "optcldsks="
set "idx=-1"
for /f "tokens=2 delims==:" %%i in ('wmic logicaldisk where "drivetype=2" get DeviceID /value') do set "optcldsks=!optcldsks!%%i"&set /a "idx+=1"

echo all in one string:
echo %optcldsks%

echo separated within a FOR /L loop:
for /l %%i in (0 1 %idx%) do echo !optcldsks:~%%i,1!
pause

I gather this is going to be a FOR loop, which I'm not real good with.
You definitely have to learn it. You will be out of luck in any programming language if you don't know how to use loops.

Steffen

Yanta
Posts: 48
Joined: 01 Sep 2019 07:08

Re: retrieving drive details into variables

#3 Post by Yanta » 01 Sep 2019 19:01

So close. USB drives respond to drivetype=2. Opticaldisks only respond to drivetype=5. That's OK, I need both

So if I am reading this right, the drive letters are in a single string. I then need to split them out into separate variables.

I tweaked your code thus;

for /l %%i in (0 1 %idx%) do (
Rem echo !optcldsks:~%%i,1!
set disk%%i=!optcldsks:~%%i,1!
)

I can then repeat for USB drives. The USB drive must be plugged in otherwise it reports "No instances found"

Now I just need a way to use the results to change the drive letter. Diskpart doesn't seem to work on optical drives.

aGerman
Expert
Posts: 4654
Joined: 22 Jan 2010 18:01
Location: Germany

Re: retrieving drive details into variables

#4 Post by aGerman » 02 Sep 2019 04:19

Batch doesn't support array types. The only kind of an array is a so-called associative array which still consists of single variables. That's something like you try to create using

Code: Select all

set disk%%i=!optcldsks:~%%i,1!
The reason why I assembled the drive letters in a string is that you may want to process it later on or maybe several times. Usually you would not even do that in Batch, but rather process the drive letters directly in the first loop (where I created the string). Taking this string to make an associative array out of it is even worse. You still would need another FOR /L loop to process these variables. So, why not doing that using !optcldsks:~%%i,1! as already shown?

I wonder why DISKPART doesn't work for you btw.

Steffen

Yanta
Posts: 48
Joined: 01 Sep 2019 07:08

Re: retrieving drive details into variables

#5 Post by Yanta » 02 Sep 2019 22:21

Because DIskpart does not see optical drives.
I want to get each drive once. Processs them once.
I need the current drive letter so that when I call my powershell script it know which of the drives I want to reassign the drive letter for.

aGerman
Expert
Posts: 4654
Joined: 22 Jan 2010 18:01
Location: Germany

Re: retrieving drive details into variables

#6 Post by aGerman » 03 Sep 2019 15:43

Unfortunately I don't have optical drives on any machine I have access to. Don't have a use for them anymore. Maybe there is a possibility using WMI. But that's something I have to search in the internet, too.
I want to get each drive once. Processs them once.
But that's exactly what you get in the body of the loop. I still don't see any reason for an associative array. Not even for my concatenated string of drive letters.

Steffen

Yanta
Posts: 48
Joined: 01 Sep 2019 07:08

Re: retrieving drive details into variables

#7 Post by Yanta » 03 Sep 2019 22:02

No problems. I did come here for help which you generously gave. It would be rude of me to presume that I'm right. I shall return it to it's original form.

As for optical drives, we all still use them extensively. I may have 100TB on my server, but I keep running out. When I run out of space I remove the oldest stuff, and people are forced to then rely on the original disks. As HDD disk prices are skyrocketing here due to a plummeting dollar, adding more storage is not viable at this stage. So - Optical drives abound ;)

I've been searching for a way to do it with WMI. There are a couple of example powershell scripts I've come across but my knowledge of powershell is even worse than my knowledge of batch.

aGerman
Expert
Posts: 4654
Joined: 22 Jan 2010 18:01
Location: Germany

Re: retrieving drive details into variables

#8 Post by aGerman » 04 Sep 2019 09:55

What I meant is something like that:

Code: Select all

for /f "tokens=2 delims==:" %%i in ('wmic logicaldisk where "drivetype=5" get DeviceID /value') do (
  echo work with %%i here, rather than just echo-ing the drive letter as in this example line
)
There are a couple of example powershell scripts I've come across
It's likely that they can be translated into another WMIC command line. Where did you find them?

Steffen

Yanta
Posts: 48
Joined: 01 Sep 2019 07:08

Re: retrieving drive details into variables

#9 Post by Yanta » 05 Sep 2019 02:14

I'd have to go through my history to track down the powershell scripts.

But I have a rather good discovery to share...

Diskpart's list disk and list partition command work with hard disks and removable drives like USB drives, but not with optical drives. However, LIST VOL[ume] does list the optical drives. And they are always first listed (volume 0) for single drive systems. For multiple drives (my system has 3), they are volumes 0, 1 and 2. I've checked all 10 PCs here and they are always the same. That means I can use diskpart to rename the optical drives.

The USB drive, if it has a 2nd partition (usually defaults to UEFI_NTFS), which doesn't need a drive letter, can be removed with mountvol [drive:] /d. That leaves the primary partition on the USB to be renamed. That's where I'm now at.

The primary SSD with boot drive has 4 partitions, so using WMIC I can retrieve the drives with 4 partitions. As all other drives only have 2, I should get the bootdrive's number. I can then use a diskpart /s script to create and format the partitions. Once that's done, my post install script which does all the customization, restores and program installations can then proceed.

The batch snippet you provided tells me how many drives I'm dealing with. I followed your example to also get the drives for the USB.

All that remains now is how to rename the USB drive with wmic,

Almost there!

aGerman
Expert
Posts: 4654
Joined: 22 Jan 2010 18:01
Location: Germany

Re: retrieving drive details into variables

#10 Post by aGerman » 05 Sep 2019 09:53

You can process all these information at once

Code: Select all

@echo off &setlocal

for /f tokens^=2^ delims^=^" %%i in (
  'WMIC Path Win32_DiskDrive Assoc /assocclass:Win32_DiskDriveToDiskPartition 2^>nul ^|findstr /c:"Disk #"'
) do for /f tokens^=4^ delims^=^" %%j in (
  'WMIC Path Win32_LogicalDiskToPartition 2^>nul ^|findstr /c:"%%i"'
) do for /f "tokens=2,4 delims=#," %%k in ("%%i") do for /f "tokens=2 delims==" %%m in (
  'wmic logicaldisk where "DeviceID='%%j'" get DriveType /value'
) do for /f %%n in ("%%m") do (
  if %%n==2 (
    echo removable: letter %%j, disk %%k, partition %%l
  ) else if %%n==5 (
    echo optical: letter %%j, disk %%k, partition %%l
  )
)

pause
All that remains now is how to rename the USB drive with wmic
Right. Try to find the PS snippets again.

Steffen

Yanta
Posts: 48
Joined: 01 Sep 2019 07:08

Re: retrieving drive details into variables

#11 Post by Yanta » 06 Sep 2019 06:24

OMG! That's awesome code.
Doesn't return any results for optical drives though.

Snippet 1

Code: Select all

# Set CD/DVD Drive to A:
$cd = $NULL
$cd = Get-WMIObject -Class Win32_CDROMDrive -ComputerName $env:COMPUTERNAME -ErrorAction Stop
if ($cd.Drive -eq "D:")
{
   Write-Output "Changing CD Drive letter from D: to A:"
   Set-WmiInstance -InputObject ( Get-WmiObject -Class Win32_volume -Filter "DriveLetter = 'd:'" ) -Arguments @{DriveLetter='a:'}
}
Snippet 2 (For systems with only one optical drive I presume)

Code: Select all

# Set CD/DVD Drive to A:
Get-WmiObject -Class Win32_volume -Filter 'DriveType=5' |
  Select-Object -First 1 |
  Set-WmiInstance -Arguments @{DriveLetter='A:'}
  
https://www.kittell.net/code/powershell ... ve-letter/

in the above examples. D: would need to be passed as a parameter for what ever drive was being changed. But as I said in my last post, I found a way around this with diskpart and the list volume command.

The point I'm at now (the last thing to do), is to change the USB drive's letter. The above code could be used if we changed the drivetype to 2.

aGerman
Expert
Posts: 4654
Joined: 22 Jan 2010 18:01
Location: Germany

Re: retrieving drive details into variables

#12 Post by aGerman » 06 Sep 2019 11:16

Code: Select all

WMIC Path Win32_Volume WHERE "DriveLetter='D:'" SET DriveLetter='A:'
That's the Batch command translated from your PS above.
All you have to do is, put it in the loop and use the FOR variable instead of D:

Steffen

Post Reply