Archive
Archive for September, 2008
Auralog Tell-me-more Demo Screencasts
2008/09/17
Leave a comment
An overview, mostly narrated:
How to force-stop Sanako Student using VbScript and WMI
2008/09/01
Leave a comment
We have been experiencing issues with the Sanako student becoming unresponsive in the Language Lab. This utility resets the student on the student computer:
'debug: 'on error resume next Const HKEY_LOCAL_MACHINE = &H80000002 arrComputers = Array("LSS-NWX13PC06") 'update this thru scriptomatic.hta strComputer = "LSS-NWX13PC06" '01<-fails, 03<- works, 'Service Name SrvName = "Sanako Helper" 'which format? example imapiservice is not in win xp services.msc 'Process Name 'ProcessName ="Student.exe" 'überflüssig For Each strComputer In arrComputers 'restart helper.exe For Each strService In GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer).InstancesOf ("win32_service") ' Set objWMIService = GetObject("winmgmts:{impersonationLevel=Impersonate}!\\" & strComputer & "\root\CIMV2") ' Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Service", "WQL", wbemFlagReturnImmediately + wbemFlagForwardOnly) If strService.Name = SrvName Then If strService.State = "Running" Then WScript.echo "Shutting down '" & strService.Name & "' Service" strService.StopService wscript.sleep 5000 strService.StartService WScript.echo "ReStarting '" & strService.Name & "' Service" Else strService.StartService wscript.echo "Starting '" & strService.Name & "' Service" End If End If Next 'service 'restart student.exe 'find path for starting Set objRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv") 'student.exe 'tutor [HKEY_LOCAL_MACHINE\SOFTWARE\Sanako\Setup] "RootDir" "C:\\Program Files\\Sanako" 'student: HKEY_LOCAL_MACHINE\SOFTWARE\Sanako\Shared Components\CMC ClientModuleLocation C:\Program Files\Sanako\Study\Student 'student: HKEY_LOCAL_MACHINE\SOFTWARE\Sanako\Study\Student\Settings InstallPath C:\Program Files\Sanako\Study\Student strKeyPath = "HKEY_LOCAL_MACHINE\SOFTWARE\Sanako\Study\Student\Settings" strValueName = "InstallPath" objRegistry.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue 'GetDWORDValue method is not needed WScript.echo "Registry BaseDir is '" & strValue & "'" If IsNull(strValue) Then 'Empty means that the registry value exists, but is blank; Null means that the registry value doesn’t exist. strStudentCommandline = "C:\Program Files\Sanako\Study\Student\Student.exe" 'todo: notbehelf Else strStudentCommandline = strValue & "\Study\Student\Student.exe" End If WScript.echo "strStudentCommandline is '" & strStudentCommandline & "'" 'do you have to do the same for vieostreamer window? For Each strProcess In GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer).InstancesOf ("win32_process") ' Set objWMIProcess = GetObject("winmgmts:{impersonationLevel=Impersonate}!\\" & strComputer & "\root\CIMV2") ' Set colItems = objWMIProcess.ExecQuery("SELECT * FROM Win32_Process", "WQL", wbemFlagReturnImmediately + wbemFlagForwardOnly) If strProcess.CommandLine = strStudentCommandline Then strProcess.terminate WScript.echo "Terminating '" & strProcess.CommandLine & "'" wscript.sleep 5000 End If 'todo: remote ' you shoule be able to do this without a shell using .Create(CommandLine) 'todo: Processes launched by WMI can NEVER be visible. They run in their own windowstation, the same as window services. 'It make it visible you have to have a System Tray application or similar hidden application which is launched when each desktop starts. Then you have to setup some kind of IPC/RPC between the system tray app and your 'the problem is that i restart the student.exe under my credentials, but would have to do it under the logged in student credentials set WshShell = WScript.CreateObject("WScript.Shell") Ret = WshShell.Run(strStudentCommandline, 3, True) 'bWaitOnReturn Optional. Boolean value indicating whether the script should wait for the program to finish executing before continuing to the next statement in your script. If set to true, script execution halts until the program finishes, and Run returns any error code returned by the program. If set to false (the default), the Run method returns immediately after starting the program, automatically returning 0 (not to be interpreted as an error code 'error checking If ret <> 0 then wscript.echo "error starting "& strStudentCommandline Else WScript.echo "Starting '" & strStudentCommandline & "' Process" End if Next 'process running Next 'strComputer
UPDATE: I haven now also coded a similar utility in AutoIt, hopefully easier to use.
Categories: service-is-programming, sourcecode
ms-windows, sanako-study-1200, student.exe, VBScript, wmi
How to map network shares using VBScript and WMI
2008/09/01
Leave a comment
- Cannot get IT to map network drives that your users need for your departmental applications (Users? Cannot get users to map them manually in Windows. VBScript to the rescue, here is an example VBScript that uses WMI and employs some error checking:
'search for TOADAPT and customize to your environment 'todo: is the default host wscript? if not, will user see messages from cscript like "Drive letters changed, please reboot to see the change, then rerun this program!" " Option Explicit 'On error resume next 'When debugging, always disable Const HKLM = &H80000002 'for ChangeDrvLetter Dim objNetwork Set objNetwork = CreateObject("WScript.Network") Dim strUser 'set at beginning strUser = objNetwork.UserName Dim strLogFileLocation 'set at beginning strLogFileLocation = "\\nebraska\Sanako_3\trp\lang\map_sanako\users\" 'trailing backslash; user needs write permission Dim strLogFilePath Dim strMessage 'set within program flow dim blnForce blnForce = true Dim blnUpdateProfile blnUpdateProfile = true dim strComputer strComputer = "." Dim objWMIService Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") Dim colDisks, objDisk Dim colVolumes, objVolume Dim astrDriveLetters, strDriveLetter Dim astrRemotePaths, strRemotePath ' targets aufzählen; TOADAPT astrDriveLetters = array("K:", "L:", "M:","V:") 'sources aufzählen; TOADAPT astrRemotePaths = Array("\\nebraska\sanako_1", "\\nebraska\sanako_2", "\\nebraska\sanako_3","\\nebraska\lssvideo") 'todo: escaping? In VBScript, \ is not an escape character (that is for JavaScript). Dim intMatchCounter intMatchCounter = 0 Dim i dim strFreeDriveLetter Dim blnExecute blnExecute =True Dim intDrives intDrives = ubound(astrDriveLetters) 'For Each strDriveLetter In astrDriveLetters for i=0 to intDrives '-1 strDriveLetter = astrDriveLetters(i) strRemotePath= astrRemotePaths(i) ' check drive types Set colDisks = objWMIService.ExecQuery ("Select * from Win32_LogicalDisk where DeviceID = '" & strDriveLetter & "'") 'Set colDisks = objWMIService.ExecQuery ("Select * from Win32_LogicalDisk where DeviceID = 'V:'") 'todo:release For Each objDisk in colDisks 'todo: if strDriveletter not already in use, this should fail quietly - or does it 80041017 The error means the query was invalid Select Case objDisk.DriveType Case 1 ' No root directory. Drive type could not be determined. ' todo: do nothing, handle later blnExecute = False Call logUserResults(strLogFileLocation, strUser, Left(strDriveLetter,1) & "_case1" ) Case 2 'Removable drive --> dismount: wmi cannot do this on xp 'todo: really, for a floppy? 'Set colVolumes = objWMIService1.ExecQuery ("Select * From Win32_Volume Where Name = "& strDriveletter & "\\") ' todo:Win32_Volume isn't availble on windows xp or earlier. 'For Each objVolume in colVolumes returncode = objVolume.Dismount(True, True) next 'blnExecute = true Dim strWarning strWarning = "Please first remove your drive " & strDriveLetter & ", then restart this program." WScript.Echo strWarning Call logUserResults(strLogFileLocation, strUser, Left(strDriveLetter,1) & "_case2" ) WScript.Quit 'oder get wmi:ejectname like 'USB Mass Storage Device' (das ist aber nicht unique) 'Call shell and run from same folder as script deveject -EjectDrive:<Drive>|-EjectName:<Name>|-EjectId:<DeviceId> [-v] [-Debug] Case 3 ' Local hard disk. -> change drive letter, if isSystemDrive(strDriveLetter) then'unless system drive 'do nothing blnExecute = False Call logUserResults(strLogFileLocation, strUser, Left(strDriveLetter,1) & "_case3" ) else ' alter ' Script that changes drive letters ' Note: Do NOT use it on SYSTEM or BOOT partition drive letters !!! ' Author: Torgeir Bakken ' from/to strFreeDriveLetter = FreeDrive() If ChangeDrvLetter(strDriveLetter, strFreeDriveLetter) Then WScript.Echo "Drive letters changed, please reboot to see the change, then rerun this program!" WScript.Quit '[exitcode] Else 'WScript.Echo "Failed changing drive letters!" ' todo: do not know how to handle this, do nothing for now blnExecute = False Call logUserResults(strLogFileLocation, strUser, Left(strDriveLetter,1) & "_case3_failedchanging" ) End If end if Case 4 'Network disk -> removenetworkdrive Set objNetwork = CreateObject("WScript.Network") objNetwork.removeNetworkDrive strDriveLetter, blnForce, blnUpdateProfile 'done: this errors if drive is not mapped 'force tut es nicht "this network connection has files open or requests pending": 'you're running the script from Z: and trying to unmap/map Z: in the script blnExecute = true Case 5 'Compact disk --> change drive letter ' Script that changes drive letters ' Note: Do NOT use it on SYSTEM or BOOT partition drive letters !!! ' Author: Torgeir Bakken ' from/to strFreeDriveLetter = FreeDrive() If ChangeDrvLetter(strDriveLetter, strFreeDriveLetter) Then WScript.Echo "Drive letters changed, please reboot to see the change, then rerun this program!" WScript.Quit '[exitcode] Else 'WScript.Echo "Failed changing drive letters!" ' todo: do not know how to handle this, do nothing for now blnExecute = False Call logUserResults(strLogFileLocation, strUser, Left(strDriveLetter,1) & "_case5failedchanging" ) End If Case 6 'RAM disk. ' todo: do nothing, handle later blnExecute = False Call logUserResults(strLogFileLocation, strUser, Left(strDriveLetter,1) & "_case6" ) Case Else 'Drive type could not be determined." ' todo: do not know how to handle this blnExecute = False Call logUserResults(strLogFileLocation, strUser, Left(strDriveLetter,1) & "_caseelse" ) End Select next 'objdisk within coldisk with strdriveletter if blnExecute then 'drive letter is free for use 'need to reconnect on logon 'five possible arguments for MapNetworkDrive: objNetwork.MapNetworkDrive: '1) strDriveLetter, 2) strRemotePath, 3) blnUpdateProfile, 4) strUser, 5) strPassword. objNetwork.MapNetworkDrive strDriveLetter, strRemotePath, blnUpdateProfile Call logUserResults(strLogFileLocation, strUser, Left(strDriveLetter,1) & "_success" ) end if next 'driveletter 'ergebnis demonstriern dim shobj Set ShObj = CreateObject("wscript.shell") ShObj.run "explorer.exe /select,z:\" WScript.Quit Function logUserResults(strLogFileLocation, strUser, strMessage) Dim objFSO dim objFile Set objFSO = CreateObject("Scripting.FileSystemObject") strLogFilePath = strLogFileLocation & strUser & "_"& strMessage & ".txt" Set objFile = objFSO.CreateTextFile(strLogFilePath, true) 'overwrite is better than erroring End Function Function ChangeDrvLetter(sSourceDrive, sTargetDrive) Dim bOk, oReg, sKeyPath , sSrc , sValue, iRC, sTrg bOk = True ' Init value Set oReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv") sKeyPath = "SYSTEM\MountedDevices" sSrc = "\DosDevices\" & UCase(sSourceDrive) iRC = oReg.GetBinaryValue(HKLM, sKeyPath, sSrc, sValue) 'getbinaryvalue outputs result into svalue (can be aray, see http://msdn2.microsoft.com/en-us/library/aa394600(VS.85).aspx) If iRC = 0 Then sTrg = "\DosDevices\" & UCase(sTargetDrive) iRC = oReg.SetBinaryValue(HKLM, sKeyPath, sTrg, sValue) If iRC = 0 Then oReg.DeleteValue HKLM, sKeyPath, sSrc Else bOK = False End If Else bOK = False End If ChangeDrvLetter = bOK End Function 'Michael Harris Function FreeDrive Dim I, oFso Set oFso = CreateObject("Scripting.FileSystemObject") For I = Asc("D") to Asc("U") If Not oFso.DriveExists(Chr(I)) Then Freedrive = Chr(I) & ":" Exit Function End If Next End Function function Get_System_Drive() Dim objShell, strSystemDrv Set objShell = WScript.CreateObject ("WScript.Shell") strSystemDrv = objShell.ExpandEnvironmentStrings("%SYSTEMDRIVE%") Get_System_Drive = strSystemDrv end function function isSystemDrive(strDriveLetter) if strDriveletter = Get_System_Drive() then isSystemDrive = true else isSystemDrive = false end if End function
- This script will also emit a poor man’s log, in the file system on the network share, per users and drives that could be mapped, for them, like in this example:
- More recently, I had to do the same for ALL users, including the Sanako Student Player installation, using AutoIt.