This hard task I need to do as a batch file, it's not the most difficult to do with C but in DOS is a hell (at least for me!) I need to convert a structure to a single var (string) to be able to convert them into that structure again inside my program. Don't worry about the comeback, it's already done.
The struct WILL vary in size and have an index inside [0] which need to be the first item in my var.
Here an exemple of these structures (just 3):
level.waypoints[0] = spawnstruct();
level.waypoints[0].origin = (1774.5,834.7,67.6);
level.waypoints[0].type = "stand";
level.waypoints[0].childCount = 2;
level.waypoints[0].children[0] = 1;
level.waypoints[0].children[1] = 6;
level.waypoints[1] = spawnstruct();
level.waypoints[1].origin = (1780.6,639.1,65.5);
level.waypoints[1].type = "stand";
level.waypoints[1].childCount = 2;
level.waypoints[1].children[0] = 7;
level.waypoints[1].children[1] = 0;
level.waypoints[2] = spawnstruct();
level.waypoints[2].origin = (1902.2,-345.2,74.2);
level.waypoints[2].type = "stand";
level.waypoints[2].childCount = 2;
level.waypoints[2].children[0] = 3;
level.waypoints[2].children[1] = 97;
level.waypoints[3] = spawnstruct();
level.waypoints[3].origin = ... (goes on...)
So the first structure:
level.waypoints[0] = spawnstruct();
level.waypoints[0].origin = (1774.5,834.7,67.6);
level.waypoints[0].type = "stand";
level.waypoints[0].childCount = 2;
level.waypoints[0].children[0] = 1;
level.waypoints[0].children[1] = 6;
I need to convert this structure into this line:
set flwp_0 "0,1774.5,834.7,67.6,stand,2,1,6"
Where 0 (flwp_) it's the index and also the first item inside "".
So the other 2 in this exemple will be:
set flwp_1 "1,1780.6,639.1,65.5,3,7,0,30"
set flwp_2 "2,1902.2,-345.2,74.2,2,3,97"
The childCount could be any value, but I don't believe will pass than 9.
So, how many childCount we have, more children will be in the next lines.
But I just need the values after the childCount value, so I with that value I know how much more items will be available in that string, so no problem.
I'm thinking removing everything I don't need first like (in order):
level.waypoints[
] = spawnstruct();
].origin = (
);
].type = "
";
].childCount =
].children[0] =
].children[1] =
].children[2] =
].children[3] =
].children[4] =
].children[5] =
].children[6] =
].children[7] =
].children[8] =
].children[9] =
;
This will left something like this in the first structure:
0
01774.5,834.7,67.6
0stand
02
01
06
Now I need to read that and transform into my single line string. But I'm having problems to know the right index because could be the first value, but if the index have 2 or 3 chars?
I also was thinking in replace with some info to track me, so will not replace the "]" of the files, so I'll know what is before that is the index and after that the values.
I was also trying to a loop without success creating a index like:
level.waypoints[X]
Where X is from 0 to 1000 (I don't believe will pass that number)
It's not working, maybe my first idea was better... :\
I need a batch file (or several) to convert several files which have structures like that inside to new files with the values as strings as I wrote in details above.
Any ideas?
Thank you!
#Squashman Also the result is a little messed up in the order as you can see:
set flwp_0 "0,1774.5,834.7,67.6,stand,2,1,6"
set flwp_100 "100,1636.76,371.924,240.125,stand,2,101,99"
set flwp_101 "101,1861.45,437.846,240.125,stand,2,102,100"
set flwp_102 "102,1843.93,557.03,240.125,stand,2,103,101"
set flwp_103 "103,1504.58,553.357,64.125,stand,2,8,102"
set flwp_104 "104,653.17,1675.32,64.125,stand,2,26,105"
set flwp_105 "105,338.784,1680.49,232.125,stand,2,104,133"
set flwp_106 "106,-919.398,1537.7,80.125,stand,3,107,109,150"
set flwp_107 "107,-928.311,1111.47,80.125,stand,3,108,106,149"
set flwp_108 "108,-696.488,1095.93,80.125,stand,2,36,107"
set flwp_109 "109,-787.781,1566.87,80.125,stand,2,106,110"
set flwp_10 "10,1423.3,-403.8,64.3,stand,4,11,12,15,3"
set flwp_110 "110,-754.274,1716.71,80.125,stand,2,109,34"
set flwp_111 "111,-736.201,1887.87,64.125,stand,4,112,34,151,152"
set flwp_112 "112,-454.293,1879.4,64.125,stand,4,111,33,34,152"
set flwp_113 "113,125.395,-451.579,58.6958,stand,3,51,114,142"
set flwp_114 "114,282.593,-447.87,68.125,stand,2,115,113"
set flwp_115 "115,304.311,-271.206,68.125,stand,2,116,114"
set flwp_116 "116,447.128,-292.167,68.125,stand,3,118,115,117"
set flwp_117 "117,437.415,-443.822,68.125,stand,2,67,116"
set flwp_118 "118,582.932,-297.811,126.125,stand,2,119,116"
set flwp_119 "119,561.586,-485.701,204.125,stand,2,120,118"
set flwp_11 "11,1240.1,-249.7,74.1,stand,5,9,16,10,12,15"
set flwp_120 "120,423.422,-470.754,204.125,stand,2,119,135"
set flwp_121 "121,1164.82,-1203.64,72.125,stand,4,123,14,126,122"
set flwp_122 "122,1064.12,-1299.76,72.125,stand,3,123,125,121"
set flwp_123 "123,1117.59,-1476.49,72.125,stand,3,124,122,121"
set flwp_124 "124,861.878,-1497.7,72.125,stand,2,125,123"
set flwp_125 "125,878.58,-1294.38,72.125,stand,2,124,122"
Is possible to write in the file in the right order?
thank you very much again for the help #Squashman
cheers
Ok, really doesn't matter the order, but I'm getting trouble to make do it to everyfile into a new one... I tryed this without success:
#echo off
setlocal enabledelayedexpansion
for %%f in (*.gsc) do (
FOR /F "tokens=1-2 delims==;^(^) " %%G IN (%%f) do set %%~G=%%~H
FOR /F "tokens=2 delims=[]" %%G IN ('set level.waypoints ^|find /I "spawnstruct"') do (
SET waypoints=!waypoints! %%G
)
FOR %%G IN (%waypoints%) do (
set line=%%G,!level.waypoints[%%G].origin!,!level.waypoints[%%G].type!,!level.waypoints[%%G].childCount!
FOR /F "tokens=2 delims==" %%H IN ('set level.waypoints[%%G].children') DO set line=!line!,%%H
set line=set flwp_%%G "!line!"
echo !line! >> %%f.cfg
)
)
pause
Any clues?
=======================================
Ok, now we are VERY close! Need to process ONLY the lines with level.waypoints[ and the rest must be ignored, and also add a final close var that I already did with success below:
#echo off
setlocal enableDelayedExpansion
set findtext="level.waypoints["
for %%F in (*.gsc) do (
set "out="
set "i=x"
> "%%~nF.cfg" (
for /f usebackq^ tokens^=2^,4^,5^ delims^=[]^=(^)^;^"^ %%A in ("%%F") do (
if %%A neq !i! (
if defined out echo !out!"
set /a "i=%%A, j=0"
set "out=set flwp_!i! "!i!"
) else (
set /a j+=1
if !j! leq 3 (set "out=!out!,%%B") else set "out=!out!,%%C"
)
)
if defined out echo !out!"
set /a "fim=i+1"
echo set flwp_!fim! "eof"
)
)
Now how can I add findstr %findtext% into these loops? I tryed in many different ways, but the syntax is wrong... Could you help me? :D
Thank you very much #Squashman and #dbenham for all the help until now.
Cheers
Here is a relatively fast pure batch solution that uses a single FOR /F loop for each file. It is significantly faster than Squashman's solution.
I set DELIMS and TOKENS to parse out all needed data elements, no matter which line I am parsing. I don't worry about the value of childCount. Instead I simply detect the change of the waypoint index to signal the start of a new record, and an incrementing waypoint line number (j variable) is used to identify which tokens are needed from each line. Each line adds new text to the out variable.
#echo off
setlocal enableDelayedExpansion
for %%F in (*.gsc) do (
set "out="
set "i=x"
> "%%~nF.cfg" (
for /f usebackq^ tokens^=2^,4^,5^ delims^=[]^=(^)^;^"^ %%A in ("%%F") do (
if %%A neq !i! (
if defined out echo !out!"
set /a "i=%%A, j=0"
set "out=set flwp_!i! "!i!"
) else (
set /a j+=1
if !j! leq 3 (set "out=!out!,%%B") else set "out=!out!,%%C"
)
)
if defined out echo !out!"
)
)
The above is able to process a 23 MB file on my machine in 70 seconds.
But I can do better if you allow yourself to go outside the bounds of pure batch. Here is an efficient JREPL.BAT solution that makes use of new version 6.0 features that were released just moments ago.
JREPL.BAT is a regular expression text processing utility for Windows. It is pure script (hybrid batch/Jscript) that runs natively on any Windows machine from XP onward. No 3rd party exe files are required.
Extensive documentation is available from the command line via jrepl /?, or jrepl /?? for paged help.
This solution should be able to handle files approaching 1 GB in size. Each file is processed completely by a single call to JREPL.BAT. It should be very efficient, as there is minimal back-tracking required. For small files, it will be slower than the pure batch method due to the startup time of the CSCRIPT engine. But for large files it is much faster than pure batch.
The code below processes the same 23 MB file in only 11 seconds :-)
This first version breaks construction of the complicated regex terms into steps, and includes commented numbers above each captured group to give you a chance at fathoming how it works. In particular, read the documentation for the /T and /P options. And also bone up on your regex skills!
#echo off
setlocal
set "filter=(.*?\[\d+])[\s\S]*?(?:\n(?!\1)|(?![\s\S]))"
:: 1 2 3 4
set "find1=l.*?\[(\d+)\][\s\S]*?\((\d.*?)\)[\s\S]*?\q(.*?)\q"
set "repl1=set flwp_$2 \q$2,$3,$4"
:: 5 6
set "find2=;[\s\S]*? = (\d+)"
set "repl2=,$6"
:: 7
set "find3=[\s\S]+"
set "repl3=\q\n"
set "find=%find1%|%find2%|%find3%"
set "repl=%repl1%|%repl2%|%repl3%"
for %%F in (*.gsc) do (
call jrepl.bat "%find%" "%repl%" /t "|" /p "%filter%" /x /m /f "%%F" /o "%%~nF.cfg"
)
And here is the exact same solution, but without showing any of the intermediate steps. I did include line continuation to improve readability.
#echo off
for %%F in (*.gsc) do (
call jrepl.bat "l.*?\[(\d+)\][\s\S]*?\((\d.*?)\)[\s\S]*?\q(.*?)\q|;[\s\S]*? = (\d+)|[\s\S]+"^
"set flwp_$2 \q$2,$3,$4|,$6|\q\n"^
/p "(.*?\[\d+])[\s\S]*?(?:\n(?!\1)|(?![\s\S]))"^
/t "|" /x /m /f "%%F" /o "%%~nF.cfg"
)
I suppose the fastest script solution would be a custom built JScript or VBS script. But I enjoy working with JREPL :-)
Update: Here is a little bonus - a JREPL script that will convert *.cfg back to *.gsc
#echo off
setlocal
set "beg=var pre,i,q='\x22',n='\r\n'"
:: 1 2 3 4 5 67
set "find=^.*?\q(\d+),(.*?,.*?,.*?),(.*?),(.*?),|(.*?)[,\q]"
set "repl=i=0;pre='level.waypoints['+$2+']';$txt=pre+' = spawnstruct();'"
set "repl=%repl%+n+pre+'.origin = ('+$3+');'"
set "repl=%repl%+n+pre+'.type = '+q+$4+q+';'"
set "repl=%repl%+n+pre+'.childCount = '+$5+';'"
set "repl=%repl%|$txt=n+pre+'.children['+(i++)+'] = '+$7+';'"
for %%F in (*.cfg) do (
call jrepl.bat "%find%" "%repl%" /x /t "|" /jq /jbeg "%beg%" /f "%%F" /o "%%~nF.gsc"
)
Edited the code with your new requests.
#echo off
FOR %%F IN (*.gsc) DO (
setlocal enabledelayedexpansion
FOR /F "usebackq tokens=1-2 delims==;^(^) " %%G IN (`find /I "level.waypoints["^<"%%F"`) do set %%~G=%%~H
(FOR /F "tokens=2 delims=[]" %%G IN ('find /I "spawnstruct" ^<"%%F"') do (
set line=%%G,!level.waypoints[%%G].origin!,!level.waypoints[%%G].type!,!level.waypoints[%%G].childCount!
FOR /F "tokens=2 delims==" %%H IN ('set level.waypoints[%%G].children') DO set line=!line!,%%H
set line=set flwp_%%G "!line!"
echo !line!
))>"%%~nF.cfg"
endlocal
)
pause
I am totally new to DOS. Infact I am a Java guy. I need to do some string search operations but unfortunately string search & file search operation in java is considerably slow. And its very fast in OS.
So here is my problem. I need to search all files with fixed extension (.sp) for strings (all lines) between 2 fixed characters. They are ';' & ';'
Here is the content of one of .sp file.
File:- Tons.sp
line 1: Skipcheck;
line 2: [Scenario:'Actual']=STET;
line 3: ['WFS':'Actual','Scenario':'Actual','Measure':'Units']=N:
line 4: IF( SUBST( !Measure, 1, 1) #= '8'
line 5: ,
line 6: ['Amount']
line 7: ,
line 8: STET
line 9: );
line10:
line11: ['Tons'] = N:
line12: DB('Volume Master',!Version,!Year,!Plant,'GL_CODE_0004',!Period,!Measure) ;
line13:
line14: ['Group1_Volume'] = N:
line15: IF ( ELISANC( 'Plant', 'Group1' , !Plant )=1
line16: , ['Take_This']
line17: , CONTINUE
line18: );
line19:
line20: ['Tons Trend']=N:
line21: IF( DB('Monthly_Trend', !Period, 'Tons_Trend_Factor') > 0
line22: , 'Current_Tons' * DB('Volume Master',!Version,!Year,!Plant,'GL_CODE_TonsProduced',!Period,!Measure)
line23: , CONTINUE
line24: );
Please Note: line numbers are just for indication.
Problem 1: Now I need to find the string (all lines) that lie between ';' & ';' that contains string "DB('Volume Master'"
ie.: The findstring will be something like this:-
FINDSTR /n "=*DB('Volume Master'*;" *.sp
The result of above command should be line 10 to 12 & line 19 to 24
line10:
line11: ['Tons'] = N:
line12: DB('Volume Master',!Version,!Year,!Plant,'GL_CODE_0004',!Period,!Measure) ;
&
line19:
line20: ['Tons Trend']=N:
line21: IF( DB('Monthly_Trend', !Period, 'Tons_Trend_Factor') > 0
line22: , 'Current_Tons' * DB('Volume Master',!Version,!Year,!Plant,'GL_CODE_TonsProduced',!Period,!Measure)
line23: , CONTINUE
line24: );
Problem 2: The output of this:-
FINDSTR /n "=*DB('Volume Master'*'GL_CODE_TonsProduced'*;" *.sp
should be:-
line19:
line20: ['Tons Trend']=N:
line21: IF( DB('Monthly_Trend', !Period, 'Tons_Trend_Factor') > 0
line22: , 'Current_Tons' * DB('Volume Master',!Version,!Year,!Plant,'GL_CODE_TonsProduced',!Period,!Measure)
line23: , CONTINUE
line24: );
Please help.
Thanks
Krishna
#ECHO Off
SETLOCAL
SET "destdir=U:\destdir"
SET "target=DB('Volume Master'"
SET "target=DB('Volume Master'.*'GL_CODE_TonsProduced'"
SET "blockend=;"
DEL "%destdir%\res*" 2>nul
FOR /f "delims=" %%a IN (q24237940.txt) DO (
>>"%destdir%\res.tmp" ECHO(%%a
ECHO(%%a|FINDSTR /l /c:"%blockend%">NUL
IF NOT ERRORLEVEL 1 (
FINDSTR /r /c:"%target%" "%destdir%\res.tmp" >NUL
IF NOT ERRORLEVEL 1 TYPE "%destdir%\res.tmp" >>"%destdir%\res.txt"
DEL "%destdir%\res.tmp" /F /Q
)
)
GOTO :EOF
I used a file named q24237940.txt containing your data for my testing.
I've used variables for convenience; destdir containing the destination directory for the resultant file, target for the target string which must occur within the block and blockend for the string that indicates end-of-block.
Note that I've left both targets in the code, the later one will be used. findstr finds on a line-by-line basis, so DB... and GL_CODE... must occur on the same line in this example. Since findstr has an attempt at using regular expressions, .* means any number of any character - where the characer set does not include newline.
In essence, create res.tmp containing a block at a time, and when end-of-block is found, detect whether that tempfile contains the magic string; append it to res.txt if it does.
Windows Vista and 7 has this switch in Network and Sharing Center. It's on by default, and that prevents unauthenticated access to shares even if they're shared with Everyone (like the Public folder). I need to teach my application to turn it on and off automagically. How? I suspect there is a value somewhere in the registry that's responsible for this, but I have no idea how to find it.
Probably too late :) , but hopefully useful for others.
The following steps worked just fine for me (it worked on W8 consumer preview too).
to turn it off:
1 - Enable guest account by running
net user guest /active:yes
2 - Obtain guest user SID by running, for example,
wmic useraccount where name='guest' get sid
3 - Obtain write access to registry folder HKLM\SECURITY
4 - Modify the following key, where $SID is the sid obtained in point 2, to:
[HKEY_LOCAL_MACHINE\SECURITY\Policy\Accounts\$SID\ActSysAc]
#=hex(0):41,00,00,00
5 - restart the machine (until now, I didn't find a better way to make the change effective)
to turn it on again:
[HKEY_LOCAL_MACHINE\SECURITY\Policy\Accounts\$SID\ActSysAc]
#=hex(0):c1,00,00,00
then restart
Export the complete register as 1.reg, turn sharing on (or off, if it was on), export to 2.reg and check for the differences?
To be able to use the diff utility, export the files in Win9X/NT4 registration files (*.reg) -format
Here is a powershell script that implements paolos answer. It is unpolished as it permits everybody write access to the specific registry key (The [7] part specifies this with regini syntax) and uses a file in C:\ root but works flawless:
# Get guest user id
$SID = & "wmic" "useraccount" "where" "name='guest'" "get" "sid" "/Value" | Out-String
$SID = $SID.Trim().Substring(4)
# Generate regini script
$PATH = "\Registry\Machine\Security\Policy\Accounts\" + $SID + "\ActSysAc"
$PATH + " [7]`r`n" + $PATH + "`r`n# = REG_NONE 4 0x41 0x00 0x00 0x00" >> "C:\firstrun.regini"
# Execute regini script
& "regini" "C:\firstrun.regini"
It is in the registry just not necessarily in the place you are expecting (it is in the SAM). From what I can tell all that setting does is enable or disable the guest account, so, well, just enable or disable the account.
You didn't say what you programming language you are using, so here is some simple C code to enable an account, if you need anything else I am sure there is plenty around via google.
#include <LM.h>
#pragma comment(lib, "Netapi32.lib")
BOOL EnableUser(LPCWSTR lpUserName, BOOL bEnable)
{
BOOL bRet = FALSE;
DWORD dwLevel = 1008;
LPUSER_INFO_1 ui1;
USER_INFO_1008 ui1008;
NET_API_STATUS nStatus;
nStatus = NetUserGetInfo(NULL, lpUserName, 1, (LPBYTE*)&ui1);
if(nStatus == NERR_Success)
{
ui1008.usri1008_flags = ui1->usri1_flags;
if(bEnable)
{
ui1008.usri1008_flags &= ~UF_ACCOUNTDISABLE;
}
else
{
ui1008.usri1008_flags |= UF_ACCOUNTDISABLE;
}
nStatus = NetUserSetInfo(NULL, lpUserName, dwLevel, (LPBYTE)&ui1008, NULL);
NetApiBufferFree(ui1);
if(nStatus == NERR_Success)
{
bRet = TRUE;
}
}
return bRet;
}
I tested Paolo's answer on windows 7 Home without success.
Comparing the .reg extraction of the registry before and after turning off the password protected sharing, I noticed modifications in 3 values:
[HKEY_LOCAL_MACHINE\SECURITY\Policy\Accounts\S-1-5-21-3207962671-1026919178-1165869658-501\ActSysAc] REG_NONE value's first byte changed from c1 to 41 (this SID is the guest account's SID)
[HKEY_LOCAL_MACHINE\SECURITY\SAM\Domains\Account] REG_BINARY "F" value's 17th byte changed from 3b to 3c
[HKEY_LOCAL_MACHINE\SECURITY\SAM\Domains\Account\Users\000001F5] REG_BINARY "F" value's 57th byte changed from 15 to 14 (0x1F5 is the type of the guest's Names value)
I tried changing only the first value as indicated by Paolo. This did not change the password protected sharing even after reboot.
But I had success when changing the 57th byte between 14 and 15 only for the third value:
[HKEY_LOCAL_MACHINE\SECURITY\SAM\Domains\Account\Users\000001F5] REG_BINARY "F".
I tested with success on another windows 7 computer.
Take a look at this file (disable_password_protected_sharing.bat)
#echo off
echo 12- get sid gust variable
for /f "delims= " %%a in ('"wmic useraccount where name='guest' get sid"') do (
if not "%%a"=="SID" (
set sid_guest=%%a
goto :loop_end
)
)
:loop_end
echo 13- create script for regini
#echo \Registry\Machine\SECURITY [1 5 7 11 17 21]> x
#echo \Registry\Machine\SECURITY\policy [1 5 7 11 17 21]>> x
#echo \Registry\Machine\SECURITY\policy\accounts [1 5 7 11 17 21]>> x
#echo \Registry\Machine\SECURITY\policy\accounts\%sid_guest% [1 5 7 11 17 21]>> x
#echo \Registry\Machine\SECURITY\policy\accounts\%sid_guest%\ActSysAc [1 5 7 11 17 21]>> x
echo 14- add permission for machine/security
net user guest /active:yes
regini x
del x
#echo Windows Registry Editor Version 5.00 > y.reg
#echo [HKEY_LOCAL_MACHINE\SECURITY\Policy\Accounts\%sid_guest%\ActSysAc] >> y.reg
#echo #=hex(0):41,00,00,00 >> y.reg
reg import y.reg
del y.reg
echo Windows will now reboot.
Pause
shutdown -r
it works fine in windows7