I am having an issue trying to run a complex HTTP Request through a powershell command from a VBA function.
VBA Code Below: The powershell script runs fine from inside powershell
Public Function PS_GetOutput(id As String) As String
'Setup the powershell command properly
psCommand = "powershell -command " & "C:\Users\promney\temp1\curlCommand.ps1 " & id
'Execute the command
CreateObject("WScript.Shell").Run psCommand, 3, True
'Get an instance of the clipboard to capture the save value
End Function
The PS1 file should grab the html and put a string on the clipboard. Instead, the PS window opens as a blue field, then it and excel crash completely and immediately. What am I doing wrong here?
Note: I would include the PS script but that is a lot of possibly sensitive info to scrub and I'm pretty sure the issue is in the VBA, since it works fine unless called from excel.
Related
I'm trying to change the file association for opening URL's in Excel cell in another browser. According to the use of (CMD) ftype command with Excel.UriLink.16, I should be able to do this from powershell (via cmd) using:
# To change it:
cmd /c 'ftype Excel.UriLink.16=C:\Program Files\BraveSoftware\Brave-Browser\Application\brave.exe "--single-argument" "%1"'
# The original is:
# cmd /c ftype | findstr /i "excel.uri"
# Excel.UriLink.16=C:\Program Files\Microsoft Office\Root\Office16\protocolhandler.exe "%1"
This seem to have no effect at all, and will always open the URL in the default browser.
What is controlling the Excel opening of URLs and how to change this?
UPDATE: 2022-07-30
Following another SO here, state to check:
HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\*\UserChoice
With:
(Get-ItemProperty HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\*\UserChoice -Name ProgId).ProgID | Where-Object -FilterScript{ $_ -like "*HTM*"}
Output:
FirefoxHTML-308046B0AF4A39CB
FirefoxHTML-308046B0AF4A39CB
MSEdgeHTM
MSEdgeHTM
MSEdgeHTM
Unfortunately not helpful.
I'm starting to understand better how this works,and it looks like this is deeply hidden in the OS. The seemingly undocumented program protocolhandler.exe is taking care of how all URI's are opened.
In addition the assoc show that .URL=InternetShortcut, is linked to:
InternetShortcut="C:\WINDOWS\system32\rundll32.exe" "C:\WINDOWS\system32\ieframe.dll",OpenURL %l.
Checking others, we find:
# (cmd /c ftype |Select-String protocol |Select-String excel ) -replace ("=","=`t")
Excel.UriLink.16= C:\Program Files\Microsoft Office\Root\Office16\protocolhandler.exe "%1"
ms-excel= C:\Program Files\Microsoft Office\Root\Office16\protocolhandler.exe "%1"
As shown in the MS Documentation on URI, uri-schemes and info on Excel
Hyperlinks, this program need to be able to handle anything...
UPDATE: 2022-07-31
Apparently the visible usage of assoc and ftype are only smoke & mirrors for determining the File Type Associations (FTA). According to this SU answer, MS assoc XML and a security researchers blog, the way files are associated in Win10+ have completely changed since Win8, preventing user to take control of this by hashing associations to ensure users can't change them easily.
To query the file association XML, you can use:
# Run as Admin
Dism.exe /online /export-defaultappassociations:.\myCurrentFileAssoc.xml
...
<Association Identifier=".url" ProgId="IE.AssocFile.URL" />
...
# If there are any errors, you can find a LOG file in:
C:\WINDOWS\Logs\DISM\dism.log
The unofficial* tools exists to query and change these are:
(* Unofficial because MS doesn't want you to mock around with file associations.)
[1] SetUserFTA - Download: SetUserFTA.zip
[2] SetDefaultBrowser - Download: SetDefaultBrowser.zip
IMPORTANT:
SetUserFTA must be run in the users context, not with administrative or system privileges. Sometimes the timing can be important a swell – make sure it runs after the profile of the user is loaded.
Running it with:
# SetUserFTA.exe get | Select-String url
.url, IE.AssocFile.URL
http, FirefoxURL-308046B0AF4A39CB
https, FirefoxURL-308046B0AF4A39CB
# To see all installed browsers
# SetDefaultBrowser.exe
...
HKLM Brave
name: Brave
path: "C:\Program Files\BraveSoftware\Brave-Browser\Application\brave.exe"
...
You can also associate portable browsers by following instructions here.
⛔ Still no progress for dealing with Excel assoc's...
This is not an answer, but may be helpful in similar situations.
Using VBA
The only way I managed to conditionally open a URL from an Excel cell with a different (than default) browser, was by using a VBA code snippet and adding it to the list of Microsoft Excel Objects. This have several drawbacks, but also one nice surprise.
Drawbacks:
Forces you to enable VBA macros in Excel
Forces you to change the Excel filetype from *.xlsx to *.xlsm
Surprise:
Long-Click on a cell can be used to separate the browser to be used to open a hyperlinked URL. This in combination with clicking on the hyperlink vs. in the blank part of the cell. In other words, a short click on the (matching) hyperlink will open the default browser, whereas a long click will open the URL in the (coded) browser.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
On Error Resume Next
Dim Link As String
Dim bravePath As String
Link = Target.Value
bravePath = """C:\Program Files\BraveSoftware\Brave-Browser\Application\brave.exe"""
SubString = "bing"
If InStr(Link, SubString) <> 0 Then
'if str contains 'bing'
'Call OpenBrave
'Application.Run "Module1.OpenBrave", Link
Shell (bravePath & " -tab " & Link)
'ElseIf InStr(Link, SubString) = 0 Then
'if str does not contain it
'Call OpenDefault
'MsgBox "That is a normal URL", , "No Party Like This"
'ActiveWorkbook.FollowHyperlink Address:=Link, NewWindow:=True, AddHistory:=True
End If
End Sub
As you can see I commented out the ActiveWorkbook.FollowHyperlink (default bahaviour), as it is not needed, and can be replaced by another browser.
This is how it looks.
Again, to add the VBA code:
Save Excel sheet as *.xlsm type
enable VBA & Macros in settings
Left-click on sheet tab and select View Code
Paste the above code.
Done!
There is, unfortunately, no way that I know of to stop Excel from opening a valid hyperlink in the default program when you click on it. (i.e. the *FollowHyperlink event does not contain a Cancel option, unlike — for example — the Workbook_BeforeClose event)
However, it is possible to create a hyperlink that goes nowhere: rather than typing the URL in manually, use the Hyperlink editor (right-click in the cell, and select "Link" down at the bottom, or press Ctrl + K with the cell selected), go to the "Place in This Document" tab, and type the Cell's own reference in. This will give you a Hyperlink that takes you to the cell you are already in! However, you can set the Text to Display to be your target URL.
Then you can "catch" the Hyperlink Click in the *FollowHyperlink event (Either the Worksheet_FollowHyperlink event for a single Worksheet, or the Workbook_SheetFollowHyperlink event for the entire workbook), check if it "goes nowhere" — and, if so, navigate to the URL in the TextToDisplay with your preferred browser:
Option Explicit
Private Const PreferredBrowser As String = "C:\Program Files\BraveSoftware\Brave-Browser\Application\brave.exe"
Private Sub Workbook_SheetFollowHyperlink(ByVal Sh AS Object, ByVal Target AS Hyperlink)
If Target.SubAddress = "" Then Exit Sub 'External Hyperlink
If Range(Target.SubAddress).Address(True,True,xlA1,True) <> _
Target.Range.Address(True,True,xlA1,True) Then Exit Sub 'Hyperlink is not recursive
Shell """" & PreferredBrowser & """ -tab """ & Target.TextToDisplay & """"
End Sub
(Alternatively, you could create a "Shell.Application" object, grab the most recently opened window, check if that is an IE/Edge window the same URL as the hyperlink you just clicked on, and then try to force-close it while you open the hyperlink in your own browser…)
I'm using Powershell version 7.2.1
When I run the command below on Powershell, it works fine, i.e. Excel is launched and the target Excel file is opened.
& 'PATH_TO_EXCEL_EXE' 'PATH_TO_TARGET_FILE'
Howewer, when I pass this command to a scheduled task, Excel is launched but the target file isn't opened. More details about my Powershell script:
$action = New-ScheduledTaskAction -Execute "& 'PATH_TO_EXCEL_EXE' 'PATH_TO_TARGET_FILE'"
...
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "myTask"
# The line below is for testing purpose, to see if my scheduled task can launch correctly.
Start-ScheduledTask -TaskName "myTask"
Can someone tell me the reason why Powershell fails to replicate the action, when it's passed to a scheduled task as above? Any workarounds/solutions would be appreciated.
Based on ZivkoK's comment, I'm adding an answer which solves the issue:
$excelExePath = ...
$excelFile = ...
$action = New-ScheduledTaskAction -Execute $excelExePath -Argument """$excelFile"""
A scheduled task based on the action above does what it intends to do.
P.S. Triple quotes surrounding excelFile parameter are needed when the excel file path contains space characters. For example, if the excel file path is "C:\MyUser\some random file.xlsx", then Excel tries to open 3 files named "some", "random", and "file.xlsx". Using triple quotes solves this problem.
I have an Excel macro that I would like to run automatically when the file is opened. The only way I have gotten this to work is by adding a msgbox before calling to my subroutines. However, this requires me to click OK or close the box for the macros to run. I have tried using a timed msgbox sub, but this also does not work.
For some reason, the msgbox pops up before Excel is fully opened, at which point the macro gets stuck here (code for this is below). From here, I tried waiting for the file itself to be opened until it is in write-mode (Workbook.ReadOnly = false). This also did not work.
Public Sub msgBoxTimer()
Const timeout = 2
Dim objShell As Object
Set objShell = CreateObject("WScript.Shell")
objShell.Popup "Measurement will begin shortly", timeout
End Sub
Private Sub Workbook_Open()
Call msgBoxTimer
Call init ' initiate device
Call updateIndex ' collect & record measurements
End Sub
I get from your comment that you are probably running other shell commands in init and updateIndex.
What needs to be clear is that when you execute a Shell command via a Shell object in VBA, the default behavior is not to wait for the shell command to complete before running the next line of codes.
If you want Excel to wait for the Shell command to be completed before continuing, you can have a look at the answers to this question.
That being say, if you want Excel to be fully open before running any shell commands, you can use a MsgBox like you originally intended, but it has to be VBA's MsgBox that you would simply call like this:
MsgBox "Measurement will begin shortly"
The VBA thread will wait for the "OK" button to be pressed before continuing the execution.
I'm trying to write a code that would create and execute two batch scripts, one after another. The 1st makes a given number of copies of my pdf file (makecopies.bat) and the 2nd one changes the names of the copies according to a list of names. Thus, it is crucial that the execution of the 1st goes to completion before the 2nd one runs. That is why I refrain from using Call Shell("cmd.exe /k cd " & CurDir & " && makecopies.bat", vbHide) - I tried it and it would result in overlapping execution of scripts.
Instead, I tried to make it work with WScript.Shell, because that method allows setting waitOnReturn value. However, the problem is as follows (I need to execute two scripts, I use one as an example):
the part below works fine on my own laptop and when I try to run the code on my company computer (the one I intend to use the code at), it gives "Run time error -2147024894(80070002) Automation error The file cannot be found"
Dim wsh As WshShell
Set wsh = New WshShell
Dim makecopies As String
Dim script_makecopies As Long
Open CurDir & "\makecopies.bat" For Output As #FileNumber
Print #FileNumber, Range("B2").Value
Close #FileNumber
makecopies = CurDir & "\makecopies.bat"
script_makecopies = wsh.Run(makecopies, windowStyle:=0, waitOnReturn:=True)
I tried to change my code in order to overcome the problem - and it kind of worked, creating another problem in turn :D I replaced the last line with wsh.Run "cmd.exe /k makecopies", 0, True. This gets the job done, however at this point Excel stops responding and the rest of code (i.e. the second batch file) is not executed. I noticed that when removing /k Excel works fine and the code that follows this line is executed, but the batch (makecopies.bat) itself is not.
Does anyone have any idea how can I make it work? (Thank you in advance!)
I have a Fortran routine which reads the data from a file, processes the data, and records the results in few *.csv files. It has perfectly worked for years.
Now I made a VBA Excel Macro which prepares the data files, calls the Fortran routine
TemporFile = Directory & "\" & "VTFeV4.exe"
Call Shell(TemporFile, 0)
, and forms an Excel workbook using the *.csv files generated by the Fortran routine VTFeV4.exe.
The problem is, it doesn't work consistently. Sometimes, the resulting files do not appear, the VBA Macro indeed canot find the file, and interrups. The Windows' Start Task Manager shows that the EXE file is still running.
(Please note, "Directory" is the correct Path).
I found that if to run the Macro stepwisely (F8), it works better. So I added time delay
Dim PauseTime, Start, Finish, TotalTime
PauseTime = pt
Start = Timer
Do While Timer < Start + PauseTime
DoEvents
Loop
which worked well with pt=10 until TODAY (02/22/17) when it stopped working at all even when pt=20s though the EXE file works well and fast (apparently much quicker than 10s, less to say!).
I also tried
ABC = Shell(Directory & "\NewVTF1.exe", 1)
with same result.
What is the problem with Shell? Please help!