My VBScript file:
If Not WScript.Arguments.Named.Exists("elevate") Then
Set objShellApp = CreateObject("Shell.Application")
objShellApp.ShellExecute(WScript.FullName, WScript.ScriptFullName & " /elevate", "", "runas", 0)
WScript.Quit 2
WScript.Echo("Done 1")
Else
I need a way to determine, whether the user clicked NO and then return an errorcode to a batch file. Does ShellExecute return any error codes or something?
The problem is that the errorcode returned to the bat is always the same (in this case 2), regardless of whether I clicked yes or no.
EDIT:
Dim objShell, objWMIService, servSpooler, objReg, objShellApp, result, oShell
Dim whoami, strWhoamiOutput, whoamiOutput
Const PrinterPort = "NUL:"
Const HKLM = &h80000002
If Not WScript.Arguments.Named.Exists("elevate") Then
Set objShellApp = CreateObject("Shell.Application")
objShellApp.ShellExecute WScript.FullName, WScript.ScriptFullName & " /elevate", "", "runas", 0
WScript.Quit 10
WScript.Echo("Done 1")
Else
Set oShell = CreateObject("WScript.Shell")
Set whoami = oShell.Exec("whoami /groups")
Set whoamiOutput = whoami.StdOut
strWhoamiOutput = whoamiOutput.ReadAll
If InStr(1, strWhoamiOutput, "S-1-16-12288", vbTextCompare) Then
Wscript.Echo("ADMIN")
WScript.Echo("Port")
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
set servSpooler = objWMIService.Get("Win32_Service.Name='spooler'")
Set objReg = GetObject("winmgmts:root\default:StdRegProv")
servSpooler.StopService
objReg.SetStringValue HKLM, "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports", PrinterPort, ""
servSpooler.StartService
WScript.Quit 1
End if
WScript.Echo("Done 2")
End If
WScript.Quit 2
WScript.Echo("Done 3")
It only ever returns the errorcode of the very first WScript.Quit, after getting the elevating rights. No matter whether I click no or yes. When I click yes, it runs the program as expected, and it does quit after starting the spooler, but the error code returned to the batch is still that of the first Wscript.Quit and not the one after the spooler.
I expect this to run as follows:
no elevated rights
get the elevation, if no, Quit with 10
if user clicked yes: run the script again
run the code in the ELSE block, quit with WScript.Quit 1
the code after the END IFs should never run
EDIT:
If Not WScript.Arguments.Named.Exists("elevate") Then
Set objShellApp = CreateObject("Shell.Application")
objShellApp.ShellExecute WScript.FullName, WScript.ScriptFullName & " /elevate", "", "runas", 0
WScript.Quit 10
WScript.Echo("Done 1")
Else
Dim fso, MyFile
Set fso = CreateObject("Scripting.FileSystemObject")
Set MyFile = fso.CreateTextFile("testfile.txt", True)
MyFile.WriteLine("This is a test.")
MyFile.Close
End If
WScript.Quit 2
WScript.Echo("Done 3")
When I run this from .../System32 it lets me create a file when I click yes. Still, the errorcode is always the same, whether I click yes or no.
Try to create a file in c:\windows\system32 and test the error code.
Only a program marked RequireAdmin will fail when executed. Everything else will start as a limited user.
For your method.
Return Value
No return value.
WScript has a two execute methods. Both have different features so read the docs.
object.Exec(strCommand)
The Exec method returns a WshScriptExec object, which provides status and error information about a script run with Exec along with access to the StdIn, StdOut, and StdErr channels.
object.Run(strCommand, [intWindowStyle], [bWaitOnReturn])
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).
One of your problems is that your code is not written correctly.
You must have On Error Resume Next or your script would have crashed. You use this statement for simple scripts that you want to keep going in case of error. In real scripts it indicates you are handling errors rather than vbs. So you need to code like this.
servSpooler.StartService
If err.number <> 0 then
'print error, exit script
wscript.echo err.number & " " & err.description & " in " & err.source
err.clear
wscript.quit
End If
But if you use vbs error handling it knows the line and column number.
Noooooooo - create the file in code.
On Error Resume Next
'Should fail for everyone so simulates being a user for an admin
Set fso = CreateObject("Scripting.FileSystemObject")
fso.CreateTextFile "C:\System Volume Information\test.txt", vbtrue
msgbox err.number & " " & err.description & " " & err.source
If err.number = 70 then
msgbox "access denied - not an admin"
err.clear
Elseif err.number <> 0 then
Msgbox "Unspecified error"
err.clear
Else
Msgbox "Is an admin"
End If
'Should succeed for admins
fso.CreateTextFile "c:\windows\system32\test.txt", vbtrue
msgbox err.number & " " & err.description & " " & err.source
If err.number = 70 then
msgbox "access denied - not an admin"
err.clear
Elseif err.number <> 0 then
Msgbox "Unspecified error"
err.clear
Else
Msgbox "Is an admin"
End If
Related
I have batch file & vbs file that runs exe application in hidden mode.
Now I would like to open this exe applicatio, but with parameters passed to it.
Batch file:
wscript.exe "C:\~some path~\invisible2.vbs" "C:\~some path~\Rserve_d.exe"
invisible2.vbs:
CreateObject("Wscript.Shell").Run """" & WScript.Arguments(0) & """", 0, False
Above code makes sure it runs hidden. But now I need to pass this parameter to the Rserve_d.exe when starting it:
--RS-conf "E:\~some path~\Rconf.cfg"
Please advise. I've tried with adjustments, but it seems, that there is always something wrong in the syntax.
Build the arguments string for your command from the arguments to the script:
Function qq(str)
qq = """" & str & """"
End Function
args = ""
For i = 1 To WScript.Arguments.Count - 1
If InStr(WScript.Arguments(i), " ") > 0 Then
args = " " & qq(WScript.Arguments(i))
Else
args = " " & WScript.Arguments(i)
End If
Next
CreateObject("Wscript.Shell").Run qq(WScript.Arguments(0)) & args, 0, False
Ansgar Wiechers posted his answer before I did so he should deserve the credits. Unfortunately, I had already made the effort of posting an answer as well. To provide some additional functionality to your batch script, you could also check for the return value of the executed VBScript.
Batch file:
setlocal
set "script=c:\~some path~\invisible2.vbs"
set "program=c:\~some path~\rserve_d.exe"
set "params=--RS-conf "e:\~some path~\rconf.cfg""
cscript "%script%" //nologo "%program%" %params%
:: %errorlevel% = 0 - VBScript was executed successfully
:: %errorlevel% = 1 - Missing arguments
:: %errorlevel% = 2 - Shell object creation failed
:: %errorlevel% = 3 - Run method was unable to execute the program
VBScript:
Option Explicit
On Error Resume Next
Dim objShell,_
strCmdLine,_
intCount
If (WScript.Arguments.Count < 1) Then
WScript.Quit(1)
End If
Set objShell = WScript.CreateObject("WScript.Shell")
If (Err.Number <> 0) Then
WScript.Quit(2)
End If
For intCount = 1 To WScript.Arguments.Count - 1
strCmdLine = strCmdLine & " " & """" & WScript.Arguments.Item(intCount) & """"
Next
objShell.Run """" & WScript.Arguments.Item(0) & """" & strCmdLine, 0, False
If (Err.Number <> 0) Then
WScript.Quit(3)
End If
I am trying to make a pretty simple .vbs in Notepad that will do the following, but I am having a bit of trouble as I am a little new to scripting:
Execute a .bat if you select 'Yes', and close the window and do nothing if you select 'No'.
Display a message so you know why you're hitting 'Yes' or 'No'.
Display a window title.
Here's what I have tried to make myself so far:
x=msgbox("MESSAGE HERE",4,"WINDOW TITLE HERE")
const Hidden = 0
const WaitOnReturn = true
set WshShell = CreateObject("WScript.Shell")
WshShell.Run "%HOMEPATH%\Documents\FOLDER\FOLDER\EXAMPLE.BAT", Hidden, WaitOnReturn
WScript.Echo "Done"
It works just fine, however, even if I select 'No', it will still execute the .bat, which I do not want.
Try this code :
Option Explicit
Const Hidden = 0
Const WaitOnReturn = True
Dim Question,BatchFilePath,Message,Title,Result
Title = "Running a .bat through a .vbs"
Message = "Did you want to continue executing this script"
BatchFilePath = "%ProgramFiles%\FolderTest\Folder Name with spaces\EXAMPLE.BAT"
'We add the double quotes in this variable to bypass spaces issues in the path
BatchFilePath = DblQuote(BatchFilePath)
Question = Msgbox(Message,VbYesNo + VbQuestion,Title)
If Question = VbNo Then
MsgBox "You have chosen to quit this script !",vbExclamation,Title
WScript.Quit() ' We quit the script
Else
Result = Run(BatchFilePath,Hidden,WaitOnReturn)
End If
'*********************************************************************
Function Run(StrCmd,Console,bWaitOnReturn)
Dim ws,MyCmd,Result
Set ws = CreateObject("wscript.Shell")
'A value of 0 to hide the MS-DOS console
If Console = 0 Then
MyCmd = "CMD /C " & StrCmd & ""
Result = ws.run(MyCmd,Console,bWaitOnReturn)
If Result = 0 Then
MsgBox "Success",VbInformation,Title
Else
MsgBox "An unknown error has occurred!",16,"An unknown error has occurred!"
End If
End If
'A value of 1 to show the MS-DOS console
If Console = 1 Then
MyCmd = "CMD /K " & StrCmd & ""
Result = ws.run(MyCmd,Console,bWaitOnReturn)
If Result = 0 Then
MsgBox "Success",VbInformation,Title
Else
MsgBox "An unknown error has occurred!",16,"An unknown error has occurred!"
End If
End If
Run = Result
End Function
'*********************************************************************
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
'*********************************************************************
Try this one:
Set obj = CreateObject("WScript.shell")
Answer = MsgBox("Content Here",vbYesNo,"Title Here")
If Answer = vbYes Then
obj.Run "PATH TO BATCH FILE"
Else
WScript.Quit 0
End If
I need to make a vbs file that asks for the minimum file size when you drag and drop a folder to it. It's a little wierd. But then, it should return the input as a string that will be turned into an integer. Then it should look for files that are bigger than this minimum file size(all, i guess) and list their folder(if it's in a sub-folder), name and size.
I found some stuff on the internet but I'm a bit lost
Option Explicit
Dim FolderPath, objFSO, objFolder, objFile, input, objArgs
input = InputBox("Minimum size: ")
Set objArgs = Wscript.Arguments
Set objFSO = CreateObject("Scripting.FileSystemObject")
For i = 0 to objArgs.count
on error resume next
Set objFolder = objFSO.GetFolder(objArgs(i))
If err.number <> 0 then
ProcessFile(objArgs(i))
Else
For Each file In folder.Files
ProcessFile(file.path)
Next
End if
On Error Goto 0
Next
Function ProcessFile(sFilePath)
msgbox "Now processing file: " & sFilePath
For each objFile in objFolder.Files
WScript.Echo objFile.Name, objFile.Size & "bytes" & VbCR_
& "created: " & objFile.DateCreated & VbCR_
& "modified: " & objFile.DateLastModified
Next
You've got some issues in your code. You're using folder.files but you don't have folder declared (or defined) anywhere. The only reason you're not getting an error is because you have On Error Resume Next specified. There's no need to use On Error here and it should be removed so that you can properly debug your script. Here's a starting point for you.
' Get the folder dropped onto our script...
strFolder = WScript.Arguments(0)
' Ask for minimum file size...
intMinSize = InputBox("Minimum size: ")
' Recursively check each file with the folder and its subfolders...
DoFolder strFolder
Sub DoFolder(strFolder)
' Check each file...
For Each objFile In objFSO.GetFolder(strFolder).Files
If objFile.Size >= intMinSize Then
WScript.Echo "Path: " & objFile.Path & vbCrLf & "Size: " & objFile.Size
End If
Next
' Recursively check each subfolder...
For Each objFolder In objFSO.GetFolder(strFolder).SubFolders
DoFolder objFolder.Path
Next
End Sub
This isn't a complete script. Notice I haven't declared objFSO anywhere. I haven't checked that strFolder is a valid folder or that intMinSize is actually a number. I'll leave it up to you to fill in the missing pieces. But this should get you going.
I got a very specific question regarding my code.
So I got a folder. In this folder there can be >=0 files.
My first script is running in the background, checking if file-count is >0.
As soon as it is >0, it activates a second script with the path+filename, and as soon as
a file is deleted/removed from the folder, it displays the lifetime of the file.
Everything works fine, but there is one problem:
If there are multiple Files in the folder simultaniously, it only "observers" the top one (filename,ascending). So if the first one gets deleted, it sure does observe the second, but the lifetime is wrong because it did not start until the first one got deleted.
Here are my two codes:
Script1.vbs:
Set fso =CreateObject("Scripting.FileSystemObject")
If WScript.Arguments.Count = 1 Then
pfadTiff0 = CStr(WScript.Arguments(0))
Else
msgbox "Bitte Argumente (Pfade) angeben"
WScript.Quit
End If
While True
Set ordnerTiff0 = fso.GetFolder(pfadTiff0)
Set filesTiff0 = ordnerTiff0.Files
anzFilesTiff0 = ordnerTiff0.Files.Count
If anzFilesTiff0 > 0 Then
For Each objFile in filesTiff0
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0, 0, True
Next
End If
WScript.Sleep 2000
WEnd
Script2.vbs:
filename = CStr(WScript.Arguments(0))
pfad = CStr(WScript.Arguments(1))
Set fso = CreateObject("Scripting.FileSystemObject")
startZeit = Timer()
komplett = pfad&"\"&filename
While fso.FileExists(komplett) = True
WScript.Sleep 100
WEnd
endZeit = Timer()
differenz = endZeit-startZeit
msgbox "Existenz von Job " & filename & " in Sekunden: " & differenz
Thanks for your help guys.
#Bond: Removing the while true loop is no option, since the program is not allowed to stop running. Even if there are no files at this time, there will always be new files later which have to be observed too. But your hint with the "false" parameter of the Run-Statement was great!
#Rob1991:
Good idea, that was actually my first idea before I put my question here.
I figured it out by myself with a different solution. Maybe it helps anybody:
Set fso =CreateObject("Scripting.FileSystemObject")
If WScript.Arguments.Count = 1 Then
pfadTiff0 = CStr(WScript.Arguments(0))
Else
msgbox "Bitte Argumente (Pfade) angeben"
WScript.Quit
End If
Set ordnerTiff0 = fso.GetFolder(pfadTiff0
Set filesTiff0 = ordnerTiff0.Files
letztesFile = "000a" // PART OF SOLUTION, IT´S "LAST FILE"
While True
For Each objFile in filesTiff0
If objFile.Name > letztesFile Then // PART OF SOLUTION
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0, 0, False // thanks Bond for "false"
letztesFile = objFile.Name // PART OF SOLUTION
End If
Next
WScript.Sleep 500
WEnd
This statement:
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0, 0, True
Uses a value of True as the last parameter. That specifies that you want to wait until the script completes (synchronous) before returning. So your main script is put in a wait state until your second script (QueueTimeUp.vbs) exits, which doesn't happen until the first file is deleted.
You should be able to use False as the last param, which doesn't wait for the second script to complete. Then remove your While True loop and just allow your main script to complete.
' Main script. Remove "While True" loop.
Set ordnerTiff0 = fso.GetFolder(pfadTiff0)
Set filesTiff0 = ordnerTiff0.Files
anzFilesTiff0 = ordnerTiff0.Files.Count
If anzFilesTiff0 > 0 Then
For Each objFile in filesTiff0
' Use False for last param to specify asynchronous call...
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0, 0, False
Next
End If
' Allow script to complete.
Now you'll have a QueueTimeUp.vbs script running for each file in your folder.
FYI: If you're familiar with scripting WMI via VBScript, it provides the __InstanceCreationEvent and __InstanceDeletionEvent classes that can notify your script when a file is created or deleted, respectively. Then you won't have to poll a folder every few seconds looking for changes.
I believe for each file it will load the vbs2, but will not start the next execution until vbs2 has ended. If i used the following code below it will not iterate until the instance of cmd has been ended
For Each objFile in colFiles
oShell.run "cmd /k CD C:\Program File" ,1 , true
Next
I think you would want to have a start timer in your first vbs, and then pipe it to the second vbs2. Which would mean the start time is only called once at the start of the programs execution
startZeit = Timer()
For Each objFile in filesTiff0
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0 & " " & startZeit , 0, True
Next
vbs 2
startZeit = CStr(WScript.Arguments(2))
Hope this helps
I have to write a file to change the IP settings to Static with an input for the static IP.
It isn't very hard to write a file that does this(trough BATCH or VBS) but the problem is the name of the connection, standard windows is Local Area Connection, but it has to work with every connection, even if i(for example) rename my connection to test. Also some people have 2 or more connections, and only the standard one should be changed and every other should be disabled(WIFI, Hamachi, etc). It is going to be used on a LAN-Party to quickly change everybody's IP adresses to the given ones(there has to be some kind of input), instead of the manual job(takes to much time with 200+ people).
Can you guys give me some tips/ examples?
Thanks in Advance,
Bart
I wrote this a while ago for a similar purpose.
Its a bit laborious but basically it asks the user which Network connection to modify, then asks them if they want to turn on DHCP, or type a manual IP address. I imagine that the logged in user would need administrative rights to change this
Option Explicit
Const SCRIPT_NAME = "Set IP"
Const SUBNET_MASK = "255.255.255.0"
Dim objWMI
Dim arrNANames
Dim colNa, objNa
Dim colNAConfig, objNAConfig
Dim strIP
Dim intIPRet
Dim intCount, strSelectString, intSelected
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
Set colNA = objWMI.ExecQuery("select * from Win32_NetworkAdapter")
ReDim arrNANames(colNA.Count)
intCount = 0
strSelectString = "Select a network adapter to modify:" & vbCrLf
For Each objNa In colNa
arrNANames(intCount) = objNA.Name
strSelectString = strSelectString & intCount & ") " & arrNANames(intCount) & vbCrLf
intCount = intCount + 1
Next
Do
intSelected = inputbox(strSelectString, SCRIPT_NAME)
If intSelected = "" Or Not IsNumeric(intSelected) Then
quitScript
End If
Loop Until CInt(intSelected) < UBound(arrNANames) And CInt(intSelected) > -1
Set colNA = objWMI.ExecQuery("select * from Win32_NetworkAdapter where Name='" & arrNANames(intSelected) & "'")
For Each objNA In colNA
Set colNAConfig = objWMI.ExecQuery("ASSOCIATORS OF {Win32_NetworkAdapter.DeviceID='" & objNA.DeviceID & "'} WHERE resultClass = win32_NetworkAdapterConfiguration ")
For Each objNAConfig In colNAConfig
If MsgBox("Do you want to enable automatic IP (DHCP/APIPA) for device " & chr(34) & objNa.Name & chr(34), vbQuestion+vbYesNo, SCRIPT_NAME) = vbYes Then
intIPRet = objNAConfig.EnableDHCP
Select Case intIPRet
Case 0 MsgBox "DHCP enabled successfully", vbInformation, SCRIPT_NAME
Case 1 MsgBox "DHCP enabled successfully" & vbCrLf & "Please reboot for changes to take effect", vbInformation, SCRIPT_NAME
Case Else MsgBox "Could not enable DHCP", vbCritical, SCRIPT_NAME
End Select
Else
Do
strIP = inputbox("Type an IP for network adapter: " & objNA.Name, SCRIPT_NAME)
If strIP = "" Then
quitScript
End If
Loop Until isValidIP(strIP)
intIPRet = objNAConfig.EnableStatic(Array(strIP),Array(SUBNET_MASK))
Select Case intIPRet
Case 0 MsgBox "IP changed to " & strIP, vbInformation, SCRIPT_NAME
Case 1 MsgBox "IP changed to " & strIP & vbCrLf & "Please reboot for changes to take effect", vbInformation, SCRIPT_NAME
Case Else MsgBox "Could not change IP", vbCritical, SCRIPT_NAME
End Select
End If
Next
Next
quitScript
'returns true if the parameter is a valid IP address
Function isValidIP(ip)
Dim arrNums, intNum
arrNums = Split(ip, ".")
If UBound(arrNums) <> 3 Then
isValidIP = False
Exit Function
End If
For Each intNum In arrNums
If Not IsNumeric(intNum) Then
isValidIP = False
Exit Function
End If
If intNum < 0 Or intNum > 255 Then
isValidIP = False
Exit Function
End If
If Len(intNum) > 1 And Left(intNum,1) = "0" Then
isValidIP = False
Exit Function
End If
Next
isValidIP = True
End Function
Sub quitScript
Set objWMI = Nothing
Set colNa = Nothing
WScript.Quit
End Sub