How to Expand Existing My.Settings StringCollection Array - vb.net

I'm a bit rusty and am updating a VB.Net program I wrote in 2013 using VS2017. I needed to expand a My.Settings StringCollection array by one entry. It was User scope, and I could not figure out how to enlarge the existing array, despite hours of online research and testing.
I tried using the .Add method, but was told "not a member of String." I tried deleting "user.config."
Finally I tried this, which worked:
1) At design time, in Settings, I added the extra placeholder value to my StringCollection variable.
2) Change the scope from User to Application.
3) Run the program.
4) Change the scope back to User.
I confirmed this worked by inspecting My.Settings at runtime.
What I want to know is:
Why did this work, and is there a more elegant way to have done this?
For index = 0 To 5 'Motor numbers
'Changing upper index limit from 4 to 5 throws an Exception
strCommand = "(0," & index.ToString & ")"
My.Settings.strMotor_Kp(index) = (Kpid(0, index))
strCommand = "(1," & index.ToString & ")"
My.Settings.strMotor_Ki(index) = (Kpid(1, index))
strCommand = "(2," & index.ToString & ")"
My.Settings.strMotor_Kd(index) = (Kpid(2, index))
Next

The StringCollection editor is quite a bit limited, you can append lines easily but insert one in the middle is not possible to my knowledge.
But you can also change the values in app.config, recompile the project and then open the settings, then VS is going to asks you
Value of setting 'Foo' was changed in the app.config file. ... Do you
want to update the value in the .settings file?
The whole thing should work without having to switch the setting to application- and back to user mode. Just compile it and then the changes are reflected in the app.config (the user.config is generated at runtime when method Save() is called).
Only if the project namespace has changed, then the old entries must be deleted from app.config prior to recompiling the project, or the namespace must be adjusted in the <[...].Properties.Settings> tag).

Related

Too many arguments to show a form, but works in another project - Almost same code

I'm trying to get started with my first add-in for Autodesk Inventor, and of course, I'm starting from an existing sample to make this task easier for a newbie like me.
I have a decent command of VB.NET, but I cannot understand what's going on here.
In this link: https://drive.google.com/drive/folders/1rs2zVzf8Ib8iwd8JjCWZ-KQbWJUAqFyJ?usp=sharing
There are two ZIP files with VS2019 Solutions:
This_Sample_Works.zip - I used this as the baseline for my new project
This_Sample_Does_Not.zip
In both, there is this line of code:
dc.Show(New WindowWrapper(ThisApplication.MainFrameHWND))
But it only compiles in the project This_Sample_Works.zip - In the project within This_Sample_Does_Not.zip, I get the error in the image below.
Frankly, I'm not even asking someone to fix it for me. I just wanted to understand why it works in one project and not in another, despite the code being virtually the same.
What is bugging me is what piece of information/skills I currently don't have to understand what the compiler is telling me.
Public Function CreateChildDialog() As Long
CreateChildDialog = Nothing
Try
'Dim dc As Object
If Not dc Is Nothing Then
dc.Dispose()
dc = Nothing
End If
dc = New dockable_form(ThisApplication)
dc.Show(New WindowWrapper(ThisApplication.MainFrameHWND))
MsgBox("Handle ID:" & dc.Handle.ToInt64(), MsgBoxStyle.OkCancel, "Debug Info")
Return dc.Handle.ToInt64()
Catch ex As Exception
MsgBox("There is problem in CreateChildDialog" & vbCrLf & vbCrLf & ex.Message & vbCrLf & vbCrLf & ex.StackTrace & vbCrLf & vbCrLf & ex.ToString)
End Try
End Function
Any help is welcome - Thanks in advance!
In your project This_Sample_Does_Not the class dockable_form is a Control (the class inherits from System.Windows.Forms.UserControl).
In the reference project This_Sample_Works the class form_dockable is a Form (the class inherits from System.Windows.Forms.Form).
The two are very different types, though a Form can behave like a Control, the opposite is not true. A control will need a containing form.
Thus, the Control does not have a Parent that can be assigned when the method Show is called, it already has a parent.
From MSDN - Control.Show Method
Showing the control is equivalent to setting the Visible property to true. After the Show method is called, the Visible property returns a value of true until the Hide method is called.
Questions for your final preferred solution:
Do you really want to create a Control that is placed on another form? or
Do you want a Form that can be shown or popped up as required?

For-Next loop not stopping

This seems crazy basic to ask, but I can't figure out what I've done wrong. Working in Access VBA to loop through an array, but the FOR loop doesn't stop and I get a "Subscript out of range" error.
compStr = "[" & uniqueIDs(0) & "]=" & rs(uniqueIDs(0))
bnd = UBound(uniqueIDs)
For i = 1 To bnd
compStr = compStr & " and [" & uniqueIDs(i) & "]=" & rs(uniqueIDs(i))
Next i
In this example I'm using the loop to build compStr and bnd stores the array size. uniqueIDs holds 2 records (0-1) and I've confirmed that bnd and UBound(uniqueIDs) value=1. However the FOR statement continues until i=2 and of course I get an error when it executes uniqueIDs(2) on the 4th line. What am I missing? (I've pasted debug window images below)
I did a test but that successfully ran, see below implementation:
Regarding above comments on the data types: I understand why people use Variants in Access: this is because often table values are assigned to variables, and only Variant can pick up NULL. However, in your case something forced the string values to be Strings and not Variants - if I used the line commented out, it would yield Variant/Variant(0 to 1), so I used a typed dummy array - I don't know how otherwise get Variant/String(0 to 1).
Nevertheless, there was no error. Did you compile your code with Debug -> Compile? If not, could you do it and re-try? Sometimes this is necessary, otherwise some code segments newly added/removed are just not executing and the previous compiled version of the code (which is stored by Access) is making a total mess.
If it's still not working, I think you should add the rest of the code as others asked in comments to see how the variables are assigned values, and the version of Access you are using.

UnauthorizedAccessException with File.AppendAllText in VB.NET

I have recently started getting System.UnauthorizedAccessException errors when using File.AppendAllText to write to a shared drive on the network. I think there were some changes to the network when this happened. The code in my application hasn't changed.
I have asked our IT dept to grant me full permission to the folder. I can see I have permissions for Modify, Read & Execute, Read, Write under my username if I navigate to the file and look at the Security tab under properties. I am also part of a group with read, write and modify permissions to the folder.
This works without error in the same folder:
File.WriteAllText(myFile, myText)
This generates a System.UnauthorizedAccessException error when it reaches the AppendallText:
If File.Exists(myFile) = False Then
' Create a file to write to.
Dim createText As String = logTime & " " & report_data
File.WriteAllText(myFile, createText)
Else
Dim appendText As String = logTime & " " & report_data
File.AppendAllText(myFile, appendText)
End If
I have tried deleting the file and creating it again, that made no difference.
I tried File.SetAttributes(myFile, FileAttributes.Normal)
The IT dept can't see what the problem is.
I can manually open, change and modify the file. The problem only arises if I am trying to do this programmatically.
Is there a different 'user' which tries to modify files? Could the file be open somehow, or would that generate a different error?
I'm using VB.NET 2012, .net framework 4.5, Windows 8.1
The network changes were the problem. It doesn't seem possible to resolve this as it is. Instead I made a copy of the text data, append my new text to that, delete the file, and save the updated text to a new file.

AppleScript path being replaced at compile time (New Keynote scripting trouble)

We've got an applescript that tells keynotes to delete slides based on criteria. The new keynote does not have an applescript dictionary, but leaves the old keynote in a subdirectory. So I'm trying to tell AppleScript to talk with the older app rather than the new one.
If I just
tell application "Clean Install:Applications:iWork '09:Keynote.app"
It works, but it doesn't recognize any of the keynote dictionary terms. (delete a slide). So I need to pull out my old friend "using terms from". The challenge here is that this is a precompile directive, so you have to use a string literal, which I don't have on the end user's machine due to different hard drive names.
Ok, still have a plan here. I will write out a new applescript file with the 'using terms from application "Clean Install:Applications:iWork '09:Keynote.app"' and then execute that file... Genius... except for the fact that when AppleScript compiles this line:
using terms from application "Clean Install:Applications:iWork '09:Keynote.app"
Gets changed to:
using terms from application "Keynote"
Which of course calls the new keynote's dictionary which is empty.
Any thoughts on how to keep applescript from helping me out in this way? (or is there a better plan?)
full code:
using terms from application "Clean Install:Applications:iWork '09:Keynote.app"
--using terms from application "Clean Install:Applications:iWork '09:Keynote.app"
tell application "Clean Install:Applications:iWork '09:Keynote.app"
activate
end tell
end using terms from
many thanks!
I'm flyin' blind here (don't have keynote) ... but have you tried using a pre-defined app string as a variable and raw event codes?
You can use Smile to easily get raw event codes by
making a new script window in Smile;
using the "tell" menu item from the Action menu to make that script window application-specific (no tell
block needed);
write a line of code; select line of code
then use the "Copy translate" menu item (cmd-shift-C)
to copy the raw event codes
pasting that raw event code code into a different window that has your working (normal tell block) script
This is what it looks like when I do this for the Mail app:
set origMail to "MyDrive:Applications:Mail.app"
tell application origMail
delete («class mssg» 1 of «class mbxp» "INBOX" of «class mact» 1)
end tell
( When put in a normal tell block, that line of code would be "delete (message 1 of mailbox "INBOX" of account 1)" )
I haven't tried this but I think it will work... when you compile your code with "using terms from" just place your new version of Keynote in the trash. That should force it to use the old version of Keynote's dictionary and your code should compile. If you then save that code as an "applescript application" then it should work on anybody's computer without need to recompile. NOTE: you may need to restart your computer before this trick would work.
Then you just have the problem of targeting the right application on the user's computer because they too might have both versions. Here's some code to find the path to older versions of Keynote and how you would target that.
set lsregister to "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister"
set appName to "Keynote.app"
set nonapplescriptVersion to "6.0"
-- get the path to all Keynote apps
set appPaths to paragraphs of (do shell script lsregister & " -dump | grep " & quoted form of appName)
-- find the one with a version number less than the nonapplescriptVersion of Keynote
set appPath to missing value
repeat with anApp in appPaths
try
-- extract the path
set AppleScript's text item delimiters to "/"
set tis to text items of anApp
set thisPath to "/" & (items 2 thru end of tis) as text
set AppleScript's text item delimiters to ""
-- check the version
if (version of application thisPath) is less than nonapplescriptVersion then
set appPath to thisPath
exit repeat
end if
end try
end repeat
if appPath is missing value then error "Needed application version not installed."
-- use the older version
using terms from application "Keynote"
tell application appPath
activate
-- do whatever
end tell
end using terms from

VBA File Dialog .FileName removing .1 from end of file name

I am using visual basic to write a Macro for Autodesk Inventor. I created a macro that calls a file dialog, see code below. Everything works fine except when a user puts a file name in with a period and a number greater than zero following it.
For example, if a user puts testfile.test in the box and hits ok. When I ask for what they put in there using .FileName, I get "testfile.test". Just like I should.
However, if the user puts testfile.1 or testfile.10 or testfile.1mdksj or anything as long as a number greater than zero directly follows the period I get back "testfile". For some reason, everything after the period and the period gets removed.
What is the reason for this? Is this a bug in visual basic or am I doing something wrong?
'Set up the file dialog
Dim oFileDlg As FileDialog
' Create a new FileDialog object.
Call ThisApplication.CreateFileDialog(oFileDlg)
'Define the filter to select part and assembly files or any file.
oFileDlg.Filter = "All Files (*.*)|*.*"
'Define the part and assembly files filter to be the default filter.
oFileDlg.FilterIndex = 1
'Set the title for the dialog.
oFileDlg.DialogTitle = "Save File As"
'Tell the dialog box to throw up and error when cancel is hit by user
oFileDlg.CancelError = True
'Show the file dialog
On Error Resume Next
oFileDlg.ShowSave
'save the user specified file
Dim newFileName As String
newFileName = oFileDlg.FileName
UPDATE:
I ended up doing the following "hack" to make things still work while dealing with a period:
oFileDlg.fileName = sFname & "."
oFileDlg.ShowSave
fullName = Left$(oFileDlg.fileName, Len(oFileDlg.fileName) - 1)
That worked fine for quite a while on Windows 7 and then Windows 10. Unfortunately, the Windows 10 Creative update seems to have changed how the file dialog works. With the above code, fullName would come back blank if there were no periods in the name and would truncate everything from the FIRST period from the left if there was a period in the name.
I'm not really sure what changed in Windows 10, but it pretty much destroyed my hack. Windows 7 still works fine and Windows 10 before the creative update works. I ended up doing the following to make everything work again in the version of Windows I mentioned above.
oFileDlg.fileName = sFname & ".00"
oFileDlg.ShowSave
fullName = Left$(oFileDlg.fileName, Len(oFileDlg.fileName) - 3)
This is a VB property, but it may extend to VBA as well. Have you tried setting the save settings to support multidotted extensions? Try something like this:
SupportMultiDottedExtensions = True
This setting is intended permit the use dotted extensions - meaning the use of periods in the file name. See this MSDN reference for documentation and information: http://msdn.microsoft.com/en-us/library/system.windows.forms.filedialog.supportmultidottedextensions.aspx#Y129
This SO article may also shed further light: SaveAs Dialog with a period in the filename does not return extension
EDIT
After checking the autodesk documentation - a difficult and unpleasant task, in my opinion - there does indeed appear to be no support for MultidottedExtensions. I did, however, find a function on VBAExpress that I have very closely adapted. The function can be used to filter strings with contain unacceptable characters. Jimmy Pena's blog has an excellent function for just such a purpose: http://www.jpsoftwaretech.com/excel-vba/validate-filenames/. I have only substantively added a period and a replace to the code:
'A function for filtering strings, with a focus on filenames.
Function FilterFileNameString(stringToScrub As String) As String
'Filters a filename string - or any string for that matter.
Dim FilteredString As String
'A highly nested replace function.
FilteredString = Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(Replace(stringToScrub, ".","|", ""), ">", ""), "<", ""), Chr(34), ""), "?", ""), "*", ""), ":", ""), "/", ""), "\", "")
'Returns filtered string.
FilterFileNameString = FilteredString
End Function
Jimmy Pena's blog also contains a recursive version as well, although he does not recommend it.
You can filter any strings to be used as filenames with another character - a space in this case. You could use an underscore, however, or any other character you deemed pleasant.
In general, if you are trying to use periods for versioning or a similar purpose, and inventor will not let you, I would strongly advise going to another character or set of characters that can provide such an indication, such an underscore "_", a numbering system, "001", "002", a lettering system, "AAA", "AAB", or whatever makes sense for your focus.
If you are just making the application user-friendly, I would suggest filtering the strings entered before saving them in the desired filetype, and separate the filtering of the strings from the save dialog if the period filtering gives you grief. It may add an extra step, but it may be the best and easiest way to filter out pesky invalid characters without creating unnecessary extra hassles for your users.
~JOL