How to run a PowerShell script file using VB.Net - vb.net

I have a desktop application. I am checking if the required text file exists. If it does not exist then I want to run a PowerShell script which will create the required text file.
Here's the code I am trying:
Dim userInfoPath As String = "C:\temp\UserInfo.txt"
If (IO.File.Exists(userInfoPath) = True) Then
MsgBox("The file exists !")
Else
Dim result As String
result = MsgBox("UserInfo.txt file does not exist. Click 'Yes' to create the required file.", vbYesNo)
If (result = vbYes) Then
Process.Start("powershell", "-File C:\Desktop\PowershellScript.ps1")
End If
End If
The PowerShell file placed at C:\Desktop\PowershellScript.ps1 contains the script to create a new file and add text to it:
mkdir C:\temp\
New-Item C:\temp\UserInfo.txt
Set-Content C:\temp\UserInfo.txt 'blah blah blah blah blah'
When I run the top most code and click on 'Yes' button, I get an error saying object reference not set to an instance of an object.
Error message link
What I am doing wrong?
And is there another way to run a PowerShell script file?

I'm using objShell.Run
Set wshArguments = WScript.Arguments
Set objShell = CreateObject("WScript.Shell")
sArg = wshArguments(0)
If wshArguments.Count > 1 Then
sArg = sArg & " " & wshArguments(1)
End If
sps1= "C:\Desktop\PowershellScript.ps1"
objShell.Run("powershell.exe -noprofile -noexit -ExecutionPolicy Bypass "+sps1+" ‘"+sArg+"’")

Related

manual entry in cmd window works, VBA executing CMD works, but not VBA when I use run (so I can hide the window)

SECOND EDIT/UPDATE: tried the path change recommendations, did not see any changes to the command string, still does not work. I re-wrote the code to use a fixed text file instead of a random temp file so I could monitor the contents of the file during execution. Able to conclusively show it is the
oShellObject.Run sCommandStringToExecute & " > " & sShellRndTmpFile, 0, True
code line that doesn't behave as expected. Still works with the w32tm command line, but not with the ntpq command line. With ntpq command, no changes made to the file, no error flags. I also tried out (again) the exec version of this problem where the window is supposed to flash a bit before it gets hidden programmatically. I get the expected reslut using exactly the same command string, cut and pasted into the other code. So the same command line works with manual entry into CMD, into PowerShell, and in the .exec code version, not the .run code version.
End of second edit. -------------------
EDIT: more debugging... ntpq -p works if I do .exec instead of .run, but then of course can't hid the cmd window. Extra test code at the end.
This Works: If I run these two commands in manually opened cmd window, or PowerShell window, both give the expected results.
w32tm /stripchart /computer:time.nist.gov /dataonly /samples:3 /rdtsc /period:1
ntpq -p
The second, ntpq -p, is bundled with NTP windows software from the home of the Network Time Protocol project that gives similar information to windows' w32tm when NTP is set up to look at the same time service computer as in the w32tm command.
This Doesn't work:
When I try to use these two command string when running CMD functions hidden using the classic "write to file" method shown in SO here and other places, the w32tm version gives the same results as the manual version, but the ntpq version just returns "error".
I read every single one of the recommended links for this question as well as searching OS and Google, and have not found an answer.
I am stuck on next step to troubleshoot the problem...only thing I could think of was to run the commands manually to confirm they work there. I can't imagine it being a administrator privileges issue since I can run them both in CMD line or PowerShell windows opened at normal rights level.
What should I look at next?
Here is the test code.
Option Explicit
Sub TestShellRun()
Dim sCmd As String, sReturnNTP As String
sCmd = "w32tm /stripchart /computer:time.nist.gov /dataonly /samples:3 /rdtsc /period:1 " ' /packetinfo"
sCmd = "%ComSpec% /C %SystemRoot%\system32\" & sCmd
sReturnNTP = fShellRun(sCmd) 'good return value, same as manual cmd line
Debug.Print sReturnNTP
sCmd = "ntpq -p"
sCmd = "%ComSpec% /C %SystemRoot%\system32\" & sCmd
sReturnNTP = fShellRun(sCmd) 'ERROR return value, even though manual cmd line has good values
Debug.Print sReturnNTP
End Sub
Public Function fShellRun(sCommandStringToExecute) As String
' This function will accept a string as a DOS command to execute.
' It will then execute the command in a shell, and capture the output into a file.
' That file is then read in and its contents are returned as the value the function returns.
' "myIP" is a user-selected global variable
Dim oShellObject, oFileSystemObject, sShellRndTmpFile
Dim oShellOutputFileToRead
Dim iErr As Long
Set oShellObject = CreateObject("Wscript.Shell")
Set oFileSystemObject = CreateObject("Scripting.FileSystemObject")
sShellRndTmpFile = oShellObject.ExpandEnvironmentStrings("%temp%") & oFileSystemObject.GetTempName
On Error Resume Next
oShellObject.Run sCommandStringToExecute & " > " & sShellRndTmpFile, 0, True
iErr = Err.Number
On Error GoTo 0
If iErr <> 0 Then
fShellRun = "error"
Exit Function
End If
On Error GoTo err_skip
fShellRun = oFileSystemObject.OpenTextFile(sShellRndTmpFile, 1).ReadAll
oFileSystemObject.DeleteFile sShellRndTmpFile, True
Exit Function
err_skip:
fShellRun = "error"
oFileSystemObject.DeleteFile sShellRndTmpFile, True
End Function
sCommand = "ntpq.exe -p"
Set WshShell = CreateObject("WScript.Shell")
Set WshShellExec = WshShell.Exec(sCommand)
strOutput = WshShellExec.StdOut.ReadAll
Debug.Print strOutput
Your fShellRun function didn't work due to error in temporary file path. Here is fixed version.
Function fShellRun(sCommandStringToExecute) As String
...
'invalid file path without path separator between directory path and filename!
sShellRndTmpFile = oShellObject.ExpandEnvironmentStrings("%temp%") & _
oFileSystemObject.GetTempName
'valid path with path separator between directory path and filename
sShellRndTmpFile = oFileSystemObject.BuildPath( _
Environ("temp"), oFileSystemObject.GetTempName)
...
End Function

vba shell command executing but no output

I am having some problems running a shell command and checking the output of the data. I wish to check using vba if the current remote user of the DB is Active. In
command prompt =
for /f "tokens=1-8" %a in ('quser') do #if "%d"== "Active" echo %COMPUTERNAME% %a %d
returns the users logged on and their state I wish to check that none of them are disconnected ("Disc"). I used this function to check the shell and return the pipe value as a string in a message box
Public Function ShellRun(sCmd As String) As String
'Run a shell command, returning the output as a string'
Dim oShell As Object
Set oShell = CreateObject("WScript.Shell")
'run command'
Dim oExec As Object
Dim oOutput As Object
Set oExec = oShell.Exec(sCmd)
Set oOutput = oExec.StdOut
Debug.Print sCmd
'handle the results as they are written to and read from the StdOut object'
Dim s As String
Dim sLine As String
While Not oOutput.AtEndOfStream
sLine = oOutput.ReadLine
If sLine <> "" Then s = s & sLine & vbCrLf
Wend
ShellRun = s
'example MsgBox ShellRun("cmd.exe /c" & "dir c:\")
End Function
Call Command used on click event
Dim CMDLineCommand As String
CMDLineCommand = "for /f ""tokens=1-8"" %a in ('quser') do #if ""%d""== ""Active"" echo %COMPUTERNAME% %a %d"
'(CMDLineCommand = "dir c:\")<------ THIS WORKS FINE
MsgBox ShellRun("cmd.exe /c " & CMDLineCommand)
This works fine for loads of command line commands I have tested it with but not query and therefore query user. The query user command works fine from command line but does not return anything when issued through a VBA Shell commands.
Any thoughts would be appreciated.
because shell does not know the path of the query.exe(quesr) it does not continue where as command prompt can use system variables to find exe's. solution find the query.exe and copy it to a working directory then run the shell command. mine was located in a hashed folder within C:\Windows\WinSxS be careful as here are 64bit versions and 32 bit.

How to execute Batch File while passing parameters from Excel

I am trying run a batch file placed at a particular path. The file requires user inputs for which I want the parameters to be passed from Excel cells. This execution of the batch file within Excel should happen by usage of click command button.
I am new to VBA. I tried the following code, but on clicking the button nothing is happening.
Private Sub CommandButton2_Click()
sid = Excel.Worksheets("Sheet1").Range("I8").Value
user = Excel.Worksheets("Sheet1").Range("I9").Value
Password = Excel.Worksheets("Sheet1").Range("I10").Value
msg = "hi"
Shell ("CMD.EXE /c C:\Users\shashank.b03\Desktop\test_CMD.bat" & sid &" "& user &" "& password &" ")
End Sub
Here is an example which I have tested and should work fine for you. It just calls the shell command and passes it a command string.
You can change the path where your batch file is in the string & if you don't want to show the shell window when you're running this use vbHide instead of vbNormalFocus.
You'll just have to change this a bit to put the cell values into the sid, user and password variables.
Hope this helps.
Dim sid As String
Dim user As String
Dim password As String
CommandString = "c:\test.bat" + " " + sid + " " + user + " " + password
Call Shell("cmd.exe /c" & CommandString, vbNormalFocus)
Here is a more basic example of using parameters and a batch file from shell.
Save the following as test.bat
set arg1=%1
echo HELLO %1!
pause
Put this code inside a button or some other component in excel;
Private Sub CommandButton1_Click()
Dim sid As String
sid = "Shashank"
CommandString = "c:\test.bat" + " " + sid
Call Shell("cmd.exe /c" & CommandString, vbNormalFocus)
End Sub
Make sure that the path where the batch file is saved is the same as the one in commandstring.
When this is run, you'll see the string held in the variable sid is passed to the batch file and used. You should be able to get it working from here.
Hope this helps

Outlook Not Running Visual Basic After Restart

So I have created a visual basic script in outlook that creates a random signature by pulling from Git.
The script works correctly but whenever I restart my machine the script doesn't run at all.
I fixed the issue by going to
"File"->"Options"->"Trust Center"->"Trust Center Settings..."->"Macro Settings"->"Enable all macros"
This let the VBA code work whenever I opened and closed Outlook but is there a better way to have the code work whenever I reopen Outlook or restart my machine.
I have tried to use
Private Sub Application_Startup()
MsgBox "Hi"
End Sub
While that code did work when I first put it in, whenever I restarted outlook it said it couldn't run because "Macros were disabled"
Here is my code for the random signature, anyway to have this work whenever I restart outlook or my machine? Or is the macro setting I edited the correct way to go?
Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
' Validate that the item sent is an email.
If Item.Class <> olMail Then Exit Sub
'These first variables is to find the file the .bat file created within the AppData folder
'Set enviro to %APPDATA%
Dim enviro As String
enviro = CStr(Environ("APPDATA"))
'Create a new variable that sets the file path for the RepoDir.txt
RepoPath = enviro & "\RepoDir.txt"
'Create a new variable to grab the line of text in RepoDir.txt
Dim RepoFilePath As String
Dim strFirstLine As String
'The new variable calls the RepoPath Variable, opens it and reads the first line of the file and copies it into a variable
RepoFilePath = RepoPath
Open RepoFilePath For Input As #1
Line Input #1, strFirstLine
Close #1
'The script runs a Shell command that opens the command line, cds to the Repo path within the str variable, does a git pull, and outputs the error level to a file in the temp directory
Shell ("cmd /c cd " & strFirstLine & " & git pull RandomSig & echo %ERRORLEVEL% > %TEMP%\gitPull.txt 2>&1")
'These second set of variables is to find the file the Shell command created within the TEMP folder
'Set enviro to %TEMP%
Dim Gitenviro As String
Gitenviro = CStr(Environ("TEMP"))
'Create a new variable that sets the file path for the RepoDir.txt
PullResult = Gitenviro & "\gitPull.txt"
'Create a new variable to grab the line of text in RepoDir.txt
Dim GitFilePath As String
Dim GitFirstLine As String
'The new variable calls the PullResult Variable, opens it and reads the first line of the file and copies it into a variable
GitFilePath = PullResult
Open GitFilePath For Input As #2
Line Input #2, GitFirstLine
Close #2
'MsgBox (GitFirstLine)
'The variable is checked to see if it does not equal 0, and if it doesn't the message is cancelled
If GitFirstLine <> 0 Then
MsgBox "There was an error when attempting to do the Git Pull, cancelling message"
Cancel = True
End If
Const SearchString = "%Random_Line%"
Dim QuotesFile As String
QuotesFile = strFirstLine & "quotes.txt"
If InStr(Item.Body, SearchString) Then
If FileOrDirExists(QuotesFile) = False Then
MsgBox ("Quotes file wasn't found! Canceling message")
Cancel = True
Else
Dim lines() As String
Dim numLines As Integer
numLines = 0
' Open the file for reading
Open QuotesFile For Input As #1
' Go over each line in the file and save it in the array + count it
Do Until EOF(1)
ReDim Preserve lines(numLines + 1)
Line Input #1, lines(numLines)
numLines = numLines + 1
Loop
Close #1
' Get the random line number
Dim randLine As Integer
randLine = Int(numLines * Rnd()) + 1
' Insert the random quote
Item.HTMLBody = Replace(Item.HTMLBody, SearchString, lines(randLine))
Item.HTMLBody = Replace(Item.HTMLBody, "%Random_Num%", randLine)
End If
End If
End Sub
Function FileOrDirExists(PathName As String)
Dim iTemp As Integer
On Error Resume Next
iTemp = GetAttr(PathName)
Select Case Err.Number
Case Is = 0
FileOrDirExists = True
Case Else
FileOrDirExists = False
End Select
On Error GoTo 0
End Function
It’s highly recommended to leave your macro security setting to only allow self-sign certificate Macros,
Do not use the Low option or run all
Create a self-signing certificate
Go to Start > All Programs > Microsoft Office > Microsoft Office Tools, and then click Digital Certificate for VBA Projects.
In the Your certificate's name box, type in name for the certificate.
Click OK. then SelfCert Success message will appears, click OK.
Go to Developer tab > click Visual Basic. or ALT+F11
In Visual Basic Editor, go to Tools > Digital Signature.
Digital Signature dialog appears and click on Choose and you’ll get a screen to select a certificate. Now you can choose the certificate you just created.
Edit
locating SelfCert.exe
Go to Start menu and typing VBA should bring up the SelfCert.exe.
Alternative method of locating SelfCert.exe
if you Can’t find it in the Start Menu? then By default you can find SelfCert.exe in the following location
Windows 32-bit
C:\Program Files\Microsoft Office\Office <version number>
Windows 64-bit with Office 32-bit
C:\Program Files (x86)\Microsoft Office\Office <version number>
Windows 64-bit with Office 64-bit
C:\Program Files\Microsoft Office\Office <version number>
Office 365 (Subscription based or Click-to-Run version of Office 2013)
C:\Program Files\Microsoft Office 15\root\office15
If SelfCert.exe is not installed
Then run Office setup and choose Add or Remove Features.
With older versions of Office you’ll need to choose Custom installation and then Advanced customization.
Expand the Office Shared Features section and select Digital Certificate for VBA Projects to run from your computer.
Simply run SelfCert.exe after locating it.

AppleScript: Main Script reading from random folder

How do you bundle an applescript that has a main script which is reading scripts randomly from a folder?
Check out this code: http://macosxautomation.com/applescript/linktrigger/index.html.
It's doing exactly that (besides other things) and you can use the sub-routine there for the script-handling.
Here is a full script that works when you follow these steps: save it as an application and put all your scripts into the "Resources" folder of that application (as described at the webpage, "Show Package Contents"). Good Luck.
property MyUserName : ""
if MyUserName is "" then
display dialog "User Name:" default answer "" buttons {"Cancel", "Continue…"} default button 2
copy the result as list to {returnedButton, returnedText}
if returnedButton is "Cancel" then return
-- What to do when the user did not input any text?
if returnedText is "" then return -- we stop.
set MyUserName to returnedText
say "Hello," & MyUserName & "!" using "Karen"
else
display dialog "User name: " & MyUserName buttons {"Ok"} default button 1 with icon 1 giving up after 10
end if
say "For your information, please start the Amuse App everytime you log on... and I will speak to you at random times during your visit with me." using "Karen"
delay 20
try
repeat 105 times
set rnd to (random number from 1 to 105)
set rndFileName to (rnd as text) & ".scpt"
if my run_scriptfile(rndFileName) is false then -- if the script execution fails,…
error number -128 -- … stop this app
end if
end repeat
on error the error_message number the error_number
display dialog "Error: " & the error_number & ". " & the error_message buttons {"OK"} default button 1
return
end try
on run_scriptfile(this_scriptfile)
-- This handler will execute a script file
-- located in the Resources folder of this applet
try
set the script_file to path to resource this_scriptfile
return (run script script_file)
on error
return false
end try
end run_scriptfile
This is how it looks with (only) 3 of the scripts you wanna randomly execute:
Your question is clear but here's an script that loads randomly a script from a folder, if the folder contains any.
set theFolder to choose folder as string
set theFiles to do shell script "ls " & quoted form of posix path of theFolder & " | grep '.scpt$' || true"
if theFiles = "" then return
set theFile to some item of (paragraphs of theFiles)
set randomScript to load script file (theFolder & theFile)