For several years we've been using code similar to the following (a result similar to that of net use) to convert UNC filenames to their legacy (drive letter) equivalents:
Dim network As Object: Set network = CreateObject("WScript.Network")
Dim netDrives As Object: Set netDrives = network.EnumNetworkDrives
Dim myLet As String
Dim myUnc As String
Dim i As Long
' loop through all network drives
For i = 0 To netDrives.count - 1 Step 2
myLet = netDrives.Item(i)
myUnc = netDrives.Item(i + 1)
myUnc = Replace(myUnc, "#SSL", "")
' hopefully we find it here
If InStr(LCase(uncname), LCase(myUnc)) Then
toLegacyName = myLet & Right(uncname, Len(uncname) - Len(myUnc))
Exit Function
End If
Next i
In the recent past, more login options (such as whether to use Citrix, VPN, or use the machine in the office) plus newer "file systems" (like Sharepoint) have rendered this code unreliable, where depending on how the user is signed on, network.EnumNetworkDrives may or may not return complete information. A drive may be present with Citrix but not using VPN, etc.
Are there other ways to do this? In the end, all we want to do is replicate net use.
I built a very complex SeleniumBasic via VBA via Excel Addin setup that interacts with one of the leading ticketing system websites to scrap and populate data. The system interacts with 90+ different fields/clickables with 3 different pages, 6 different tabs, and nested popups...deployed to 120 users who use the automations about 20 times per day.
And it has been working flawlessly for over a year...
We have just provisioned 20 more users on the same system, and their automations refuse to work.
Here is where I am at with my research:
I am able to manually step through code on the new system and have it successfully go through the entire automation, so the issue probably has something to do with the speed VBA/Selenium is trying to interact with the website.
Once the system is unable to find a field or clickable, it refuses to find any other ones after that.
The way the system is built in order to go as fast as possible is via standard VBA error handling. It fails to find something, it goes to the error handler, the error handler says to wait for one second then try again. Again, this system has been working flawlessly for over a year and is currently working on 120 user's systems.
To see if maybe Selenium was refusing to reload the clickable, I broke out the error handling from a Resume to a Resume Next, and then had a do while loop with a boolean flag to keep trying until it was successful, but after the first failure, it refused to find anything else, including different fields
The one thing the 20 new users have in common is that they are all using v66 of Chrome, whereas all of the systems that are working have old copies of Chrome that are at least 9 months old
Thinking this might be an issue, I grabbed all of the ChromeDrivers and systematically went through one by one to test if we got a different performance with a different ChromeDriver, but all of the ChromeDrivers had the same error
So that is where I stand. I'm wondering if there is some key insight I am missing or a workaround that will get newer versions of Chrome to retry the fields. Or...do I need to try a VBA/Selenium tool other than SeleniumBasic to fix this. Or...do I need to roll back these 20 users to older versions of Chrome.
Thanks for sharing your expertise.
''''Check to see if there are any aliases=================================
For AliasCheck = 2 To AliasCounter + 1
If Hash = Sheets("Temp Subjects & Locations").Range("AY" & AliasCheck) Then
AliasName = Sheets("Temp Subjects & Locations").Range("AY" & AliasCheck)
AliasCount = AliasCount + 1
AliasDisplayName = Sheets("Temp Subjects & Locations").Range("AZ" & AliasCheck)
temp1 = ""
temp2 = ""
Call countryDictionary
'drops the country back into Excel to later remove the dupes
temp1 = Sheets("Temp Subjects & Locations").Range("BA" & AliasCheck)
temp2 = dict(temp1)
Sheets("Temp Subjects & Locations").Range("BG" & AliasCount + 1) = temp2
''''Click to add AKA's names
iframeText = "iframe_win_" & AddParty
robot.SwitchToDefaultContent
robot.SwitchToFrame iframeText
iframeTracker = iframeTracker + 1
iframeText = "iframe_win_" & iframeTracker
robot.SwitchToDefaultContent
robot.SwitchToFrame iframeText
robot.FindElementById("X_SUBJECT_ALTERNATE_NM.X_ALTERNATE_NM").SendKeys (AliasDisplayName)
robot.FindElementById("dijit_form_Button_0").Click
End If
Next AliasCheck
The AddParty variable is a way to track the number of the pop-up we came from.
The iFrameTracker variable is a way to track the number of the pop-up we are going to...the system sequentially numbers its pop-ups...instead of legible names...
The newer systems will make it down to the SendKeys and then decide not to work. On a resume next, it will then refuse to find the OK button ("dijit_form_Button_0")
Here is the code I was playing around with to see if I could get it to retry using a "Resume Next" instead of a "Resume"
robot.FindElementById("X_SUBJECT_ALTERNATE_NM.X_ALTERNATE_NM").SendKeys (AliasDisplayName)
Do While FailRetry = True
FailRetry = False
robot.FindElementById("X_SUBJECT_ALTERNATE_NM.X_ALTERNATE_NM").SendKeys (AliasDisplayName)
Loop
errHandler4:
If errorCounter < 21 Then
Application.wait (Now + TimeValue("00:00:01"))
errorCounter = errorCounter + 1
FailRetry = True
Resume Next
Else
MsgBox "Reached 20 second timeout. Stopping processing."
Exit Sub
End If
I am using excel vba to make an application that acts as a job card. User will fill in relevant fields, press a button to update a running summary of costs, as well as generate a printable pdf of the job card. I have very limited experience in coding (a semester of java 4 years ago) so i am relatively new to this.
Currently, the application automatically updates the summary file and can open a word template file and fill it in with information from the input fields, so it mostly works. I have realised an issue in the way it is finding the summary files, in that as soon as a folder name does not align with the way i am constructing the folder paths in the app, it will return errors.
At the moment I am going into folders like this:
templatePath = "C:\SERVICE\Card Template.doc"
If cbxType.Text = "Plant" Then
savePath = "C:\SERVICE\0.1 PLANT\" & cbxNo.Text & " - " & txtMakeModel.Text & " " & txtRego.Text & "\0.2 SERVICE SHEETS\"
ElseIf cbxType.Text = "Vehicle" Then
savePath = "C:\SERVICE\0.2 VEHICLES\"
End If
The directory is constructed from text and combo boxes which are populated once the user chooses a type (plant, vehicle, etc.) and then ID, which fills in boxes for model name, registration number, hours etc.
I am after a piece of code that can iterate through a given directory, searching the folder names for a string and returning the path of that folder. Each folder begins with the ID number, so I figure I can search folder names for that but I am not sure how to construct the loop. Any help with this, or alternative ideas would be appreciated. If it isn't too much to ask I'd also like a little bit of an explanation on how it works.
So my code works fine on my system running Windows 7 Ultimate. It runs fine on a laptop running the same. But my servers are either Windows server OS's or in one case Windows 7 Professional.
Now part of my code reads data from a website. But this data may or may not be there. I have a browser control reading it and I use StringSplit to break it down. If certain parts are there great. If not I let a catch set it to 0.
So the start bit:
Dim parts As String() = webdata.Split(New String() {Environment.NewLine},
StringSplitOptions.None)
I had assumed this is where the problem was. Enviroment.NewLine could be different even under the slightly different Windows 7 server. So I ran a loop on both to dump the data.
Dim testloop As Integer = 0
Do Until testloop = 25
MsgBox(testloop & ") " & parts(testloop))
testloop = testloop + 1
Loop
They both return exactly the same results in exactly the same order. So unless I'm missing something it can't be an environment change there.
But this reads fine on my Windows systems just not the VPS:
Try
Firstdata = Parts(22)
Seconddata = Parts(24)
Catch
Firstdata = 0
Seconddata = 0
End Try
This might not be the neatest way to do it but it works consistently outside of the VPS and I can't see why an environment would change that.
Looking at the exact same data at the exact same time locally it looks at the table returning the data when it's there and 0's otherwise. On the VPS it just returns 0's.
I thought this would be a simple change to the stringsplit but the loop shows (22) and (24) as the data I'm looking for in the loop. I don't see why the TRY would be different in a different environment.
Any help here would be much appreciated. I can set up a 7 Ultimate server but I'd rather understand what the heck is going on.
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.