|
|
|||||||
I found this script....but I don't think it's going to do what I need it to do...can someone take a look please? Thanks! What I want to do is Move users psts to another sharedrive and create their folder path for example move from: \\server\username\thepst.pst move to: \\server\username\thepst.pst Script: ;----------------- ; Move_PST_PAB.txt ;----------------- ; This Kixtart script file will move a user's Personal ; Folders and Personal Address Book to a new location ; By doing the following: ; ; Kixtart: ; - Prompt the User ; - Copy the file to new location ; - Rename the old file so that ; Outlook can't find it. ; - Create and call an AutoIt Script ; AutoIt: ; - Open Outlook 97 ; - If an error about the PAB file appears, ; Type the new location of the address book ; - Go to Tools/Services ; - Select each Service that has changed locations ; - When Outlook prompts for the new path to the file ; type it in. ; - Exit Outlook ; ; You can obtain AutoIt for free from: ; http://www.hidden.demon.co.uk/AutoIt/index.html ;----------------- ;........................................ ; Change the following two variables to ; match the path where you want PST and ; PAB files to be moved to: ;........................................ $ExchangeFileLoc = "C:\Exchange" $ExchangeHomeDrive = "C:" ;........................................ ; Set the following variable to be the ; name of your support team. ; This is used to create custom entries ; in the Registry ;........................................ $SupportGroup = "EASG" ;........................................ ; The following variable points to the ; location of the AutoIt.exe file ; You can obtain AutoIt from http://www.hidden.demon.co.uk/AutoIt/index.html ;........................................ $AutoItPath = @LDrive + "\US\NY\MLCSIM\Autoit.exe ;........................................ ; Initialize Generic Variables ;........................................ $ProfileCount = 0 $MsgKey = "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles" $ExchangeFileType = "" $WantFileMoved = "No" $ServiceCount=2 ;........................................ ; The following key is used to track what ; files need to be migrated ;........................................ $RC=ADDKEY("HKEY_CURRENT_USER\Software\" + $SupportGroup + " Controlled Apps\NT_Migration") ;........................................ ; The User's home server is determined ; based on their Home Share ; (If no Home Share is defined, this ; script won't work) ;........................................ IF LEN(@HOMESHR) > 0 $HomeDeptServer=SUBSTR(SUBSTR(@HOMESHR,3,len(@HOMESHR)-2),1,instr(SUBSTR(@HOMESHR,3,len(@HOMESHR)-2),"\")-1) ELSE $HomeDeptServer="UNKNOWN" EXIT 0 ENDIF ;........................................ ; Delve into the registry to find Info ; About what PSTs and PABs are set up ;........................................ DO $MProfile=EnumKey($MsgKey, $ProfileCount) IF @ERROR=0 IF Len( $MProfile ) $SettingCount = 0 DO $MSetting=EnumKey($MsgKey + "\" + $MProfile, $SettingCount) IF @ERROR=0 IF Len( $MSetting ) $ValueName=ReadValue($MsgKey + "\" + $MProfile + "\" + $MSetting, "001e3001") IF @ERROR=0 ;? $ValueName ENDIF ;--- PST Files $FileLocation=ReadValue($MsgKey + "\" + $MProfile + "\" + $MSetting, "001e6700") IF @ERROR=0 $ExchangeFileType = "Personal Folder" GOSUB ProcessHere ENDIF ;--- PAB Files $FileLocation=ReadValue($MsgKey + "\" + $MProfile + "\" + $MSetting, "001e6600") IF @ERROR=0 $ExchangeFileType = "Personal Address Book" GOSUB ProcessHere ENDIF ENDIF ENDIF $SettingCount = $SettingCount + 1 UNTIL Len( $MSetting ) = 0 ENDIF ENDIF $ProfileCount = $ProfileCount + 1 UNTIL Len( $MProfile ) = 0 IF $WantFileMoved = "Yes" GOSUB MakeFooter ;............................................ ; Execute the AutoIt script that was created ;............................................ SHELL $AutoItPath + " " + $ExchangeHomeDrive + "\_ExFil.txt" ENDIF EXIT 0 ;------------------ :StripPath ;------------------ ; This routine will take the UNC path and parse it out ; Into a filename and a name that the original file ; will be renamed to. (pab becomes paX while pst becomes psX) ;------------------ $FileName = substr($FileLocation,3,500) WHILE INSTR($FileName,"\") > 0 $FileName = SUBSTR($FileName,INSTR($FileName,"\")+1,500) LOOP $RenFileName = SUBSTR($FileName, 1, len($FileName) -1) + "X" RETURN ;------------------ :ProcessHere ;------------------ ; This routine will prompt the user if they want to move each ; eligible file to it's new location. ; If they say yes, an AutoIt script file is built which will ; handle the transfer ;------------------ $ServiceCount = $ServiceCount + 1 ;........................................... ; If the file has already been moved to the ; New destination, don't do anything ;........................................... IF SUBSTR($FileLocation, 1, len($ExchangeFileLoc)) = $ExchangeFileLoc Return ENDIF $RC = READVALUE("HKEY_CURRENT_USER\Software\" + $SupportGroup + " Controlled Apps\NT_Migration",$FileLocation) IF @ERROR=0 ;--- This File has already been processed Return ENDIF ;? $ExchangeFileType + ": " + $ValueName ;? "Previous Location: " + $FileLocation GOSUB StripPath ;? "New Location: " + $ExchangeFileLoc + "\" + $FileName ;? "Renamed File: " + $RenFileName ? $MigrationComplete = "No" $RC=MESSAGEBOX("Would you like to move your Outlook " + $ExchangeFileType + " named '" + $ValueName + "' from it's current location at " + $FileLocation + " to your personal directory on the new NT Server, " + $HomeDeptServer + " at this time?" , "Windows NT Migration", 4 + 4096) IF $RC = 7 ;--- They said no $RC = MESSAGEBOX("Do you want to move it later?", "Windows NT Migration", 4 + 4096) IF $RC = 7 ;--- They said no again $RC=WRITEVALUE("HKEY_CURRENT_USER\Software\" + $SupportGroup + " Controlled Apps\NT_Migration",$FileLocation,"DontMove","REG_SZ") RETURN ELSE ;--- They will move it later RETURN ENDIF ELSE ;--- They said yes they want to move it now IF $WantFileMoved = "No" GOSUB MakeHeader ENDIF IF $ExchangeFileType = "Personal Folder" GOSUB MakeBody ELSE $PABFileName = $FileName ENDIF IF EXIST ("\\" + $HomeDeptServer + "\" + @USERID + "$" + "\_ExFil.txt") MD $ExchangeFileLoc $RC=setconsole("MAXIMIZE") COLOR g+/n ? ? "Copying " + $FileLocation ? " to " + $ExchangeFileLoc + "\" + $FileName + "..." COPY $FileLocation $ExchangeFileLoc + "\" + $FileName SHELL 'cmd.exe /c ren "' + $FileLocation + '" "' + $RenFileName + '"' ? "Done." ? COLOR w/n ELSE MESSAGEBOX("Your " + $ExchangeHomeDrive + " drive is not mapped correctly!" + chr(10) + "Please Submit A ticket","Windows NT Migration",4096) EXIT 1 ENDIF ENDIF :EndProcessHere RETURN ;------------------ :MakeHeader ;------------------ ; This will create the top of the AutoIt Script ;------------------ $WantFileMoved = "Yes" ; Read the path to Microsoft Outlook from the registry. $OutlookPath = READVALUE("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MOS\Mail", "Inbox") ;IF EXIST($ExchangeHomeDrive + "\_ExFil.txt") DEL($ExchangeHomeDrive + "\_ExFil.txt") ENDIF $RC=REDirectOutput($ExchangeHomeDrive + "\_ExFil.txt", 1) ? 'Run, "' + $OutlookPath + '"' ? "WinWaitActive, Inbox - Micros" ? "Send, !T" ? "Send, v" $RC=REDirectOutput("") RETURN ;------------------ :MakeBody ;------------------ ; Each file that is to be moved will be added to the body of ; the AutoIt script Here. ;------------------ $RC=REDirectOutput($ExchangeHomeDrive + "\_ExFil.txt", 0) ? ? "Goto, FirstLetter" ? "TryAgain:" ? "Send, {ESC}" ? "FirstLetter:" ? "WinWaitActive, Services" ? "Send, " + SUBSTR($ValueName,1,1) ? "sleep 2000" ? ";Get Properties for the selected Service" ? "Send, !r" ? "sleep 500" ? "IfWinNotActive, " + $ExchangeFileType + ", The file " + $FileLocation + ", TryAgain" ? "Send, {ENTER}" ? "WinWaitActive, Create/Open" ? "Send, " + $ExchangeFileLoc + "\" + $FileName + "#{ENTER}" ? ";Say OK to this service" ? "WinWaitActive, " + $ExchangeFileType + ", Name" ? "Send, +{TAB}#+{TAB}#+{TAB}#+{TAB}#{ENTER}" $RC=REDirectOutput("") RETURN ;------------------ :MakeFooter ;------------------ ; This will create the bottom of the AutoIt script ;------------------ $RC=REDirectOutput($ExchangeHomeDrive + "\_ExFil.txt", 0) ? ? ";Exit Services" ? "Send, +{TAB}#+{TAB}#+{TAB}#+{TAB}#{ENTER}" ? "WinWaitActive, Inbox - Micros" ? "Send, !{F4}" ? "Goto, Done" ? "Error:" ? "Run, Notepad.exe" ? "WinWaitActive, Untitled - No" ? "Send, Your Personal Folder could not be moved.{ENTER} Please Submit A ticket." ? "Exit" ? "Done:" ? "exit" ? ? "[ADLIB]" ? "Personal Address Book Logon,,Y" ? "Personal Address Book, Name,{TAB}#" + $ExchangeFileLoc + "\" + $PABFileName + "{TAB}{TAB}{TAB}{ENTER}" $RC=REDirectOutput("") RETURN |
||||||||
|
|
|||||||
Hi, I think you might be trying something a little more complicated than you need. Could you give a little more detail about what you are trying to accomplish? If you are just trying to share where users mount from to get their pab and pst files, then I would suggest: 1. Copy the current files from the existing location to the new location and if possible, set up an rsync process of some type to keep the new location updated. 2. If they had been mounting from: \\server1\exchange\users\username Then make the new location: \\new_server\some_other_share\users\username Just in the startup script delete the current share mounting and create the new one. The change will be transparent to the users and their outlook programs. As each person logs in and gets his share re-mapped, you can have a message of that fact sent to you so you will know who has and who has not re-mapped to the new server. If I missed what you are trying to accomplish, again, please send some more details. Regards, Brad V |
||||||||
|
|
|||||||
Thanks...what I am trying to do is. Move a users pst to another share drive...example from F:\Username\PSTFOLDER to H:\Username\PSTFOLDER after that i need to have outlook open and automatically find the new location of the psts and it's seamless to the users. Thanks for all your help!! |
||||||||
|
|
|||||||
Any reason you can not change what F: and H: mappings are? As mentioned it would be the easiest way to do what you are looking for. |
||||||||
|
|
|||||||
Well, I created a batch file to move psts but I don't like how it works. I am looking for one script for kix to handle everything. Users have psts on F and C local but my main concern is to move the pst from f:\%username\pstfolder and have it create H:\%username%\pstfolder after that i need outlook to configure itself to map the new path automatically. Sorry, I am new to this...let me know if I am not making myself clear... |
||||||||
|
|
|||||||
Again, I think you are making it more complicated than it needs to be. How many users are you talking about? If it is a small number, I would just tell everyone they have to be logged off their systems by x o'clock on Friday night. Then, from your server, copy all of the user files from the one server to the other. Modify your startup script to delete the current f drive and map the new f drive. If it is a large number, you still do the same thing except I would add some sort of rsync process from the old pst shares to the new ones in case someone doesn't listen and stays logged in. In either case, outlook won't have to change because it will find the pst files in the exact same location. Does that make sense? Do the work from your server, not from a client script. Regards, Brad V |
||||||||
|
|
|||||||
gotcha....I see what you mean...it is approximately 325 or so. Oh, but one thing. The pst folder they have is on their personal share drive...so they have other docs etc on it. I need to specifically pull the path \\servername\username\outlookpst It would be too time consuming to copy each folder manually so I wanted a script to either copy or move that specific folder from each users personal drive and create \\newservername\username\outlookpst\ We dont have anything in our login script pertanining to outlook. When a user creates a pst they have been manually creating it and pointing it right to the folder on their F:\ called OutlookPST... |
||||||||
|
|
|||||||
Is there a reason you are splitting the pst files out of the user's personal share? That makes it more complicated. In any case, you should be able to write a script to run on your server to find all the pst and pab files under a given directory and copy them to their new location. Then you can add the map to the second drive in your startup script. As far as changing the mappings in outlook - take a look in the udfs and see if you can find anything to help. Unfortunately, I can't get in to the registry on my system so I can't look for keys. Maybe someone else can pipe in with a COM solution. Regards, Brad V |
||||||||
|
|
|||||||
We want to have all PST's located in one central location. I'm new to kixstart and scripts in general so this is going to be a HUGE challenge...but I have 1 week from today to get it done. I appreciate any and all help. If I can figure out how to move them from one location to another as the first step that would be a start. |
||||||||
|
|
|||||||
Well just an FYI that if you attempt to do this from a Logon script you're looking for some real problems unless you have a very robust network and server. Moving a PST during a logon script is going to put a LOT of data in motion at or around the same time. Also some people may have Outlook setup in their Startup folder which would then lock the PST from being copied/moved. Also if you change a drive mapping to the location then the Registry for that profile also would need updating. Just some more things to be aware of. |
||||||||
|
|
|||||||
Oddly enough, we just started a mail archive project this week. In the coming week, I'll be implementing a set of scripts that does what you want - sort of. We are deploying a GPO that prevents users from accessing PST files. Once that's in place, code will be placed in the login script to run on the user's PC. This script will terminate outlook, identify the location of all PST files, rename each PST file so the user and outlook can't find it, then identify the path of the PST (in its newly named form) to a central process. That process will then move the file to a central location. The login process happens in 3-4 seconds, while the background file copy can take quite a while, depending on size. The advantage of this is that many of our users have their PSTs in a central file server where their home profile structure is mapped to. The move will happen server to server. The backend process will return the file to its original name and log it into the archiving system for processing. I should be able to post some code in a week or so. Glenn |
||||||||
|
|
|||||||
Thats pretty much exactly what I am trying to do!!! Thanks! |
||||||||
|
|
|||||||
Here's Vresion 1.0 of the part that runs in the login script. It runs very quickly, and identifies the PSTs used by the default profile. It terminates outlook if it is running, disassociates the PSTs from outlook, renames the PSTs, and writes a log to a central network server. Individual logs are written by each workstation. Each time it runs, it creates a unique log file, which is then processed by a back-end script. That reads all the files, identifies the locations, and moves them within the local server to a processing folder. This eliminates network copying. I'll post the backend script as I complete it. One thing missing from this release is any logic to prevent it from running multiple times. This would be easy to implement by writing a registry value and exiting immediatly if it was present. Add this after testing/modification is complete. Glenn
|
||||||||
|
|
|||||||
Reading your posts again, it seems like this would be a good starting point for you - here's the mods I'd consider: It might be better to move the files interactively, rather than on the back end. Modify the Move line so the destination path is your common share instead of the original folder. My method is a simple rename, but you can actually move the file by specifying a new target path. The PST files will all have the format "USERID_originalname.PST", which should work well if they are all in a common folder. Don't run the Disassociate command - instead, update the path in the registry to reflect the new path and file name. Actually, you might want to update the registry with the new path, export the registry key, then delete the key. This will prevent outlook from opening the file while it is moved. Once the move completes, you can import the reg key and Outlook will find the PST in its new location the next time it starts. You can eliminate the log, or place the log on the local system to aid in troubleshooting, rather than using a central logging folder. You can update the script so if the PST file is already in the new location, simply exit. Keep in mind that users may have very large PST files, and it could take several minutes to several hours to copy, depending on size and network speed. (copying a 3Gig PST over a 256K Frame Relay link can take a LONG time!) The user will not be able to access the PST during this time. Hope that gets you a start in the right direction. Glenn |
||||||||
|
|
|||||||
You are the man! It's working great....the only thing I don't need it to do is "rename the psts" and I need it to move them to a share....once I figure that out it will be perfect! Excellent!! |
||||||||
|
|
|||||||
Read my second post more carefully - you still need the MOVE line, but need to change the second part - different destination path instead of a new filename. The MOVE command will RENAME the file if the source and destination PATH is the same, but will MOVE the file if the paths are different. Seems like all you need to do is a few minor mods: Code: Dim $NewPSTPath ; instead of $NewPSTName ; define the NewPSTPath instead of NewPSTName $NewPSTPath = '\\server\share\@USERID' ; Make sure the destination folder exists MD $NewPSTPath ; adjust the Move command to use the new target path with the original name Move $PSTPath + $PSTName $NewPSTPath + '\' + $PSTName Glenn |
||||||||
|
|
|||||||
Right, I am working on that now! |
||||||||
|
|
|||||||
So what's taking so long? Be sure to post your updates - I'll combine the code and post it to the script library. Glenn |
||||||||
|
|
|||||||
Well, i actually think I was making this harder than i needed to...like stated above...I don't think there is a way to make outlook capture the new path of the pasts after they are moved through the registry is there? I can just move the users pst's for now until i figure out how to make outlook map to the new location of the psts since they are not being renamed...I'm just changing paths. I'm not at your advanced level so I can only do but so much haha. If Exist ("\\server\" + @userid + "\TESTPST\")=0 MD "\\server\" + @userid + "\TESTPST" EndIf Copy "\\server\" + @userid + "\OutLookPST\*.pst" "\\server\" + @userid + "\TESTPST\" |
||||||||
|
|
|||||||
Ah, yes... you need to create a AtoU() UDF to update the path in Outlook, for each registry path where the '001f6700' value is found. This is the PST path, in what appears to be Unicode format. Glenn |
||||||||
|
|
|||||||
Thanks, i'll do some research and hopefully I can find something. |
||||||||
|
|
|||||||
Well, if you were able to remove them from the registry it has to be a way to add them back. :-) |
||||||||
|
|
|||||||
OK - try this - add it to the external UDFs from the earlier version. There's a new flag - $MoveFlag - when true, it moves and reassociates the PST instead of renaming & disassociating the file. Glenn
|
||||||||
|
|
|||||||
Forgot to mention / change before posting... The line (line 130) $_ = WriteValue($aPSTKeys[$], '001f6700-0', $_, 'REG_BINARY') creates an alternate key, with a "-0" suffix. I did this to not mess with the original value. You should remove the "-0" suffix in the key name on that line when you are ready to do the actual updating. Glenn |
||||||||
|
|
|||||||
Thanks...this is what I had so far...close outlook, copy the psts..could you add the reassociate part to mine if you have some time or modify it? Code: ;Created 3/25/2008 ;Edited: 2:24pm, 3/25/2008 ;This kills Outlook so psts are not in use which will interfere with copying Break On $nul=SetOption('WrapAtEOL','ON') $nul=SetOption('Explicit','ON') $nul=SetOption('NoVarsInStrings','ON') Dim $wksta,$EndOutlook $wksta = @WKSTA $EndOutlook = ENDPROC($wksta,'outlook.exe') Function ENDPROC($wksta,$proc) Dim $Process,$EndOutlook For Each $Process in GetObject('WinMgmts:'+'{impersonationLevel=impersonate}!\\'+$wksta+'\root\cimv2').ExecQuery('select * from Win32_process where name="outlook.exe"') $EndOutlook = $Process.Terminate() Next EndFunction ;Copy from source folder to destination folder If Exist ("\\server\" + @userid + "\TESTPST\")=0 ;Destination Folder MD "\\server\" + @userid + "\TESTPST" ;Create Destination Folder EndIf Copy "\\server\" + @userid + "\OutLookPST\*.pst" "\\server\" + @userid + "\TESTPST\" |
||||||||
|
|
|||||||
Ok, this is what I have so far...what this does is: close outlook copy the pst from location 1 to location 2 when you open outlook it asks for the path of the pst. - I need to have outlook automatically find the new location!! Once that is done it will be complete!! Also for the relocate...I need to make the $newpstroot = \\server\share\and create the username folder to drop the pst in. example... \\server\share\username\pstfile.pst That would be \\server\share\ + @userid ??? Please help! I really appreciate it. Thanks!! :-) Break On Dim $, $_ ; temp, throwaway var Dim $aPSTPaths[0] ; Array of PST paths Dim $aPSTKeys[0] ; Array of PST key paths Dim $RootPath ; registry root path Dim $WKey ; working key path Dim $EKey ; enumerated registry path Dim $TVal ; temp value for Dim $aIndex, $eIndex ; index pointers for array and enumeration Dim $MServer, $DName, $DProfile ; user data vars Dim $aMapped ; array of mapped network drives Dim $Drv, $NetFlag, $IsNet, $MoveFlag ; Drive letter enumerator, Network Only flag, IsNetwork flag, Move Flag Dim $PSTName, $PSTPath ; name & Path of current PST file Dim $NewPSTName, $NewPSTPath ; name of renamed PST file or new Path Dim $NewPSTRoot ; path of new PST path, when moving instead of renaming Dim $LogPath ; UNC path where logs are written $ = SetOption('Explicit', 'On') $ = SetOption('WrapAtEOL', 'On') $ = SetOption('NoVarsInStrings', 'On') $ = SetOption('NoMacrosInStrings', 'On') ; # # # # # START OF CUSTOM PARAMETERS # # # # # $NetFlag = 0 ; only process network PST files if 1 $MoveFlag = 1 ; Move files if 1, otherwise disassociate and rename $LogPath = '\\server\share\' ; UNC path where renamed PST file locations are logged $NewPSTRoot = '\\server\share\' ; UNC or mapped drive ; # # # # # END OF CUSTOM PARAMETERS # # # # # $RootPath = 'HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles' ; get list of mapped drives $aMapped = WMIMappedDrives() $DProfile = ReadValue($RootPath, 'DefaultProfile') $WKey = $RootPath + '\' + $DProfile + '\' $MServer = ReadValue($WKey + '13dbb0c8aa05101a9bb000aa002fc45a', '001e6602') $DName = UtoA(ReadValue($WKey + '13dbb0c8aa05101a9bb000aa002fc45a', '001f3001')) ; find the PST files associated with this profile - need to enumerate each subkey and find the 001f6700 value $eIndex = 0 $aIndex = -1 $EKey = EnumKey($WKey, $eIndex) While Not @ERROR $TVal = UtoA(ReadValue($WKey + $EKey, '001f6700')) If $TVal $aIndex = $aIndex + 1 ReDim Preserve $aPSTPaths[$aIndex] ReDim Preserve $aPSTKeys[$aIndex] $aPSTPaths[$aIndex] = $TVal $aPSTKeys[$aIndex] = $WKey + $EKey EndIf $eIndex = $eIndex + 1 $EKey = EnumKey($WKey, $eIndex) Loop ; Exit if nothing to do If $aIndex < 0 'No PST files are registered for user ' $DName ' - exiting!' ? ? Exit 0 EndIf ? ? 'Preparing for Mail Archiving on ' @WKSTA ' for user ' $DName ? ; now have all needed info ; - terminate Outlook if it is running ; - delete the PST registry keys ; - rename the PST files ; terminate Outlook $ = Split(WMIProcessList('outlook.exe')[0], ',')[1] If Not @ERROR ' Closing Outlook...' ? $ = WMIProcessKill($) ; terminate Outlook Sleep 3 ; wait for Outlook to close open files EndIf ; Enumerate the PST files that are registered in Outlook For $ = 0 to UBound($aPSTPaths) $IsNet = -1 ; Default to Not Network, will be 0 or more if network PSTs are found $Drv = Left($aPSTPaths[$], 2) ; drive letter where PST is stored $_ = InStrRev($aPSTPaths[$], '\') $PSTName = SubStr($aPSTPaths[$], $_ + 1) ; get name part $PSTPath = Left($aPSTPaths[$], $_) ; get path part ; determine if the PST is on a network drive. For $_ = 0 to UBound($aMapped) If $aMapped[$_][0] = $Drv $IsNet = $_ ; is network! EndIf Next ; Decide if this file should be processed - NetFlag=0 for all, or NetFlag=1 AND IsNet >= 0 If Not $NetFlag Or $NetFlag And $IsNet >= 0 ; Display the PST name ' ' Left($Drv + $PSTName + ' ', 25) '- ' If $MoveFlag ; Relocate the file to a user-specific folder on a common share $NewPSTPath = $NewPSTRoot 'move' Move $PSTPath + $PSTName $NewPSTPath + $PSTName ; re-associate the PST registry key with the new location '; reassociate' $_ = AtoU($NewPSTPath + $PSTName) $_ = WriteValue($aPSTKeys[$], '001f6700-0', $_, 'REG_BINARY') ; convert local to UNC for logging If $IsNet = -1 If Left($NewPSTPath, 1) = '\' $aPSTPaths[$] = $NewPSTPath + $PSTName Else $aPSTPaths[$] = '\\' + @WKSTA + '\' + Left($aPSTPaths[$], 1) + Chr(36) + SubStr($NewPSTPath, 3) + $PSTName EndIf Else If Left($NewPSTPath, 1) <> '\' $aPSTPaths[$] = $aMapped[$IsNet][1] + SubStr($NewPSTPath, 3) + $PSTName EndIf EndIf Else ; Disassociate by deleting the registry key 'Disassociate' $_ = DelTree($aPSTKeys[$]) ; Rename the file $NewPSTName = @USERID + '_' + Join(Split(Join(Split($PSTName, ' '), '_'), '.pst'), '.stp') '; move' Move $PSTPath + $PSTName $PSTPath + $NewPSTName ; convert local to UNC for logging If $IsNet = -1 ; local $aPSTPaths[$] = '\\' + @WKSTA + '\' + Left($aPSTPaths[$], 1) + Chr(36) + SubStr($PSTPath, 3) + $NewPSTName Else $aPSTPaths[$] = $aMapped[$IsNet][1] + SubStr($PSTPath, 3) + $NewPSTName EndIf EndIf ; write log for processed PST files - these files will be processed offline to move the ; renamed PST files to a central folder for processing '; write log' $_ = RedirectOutput($LogPath + '\' + @WKSTA + '_PST.txt') $aPSTPaths[$] ? $_ = RedirectOutput('') ' - Done!' ? EndIf Next Exit 0 ; convert Unicode strings to ASCII Function UtoA($_String) ; return if string is empty If Not $_String Exit 0 EndIf Dim $_S, $_I ; temp string, index pointer ; get each character pair as hex and convert to ASCII character For $_I = 1 to Len($_String) Step 4 $_S = $_S + Chr(Val('&' + SubStr($_String, $_I, 2))) Next $UtoA = $_S Exit 0 EndFunction Function AtoU($_String) Dim $_S, $_I ; temp string, index pointer ; get each ASCII character and convert to hex words For $_I = 1 to Len($_String) $_S = $_S + Right('00' + DecToHex(Asc(SubStr($_String, $_I, 1))), 2) + '00' Next $AtoU = LCase($_S) + '0000' Exit 0 EndFunction ;; ;;====================================================================== ;; ;;FUNCTION TimeDiff() ;; ;;AUTHOR Glenn Barnas ;; ;;VERSION 2.2 / 2007/10/14 ;; Modified to increase accuracy, permit fracional second calculations ;; 2.1 / 2007/03/17 ;; added "now" and "today" options for both start and end times ;; 2.0 / 2006/11/20 ;; Changes for code efficiency; added defaults for midnight ;; ;;ACTION Calculates the time difference between two given date/time strings ;; ;;SYNTAX TimeDiff(Start [, End] [, Format] [, MSec]) ;; ;;PARAMETERS Start - REQUIRED, String value representing the start timestamp ;; Format yyyy/mm/dd hh:mm:ss ;; ;; End - OPTIONAL, Defaults to "now" ;; String value representing the ending time ;; Format yyyy/mm/dd hh:mm:ss ;; Can be the special value "now" for the current date/time, or "today" ;; for midnight of the current day. ;; ;; When the time value is not specified, it defaults to 00:00:00.000 (midnight) ;; ;; Format - OPTIONAL, one of: ;; "m" - return minutes ;; "h" - return hours ;; "d" - return days ;; "y" - return years ;; When a format value is specified, it returns the fractional part (ie 0.5 days for 12 hours). ;; ;; MSec - OPTIONAL, True if the fractional seconds should be returned. Default ;; is false, returning whole seconds, to maintain compatibility with earlier versions. ;; MSec only affects the return of fractional seconds, not fractional parts of other time formats. ;; ;;REMARKS Returns a value representing the difference in time between two date/time ;; strings. Assumes that "Start" is in the past, but will properly return a ;; negative value if it is in the future. ;; ;;RETURNS Double - difference between Start and End timestamps in seconds ;; ;;DEPENDENCIES None ;; ;;TESTED WITH Kix 4.2+, NT4, W2K, WXP, W2K3 ;; ;;EXAMPLES If TimeDiff(GetFileTime('SomeFile.txt'), 'now', 'h') > 48 ;; "File is more than 2 days old!" ? ;; EndIf ; Function TimeDiff($_Start, OPTIONAL $_End, OPTIONAL $_Fmt, OPTIONAL $_MSec) Dim $_, $_SDate, $a_Start, $_EDate, $a_End, $_Duration ; Check for special START parameters Select Case $_Start = 'now' $_Start = @DATE + ' ' + @TIME + '.' + @MSECS Case $_START = 'today' $_Start = @DATE + ' 00:00:00.000' EndSelect ; Check for special END parameters Select Case $_End = 'now' Or $_End = '' $_End = @DATE + ' ' + @TIME + '.' + @MSECS Case $_End = 'today' $_End = @DATE + ' 00:00:00.000' EndSelect ; Validate parameters ; Parameters passed are "yyyy/mm/dd hh:mm:ss[.sss]" - make sure the default time is added $a_Start = Split(Join(Split(Join(Split($_Start + ' 00:00:00.000', '/'), ' '), ':'), ' '), ' ', 6) If UBound($a_Start) <> 5 Exit 87 EndIf ; bad start time parameter For $_ = 0 to 5 $a_Start[$_] = CDbl($a_Start[$_]) ; convert to numeric values Next $a_End = Split(Join(Split(Join(Split($_End + ' 00:00:00.000', '/'), ' '), ':'), ' '), ' ', 6) If UBound($a_End) <> 5 Exit 87 EndIf ; bad start time parameter For $_ = 0 to 5 $a_End[$_] = CDbl($a_End[$_]) ; convert to numeric values Next ; Convert dates to Days, then convert to seconds and add the time value If $a_Start[1] < 3 $a_Start[1] = $a_Start[1] + 12 $a_Start[0] = $a_Start[0] - 1 EndIf $_SDate = $a_Start[2] + ( 153 * $a_Start[1] - 457 ) / 5 + 365 * $a_Start[0] + $a_Start[0] / 4 - $a_Start[0] / 100 + $a_Start[0] / 400 - 306 $_SDate = CDbl($_SDate) * 86400.0 $_SDate = $_SDate + $a_Start[3] * 3600 + $a_Start[4] * 60 + $a_Start[5] If $a_End[1] < 3 $a_End[1] = $a_End[1] + 12 $a_End[0] = $a_End[0] - 1 EndIf $_EDate = $a_End[2] + ( 153 * $a_End[1] - 457 ) / 5 + 365 * $a_End[0] + $a_End[0] / 4 - $a_End[0] / 100 + $a_End[0] / 400 - 306 $_EDate = CDbl($_EDate) * 86400.0 $_EDate = $_EDate + $a_End[3] * 3600 + $a_End[4] * 60 + $a_End[5] ; Get the duration between the timestamps $_Duration = CDbl($_EDate - $_SDate) ; Trim fractional seconds if the MSec flag wasn't set ; Value returned is whole seconds If Not $_MSec $_Duration = CInt($_Duration) EndIf ; Return data as a Double - seconds (default), hours, minutes, days, or years Select Case $_Fmt = 'm' ; minutes $TimeDiff = $_Duration / 60.0 Case $_Fmt = 'h' ; hours $TimeDiff = $_Duration / 3600.0 Case $_Fmt = 'd' ; days $TimeDiff = $_Duration / 86400.0 Case $_Fmt = 'y' ; years $TimeDiff = $_Duration / 31536000.0 Case 1 $TimeDiff = $_Duration EndSelect Exit 0 EndFunction ;; ;;====================================================================== ;; ;;FUNCTION WMIMappedDrives() ;; ;;ACTION Return a list of mapped drives from a computer ;; ;;AUTHOR Glenn Barnas ;; ;;VERSION 1.0 / 2008/03/24 ;; ;;SYNTAX WMIMappedDrives([, AuthPtr]) ;; ;;PARAMETERS AuthPtr - OPTIONAL - pre-authenticated WMI object pointer ;; Use WMIAuthentication() udf to create the AuthPtr value ;; AuthPtr is not needed if user has admin rights ;; ;;REMARKS By default, returns a detailed list of all processes from the local computer. An ;; alternate computer can be specified, as can a specific process. When specifying ;; processes, you can use a name (cmd.exe) or process ID. If you specify a name, all ;; processeses matching that name will be returned, while specifying a PID will return ;; exactly one element that matches that process (if it was found) ;; If no match is found, the function exits with status 2 (file not found) ;; ;;RETURNS Array of drive letter / UNC Path arrays ;; ;;DEPENDENCIES WMI, ;; ;;TESTED WITH W2K, WXP, W2K3, Vista, x64 ;; ;;EXAMPLES ; Function WMIMappedDrives(OPTIONAL $_pAuth) Dim $_objWMIService, $_colItems, $_objItem ; WMI object vars Dim $_Line ; line string Dim $_aTmp[0], $_I ; return array, index Dim $_ ; temp var $_I = -1 ; If a pre-authenticated WMI object pointer was provided, use it, otherwise create a new object pointer If $_pAuth $_objWMIService = $_pAuth Else $_objWMIService = GetObject('winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2') If @ERROR Exit Val('&' + Right(DecToHex(@ERROR), 4)) EndIf EndIf ; get the collection of process objects $_colItems = $_objWMIService.ExecQuery("Select * from Win32_MappedLogicalDisk",,48) If @ERROR $_colItems = 0 Exit Val('&' + Right(DecToHex(@ERROR), 4)) EndIf ; Enumerate the collection of process data For Each $_objItem in $_colItems $_I = $_I + 1 ReDim Preserve $_aTmp[$_I] $_aTmp[$_I] = $_objItem.Name, $_objItem.ProviderName Next ; return the array, close the collection, and gripe if no items were found $WMIMappedDrives = $_aTmp $_colItems = 0 Exit 0 EndFunction ;; ;;====================================================================== ;; ;;FUNCTION WMIProcessKill() ;; ;;ACTION Terminates a specific process by numeric PID ;; ;;AUTHOR Glenn Barnas ;; ;;VERSION 1.0 / 2007/10/20 ;; ;;SYNTAX WMIProcessKill(Process [, Computer] [, AuthPtr]) ;; ;;PARAMETERS Process - PID of process to terminate ;; ;; Computer - OPTIONAL, Name of computer to target ;; ;; AuthPtr - OPTIONAL - pre-authenticated WMI object pointer ;; Use WMIAuthentication() udf to create the AuthPtr value ;; AuthPtr is not needed if user has admin rights ;; ;;REMARKS Terminates the process after verifying it exists ;; ;;RETURNS 1 (success) or 0 (failure) ;; ;;DEPENDENCIES WMI ;; ;;TESTED WITH W2K, WXP, W2K3, Vista, x64 ;; ;;EXAMPLES ; Function WMIProcessKill($_Process, Optional $_Computer, OPTIONAL $_pAuth) Dim $_objWMIService, $_colItems, $_objItem ; WMI object vars Dim $_ ; temp var Dim $_Err ; error code ; Must be a single numeric value to terminate If Val($_Process) <> $_Process $WMIProcessKill = 0 Exit 87 EndIf ; insure a properly formatted computer name, default to local computer is not specified $_Computer = IIf(Not $_Computer, '.', Join(Split($_Computer,'\'),'')) ; If a pre-authenticated WMI object pointer was provided, use it, otherwise create a new object pointer If $_pAuth $_objWMIService = $_pAuth Else $_objWMIService = GetObject('winmgmts:{impersonationLevel=impersonate}!\\' + $_Computer + '\root\cimv2') If @ERROR Exit Val('&' + Right(DecToHex(@ERROR), 4)) EndIf EndIf ; get the collection of process objects $_colItems = $_objWMIService.ExecQuery("Select * from Win32_Process Where ProcessID=" + '"' + $_Process + '"',,48) If @ERROR $_colItems = 0 Exit Val('&' + Right(DecToHex(@ERROR), 4)) EndIf $_Err = 2 ; prepare for not found ; Enumerate the collection of process data For Each $_objItem in $_colItems $_ = $_objItem.Terminate $_Err = @ERROR Next $_colItems = 0 ; return appropriate values $WMIProcessKill = Not $_Err Exit $_Err EndFunction ;; ;;====================================================================== ;; ;;FUNCTION WMIProcessList() ;; ;;ACTION Return a list of process info from a computer ;; ;;AUTHOR Glenn Barnas ;; ;;VERSION 1.0 / 2007/10/12 ;; Written as a replacement for PSList(), which uses SysInternals PSList.exe ;; ;;SYNTAX WMIProcessList([Process] [, Computer] [, AuthPtr]) ;; ;;PARAMETERS Process - return information about a specific process (group) by name ;; or individual process ID (PID) ;; ;; Computer - OPTIONAL, Name of computer to query ;; ;; AuthPtr - OPTIONAL - pre-authenticated WMI object pointer ;; Use WMIAuthentication() udf to create the AuthPtr value ;; AuthPtr is not needed if user has admin rights ;; ;;REMARKS By default, returns a detailed list of all processes from the local computer. An ;; alternate computer can be specified, as can a specific process. When specifying ;; processes, you can use a name (cmd.exe) or process ID. If you specify a name, all ;; processeses matching that name will be returned, while specifying a PID will return ;; exactly one element that matches that process (if it was found) ;; If no match is found, the function exits with status 2 (file not found) ;; ;;RETURNS Array of comma-delimited values, one element per process: ;; Process Name ;; Process ID (PID) ;; Thread Count ;; Handle Count ;; Memory Usage (Bytes) ;; User Time D:HH:MM:SS.sss format ;; Kernel Time D:HH:MM:SS.sss format ;; Elapsed Time D:HH:MM:SS.sss format ;; ;;DEPENDENCIES WMI, TimeDiff() external UDF ;; ;;TESTED WITH W2K, WXP, W2K3, Vista, x64 ;; ;;EXAMPLES ; Function WMIProcessList(OPTIONAL $_Process, Optional $_Computer, OPTIONAL $_pAuth) Dim $_objWMIService, $_colItems, $_objItem ; WMI object vars Dim $_Line ; line string Dim $_aTmp[0], $_I ; return array, index Dim $_ ; temp var Dim $_BTime, $_CTime ; boot and current times from target system $_I = -1 ; insure a properly formatted computer name, default to local computer is not specified $_Computer = IIf(Not $_Computer, '.', Join(Split($_Computer,'\'),'')) ; If a pre-authenticated WMI object pointer was provided, use it, otherwise create a new object pointer If $_pAuth $_objWMIService = $_pAuth Else $_objWMIService = GetObject('winmgmts:{impersonationLevel=impersonate}!\\' + $_Computer + '\root\cimv2') If @ERROR Exit Val('&' + Right(DecToHex(@ERROR), 4)) EndIf EndIf ; Get the current and boot times from the client system $_colItems = $_objWMIService.ExecQuery("Select * from Win32_OperatingSystem",,48) For Each $_objItem in $_colItems $_BTime = $_objItem.LastBootUpTime ; host-local boot time $_CTime = $_objItem.LocalDateTime ; host-local current time Next $_colItems = 0 ; convert to a normalized time string $_CTime = SubStr($_CTime, 1,4) + '/' + SubStr($_CTime, 5,2) + '/' +SubStr($_CTime, 7,2) + ' ' + SubStr($_CTime, 9,2) + ':' + SubStr($_CTime, 11,2) + ':' + SubStr($_CTime, 13,6) ; get the collection of process objects $_colItems = $_objWMIService.ExecQuery("Select * from Win32_Process",,48) If @ERROR $_colItems = 0 Exit Val('&' + Right(DecToHex(@ERROR), 4)) EndIf ; Enumerate the collection of process data For Each $_objItem in $_colItems ; add the data to the array if no process is specified, or if a specific process name or ID is specified If Not $_Process Or $_Process = $_objItem.Name Or $_Process = $_objItem.ProcessID $_Line = $_objItem.Name $_Line = $_Line + ',' + $_objItem.ProcessID $_Line = $_Line + ',' + $_objItem.Priority $_Line = $_Line + ',' + $_objItem.ThreadCount $_Line = $_Line + ',' + $_objItem.HandleCount $_Line = $_Line + ',' + $_objItem.WorkingSetSize ; convert the following to d:hh:mm:ss.sss format $_Line = $_Line + ',' + _WMIPLTC(CDbl($_objItem.UserModeTime) * 0.0000001) $_Line = $_Line + ',' + _WMIPLTC(CDbl($_objItem.KernelModeTime) * 0.0000001) ; Use the system boot time if creation date is not set $_ = IIf($_objItem.CreationDate , $_objItem.CreationDate, $_BTime) ; calculate elapsed time and convert to d:hh:mm:ss.sss format $_Line = $_Line + ',' + _WMIPLTC(_WMIPLET($_, $_CTime)) ; Update the array $_I = $_I + 1 ReDim Preserve $_aTmp[$_I] $_aTmp[$_I] = $_Line EndIf Next ; return the array, close the collection, and gripe if no items were found $WMIProcessList = $_aTmp $_colItems = 0 If $_Process And $_I < 0 Exit 1911 EndIf Exit 0 EndFunction ; support function to calculate elapsed time as Seconds ; Dependent on TimeDiff UDF! Function _WMIPLET($_Time, $_CTime) Dim $_CurrentTime ; Break into Date and Time parts, including 3 decimal points $_Time = SubStr($_Time, 1,4) + '/' + SubStr($_Time, 5,2) + '/' +SubStr($_Time, 7,2) + ' ' + SubStr($_Time, 9,2) + ':' + SubStr($_Time, 11,2) + ':' + SubStr($_Time, 13,6) ; return the value with 3 decimal places $_WMIPLET = TimeDiff($_Time, $_CTime, '', 1); FormatNumber(, 3, -1, 0, 0) Exit 0 EndFunction ; support function to conver the time value (100ns units) to D:H:M:S.s format Function _WMIPLTC($_Units) Dim $_D, $_H, $_M, $_S ; day, hour, minute, & second values ; Find d/h/m and subtract result from units $_D = Int($_Units / 86400) $_Units = $_Units - $_D * 86400 $_H = Int($_Units/3600) $_Units = $_Units - $_H * 3600 $_M = Int($_Units/60) $_S = FormatNumber($_Units - $_M * 60, 3, -1, 0, 0) ; return a time string $_WMIPLTC = '' + $_D + ':' + $_H + ':' + $_M + ':' + $_S Exit 0 EndFunction |
||||||||
|
|
|||||||
As I said - line 130 (in my original script) is this: $_ = WriteValue($aPSTKeys[$], '001f6700-0', $_, 'REG_BINARY') It uses an alternate key name for validation. You need to change it to: $_ = WriteValue($aPSTKeys[$], '001f6700', $_, 'REG_BINARY') for production. Note that the only change is the removal of the "-0" from the key name. Glenn |
||||||||
|
|
|||||||
Thanks for all the help!! I did a little editing and reading in a manual and I just got it working!!! |
||||||||
|
|
|||||||
Hello DB25 Please review this FAQ on how to post on a Bulletin Board. It will help you to post better here as well as other sites which use quite similar methods Pay close attention to CODE TAGS for posting code, etc... It makes it much easier to read and help you when your post is formatted properly. The Post/Reply Formatting Box and How to use it Thanks |
||||||||
|
|
|||||||
Hello, I need a script to do the same thing. can you post the script that worked for you? Thanks, Marie |