Restricting Excel sheet to open only within organization network - vba

I want to restrict Excel sheet to open only within my organization's network. If my system is connected with company's internet, only then it should get open. If the system is not connected to internet or connected with outside network, it should not get open.
I am using Macro for this. I have used the below code so far, found this on another answer on Stack Overflow. This code is giving same value for a system in different connected network. This will work only if the system is different. but not for different networks.
Option Explicit
Enum COMPUTER_NAME_FORMAT
ComputerNameNetBIOS
ComputerNameDnsHostname
ComputerNameDnsDomain
ComputerNameDnsFullyQualified
ComputerNamePhysicalNetBIOS
ComputerNamePhysicalDnsHostname
ComputerNamePhysicalDnsDomain
ComputerNamePhysicalDnsFullyQualified
End Enum
Declare Function GetComputerNameEx Lib "kernel32" Alias "GetComputerNameExA"
( _
ByVal NameType As COMPUTER_NAME_FORMAT, _
ByVal lpBuffer As String, _
ByRef lpnSize As Long) As Long
Sub test()
Dim buffer As String
Dim size As Long
size = 255
buffer = Space(size)
GetComputerNameEx ComputerNameDnsFullyQualified, buffer, size
Debug.Print Left$(buffer, size)
End Sub

I'll respond even though there was no actual question in your post, and it will probably get closed unless you edit it to add information about a specific programming-related issue, along with examples, detail of what you've tried, and an actual question. (See this and this and this.)
The short answer is:
IT'S NOT POSSIBLE.
Anyone who really wants to access your workbook (or any other Office document) can do a quick Google Search to bypass any security "features" you add.
AUTO_OPEN macros and On Open events can be easily bypassed by holding Shift while opening, or distrusting macros in their Trust Centre. (Here is the first result of a Google search on the topic.)
Passwords can be cracked within minutes using freeware utilities or manually with only a few steps. (See my answer here.)
If the people you are concerned about are not computer-savvy, I suppose you could have the workbook silently notify you of where it's being opened (for example, the IP address or computer name)) but, once again, these could be faked or bypassed altogether.
Assuming the issue is concerns over employees using the workbook (or the data it contains) for "unapproved purposes", the ideal solution would be to either start trusting your staff, or if that's not possible, you need to fire them and find people you do trust.
Edit: Bypassing Workbook_Open
Here's an example of a workbook with a Workbook_Open event, first opened normally, then bypassed by opening the workbook a slightly different way:
Edit: Prevent Any Code From Running
As a developer, I often keep my macro security settings reduced or off. However, a default installation has security turned on, and even if it was disabled, it's not hard to re-enable security in:
File ➡Options ➡Trust Centre
You can't force code to run or bypass security programmatically.
Anything you think you can do or find or do to force code to execute without the user's consent will not work, and at the very least will have a workaround.
Why?
Compare it to Virus Scanner software.
Imagine what would happen if code was able to disable your Virus Scanner? That would make all Virus Scanners absolutely useless, forever. If it were possible, virus creators would be doing it routinely.
The same goes for VBA Macro security options: If it could be bypassed programmatically, the "options" wouldn't have any point and wouldn't even be included. It's not a matter of convenience; it's a matter of security.

Related

Collection similar to Document.Revisions

Using VBA in Word 2013.
In the Word object model, Document.Revisions gives you a collection of revision objects (tracked changes), and you can accept or reject them programmatically. Plus, the collection itself has a Count property.
I did not find any feature in the object model that exposes the Undo/Redo count or history. To clarify, I am looking for a way to determine how many user changes are in the Undo stack and the Redo stack at a given time (because I am not editing the document contents via macro). It would be a bonus to be able to see the individual changes that are available to undo or redo, but I'm okay without that.
I know I can use the Document.Undo and Document.Redo methods, but I don't see a way to get a count of changes that can be undone or a count of undone changes that can be redone.
I suppose I could just iterate through the stack, so to speak, by invoking Document.Undo or .Redo and checking the return value to see whether there was anything there, then reversing what I had just undone/redone. I was hoping for something akin to Document.Revisions.Count.
EDIT: I need to access the Redo stack. It begins to look as though the object model does not expose that object. An old (2013) question recorded here suggests that there is no such object/collection (search for "redorecord").
Any ideas?
Thanks!
You could create & deploy a custom UndoRecord, so you can roll back all your actions in one go at the end, via code like 'ActiveDocument.Undo', without the need to keep track of all the intervening edits. See: https://learn.microsoft.com/en-us/office/vba/word/Concepts/Working-with-Word/working-with-the-undorecord-object
To deploy this for end-user actions in the document itself, simply use:
Option Explicit
Dim objUndo As UndoRecord
Sub CreateUndoRecord()
Set objUndo = Application.UndoRecord
objUndo.StartCustomRecord
End Sub
to create the Custom Record then, when you're finished, clear the lot with:
Sub ClearUndoRecord()
objUndo.EndCustomRecord
ActiveDocument.Undo
End Sub

VBA Access security question: Detect if the instance of access is from Access.Application?

My file (c:\mydb.accbe) has protection against the shift bypass, hidden access object window protection, disabled ctrl-g, hotkey bypass protection, etc. Project is also password protected, then compiled, and encrypted.
The problem is any user with read access to that accde file can create a new access project and create an instance of the protected file of that project using this code:
Dim appAccess As Access.Application
Set appAccess = CreateObject("Access.Application")
appAccess.OpenCurrentDatabase = "c:\mydb.accbe"
Now they can call any public function of that instance, for example:
call appAccess.run("thisIsPublicFunctionIn_mydb")
I can see two potential ways to mitigate this:
1# Any potentially sensitive function would get an extra parameter that contains the 'security' code.
2# Add some security by obscurity by renaming all the functions to random numbers at the end.
Other then using a real programming language (sadly not an option), got any suggestions on how I can detect this or protect against it?
When the app is opened through automation the UserControl property is updateable, so that is not really an option.
You cannot prevent that from happening. Best you can do is use a SQL server backend, where you tightly control permissions on tables, and use procs (with permissions) to update sensitive data.
I believe that application.UserControl does something around this. I've just tried, and seems to be ok for opening via access.application

Killing other applications Window

I have the problem, I'm in a network, where everyone sends messages through msg. Through it's really annoying, I thought about killing the messageboxes process. Running under csrss.exe thats not possible. When I looked through the taskmanager I noticed, when opening the tree structure of the csrss.exe, there was the messagebox and I could kill it. Has anyone any idea, how to do that in Visual Basic.
A simple web search led me to this question, which has some good answers already.
With a little work, I came up with this solution. It find the process by name (csrss), then filters by window title (Message from).
Sub Main()
killProcesses("csrss", "Message from")
End Sub
Private Sub killProcesses(processName As String, mainWindowTitle As String)
Dim processes = Process.GetProcesses().
Where(Function(p) p.ProcessName.Contains(processName)).
Where(Function(p) p.MainWindowTitle.Contains(mainWindowTitle))
' (Where clauses can be combined into one of course)
For Each p In processes
p.CloseMainWindow()
Next
End Sub
It works like this. Send a message
C:\Users\djv>msg djv hey whats up
Get a message
Here is the task
And what the code sees
It is closed upon the p.CloseMainWindow() call. It will also close any other window which matches the description, since it's not limited to one. This should satisfy your requirement.
Just so the question hast a proper answer, I found a solution using the win32 api (PInvokes) specifically the user32.dll. It provides methods like GetWindow, GetWindowThreadProcessId and CloseWindow, which solved my problem.

Outlook code stopped working

I have a 1-min delay on all emails and want to assign a category set up as an exception to the rule to send immediately.
I created the macro but it stopped working.
Public Sub CategoriesButton()
Dim Item As Outlook.MailItem
Set Item = Application.ActiveInspector.CurrentItem
Item.Categories = "SendMe"
Item.Save
End Sub
Interesting - I just had the same issue. Working perfectly but then I restarted Outlook and it stopped working - for no apparent reason.
Took me a while to work this out - but when you restart Outlook it applies Macro security permissions to your macro.
If you haven't digitally signed your macro, the default behaviour is to prevent it from running.
You can relax the security settings so that Outlook with either ask your permission to run macros, or just run all macros regardless (this latter option is probably not a good idea!)
You can self-sign your own macro, there's quite a good guide to doing that here: http://www.slipstick.com/developer/how-to-use-outlooks-vba-editor/
But annoyingly it seems you will always get a notification, even with a signed macro... so it's probably easier to just change the security settings to 'notification for all'.
Hope this helps - the code you posted certainly helped me, it was exactly what I was looking for, also to control 1 minute delay!
Man, every time I go near macros in Outlook I end up losing half a day or so...

Is it possible to host a webserver in VBA?

I want to host a web server and want to use VBA to do it. Is this possible? I'm just doing this to prove someone wrong and really want to make this program.
So is it possible to make a really simple web server (just listens for get requests)? Help would be very much appreciated.
EDIT
I'm trying something like this
Sub startServer()
Set wunsock = CreateObject("OSWINSCK.Winsock")
wunsock.LocalPort = 80
wunsock.Listen
End Sub
Sub wunsock_ConnectionRequest(ByVal requestID As Long)
If sockMain.State <> sckClosed Then
sockMain.Close
End If
sockMain.Accept requestID
End Sub
Private Sub wunsock_DataArrival(ByVal bytesTotal As Long)
Dim strData As String
sockMain.GetData strData, vbString
txtStatus.Text = txtStatus.Text & _
strData & vbCrLf
End Sub
However it doesn't work?
Although this is a rather old question, I'd still like to mention that I built an Excel hosted REST webserver using plain VBA macros and some Winsock C calls, as proposed by Daniel A. White.
I added this as an answer instead of a comment, since it's built as a modular library, so you can adjust it to your needs, and others might need exactly this kind of library. It can serve both worksheets, basic files and also create custom hooks using an IWebController to listen on specific routes (which was mentioned by OP in a comment):
http://github.com/michaelneu/webxcel
To use it, you'll have to either import the classes/modules into your workbook, or let the build script create a new one for you. See Main.bas on how to start the server from within VBA.
http://www.ostrosoft.com/oswinsck.asp#inst
is a winsock type of library which can be used from VBA. It is possible to do what you are looking to do though is not the most efficient thing to do.
I do applaud your tenacity hope it works out for you.
I'm not sure I fully understand the question. Generally, you don't "host a web server", you host a web site.
But if you can do TCP sockets with VBA, then you can make an incredibly simple web server by following the HTTP standard protocol.
Edit: based on your comment, yes you can make a simple web server as long as you can open up a TCP socket.
Well, at the risk of violating the spirit of the question, you can always use VB's support for library functions and just create a library binding to one of a number of C-language web server options (such as http://www.acme.com/software/micro_httpd/, http://www.gnu.org/software/libmicrohttpd/ or http://code.google.com/p/mongoose/). You'd have to make DLLs out of the selected web server but that is reasonably easily done and this will work just fine in VBA.