1. Computer problem? Tech Support Guy is completely free -- paid for by advertisers and donations. Click here to join today! If you're new to Tech Support Guy, we highly recommend that you visit our Guide for New Members.

Solved: batch file using NET SHARE - parsing issues

Discussion in 'DOS/Other' started by geriatric, Jan 16, 2013.

Thread Status:
Not open for further replies.
Advertisement
  1. geriatric

    geriatric Thread Starter

    Joined:
    Aug 26, 2003
    Messages:
    10
    Hello.

    I have been hammering away at a particular problem for awhile now, off and on. I am tired of windows 7 ridiculous network sharing scheme. Give me good old XP style, insecure and easy to use. lol.

    Anyway, what I am doing is, via a context menu, calling a batch file, with two parameters. %1 is a command, such as "share", and %2 is the path (context menu is always passing an FQP, on a directory).

    When the batch script gets the parameter to create a share, it will:
    1. check the target exists
    2. concatenate a target directory with underscores (ie. some path will become some_path)
    3. prepend a user supplied value (ie. temp_ prepended like temp_some_path)
    4. use net share to create the share with /grant:everyone,full (exactly what the OS does)
    5. use icacls to grant everyone RX rights with OICI inheritance (exactly as the OS does)
    (note this is all about simple file sharing for the home, no security required really behind the router)

    The batch script will also reverse this process, but I originally built it to delete ALL of these shares, because the idea WAS to use it at LAN parties, so ALL the shares were really temporary anyway. So the batch file would:
    1. use a for loop, look for any share name with the prepend tag (ie. temp_ )
    2. ignore anything without the prepend tag implicitly
    3. use net share with /del parameter
    4. use icacls with /remove:g everyone

    It works fine enough. However, I became fed up with the "new and improved" windows 7 sharing, tweaked a few things so that no credential prompts come up when sharing, at all, and now want to rid myself of the "share with" context menu and create my own. Not hard.

    However, the hard part is being choosy about what to stop sharing.

    The NET SHARE command will return a (I think) tab delimited output of share names to FQP. I want the option of simply sharing a directory with the same name as the directory, which might contain spaces (although I rarely use spaces, it happens when you get lazy ;) ). So my For loop will never know how many tokens to use, thus I can't know how many to expect.

    Here is a snippet of the batch file
    Code:
    @ECHO OFF
    SETLOCAL EnableDelayedExpansion
    
    SET _prepend=temp_
    SET _alen=5
    
    IF /I [%1]==[unshare] GOTO :xunshare
    IF /I [%1]==[share] GOTO :xshare
    IF /I [%1]==[add_rights] GOTO :xadd_rights
    IF /I [%1]==[rem_rights] GOTO :xrem_rights
    GOTO :bye
    
    :xunshare
    FOR /F "skip=4" %%I IN ('NET SHARE') DO (
    	SET Share=%%I
    	SET var=!Share:~0,%_alen%!
    	IF !var!==!_append! NET SHARE !Share! /del
    )
    GOTO :bye
    
    :xshare
    IF /I [%2]==[] GOTO :bye
    IF NOT EXIST %2 GOTO :bye
    FOR /D %%I IN (%2) DO (
    	SET Share=%%~nxI
    	SET Share=!Share: =_!
    	NET SHARE !_prepend!!Share!=%2 /GRANT:Everyone,Full
    )
    GOTO :bye
    
    
    So, what I am trying to do is parse the output of NET SHARE, and return the SHARE NAME for each share listed. This I will then match against the %2 parameter which I will have to parse out to find the directory, and if they match can delete the share using net share. I could of course write this in a number of languages, or create a full blown app, but what fun is that lol?

    So I need help on how I can parse the NET SHARE results out.

    For example, suppose the NET SHARE output was something like this:
    Code:
    my test dir 2     c:\my test dir\test_dir\my test dir 2
    some_dir                   c:\my test dir\some_dir
    You can see my output will vary in structure. I understand a lot of the commands, but this one I am struggling with.

    Is there any batch geeks who might like to try and help me with this?

    Any help appreciated.

    geri.

    btw, been messing with permutations of this, trying to come up with something that works. Very messy and very verbose lol
    Code:
    @echo off
    SetLocal EnableDelayedExpansion
    for /f "skip=4 tokens=*" %%a in ('net share') DO SET M=!M!%%a:::
    
    ECHO %M%
    
    
    for /f "skip=4 tokens=2,3 delims= " %%a in ('net use ^| FIND /I "%1"') do (
    	echo share b.. %%b
       Set SHARE=%%b
       echo cho shar.. !SHARE!
       Set SHARE=!SHARE:%1=%2!
       echo cho shar end.. !SHARE!
    
    )
    echo cho =================
    
    For /F "skip=4 delims=<tab>" %%I IN ('net share') do (
    	set m=!m!%%I_
    	echo !m!
    )
    
    for /F "skip=4 tokens=* delims=*" %%I in ('net share') do (
    	echo I is ________ %%I
    	echo j is %%J
      REM ~ set share=%%i
      echo cho nxi .. %%~nxI
      echo cho nxj--....  %%~nxJ
      REM ~ echo cho XXX.. %%~dp$PATH:I
      REM ~ echo choZZZZ %%~ftzaI
      SET fat=%%I
      SET fat=!fat: =.!
      echo fat is now !fat!
      SET Var=%%~nxI
      echo cho var now.. !Var!
      REM ~ SET share=%%~nxI
      SET Var=!Var: =_!
    
      REM ~ SET var=!Share:~0,%_alen%!
      echo this is.. !Var!
    
    )
     
  2. geriatric

    geriatric Thread Starter

    Joined:
    Aug 26, 2003
    Messages:
    10
    I got it to work, but its long and complicated because I don't know all the right tricks of the trade yet lol.

    It steps through the output of net share, cleaning up the whitespace, to find all the share names. It then compares the found names to the input parameter, and removes the share.

    Maybe there is some kind soul who would care to teach an oaf like myself how to stream-line this. If not, maybe someone along the way can get something useful out of it.

    Code:
    :unshare
    :: stop sharing specific shared directories
    IF /I [%2]==[] GOTO :bye
    IF NOT EXIST %2 GOTO :bye
    FOR /D %%I IN (%2) DO SET sname=%%~nxI
    
    FOR /F "skip=4 tokens=1,2 delims=:" %%I IN ('net share') DO (
    	SET xshare=%%I
    	SET xpath=%%J
    	IF DEFINED xpath (
    		SET xshare=!xshare:~0,-1!
    		FOR /L %%Q IN (1,1,100) DO IF "!xshare:~-1!"==" " SET xshare=!xshare:~0,-1!
    		IF "!xshare!" EQU "" (
    			REM ~ do nothing
    		) ELSE (
    			IF "!xshare!" EQU "The command completed successfully." (
    				REM ~ do nothing
    			) ELSE (
    				IF /I "!xshare!" EQU "!sname!" (
    					NET SHARE "!xshare!" /del
    					GOTO :xrem_rights
    					GOTO :bye
    				) ELSE (
    					REM ~ do nothing
    				)
    			)
    		)
    	) ELSE (
    		FOR /L %%Q IN (1,1,100) DO IF "!xshare:~-1!"==" " SET xshare=!xshare:~0,-1!
    		IF "!xshare!" EQU "" (
    			REM ~ do nothing
    		) ELSE (
    			IF "!xshare!" EQU "The command completed successfully." (
    				REM ~ do nothing
    			) ELSE (
    				IF /I "!xshare!" EQU "!sname!" (
    					NET SHARE "!xshare!" /del
    					GOTO :xrem_rights
    					GOTO :bye
    				) ELSE (
    					REM ~ do nothing
    				)
    			)
    		)
    	)
    )
    GOTO :bye
    geri.
     
  3. foxidrive

    foxidrive Banned

    Joined:
    Oct 20, 2012
    Messages:
    793
    You don't specify what the input data is.

    if it is a sharename to remove then you can test for it's existence and just remove it if it is found:

    Code:
    net share |findstr /i /c:"%~1">nul && net share "%~1" /del
     
  4. geriatric

    geriatric Thread Starter

    Joined:
    Aug 26, 2003
    Messages:
    10
    My apologies, I thought in my first thread this might explain it
    but then, walls of text like mine usually are don't help ;)

    Yes, then, the input is a FQP, already quoted, from context menu command. This is a, umm, short piece of code you present lol. Lets see if I follow it, as I haven't ran it yet.

    Code:
    net share |findstr /i /c:"%~1">nul && net share "%~1" /del
    net share is piped to findstr.
    findstr is looking for %1 with no case sense and using literal string, output to nul
    the double & is going to process to the right if the left produces errorlevel 0?
    so the logic flow is that findstr searches the resulting output (aka findstr's input) of net share, and it is findstr that returns a 0 errorlevel? or does redirecting to nul produce the errorlevel? I understand I think what the logic is, I don't however understand how you decided to use the && - that is, how you know what errorlevel to expect when piping and redirecting like that. Can you explain that part at all?

    How can I catch this if I wanted to, as success or failure? When you do multiple commands on one line, is it always the last command that you trap the errorlevel for?

    Also, is the use of "%~1" meant to remove any quotes if they exist, but then ensure they are present if needed? So if the registry command was: batchfile.bat "%1", that command will strip my quotes, making sure to replace them, but if there were no quotes, it does nothing and still encloses?

    One more thing. Have you ran this at all? I will in a bit here, but when I tried using findstr with the output of net share, it hangs on win7. This appears to be the behaviour of findstr if there is no crlf? It did this multiple times when I tested it, so I used find instead. I will give this a go later today when I have time to work on it and see what happens.

    Thanks for taking the time to reply. Much appreciated. Sorry for so many additional questions, but I like to understand things.

    geri.
     
  5. foxidrive

    foxidrive Banned

    Joined:
    Oct 20, 2012
    Messages:
    793


    This might work: and the %~nx1 will return the share name, if it assumed to be the same as the folder name.




    Code:
    net share |find /i "%~1">nul && (net share "%~nx1" /del || echo share deletion failed && echo share deleted successfully)
     
  6. geriatric

    geriatric Thread Starter

    Joined:
    Aug 26, 2003
    Messages:
    10
    Your first idea appears to work using findstr. Here is what I used
    Code:
    net share |findstr /i /c:"%~1">nul && (net share "%~1" /del || echo share deletion failed && echo share deleted successfully)
    The output of net share when piped into findstr likely has a crlf at the end of the total output. I was using it in a FOR /F loop, so each "line" likely had no termination. It sounds like the case anyway.

    I like the idea of using "%~nx1" to get the drive letter out of the equation. However, wouldn't "%~n1" be better, as we are dealing explicitly with containers and not objects? Is there a caveat I am not aware of that one would want to use nx1 instead of n1?

    My code looks too much like script languages I think. I don't make good use of piping and redirection. Replies like yours offer a lot of valuable ideas. Thanks!!

    geri.

    EDIT: I found out that when using net share <sharename> /del, that you can use a FQP so you don't need the actual share name as represented. I did not know that, and makes the whole thing much easier! Again, thanks for spurring the creative juices!
     
  7. foxidrive

    foxidrive Banned

    Joined:
    Oct 20, 2012
    Messages:
    793
    beauty! I didn't know that and am happy to learn it too.

    Cheers
     
  8. geriatric

    geriatric Thread Starter

    Joined:
    Aug 26, 2003
    Messages:
    10
    That one-liner is awesome. Replaced 3 pieces with that one. Very nice.

    I am afraid though, I am still struggling with my original issue.

    If we suppose that the NET SHARE output looks like this
    Code:
    Share name   Resource                        Remark
    
    -------------------------------------------------------------------------------
    _temp_Control_Panel_Client
                 C:\Program Files\NVIDIA Corporation\Control Panel Client
    
    purple place C:\Program Files\Microsoft Games\Purble Place\en-US
    
    test dir f   F:\test dir f
    test share 2 C:\test share\test share 2
    The command completed successfully.
    we can see that one share is actually in two lines.

    The shares are created by the batch script in two ways. One is with the line provided by foxidrive, passing the FQP to the script, and the share is made exactly as the directory is, spaces included. Removing these shares is easy also, thanks again to foxidrive, as I used his/her idea to remove the share too.

    The other way shares are created is to replace all spaces with underscores, and prepend a marker to the name. For example, the directory "c:\program files\microsoft games\purble place" would be shared AS _temp_Purble_Place (where _prepend would be a unique marker, like _temp_ ). This gives me a way to easily find any share with the prepend value of _temp_ and remove the shares with something simple like this (where _alen is the length of the _prepend value)
    Code:
    FOR /F "skip=4" %%I IN ('NET SHARE') DO (
    	SET Share=%%I
    	SET var=!Share:~0,%_len%!
    	IF "!var!"=="!_prepend!" (
    		NET SHARE !Share! /del
    		REM ~ CALL :rem_loop
    	)
    )
    This is easy enough, as I can extract the _prepend value and find matches easily. This works because the resulting output of the loop is always going to be the first token, and when the share name has no spaces, it will always be the full share name (or at least something I can check on). So I pull the first X number of characters, see if they match my marker, and if so, remove the share.

    However, note the CALL I am trying to do. The purpose of this call is to use ICACLS on each share that was removed, to also remove the DACL rights of everyone that was assigned earlier by the script.

    The problem lies in that the FOR loop will return only the share name, or only the path of the share, or sometimes even the share name and path may contain whitespace. You can see in my second reply that long FOR loop gets rid of whitespace and successfully removes the share. It then calls the ICACLS function to remove the rights based on the input (aka %2 in this case, which is the FQP to the directory being worked on).

    I know, a lot of text here, but I don't know how to describe it without details. I am sure I can hack up a nice long FOR loop, but is there some way to do this that is less confusing, and maybe cleaner?

    To sum it up:
    I need a way to step through the net share output, gathering both the share name and the FQP of the share. Any whitespace needs to be removed. Then I can use (as we found out) just the FQP to remove the share and also remove the rights using ICACLS.

    Thank you again for anyone willing to help.

    geri.
     
  9. geriatric

    geriatric Thread Starter

    Joined:
    Aug 26, 2003
    Messages:
    10
    I think I solved it.

    Assume that a directory is shared, such as
    C:\Program Files\NVIDIA Corporation\Control Panel Client
    and assume that it was shared AS _temp_Control_Panel_Client

    Now assume that you had multiple shares using _temp_ in the naming structure, and that you wanted to remove all of these "_temp_" shares at one time. You might not be able to use NET SHARE to do this because the output of it might look like this:
    Code:
    Share name   Resource                        Remark
    
    -------------------------------------------------------------------------------
    _temp_Control_Panel_Client
                 C:\Program Files\NVIDIA Corporation\Control Panel Client
    
    _temp_Uninstall
                 C:\Program Files\NVIDIA Corporation\Uninstall
    
    purple place C:\Program Files\Microsoft Games\Purble Place\en-US
    
    test dir f   F:\test dir f
    test share 2 C:\test share\test share 2
    The command completed successfully.
    As you can see, for some reason the share name and the share path are not on the same line. It can be done, but is overly complicated. Instead, you can do a reg query to find all the current shares, and parse the result out, looking for the _temp_ value. Something like this:
    Code:
    @ECHO OFF
    SETLOCAL EnableDelayedExpansion
    
    SET vRegQuery=reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Shares /t REG_MULTI_SZ /se #
    FOR /F "skip=2 tokens=*" %%S IN ('%vRegQuery%') DO (
    	ECHO %%S | FINDSTR /I /B /C:"_temp_">NUL && (
    	FOR /F "tokens=3,5 delims=#" %%H IN ('ECHO "%%S"') DO (
    		set ll=%%H&set ll=!ll:~5!&echo !ll! - the full path, can do something with it
    		set jj=%%I&set jj=!jj:~10!&echo !jj! - the share name, can do something with it
    		)
    	)
    )
    
    EXIT
    The result is all share names that have the _temp_ at the beginning of the name, and the FQP to the share. Now you can call NET SHARE <FQP> /del and remove all those shares. If, as in my case, you also need to call ICACLS, you have the FQP, not just the share name.

    Maybe there is a better way to do this? I am always open to being taught new tricks ;)

    One other thing I found (new to me anyway) was that when FINDSTR gets stuck in situations where there is no crlf at the end, you can enter one yourself, or just use it to format your output on multiple lines rather than one. The trick is to assign the carat to a variable, and then leave two blank lines before any other syntax. You must also use EnableDelayedExpansion. Something like this:
    Code:
    @ECHO OFF
    SETLOCAL EnableDelayedExpansion
    SET LF=^
    
    
    :: the two blank lines are needed for LF to become a linefeed with !LF!
    
    :: first show how variable grows on one line
    SET lin1=this is line one, or first part of output
    SET lin1=!lin1!this is line two, or additional part of output
    ECHO !lin1!
    
    :: using the LF variable, you could do this
    SET lin1=this is line one, or first part of output
    SET lin1=!lin1!!LF!this is line two, or additional part of output
    ECHO !lin1!
    
    
    geri.
     
  10. foxidrive

    foxidrive Banned

    Joined:
    Oct 20, 2012
    Messages:
    793
    I'm glad you have a solution.

    I had only come up with shareEnum by Microsoft PStools (and Softperfect Network Scanner) which can export a list of sharenames and FQP in quoted format, but it's a GUI tool and you'd have to use sendkeys of similar to get a batch file to export the data. Querying the registry seems like a better plan.
     
  11. Sponsor

As Seen On
As Seen On...

Welcome to Tech Support Guy!

Are you looking for the solution to your computer problem? Join our site today to ask your question. This site is completely free -- paid for by advertisers and donations.

If you're not already familiar with forums, watch our Welcome Guide to get started.

Join over 733,556 other people just like you!

Thread Status:
Not open for further replies.

Short URL to this thread: https://techguy.org/1085575

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice