|
|
|||||||
Hey guys I am off doing another little project this is my algorithm that I want to perform. there is more to it but i have that down pat this is what i want to do in for each loop: Code: for each $Element in $PClist open file "fsp.ini" look for string line "pcAlias=" and swap with it "pcAlias=$Element" close file "fsp.ini" next what string manip function or syntax does kix provide any examples thank you happy thanksgiving to you all |
||||||||
|
|
|||||||
You could read the file into an array with the ReadFile() UDF, get the location of "pcAlias=" with ASCAN, change the value, and re-write the file with the WriteFile() UDF: Code: for each $Element in $PClist $array = ReadFile("fsp.ini") $loc = AScan($array, "pcAlias=",,,1) if $loc <> -1 $array[$loc] = "pcAlias="+$Element $ = WriteFile("fsp.ini",$array) endif next However, the logic you have mapped out would ultimately just replace the same line in the same file repeatedly until the end of the array, so I'm a little confused as what you're really trying to do... |
||||||||
|
|
|||||||
thank you for replying eriqjaffe do i really need the if/endif condition? since when it finds it it is going to write to and move on due to the for each/next loop? just curious wha you think? Code: for each $Element in $PClist $array = ReadFile("fsp.ini") $loc = AScan($array, "pcAlias=",,,1) $array[$loc] = "pcAlias="+$Element $ = WriteFile("fsp.ini",$array) copy fsp.ini to \\$Element\c$\Windows\ ;my psuedocode next eriqjaffe does this makes sense? |
||||||||
|
|
|||||||
RTFM!! 15 years writing Kix scripts and I still have a hardcopy manual on my desk that I reference regularly! INI file manipulation is done via ReadProfileString and WriteProfileString functions - it's like using a very simple database. Use standard file I/O and you've got a headache. Look for EnumINI UDFs to help you explore the contents of the INI file. Glenn |
||||||||
|
|
|||||||
okay glenn will do thanks yeah a reference is very handy -Robert |
||||||||
|
|
|||||||
eriqjaffe how is this? Code: for each $Element in $PClist $array = ReadFile("fsp.ini") $loc = AScan($array, "pcAlias=",,,1) $array[$loc] = "pcAlias="+$Element $ = WriteFile("fsp.ini",$array) Shell "CMD.EXE /C xcopy fsp.ini \\$Element\C$\WINDOWS\ /-Y" next |
||||||||
|
|
|||||||
No need to shell out, you could just have WriteFile() directly write the file. Now that I see a bit more what you're going for, there really isn't any need to look for that string every time, either: Code: $array = ReadFile(@SCRIPTDIR+"\fsp.ini") $loc = AScan($array, "pcAlias=",,,1) if $loc <> =1 for each $Element in $PCList $array[$loc] = "pcAlias="+$Element $ = WriteFile("\\"+$Element+"\c$\windows\fsp.ini") next endif |
||||||||
|
|
|||||||
eriqjaffe this is what I have it just hangs? not sure why? can you see what I am doing wrong. It looks right but when I execute it with the command cmd like this kix32.exe fspreplace.kix it juts hangs nothing happens?? Code: Break On Dim $PCList Dim $array Dim $loc $PCList = "isasst", "isasst", "isasst" $array = ReadFile("fsp.ini") $loc = AScan($array, "pcAlias=",,,1) if $loc <> =1 for each $Element in $PCList $array[$loc] = "pcAlias="+$Element $ = WriteFile("\\"+$Element+"\c$\windows\fsp.ini") ? $Element next endif ;************************************ ; ReadFile() UDF ;************************************ ;Function ReadFile() ; ;Author Radimus ; ;Contributors Lonky... This is basically his code that I trimmed down to its ; simplest function ; ;Action Reads a file into an array ; ;Syntax $array=ReadFile($file) ; ;Version 1.0.1 ; ;Date 10/21/2003 ; ;Date Revised 10-22-2003 - dimmed vars ; ;Parameters file ; source filename ; ;Remarks Pair this with WriteFile() to read and write an entire file easily ; ;Returns @error if failed ; ;Dependencies None ; ;KiXtart Ver 4.02 ; ;Example(s) $array=ReadFile('c:\file.txt') Function ReadFile($file) Dim $lf, $f, $_, $t $lf=chr(10) $f=freefilehandle $_=open($f,$file) if @error exit @error endif do $t=$t+$lf+readline($f) until @error $_=close($f) $ReadFile=split(substr($t,2),$lf) EndFunction ;************************************ ; WriteFile() UDF ;************************************ ;Function WriteFile() ; ;Author Radimus ; ;Contributors Lonky ; ;Action Writes an array as a file ; ;Syntax WriteFile('filename','array') ; ;Version 1.1 ; ;Date 10/21/2003 ; ;Date Revised 11/13/2003 ; ;Parameters file ; destination filename ; array ; an array of data to write to a file ; ;Remarks Pair this with ReadFile() to read and write an entire file easily ; ;Returns @error if failed ; ;Dependencies None ; ;KiXtart Ver 4.02 ; ;Example(s) $=WriteFile('c:\file.txt',$array) Function WriteFile($file,$array) Dim $, $f, $line If Not VarType($Array) & 8192 Exit(1) EndIf $f=freefilehandle $=open($f,$file,5) if @error exit @error endif for each $line in $array $=writeline($f,$line+@crlf) if @error exit @error endif next $=close($f) EndFunction |
||||||||
|
|
|||||||
Robert - Please post your INI file (or part of it, starting from the [SECTION] that contains the data you're trying to manipulate.. this can probably be reduced to 1 or 2 lines and be solved in a heartbeat. Glenn |
||||||||
|
|
|||||||
Or 3... Code: For Each $Element in $PClist $=WriteProfileString("C:\MyIni.ini","MySECTION","pcAlias",$Element) Next |
||||||||
|
|
|||||||
I wasn't counting the "glue" code.. I'm thinking that a ReadProfileString to determine if the value exists in the section (maybe) and a WriteProfileString to update it is all that would be necessary to change the setting. It depends on whether the value "must contain specific data IF it exists" or the value "must exist with specific data". Enumerating an INI file via traditional file read/write methods can become convoluted by comparison to using EnumINI to get a list of sections, and a loop of Read & WriteProfileString calls to check for and update the data. Glenn |
||||||||
|
|
|||||||
I do agree, a ReadProfileString might be needed if the value contains data that musn't be overwritten. |
||||||||
|
|
|||||||
The reason I am doing this is because I have scripts that install an MSI file on each machine and this program/msi uses a ini file called fsp.ini. If I need to for any reason uninstall the msi file with a switch /u, it destroys the fsp.ini file. which means that I have to remote into 150 PCs and change one line entry "pcAlias=(blank)" to "pcAlias=(pcname)".(each pass of the fsp.ini mod will have the previous pcname to the right of the "=" sign). There is only one entry that is exclusive and that is the pcname on the right side of "pcAlias=" and the rest of the "ini" file is the same canned soup for each pc. The only thing that changes is the pcname so I want to auto generate it. I already use the LDAP program yo guys helped me build to fill my arrays of $Elements up so I just need to do the simple algorithm I have outline below. and sorry sow late getting back to you all. I have been sick as a dog. when i get sick PC time is at a hault. but I am better now. thank you Glenn and Apronk for your help! you dudes rock! so what do you think after all this info???? Code: /* my algorithm ; trying to kee it simple */ for each $Element in $Branch file open read in line that matches "pcAlias=" swap string "pcAlias=" with "pcAlias=$Element" writeline that is "pcAlias=$Element" file close copy fsp.ini to that $Element Next $Element Code: /* this is top of the ini file called fsp.ini */ [Ubs] LastUser=rvand pcAlias=pcname PortNumber=9600 HostName=192.168.1.94 SessionName=Original Session /* there is more but the top is all I need */ |
||||||||
|
|
|||||||
Well, if the ini file is always structured the same, there's really no need to go looking for the line. Going back to my original solution... Code: for each $Element in $PClist $array = ReadFile("fsp.ini") $array[2] = "pcAlias="+$Element $ = WriteFile("\\"+$Element+"\C$\fsp.ini",$array) next |
||||||||
|
|
|||||||
eriqjaffe thanks for you help. I am alittle confused. I am going to interpret your code to the right let me know if I am on right track. Code: for each $Element in $PClist $array = ReadFile("fsp.ini") /* read entire ini file into array $array[2] = "pcAlias="+$Element /*set value array(2) to string value $ = WriteFile("\\"+$Element+"\C$\fsp.ini",$array)/* write array back to file? next but how does this code know where to remove and replace the string it has to remove and replace the exact line of code????? that last line seems to copy the fsp.ini to a pc via UNC path sure but it write the entire array back to file? how does it remove and replace the exact line string pcAlias=previouspcname with pcAlias=newpcname???? |
||||||||
|
|
|||||||
Glenn and Apronk I will look into the UDF Enumini for sure that seems more like it thanks for your help guys |
||||||||
|
|
|||||||
I see something I neglected to put in the code. This may be better: Code: for each $Element in $PClist $array = ReadFile(@LDRIVE&"\fsp.ini") ;read "master" ini file into array $array[2] = "pcAlias="+$Element ;set value array(2) to string value $ = WriteFile("\\"+$Element+"\C$\fsp.ini",$array) ;write array back to file on the target machine. next From what you've said, I assume that the INI file is static, aside from the one line. That being the case, there's no need to look for the line, or to verify what the line says. A "master" INI file (which can be located on, say, @LDRIVE or some other network location) gets read into an array (since the INI file can get deleted from the remote systems, this make for a safety net). The value you want to change will always be the third line in the file, so I'm simply changing the value of $array[2] to reflect the correct target. Then, the array gets written to a file on the target machine with the appropriate value in there. |
||||||||
|
|
|||||||
eriqjaffe you know now I see what you mean...hahah thanks okay that is how it is array2 is the 3 element of the array okay that makes sense to me know.. Glenn and apronk I think for this case since my ini file is static and doesnt need to read much and do much, I want to keep it simple, the enumini looks for more sophisticated algorithm type girations maybe but I can see how powerful the enumini data structure is set to manipulate the ini data very nice coding..wow! |
||||||||
|
|
|||||||
eriqjaffe when i run it it doesnt like line with $array[2] in it ? now what?? Code: Break on Dim $PClist $PClist = "ftran1", "ftran2", "ftran3" for each $Element in $PClist $array = ReadFile("fsp.ini") $array[2] = "pcAlias=$Element" $ = WriteFile("\\"+$Element+"\C$\WINDOWS\fsp.ini",$array) ? $Element next |
||||||||
|
|
|||||||
what a dummy i forgot the UDFs read and write omg gosh i look at it hhahahha right i need to have the udf added to the file correct they dont come with kix32 engine do they?? hey do you guys know of the function to force lower case letters on a name i need the pcAlias=tolower($Element) to do something like that? i cant find the tolower function?? in kix Code: [Ubs] PCAlias=fcall1 HostName=192.168.1.94 PortNumber=9600 LastUser=larno SessionName=Original Session i was wrong see the above section? well the line PCAlias= varies it wil always be in this section and the top section is static but it maybe be on one pc located on the last line or any line in this section so I need to some do a scan and find it in this block and then edit it? how do i do that? |
||||||||
|
|
|||||||
No, you have to get the UDFs separately. |
||||||||
|
|
|||||||
Originally Posted By: itdaddy .... hey do you guys know of the function to force lower case letters on a name i need the pcAlias=tolower($Element) to do something like that? i cant find the tolower function?? in kix .... Kix has Ucase and Lcase to convert to upper or lower case characters. See the example below. Code: Break on $test = "ABCdefGHI" ? LCase($test) ? UCase($test) Sleep 5 Originally Posted By: itdaddy ... so I need to some do a scan and find it in this block and then edit it? how do i do that? If the section is always called UBS then you can just use the ReadProfileString funtion (build in in kix. it does not matter if the name value to read in the first second or whatever line. |
||||||||
|
|
|||||||
Code: If ReadProfileString('.\fsp.ini', 'Ubs', 'pcAlias') <> 'Correct_Value' $Rc = WriteReadProfileString('.\fsp.ini', 'Ubs', 'pcAlias', 'Correct_Value') EndIf Just reference the correct path for '.\fsp.ini', and change the 'Correct_Value' string to what you need. Glenn |
||||||||
|
|
|||||||
Itdaddy, I may be missing something, but won't it be easier to just use readprofilestring as earlier suggested instead of reading the entire file into an array? |
||||||||
|
|
|||||||
Originally Posted By: itdaddy hey do you guys know of the function to force lower case letters on a name I suggest that you (and anyone else not totally familiar with the Kix language) take 10 minutes, browse to the online command reference, and do the following: Create a spreadsheet with two columns.. in the left column, copy & paste the COMMAND name In the right column, copy & paste the ACTION sentence. You now have a command index. It simply lists the commands that are available and what they do.. it can likely fit on one double-sided page. If you want to know how to use the command, you check the manual or online reference. The biggest challenge that most of my students have is knowing what commands exist, whether we're talking about programming, or Unix shell. Most people can read the manual and figure out what to do once they know which command to use. I have a similar chart on the wall of my office, except it references the UDFs in my library. Saves lots of wear on the bald spot. Glenn |
||||||||
|
|
|||||||
Ah, that is what is under the hat! I just don't bother hiding mine. |
||||||||
|
|
|||||||
LOL - I wasn't hiding it.. I was protecting it from sunburn! Glenn |
||||||||
|
|
|||||||
Glenn and Apronk you both were right..darn I shuld have just listen to you both. When I used eriqjaffe code it distorts the INI file big time weird stuff happens but we both tried. It was nice to see what happens with and INI file wow really weird stuff for the outputarray..I might end up doing it in C++ I know C++ better than Kixtart. But will give the enumINI UDFs a try. and get back with you guys later once I have perfected it. and to you eriqjaffe thanks for helping me. I learned more about Kix from using your code thank you ver much sir! -Robert |
||||||||
|
|
|||||||
Oh I see cool! wow hey thanks was wondering how to handle the dynamic line of code like that. wow thank yeah will have to use the enumini like you guys suggested the other way distorts the ini file output array big time |
||||||||
|
|
|||||||
hey mart thanks for you help duh i forgot that function . hey thanks for the reminder |
||||||||
|
|
|||||||
oh mart and glenn thanks and thanks glenn for the example code that helps wow this is so cool will post everything when i am done to give a complete code i am using. super !man I have learn so much |
||||||||
|
|
|||||||
oh glenn i thought they were UDFs to be reference oops my bad! ;hee hee way cool! way cool! |
||||||||
|
|
|||||||
Hey glenn it gives me an error on the write I am sure my syntax is wrong? I will keep trying, but any suggestions will be helpful..thanks back to the debugging and trial and errror. thanks Code: Break on Dim $PClist Dim $array $PClist = "ftran1", "ftran2", "ftran3" for each $Element in $PClist If ReadProfileString('.\fsp.ini', 'Ubs', 'PCAlias') <> 'PCAlias=$Element' LCase($Element) ? $Element $Rc = WriteReadProfileString('.\fsp.ini', 'Ubs', 'pcAlias', 'PCAlias='+$Element) Shell "CMD.EXE /C xcopy .\fsp.ini \\$Element\c$\WINDOWS\ /y" EndIf next |
||||||||
|
|
|||||||
My head hurts... Please look at my example - carefully.. then look at your code - they are quite different. Glenn |
||||||||
|
|
|||||||
sorry glenn, not sure what goes in the correct_value is that the value on the right of the = sign? of pcalias? sorry for not understanding. Code: $PClist = "ftran1", "ftran2", "ftran3" for each $Element in $PClist If ReadProfileString('fsp.ini', 'Ubs', 'pcAlias') <> '$Element' $Element = LCase($Element) $Rc = WriteReadProfileString('fsp.ini', 'Ubs', 'pcAlias', '$Element') EndIf next |
||||||||
|
|
|||||||
Closer.. Get the variables out of the quotes - $Element, not '$Element', and you need to make up your mind - READWRITEprofilestring is much too indecisive - do you want to READ or WRITE a profile string? Glenn |
||||||||
|
|
|||||||
thanks sorry about that..my goal is only to write a string only then copy that file to the respective $Element and then do it again for the next $Element..I just want the code to find the PCAlias= line and place the $Element on the line. I know that you know that but I am just resummarizing it. will give it a go! thank you what do you mean about the read or right? then do I leave the <> '' blank like that and then leave $Element in the write line? |
||||||||
|
|
|||||||
Hey glenn I keep getting this error..man do I feel stupid here.. Code: C:\KIX>kix32 RFSPINI.KIX ERROR : expected ')'! Script: C:\KIX\RFSPINI.KIX Line : 11 C:\KIX>PAUSE Press any key to continue . . . and my code is now this? Code: for each $Element in $PClist If ReadProfileString('C:\KIX\fsp.ini', 'Ubs', 'pcAlias') <> '' $Element = LCase($Element) $Rc = WriteReadProfileString('fsp.ini', 'Ubs', 'pcAlias', $Element ) EndIf next do you mean take out the if/endif statement and the read function? and just leave the write function? |
||||||||
|
|
|||||||
Glenn you would be pround of your dumb code monkey(hee hee) I looked at the kix manual for WriteReadProfileString() and took out the 'Read' and it works hahhaa you the man glenn now take care of that headache! ahah thanks fortaking your time to help me;) really glenn this works perfect thanks some day I hope I am as good as you are probably not but I will try Code: $PClist = "ftran1", "ftran2", "ftran3" for each $Element in $PClist $Element = LCase($Element) ? $Element $Rc = WriteProfileString('C:\KIX\fsp.ini', 'Ubs', 'pcAlias', $Element) sleep 20 next |
||||||||
|
|
|||||||
Quote: My head hurts... LOL! I don't think it was the sunburn this time. |
||||||||
|
|
|||||||
very funny! hahahaahahha I have that affect/effect on people sorry but I do appreciate your expert guidance you all. you dudes rock! |
||||||||
|
|
|||||||
Thanks you experts! I was able to make this work! Thank you. Here is the program in its completion. I am able to update 150 Pcs within seconds. Fantastic. That is what scripting is all about! Speed and efficiency! -Thank you -Robert Code: ;******************************** ; Update FSP.ini Domain-wide ;******************************** Break on Dim $PClist Dim $array $PClist = "ftran1", "ftran2", "ftran3" for each $Element in $PClist ? $Element $Rc = WriteProfileString('\\$Element\C$\WINDOWS\fsp.ini', 'Ubs', 'PCAlias', LCase($Element) ) If @error <> 0 ? "Updated (pcAlias) successful" endif $Rc = WriteProfileString('\\$Element\C$\WINDOWS\fsp.ini', 'Ubs', 'PortNumber','9600' ) if @error <> 0 ? "Updated (PortNumber) successful" endif $Rc = WriteProfileString('\\$Element\C$\WINDOWS\fsp.ini', 'Ubs', 'HostName', '192.168.1.94' ) if @error <> 0 ? "Updated (Hostname) successful" endif $Rc = WriteProfileString('\\$Element\C$\WINDOWS\fsp.ini', 'Ubs', 'SessionName', 'Original Session' ) if @error <> 0 ? "Updated (Session Name) successful" endif shell "notepad.exe \\$Element\C$\WINDOWS\fsp.ini " sleep 2 next ;******************************** ; End of Update FSP.ini ;******************************** |
||||||||
|
|
|||||||
Hello Glenn I need to know why doing the shell or comspec command line is not exactly like a locally run CLI? or say I use PSTOOLS psexec command these claim to run a CLI shell dont they, but isnt really a true shell is it? I mean I have this problem running a msi remotely using psexec and I can run many other msi installer files with the comspec/shell command in kix but I can run the msi locally thru the CLI on that machine as admin of that machine and it runs fine but when I run the same command using psexec and msiexec /switches type command it doesnt scope correctly. My ramblings is my lack of terms to use for you to help me understand but I am grasping at the words scope you know path reference. running programs locally from the cli is to me a diferent scope reference that running thing remotely and scope is a very important issue when dealing with programs and installing them remotely. how can I get the same scope installing things remotely as I would running the same file and same commands locally on the machine thru the local CLI. I just dont understand how I can mimic the pure CLI environment and scope but do it remotely? did I make sense or give you a big headache.? I just wish I had a greater understanding of why I cant get the same scope remotely as I have with local CLI programs and command line? thanks ~Robert |
||||||||
|
|
|||||||
PSexec isn't exactly the same on a couple of points.. unless you provide user credentials to start PSexec, it runs in the System context. There are some limitations, most notably the inability to use network resources. The environment can also be different - run psexec to connect to a remote system and simply type SET > C:\P_ENV.TXT. Then log into the same system and run SET > L_ENV.TXT. Compare the two files - they may be different, and may hold a clue to why some things work differently. I'll keep this simple - if you want to install an MSI package remotely, use the task scheduler. I use it all the time, and my SWDIST product can push software installs to hundreds of systems using this method, and with a high degree of success. I can control exactly when it is installed, and which user account performs the install, and have full network access. I'm working on a new product that will provide the ability to trigger a local event from a remote server via login or other non-admin method. In short, a user can log in, the login script can detect that something needs to be done (with admin rights), and a request is placed on a server. Within seconds, that server delivers instructions (usually a batch file), defines an event, and triggers the event to run immediately. The process runs with whatever credentials the admin wants, and usually starts before the login script even completes. If you can wait, the initial release should be available in early to mid January. If you need instant gratification, look at the tcLib package for a library of task control functions, or tsAdm for a GUI tool that can push and trigger task events to one or many systems. tsAdm uses the tcLib package, and has a "blast" mode that can push a task to any number of systems. You can even interactively trigger the event to "run right now". Glenn |
||||||||
|
|
|||||||
Ah glenn thank you. when you mention the trick with the environmental varaibles ahhhh that might be it.you are a genius and yes I have used your tclib before fantastic stuff you have..looking forward to seeing you product..let me know when you get it it..you are selling it arnt you? my boss may buy it if he likes it;) -robert |
||||||||
|
|
|||||||
Glenn I did your trick of checking env variables is that true? of course running on the PC i got all its env variables? but running with psexec I got NO env variables is that true? did I do it right? well then that is the case huh? no wondering many people use client server apps some how it is impossible to replicated a true CLI remotely huh? get i set them the certain env variable the program needs then execute the program if need be???? again, can i set the env variable on the fly before i execute the program or do they even stick since maybe the session close withe each psexec command??? what you think? |
||||||||
|
|
|||||||
Glenn I wouldnt answer me anyway I will figure it out. thank you for you fast reply....I know sometimes us young pups needto figure things out by self. thank you for your time bottome line is their msi use to work they have to fix the scope oftheir program then it will work is my conclusion thank you |