0

I have Written a nice little batch file that appeared to work so I thought, but in testing I found one little subroutine isn't doing it's job and I can't see why. I copied the snippet of code into it's own bat file and swapped the goto functions for simple true false statements to try and figure this out and I still couldn't.

If 28937064448 GTR 21474836480 ( 
echo true 
) else ( 
echo false 
)

The context of this is the free space of a drive is being called and compared to a manually set number. If the free space is greater then the script should jump to do something one way, if the free space is smaller it should jump elsewhere to do it differently.

In the VM I am developing this on the drive size is always to small so I commented out the 150gig number and set it to something that should evaluate to true, and to my surprise nothing would. The other context that is important here is I am pulling the free space from wmic and it is reported in bytes I think. Which if my suspicion about the number being too large has any merit is it's own problem because these numbers are always going to be large.

==========

New bit below

Compo provided a very elegant solution that worked though I don't want to mark it as the answer and close the thread as I would like to ask how in the world that solution actually did work. I can clearly see there is a conditional at the end and in my script I modified it into goto statements, but I don't understand how that syntax works for the way it does.

In a few days though I will mark Compo's solution as the answer because it was, though shout out to Mofi for excellent contextual information about if that made me realized I hadn't solved what I thought I had and it was only working for a moment due to have the same number of digits.

At this moment I seek comprehension of the solution Compo provided but the original problem is solved although I would discover group policy would need to be edited to allow a particular part of this to work on non-administrative accounts.

If anyone is curious this is the completed script, Compo's solution lives in the :CheckSync subroutine shortly after the setting of the drive size, to be measured against.

@echo off
Setlocal EnableDelayedExpansion
ping -n 50 127.0.0.1 >NUL
:CheckServer
Echo Checking if Server share is mounted as Drive Z:
::echo Debug: Script Begin
IF EXIST Z:\OTL-Users\OTL-Users.id goto :CheckUser
::echo Debug: if you see this, first goto command skipped
Echo Server was not mounted, attempting to mount now.
net use Z: "\\OC3-Omega01\Central File Store"

ping -n 2 127.0.0.1 >NUL
::echo debug: net use and ping commands just issued, if worked script should jump to :CheckUser
IF EXIST Z:\OTL-Users\OTL-Users.id goto :CheckUser
Echo The Server is Unavailable and cannot be mounted, are you connected to the network?
Echo This script will now exit.
::echo Debug: script did not jump to :CheckUser, is the computer off network, or is the script broken?
:: If Server is still not available it is good to assume off network
::echo Debug: script should now exit.
goto :Exit
echo escape error 1
::echo Debug: (:CheckServer) there should be no way to see this message, if you see it there is a error

:CheckUser
Echo The Server is available at Z:
Echo Determining if this user has a base copy of their account on the server.
::echo Debug: this is the begining of the CheckUser Subroutine
IF EXIST Z:\OTL-Users\%UserName%\%Username%.id goto :CheckSync
::echo Debug: if you see this the first goto command of :Checkuser was skipped
Echo There is currently no copy of your user account on the server
Echo Your account will now be copied to Z:\OTL-Users\%UserName% 
Echo This step is the longest step but will not run again from any computer 
Echo Unless you explicitly delete your profile from the server.
robocopy /copy:DATSO /E /xj %UserProfile% \\OC3-Omega01\OTL-Users\%UserName% /R:2 /W:2 >Nul
ping -n 2 127.0.0.1 >NUL
fsutil file createnew \\OC3-Omega01\OTL-Users\%UserName%\%Username%.id 0

Echo Your Profile has now been copied to the Server.
::echo Debug: User profile flag on the server share should have been generated and user profile should have been robocopy'd
goto :CheckSync
echo escape error 2
::echo Debug: (:CheckUser) there should be no way to see this message, if you see it there is a error
goto :Exit

:CheckSync
Echo Determining if a Sync relationship has been setup between your account on this PC and the Server
::echo Debug: this is the begining of the CheckSync Subroutine
IF EXIST C:\Windows\Config\Users\%Username%.id goto :Exit2

Echo Sync Relationship not found setting up now
::echo Debug: if you see this the first goto command of :CheckSync was skipped
fsutil file createnew C:\Windows\Config\Users\%Username%.id 0

for /f "tokens=2 delims==:" %%z in ('wmic logicaldisk where volumename^="UserData" get name /value') do set "volume=%%z:"

::echo Debug: The UserData partition is %volume%
::echo Debug: now attempting to determine if partition is more or less then 150Gigs and conditionally jump

Set DriveLimit=161061273600
::Set DriveLimit=161061273600


::for /f "usebackq delims== tokens=2" %%x in (`wmic logicaldisk where "DeviceID='%volume%'" get FreeSpace /format:value`) do set FreeSpace=%%x
::Echo FreeSpace="%FreeSpace%"
Echo Limit="%DriveLimit%"
ping -n 2 127.0.0.1 >NUL
::If "%FreeSpace%" GTR "%DriveLimit%" (
:: Goto :SetSyncFull
::) else (
:: Goto :SetSyncPart
::)

Echo Determining if the free space in your user Partition is in excess of 150Gigs or not to Determine
Echo The Sync relationship to be used

%__AppDir__%wbem\WMIC.exe LogicalDisk Where "DeviceID='%volume%' And FreeSpace>'%DriveLimit%'" Get DeviceID 2>NUL|%__AppDir__%find.exe ":">NUL&&( Goto :SetSyncFull )||Goto :SetSyncPart



Echo Escape error 3
::echo If you see this there was an error in the :CheckSync subroutine and the jump to either :SetSyncFull or :SetSyncPart failed
Goto :Exit

:SetSyncFull

Echo User Partition Free space is indeed in excess of 150Gigs
Echo Setting up full account Syncronization  

::echo Debug: This is the start of the :SetSyncFull subroutine
"%programfiles%\SyncToy 2.1\SyncToy.exe" -d(left=%UserProfile%,right=\\OC3-Omega01\OTL-Users\%UserName%,name=%UserName%-%COMPUTERNAME%-Full,operation=synchronize,check=yes,excluded=*.lnk;*.id)
::echo Debug: supposedly Full Sync job has been set in synctoy, validation is in order though
ping -n 2 127.0.0.1 >NUL
::echo Debug Ping wait timer just happened, About to generate random time for sync to happen
Set /a Hr=(%random%*12/32768)+1
Set /a Min=(%random%*60/32768)+1
::Echo %Min% before mod
::Echo %Hr% before mod
Set MClock=10
If %MClock% GTR %Min% (
 Set  Min=0%Min%
)
ping -n 2 127.0.0.1 >NUL
If %MClock% GTR %Hr% (
 Set  Hr=0%Hr%
)


Echo Sync Time is generated randomly per user on each computer to prevent file access conflicts. 
Echo This acct on this PC will sync at: %Hr%:%Min% 
Echo Enter Password When Prompted. You will only need to do this once per PC.
Echo If your password changes or this need to be reset for any reason, 
Echo delete the %UserName%.id file in C:\Windows\Config\Users  
Echo The first run of this takes a while, but afterwards you should barely see the prompt window 
SCHTASKS /CREATE /RU %UserName% /SC DAILY /TN "SyncToy\%UserName%-Full" /TR "%WINDIR%\Config\Scripts\RunSync.vbs" /ST %Hr%:%Min%
::Echo Task scheduler is command issued
Goto :Exit 

:SetSyncPart

Echo User Partition Free space is less then 150Gigs
Echo Setting up Partial Sync Relationship.
Echo Documents, Downloads, Music, and Videos 
Echo Will sync up to the server but not Down from the Server.
::echo Debug: This is the start of the :SetSyncPart subroutine

"%programfiles%\SyncToy 2.1\SyncToy.exe" -d(left="%UserProfile%\Contacts",right="\\OC3-Omega01\OTL-Users\%UserName%\Contacts",name="%UserName%-%COMPUTERNAME%-Contacts-Part",operation=synchronize,check=yes,excluded=*.lnk;*.id)
ping -n 2 127.0.0.1 >NUL
"%programfiles%\SyncToy 2.1\SyncToy.exe" -d(left="%UserProfile%\Desktop",right="\\OC3-Omega01\OTL-Users\%UserName%\Desktop",name="%UserName%-%COMPUTERNAME%-Desktop-Part",operation=synchronize,check=yes,excluded=*.lnk;*.id)
ping -n 2 127.0.0.1 >NUL
"%programfiles%\SyncToy 2.1\SyncToy.exe" -d(left="%UserProfile%\Documents",right="\\OC3-Omega01\OTL-Users\%UserName%\Documents",name="%UserName%-%COMPUTERNAME%-Documents-Part",operation=contribute,check=yes,excluded=*.lnk;*.id)
ping -n 2 127.0.0.1 >NUL
"%programfiles%\SyncToy 2.1\SyncToy.exe" -d(left="%UserProfile%\Downloads",right="\\OC3-Omega01\OTL-Users\%UserName%\Downloads",name="%UserName%-%COMPUTERNAME%-Downloads-Part",operation=contribute,check=yes,excluded=*.lnk;*.id)
ping -n 2 127.0.0.1 >NUL
"%programfiles%\SyncToy 2.1\SyncToy.exe" -d(left="%UserProfile%\Favorites",right="\\OC3-Omega01\OTL-Users\%UserName%\Favorites",name="%UserName%-%COMPUTERNAME%-Favorites-Part",operation=synchronize,check=yes,excluded=*.lnk;*.id)
ping -n 2 127.0.0.1 >NUL
"%programfiles%\SyncToy 2.1\SyncToy.exe" -d(left="%UserProfile%\Music",right="\\OC3-Omega01\OTL-Users\%UserName%\Music",name="%UserName%-%COMPUTERNAME%-Music-Part",operation=contribute,check=yes,excluded=*.lnk;*.id)
ping -n 2 127.0.0.1 >NUL
"%programfiles%\SyncToy 2.1\SyncToy.exe" -d(left="%UserProfile%\Pictures",right="\\OC3-Omega01\OTL-Users\%UserName%\Pictures",name="%UserName%-%COMPUTERNAME%-Pictures-Part",operation=synchronize,check=yes,excluded=*.lnk;*.id)
ping -n 2 127.0.0.1 >NUL
"%programfiles%\SyncToy 2.1\SyncToy.exe" -d(left="%UserProfile%\Saved Games",right="\\OC3-Omega01\OTL-Users\%UserName%\Saved Games",name="%UserName%-%COMPUTERNAME%-Saved Games-Part",operation=synchronize,check=yes,excluded=*.lnk;*.id)
ping -n 2 127.0.0.1 >NUL
"%programfiles%\SyncToy 2.1\SyncToy.exe" -d(left="%UserProfile%\Videos",right="\\OC3-Omega01\OTL-Users\%UserName%\Videos",name="%UserName%-%COMPUTERNAME%-Videos-Part",operation=contribute,check=yes,excluded=*.lnk;*.id)
ping -n 2 127.0.0.1 >NUL
"%programfiles%\SyncToy 2.1\SyncToy.exe" -d(left="%UserProfile%\AppData",right="\\OC3-Omega01\OTL-Users\%UserName%\AppData",name="%UserName%-%COMPUTERNAME%-AppData-Part",operation=synchronize,check=yes,excluded=*.lnk;*.id)
::echo Debug: supposedly Part Sync jobs has been set in synctoy, validation is in order though
ping -n 2 127.0.0.1 >NUL
::echo Debug Ping wait timer just happened, About to generate random time for sync to happen
Set /a Hr=(%random%*12/32768)+1
Set /a Min=(%random%*60/32768)+1
::Echo %Min% before mod
::Echo %Hr% before mod
Set MClock=10
If %MClock% GTR %Min% (
 Set  Min=0%Min%
)
ping -n 2 127.0.0.1 >NUL
If %MClock% GTR %Hr% (
 Set  Hr=0%Hr%
)

Echo Sync Time is generated randomly per user on each computer to prevent file access conflicts. 
Echo This acct on this PC will sync at: %Hr%:%Min% 
Echo Enter Password When Prompted. You will only need to do this once per PC.
Echo If your password changes or this need to be reset for any reason, 
Echo delete the %UserName%.id file in C:\Windows\Config\Users
Echo The first run of this takes a while, but afterwards you should barely see the prompt window 
SCHTASKS /CREATE /RU %UserName% /SC DAILY /TN "SyncToy\%UserName%-Part" /TR "%WINDIR%\Config\Scripts\RunSync.vbs" /ST %Hr%:%Min%







Goto :Exit
:Exit2
Echo All Sync Relationships were previously set, nothing to do this time.

:Exit
Echo Your done Here
::echo Debug: this is the Exit subroutine and the end of the script

The Debug echos were for my benifit during editing more proactive as most were never needed, the other echo's were supposed to be for the end user's benefit but were pointless as when set as a login script I discovered the CMD window was hidden.

Theo Lehr
  • 23
  • 2
  • 2
    CMD does 32 bit signed integers only. –  May 21 '20 at 08:54
  • 1
    …and that effectively means anything a under 2 Gig, not 20. – Compo May 21 '20 at 10:08
  • 2
    See [weird results with IF](https://stackoverflow.com/a/49601468/3074564) for an explanation of the result. The solution would be prepending both values with zeros so that both values have the same number of digits and use a string comparison with `GTR` as explained in detailed by my answer on [Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files](https://stackoverflow.com/a/47386323/3074564). – Mofi May 21 '20 at 10:20
  • 1
    You could split the numbers and compare the parts individually to work around the 32-bit integer limitation... – aschipfl May 21 '20 at 12:48

1 Answers1

1

32-bit signed integers are not a limitation for though, so this may be an option for you.

@%__AppDir__%wbem\WMIC.exe LogicalDisk Where "DeviceID='%SystemDrive%' And FreeSpace>'21474836480'" Get DeviceID 2>NUL|%__AppDir__%find.exe ":">NUL&&(Echo TRUE)||Echo FALSE

In the example above, I've used %SystemDrive% as a variable holding a drive letter to be checked. You'd obviously replace that with with your chosen drive letter or variable.


I suppose you could modify it slightly, so that you can see the returned value if it is TRUE too!
@%__AppDir__%wbem\WMIC.exe LogicalDisk Where "DeviceID='%SystemDrive%' And FreeSpace>'21474836480'" Get FreeSpace /Format:List 2>NUL|%__AppDir__%find.exe "="&&(Echo TRUE)||Echo FALSE
Compo
  • 36,585
  • 5
  • 27
  • 39
  • something I saw somewhere before walking away that night inspired me to try adding quotes. The If statement then began working as expected and I quit for the night. Next day I planned to come here and say as much, but I saw the replies from Mofi and Compo and decided to give these responses the appropriate deep dive. I now believe my If statement only worked that night because by happenstance the number of digits on both sides were the same from reading the link Mofi provided. – Theo Lehr May 25 '20 at 20:44
  • I saw a nice little script on the page Mofi linked to that I took sevral hours to understand what was being done (I was unaware some of what was being used like ~zi had some predefined meanings so that was good learning moment about "IF"). that snippet of a script would have worked, but Compo provided a more elegant solution, that I used though I don't have a clue how the if condition on the back end of his one liner is in anyway valid (it clearly works in testing, but for me the human reading it is 'Syntax error invalid entry' ) if I could get you to expand on that I would love that. – Theo Lehr May 25 '20 at 20:46
  • `&&` means process the following command if the last command was successful. `||` means process the following command if the previous command was unsuccessful. The command `Echo TRUE` is run if the command `find.exe` matches a line containing a colon `:`, _(i.e a drive letter)_. The command `Echo FALSE` is run if the command `Echo TRUE` is not run. For the idea to work, all I do is output the drive letter, _(`DeviceID`)_ if its `FreeSpace` is greater than `21474836480` bytes. I've used `2>NUL` to effectively throw away error output, such as when the free space is less or it's an invalid drive. – Compo May 26 '20 at 09:45
  • Thanks That was exactly what I sought. the only remaining mystery I see is the '2' in your 2>NUL as opposed to any other number or as I have used it, w/o a number at all? – Theo Lehr May 26 '20 at 16:14
  • Change it back to `2` then @TheoLehr, I didn't add it for no reason! The idea of it is to pass any error to the `NUL` device. If the free space is not greater, an error is output, and an error will also be output if the device ID is not found too. The idea is not to have to pointlessly pipe that to the `find` command. Whilst you may still get the result you wanted, it's not my intention to do that, because it relies upon guaranteeing that the output error in any possible locale/language does not contain the `:` character anywhere within it. I know for sure that no output will not contain one! – Compo May 26 '20 at 16:34
  • lol, in copying your code I left that in tact but I use ``` ping -n10 127.0.0.1 >NUL ``` all over the place in my code to kill time to wait for things to happen – Theo Lehr May 26 '20 at 17:43
  • A explanation of the number's meaning though is what I seek here, the 2>NUL survived in your code snippet, fret not. @Compo – Theo Lehr May 26 '20 at 17:45
  • @TheoLehr, `0<` is initially redirection from standard input, StdIn, usually shortened to just `<`. `1>` is initially redirection to standard output, StdOut, and usually shortened to just `>`. `2>` is initially redirection to standard error, StdErr. In addition to that don't use `ping.exe` to delay, since [tag:windows-vista], there's been a utility for doing that, `timeout.exe`. For a nine second delay, _which is the nearest equivalent of what `%__AppDir__%ping.exe -n 10 127.0.0.1 1> NUL` will achieve_, use `%__AppDir__%timeout.exe /T 9 /NoBreak 1> NUL`. See `help timeout` for its usage info. – Compo May 26 '20 at 18:34