wshshell.popup not being displayed to other user when using task scheduler - vb.net

I've got a tricky thing to do here.
I'm using task scheduler to auto-reboot all the computer during the weekend by calling a simple .bat file containing a shutdown command.
I wanted to give the user the possiblilty to cancel that reboot by displaying them a popup saying "Computer is about to restart, do you wish to continue ? Ok or Cancel". I have done that with VB using the popupbox method, it works perfectly.
Here is the problem i'm facing: The task is running under the System account and unless the task is set to run with the current logged on user, the popup box won't appear. I could change the account set in the task but I've got hundreds of users so impossible.
I've done some kind of a workaround, calling the VBS from Psexec... Works, but it's not perfect.
Here is my Psexec command that calls the VB:
Psexec -accepteula -s -i cmd /c C:\Windows\System32\Weekly_Reboot.vbs
Here is my VB:
Dim WshShell, BtnCode
Set WshShell = WScript.CreateObject("WScript.Shell")
BtnCode = WshShell.Popup("Computer is about to restart, do you wish to continue?", 30, "/!\ Weekly Restart /!\", 4 + 32)
Select Case BtnCode
case 6
Dim objShell
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run "c:\Windows\System32\Weekly_Reboot.bat"
case 7
WScript.Echo "No prob - the computer won't restart"
case -1
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run "c:\Windows\System32\Weekly_Reboot.bat"
End Select
And here is the actual reboot command:
Shutdown /f /r /c "This is the weekly reboot"
Any idea would be really awesome ! I really tried googling it, but no luck.

Here is the problem i'm facing: The task is running under the System account and unless the task is set to run with the current logged on user, the popup box won't appear. I could change the account set in the task but I've got hundreds of users so impossible.
Change the task to run under the group called Users. It will make the task run for any logged in user.
I'm not certain if this is needed: but you might want to run it using the highest privileges.

Related

Shell hitting Run-Time error '5' trying to call R script in Access VBA

I made a simplified version of my code that directly highlights the issue.
I have read dozens of similar issues/solution.
Part of my workflow in VBA in Microsoft Access involves calling an R script that does some logic and returns information to a table in the same database.
It was working until we moved the location of the R installation to a new drive. Changing the path to this new install location does not work. No other code is changed.
cmd = "C:\R\bin\i386\Rscript.exe C:\R\test.R"
Debug.Print cmd
Shell cmd
I get
runtime error '5'
I am using the immediate window to check the paths are correct and copying them into RUN to verify that they do work.
The above outputs:
C:\R\bin\i386\Rscript.exe C:\R\test.R
It works in RUN.
The first thing I found when searching online is to add more (") as shell can handle them weirdly:
cmd = """C:\R\bin\i386\Rscript.exe""" & " " & """C:\R\test.R"""
Or any iterations of using "s in different places, output:
"C:\R\bin\i386\Rscript.exe" "C:\R\test.R"
Same error but works in RUN. I also tried them all successfully in CMD.
It seems just Shell refuses to launch R from that path. I have moved it elsewhere on my C drive with same effect.
I cannot recreate the original R installation path as that shared drive is now completely dead.
EDIT:
I changed to using ShellExecute simply to try and make Notepad ++ open, again works in cmd.
Set objShell = CreateObject("Shell.Application")
objShell.ShellExecute "C:\N\notepad++.exe", "C:\R\test_in.csv", "", "open", 1
This time I hit a "suspicious macro error" that leads me to believe that it may be an antivirus setting (macros are enabled in Access) blocking Shell from calling anything.
After days of testing I have found the solution, hopefully this can help anyone else in a similar situation. Windows Defender only blocks shell calls to non-Microsoft products, so I nested a call to PowerShell within the call to Shell:
Shell ("powershell.exe C:\R\bin\i386\Rscript.exe C:\R\test.R")
Take note you need to play around with the "s a lot ot get it working, my actual pipeline has more arguments and I had to enclose them in 5 sets of "s for it to pass through to powershell properly. IE:
Dim codePath As String: codePath = """""\\example\example"""""
Try these variations using Start or a second Command:
cmd = "Start C:\R\bin\i386\Rscript.exe C:\R\test.R"
or:
cmd = "cmd /c ""C:\R\bin\i386\Rscript.exe C:\R\test.R"""

Running Macro from .bat with another Access db open

I need to run a few Access macros automatically periodically throughout the day, I do this by scheduling a batch file to open the relevant Access db and run the macro.
The problem that I am having is, if I am working on another Access database and therefore already have an instance of Access open, the batch file runs but only opens the database containing the macro that is supposed to run and stops. So the macro doesn't run.
Has anyone else had this issue or know how to solve it?
The batch files that task scheduler calls look like this:
start /min "C:\Program Files\Microsoft Office 15\root\office15\MSACCESS.EXE" "Q:\TC\DNI_Updater\DNIUPDATER.accdb" /X DailyUpdate
I could not find a way to get the DailyUpdate macro to run in the second Access session when using start /min to open that session.
I'm still unsure whether it's possible, but I gave up and switched to VBScript instead. With that approach, it's easy to start the second Access session minimized and run the macro ...
Option Explicit
Dim AccessExePath, DbPath, CmdLine, objShell
DbPath = "C:\Users\hans\Documents\test_hfu.accdb"
AccessExePath = "C:\Program Files (x86)\Microsoft Office\Office14\MSAccess.exe"
CmdLine = """" & AccessExePath & """ """ & DbPath & """" & " /X DailyUpdate"
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run CmdLine, 7 ' Minimize. The active window remains active.
If this approach is satisfactory, you can use the script file as your scheduled task's "Start a program" Action property ...

Toggle Windows Explorer "Work Online" mode via Excel VBA

I have written several VBA macros that access intranet network locations. They work well when users are located on-site. However, when they are off-site and accessing the network via VPN, these network locations are not available unless they manually navigate to them via Windows Explorer and select the "work online" option at the top of the explorer window.
I can already verify whether they are connected via VPN programmatically.
What I need is to be able to perform the equivalent of activating "work online" mode via Excel VBA.
Any suggestions from the hive mind?
Didn't have any success via Google or existing SO posts.
Simplest approach would be to trap the error when the folder cannot be accessed, display a message box to inform the user of the required option, and use Shell command to open the Windows Explorer:
Dim Foldername As String
Foldername = "\\UNCPATH\TO\NETWORK_DRIVE\"
Shell "C:\WINDOWS\explorer.exe """ & Foldername & "", vbNormalFocus
Alternatively, you may be able to get this to work, although I could not, it was too long to post as a comment so I will include the procedure here:
Sub fnOfflineStatusVB()
Dim objShell As Object 'IShellDispatch5
Dim objFolder As Object 'Folder3
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace("\\UNCPATH\TO\NETWORK_DRIVE\")
If (Not objFolder Is Nothing) Then
Dim nReturn As Integer
nReturn = objFolder.OfflineStatus()
End If
Set objFolder = Nothing
Set objShell = Nothing
End Sub
Found it here
Found PowerShell commands that can be executed through CMD successfully. Roadblock that remains is integrating these into a batch file.
These CMD commands work when entered manually:
powershell.exe -noexit "$oWMI=[wmiclass]""\\localhost\root\cimv2:win32_offlinefilescache"""
$oWMI.TransitionOnline("<path here>")
Where "Path here" in angle brackets is an UNC path on my network. However, executing them in a batch file has been unsuccessful thus far.
Here is the code:
#ECHO ON
::Move to non UNC Path directory
cd /D "C:\"
powershell -NoExit -Command "& {'$oWMI=[wmiclass]''\\localhost\root\cimv2:win32_offlinefilescache';$oWMI.TransitionOnline('<Path here>')}"
:: Pause CMD window to give user confirmation that execution has occurred
PAUSE
If anyone has any suggestions on the issue, your advice would be greatly appreciated.
Running PowerShell scripts directly are not permitted due to Group Policy set by IT, which is the reason for this round-about method.

Get Currently Logged in username

I am trying to get the logged in username of the user by using VBS.
I tried some codes which works when I run the script directly (Double Clicking it)
Set wshNetwork = CreateObject("WScript.Network")
strUser = wshNetwork.Username
WScript.Echo "Current User: " & strUser
However, what I need to do is to use CMD to run a scheduled task using the AT command.
When it ran, the username would be the computer's name instead of the logged in user.
This problem also occurs when I run CMD as administrator and use wscript to run the script.
Is there any way to bypass this context and get the logged in user instead of the one that runs the script?
The command
query session console
should provide what you need
For an easier to parse
quser console
EDITED - Included sample vbs code
Dim strCmd
strCmd = "cmd /q /c ""quser console | find /i ""console"" "" "
Dim buffer
buffer = WScript.CreateObject("WScript.Shell").Exec(strCmd).StdOut.ReadAll()
Dim c, consoleUserName
c = InStr(buffer,"console")
If c > 2 Then
consoleUserName = Trim(Mid(buffer,2,c-2))
Else
consoleUserName = ""
End If
WScript.Echo consoleUserName
I suggest you execute the command
set
from the prompt. It may reveal a few items that are set in the environment that may be of interest.
set user
will censor the list so that only variables that start user will be displayed.

WMI remote process to copy file

Long story short, my application needs to copy a file to a remote target where UNC connections TO the target might not be possible. However UNC connections FROM the target and BACK to the server will always be possible. So the plan was to use WMI to start a remote command shell (cmd) and use the copy command to grab the file. But this doesn't work. The following command works fine when executed manually from the command line of the target:
copy \\192.168.100.12\c$\remotefile.txt c:\localfile.txt
But when I try this same command as part of the InputParameters("CommandLine") it does not work, and produces no error. Note that I can use WMI to connect to the target and remote execution works just fine as I can start calc.exe etc. Here is the code that doesn't work:
Dim ConnectionOptions As New System.Management.ConnectionOptions
With ConnectionOptions
.Username = "target\Administrator"
.Password = "password"
End With
Dim ManagementScope As New System.Management.ManagementScope("\\192.168.100.11\root\cimv2", ConnectionOptions)
Try
ManagementScope.Connect()
MsgBox("connected")
Dim ManagementPath As New System.Management.ManagementPath("Win32_Process")
Dim ManagementOptions As New System.Management.ObjectGetOptions
Dim ManagementClass As New System.Management.ManagementClass(ManagementScope, ManagementPath, ManagementOptions)
Dim InputParameters As System.Management.ManagementBaseObject = ManagementClass.GetMethodParameters("Create")
InputParameters("CommandLine") = "cmd /c copy \\192.168.100.12\c$\remotefile.txt c:\localfile.txt"
Dim OutputParameters As System.Management.ManagementBaseObject = ManagementClass.InvokeMethod("Create", InputParameters, Nothing)
MsgBox("done")
Catch ex As Exception
MsgBox(ex.Message)
End Try
Any ideas why this isn't working? Or does anyone have a better way of doing what I'm trying to do?
Frank you should actually give yourself credit since the method you created is likely the first ever to get around WMI limitations of remote file copy! I did 3 weeks of searching for info/workaround and yours is the only one that works! If I had any points I would vote for your solution...
I created a fully working VBS & WMI script based on your method:
InputParameters("CommandLine") = "cmd /c echo myFTPCommands > c:\ftpscript.txt"
where you replace myFTPCommands as needed with whatever script you want to go into the file c:\ftpscript.bat (or .vbs, .ps1, or whatever you like). If you couldn't fit enough text in the one-line script, then append with the same method using >>. Now, you can use XCOPY, PSEXEC, COPY, or anything else to run the script you just created on the remote host's file system.
Here's my fully fleshed out VBScript using your method. Thanks again. :)
HTH,
Lizz
For security reasons, most methods of programatically connecting to a remote machine and telling it to copy a file to itself from another machine are blocked. One thing that finally worked for me is FTP. Using the above code I can do something like this:
InputParameters("CommandLine") = "ftp -s:c:\ftpscript.txt"
Which causes the ftp commandline utility to run on the remote machine, using c:\ftpscript.txt to get a list of commands from. Since there is no way to copy the ftp script file to the target (again, no UNC connection), I can first do:
InputParameters("CommandLine") = "cmd /c echo myFTPCommands > c:\ftpscript.txt"
And this works :)
UPDATE: Never thought to use XCOPY and it works perfectly:
InputParameters("CommandLine") = "cmd /c echo F | xcopy remotefile localfile"
UPDATE: XCOPY worked yesterday, now it doesn't. NOTHING has changed, so I am at a complete loss for explanation.