Check Excel Macro Security Settings - vb.net

I have a vb.net Application that starts a Excel macro.
Is there a way to check the macro Security Settings of the Excel first?
Imports Excel = Microsoft.Office.Interop.Excel
Private Sub macrotest ()
objExcel.Workbooks.Open(strPath)
if ***'Check her what macro Security Settings is selected!*** Then
objExcel.Run("SortIO")
end if
End Sub

This seems to have cross-posted to the Excel VBA questions page: would you mind speaking a little more slowly?
... reads slowly ...
Well, I can give you an answer in VBA: the Excel.Application.AutomationSecurity property.
The available values are enumerated by Office.MsoAutomationSecurity:
1 msoAutomationSecurityLow
2 msoAutomationSecurityByUI
3 msoAutomationSecurityForceDisable
These are the settings for macros available in the API exposed to VBA. The user interface, visible in the 'Developer' tab of the ribbon, corresponds to the registry settings explained by NoAlias in the previous answer:
HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Excel\Security\VBAWarnings
With the following enumerated values:
Enable all macros
Disable all macros with notification
Disable all macros except digitally signed macros
Disable all macros without notification
If you go down the registry route, a VBA coder's advice would be to use the safe registry classes exposed by WMI scripting... And check that your user does actually have the privileges to make that registry write: there may be a registry policy in place preventing it.

I found on this site that you can check the registry for the security settings. The one issue I found was that my registry key was not in the exact place that was referenced on the site. That being said, you may want to just Try Catch it or make a more elaborate method for finding the VBAWarnings key in the registry.
Dim strVBASecuritySetting As String = My.Computer.Registry.GetValue("HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Excel\Security", _
"VBAWarnings", String.Empty)
If strVBASecuritySetting = "1" Then
objExcel.Run("SortIO")
End If
These are the possible values for VBAWarnings:
Enable All
Disable All with Notification
Disable All Except Digitally Signed
Disable All without Notification

Related

Getting a .xlsm file to not execute code when being opened with VBA

I have a macro in Excel. Part of that macro opens up other workbooks using Workbooks.Open(Filepath).
Some of the workbooks I'm opening have (badly done) VBA code inside of them, that try to then calculate a UDF and fail horribly.
Without resorting to an On Error Resume Next or an On Error GoTo, how do I say "Open this file, DO NOT RUN ANY CODE".
Trying to avoid letting the code execute in the first place due to possible security concerns. I feel comfortable enough opening these files, and there's a decent chance that they're not going to be compromised, but breaches can happen, and why have a hole when I don't need one? I also don't want error messages interrupting my code executing.
Searching the web just shows me shift+open opens the file without executing code, which is not at all what I'm looking to do. I'm looking for the equivalent VBA method.
AutomationSecurity is likely what you want:
https://learn.microsoft.com/en-us/office/vba/api/Excel.Application.AutomationSecurity
MsoAutomationSecurity can be one of these MsoAutomationSecurity
constants.
msoAutomationSecurityByUI . Uses the security setting specified in the
Security dialog box.
msoAutomationSecurityForceDisable . Disables all
macros in all files opened programmatically without showing any
security alerts. Note This setting does not disable Microsoft Excel
4.0 macros. If a file that contains Microsoft Excel 4.0 macros is opened programmatically, the user will be prompted to decide whether
or not to open the file.
msoAutomationSecurityLow . Enables all
macros. This is the default value when the application is started.
You can disable the macros for newly opened files, open the workbook, and then re-enable the macros:
Private Sub OpenWorkBookMacroDisabled(wbPath As String)
Application.AutomationSecurity = msoAutomationSecurityForceDisable
Workbooks.Open (wbPath)
Application.AutomationSecurity = msoAutomationSecurityByUI
End Sub

Hide worksheet in Excel Add-In from other VBA Projects

I have an Excel Add-In which I am building which stores users settings in a Settings worksheet within the Add-In. I use the Settings sheet essentially as storage for boolean values and potentially, the user's registration details.
However, if I open up a new VBA Project and include the Add-In as a reference (In VBA: Tools > References > MY Add-In) then I can access the Settings worksheet and potentially break the password on it and hack the registration details.
The Settings sheet is set to be xlVeryHidden however it can be accessed via VBA code. Is there anyway to prevent this in Excel? In a module for example I can use the Option Private Module method.
If you password protect and lock the project then your code and the worksheet objects can't be viewed. Go to Tools > VBAObject properties > Protection tab then tick 'Lock Project For Viewing' and then set a password in 'Password to view object properties'.
However, there is nothing to stop a hacker from...
For s = 1 to Sheets.Count
Sheets(s).visible = True
Next s
...to see your Settings sheet.
There are a few options:
1) Have the settings sheet in a seperate workbook, or some other format like .txt and read from that (recommended).
2) Use some kind of encryption in your Setting sheet and decrypt it in your code, a really simple example is to use numbers in place of text so 'example' would = '5,24,1,13,16,12,5', but obviously you want to employ something more sophisticated that than and you can search online for many ways to do it.
3) Use 2, but store the decryption code somewhere else.
Be aware though, that for someone who knows what they're doing there really is no way to prevent a VBA hack, unless you use option 1/3 and have a way to store the file somewhere that isn't publicly accessible.

When opening a workbook via IE, a form that is activated on Workbook_Open appears behind internet explorer for some users

For some users of an excel workbook, a login form that is activated on workbook_open appears behind the Internet Explorer 11 window that they use to access the workbook. (Yes, the user has either made this a trusted document or thier security settings in excel automatically enable macros)
I am unable to replicate the problem myself but have seen it occur via screen sharing.
I have tried the workbook.activate and setfocus methods but this doesn't help the users in question. Best case scenario may be to automatically minimise IE from the workbook when the form is activated (if this is possible).
Is there a fool-proof way to ensure that the excel workbook, and specifically the login form, is visible when the user opens the application via IE?
My code as it stands is ludicrously simple having removed failed attempts to remedy the problem:
Private Sub Workbook_Open()
frmLogin.Show
End Sub
I have not asked many questions on this site. Please let me know if more information is required.

Prevent Word macro in Normal.dotm for some templates

I have a Normal.dotm file that contains an AutoNew macro.
This macro is automatically executed each time a new document is created using any other template.
Is there any way I can prevent this automatic behavior for a specific template?
I have a Word VSTO add-in running, so I can hook into Word's events, but so far I havn't found a way to prevent this.
I do know that I can prevent macro execution when using templates programmatically, for example like this:
' Disable auto-macros before opening document
wordApplication.WordBasic.DisableAutoMacros(1)
' Open document
newWordDocument = wordApplication.Documents.Open(template.FullName, ConfirmConversions:=False, [ReadOnly]:=True, AddToRecentFiles:=False, Revert:=True)
' Re-enable auto-macros
wordApplication.WordBasic.DisableAutoMacros(0)
But this solution doesn't work when the user uses a Word template from Windows explorer or the Open-dialog in Word, since in those cases I can't execute code before it's too late already.
Or can I?
I hope someone has a trick for me :-)
-
Edit: While trying different solutions, I discovered something that might help others in similar situations, though unfortunately it doesn't help me.
It seems that if a template contains a module containing an AutoNew (or AutoOpen for that matter), that local macro is executed instead of the one in Normal.dotm.
Example:
Normal.dotm contains the following macro:
Sub AutoNew()
MsgBox "Normal.dotm"
End Sub
Test.dotm contains the following macro:
Sub AutoNew()
MsgBox "Test.dotm"
End Sub
When executing Test.dotm the message "Test.dotm" is displayed, while the message "Normal.dotm" is not displayed.
If the AutoNew macro is removed from the Test.dotm template, the message "Normal.dotm" is indeed displayed.
So it is possible to easily override the auto-macros.
The local versions of AutoNew and AutoOpen can even be empty subs that do nothing. It still works.
This is not possible in my case though, since the template I use is generated by code, and cannot contain macros (because adding macros to templates programmatically requires the user to manually activate the option "Trust access to the VBA project object model", and that's something I cannot ask my customers to do for all users. It's also a security risk.)
Based on the workaround described in the "Edit" part of the question - providing a template with "empty" Auto-macros - it's possible to use the Open XML SDK to create a template and add the VBA project to it in order to provide this functionality. This approach avoids the user needing to allow access to the VBA project on his installation. The only "macro security" that could be triggered is that for not allowing macros to run. But since the client uses macros, anyway, this should not be a major obstacle.
The simplest method is to create as much of the basic template as possible in the Word UI and use this as a starting point.
Since you're unfamiliar with the Open XML SDK, the next step would be to create one (or more) templates in the Word UI using the basic template as the starting point, saving under a different file name.
You can then use Open XML SDK Productivity Tool to see the code required to generate any one of these files, as well as, using the Compare tool, the code for converting the basic template to the derived version. This should give you a decent start with the SDK and it's object model. Once you get a feel for how the Open XML SDK works, if you're familiar with Word's object model, using that provided by the SDK is relatively straight-forward as an effort was made to make it correspond as closely as possible to the "COM" object model.
The VBA project can be added later, but you can also include it in the basic template. That would be the simplest approach.
Include this "starting point" basic template as part of your solution, installing it as part of the solution.
Within the AutoNew macro you can check the AttachedTemplate property. Only if it is a template where you want to apply the cleaning you can execute the respective macros.
Sub AutoNew()
If ActiveDocument.AttachedTemplate <> "Normal.dotm" Then
Exit Sub
End If
' rest of the macro
End Sub
If you don't control the Normal.dotm you can put an empty AutoNew macro in your own templates. As Word only executes the auto macro in the closest context, the macro in the Normal.dotm file would not be executed.
If you don't control the other templates either, you can tell your users to hold down the SHIFT key while creating a document. This prevents the execution of the auto macro.
Probably it is best, however, if you ask the owner of the other system to find another solution that does not rely on polluting the Normal.dotm file.

macros on document open. Bug in ms office 2013?

I have a macros that starts running when a document opens. It looks like this:
Private Sub Document_Open()
....
Dim strInput As String
strInput = ActiveDocument.Content
....
In office 2010 this macros works nicely, however, in office 2013 I get this error message (translation to English):
This command is not available, because there are no documents opened
And when I hit on Debug button, I see that this line of code is highligthed:
strInput = ActiveDocument.Content
I think it's a bug of office 2013, because for some insane reason it invokes this macros before the document is opened, even though I clearly force it to do right after opening - Private Sub Document_Open(). So, what is wrong with that and how can I fix that?
If you're seeing the yellow message bar then this isn't a bug. It's because your document isn't "trusted" - it's "sandboxed". You need to check whether it's a ProtectedViewWindow - introduced in Office 2010 - and take appropriate action.
The Protected View is explained in this article: https://support.office.com/en-us/article/What-is-Protected-View-d6f09ac7-e6b9-4495-8e43-2bbcdbcb6653. Basically, it prevents code from running in any document that comes from an origin / author that isn't trusted. The user needs to make an explicit decision to trust the document in order to go into Edit mode.
Obviously, this is a major impediment to VBA code, so you have the ProtectedViewWindow object in the object model. There are application-level events that can be used to manage this state in the entire Word environment, such as ProtectedViewWindowOpen that triggers when a document is opened "sandboxed". After determining whether the document is trustworthy, the code can make the document editable using the ProtectedViewWindow.Edit method.
For example, to trust all documents that come from a specific file path:
Private Sub app_ProtectedViewWindowOpen(ByVal PvWindow _
As ProtectedViewWindow)
If PvWindow.SourcePath = "C:\Test" Then
PvWindow.Edit
End If
End Sub
The above needs to be in an application-level class module and events for this class need to be active on the application. If you're not familiar with using application-level events, see https://msdn.microsoft.com/en-us/library/office/ff821218.aspx