Why would my app only see one of two associated files? - vb.net

This is a fairly simple app that opens and decodes packed XML. I can open the files directly from the apps UI no problem.
The issue is, I have 2 types associated with my app.
The ICON shows next to the 2 file types as they should, how ever, only one, if double clicked shows up in the Environment.GetCommandLineArgs().
Dim arguments() = Environment.GetCommandLineArgs() seems fool-proof.
I have used a msgbox to trap and display anything in position 1 of the list and the 2nd file type NEVER sends anything to the args list.
I am deploying (for now) using clickOnce and added per what I read at MS's site the following to the manifest file:
<fileAssociation
xmlns="urn:schemas-microsoft-com:clickonce.v1"
extension=".visual"
description="WoT visual file"
progid="wotvisual"
defaultIcon="XMLFile_789_32.ico"
/>
<fileAssociation
xmlns="urn:schemas-microsoft-com:clickonce.v1"
extension=".chunk"
description="WoT chunk file"
progid="wotchunk"
defaultIcon="XMLFile_789_32.ico"
/>
This is at the head of my main form load event:
Dim arguments() As String = Environment.GetCommandLineArgs()
If arguments.Length > 1 Then
Dim s1 = arguments(1)
If s1 <> String.Empty Then
openVisual(s1)
End If
I should mention that dbl clicking either file does indeed open my app.. It just never sees anything as in file path, from the .chunk types.
And if you spotted it, this is World Of Tanks I'm working with. I write tools for the modding community.

Related

VB.NET open a Text File within the same folder as my Forms without writing Full Path

I found a similar question but it was 5 years 8 months old, had 2 replies and neither worked for me (VB.Net Read txt file from current directory)
My issue is that when I use the following code:
Dim fileReader As String
fileReader = My.Computer.FileSystem.ReadAllText(Application.StartupPath & "\Username_And_Password_Raw.txt")
Dim usernameAndPassword = Split(fileReader, ",")
I get an error saying:
System.IO.FileNotFoundException: 'Could not find file 'C:\Users\wubsy\source\repos\NEA Stock Page System\NEA Stock Page System\bin\Debug\net6.0-windows\Username_And_Password_Raw.txt'.'
I have tried using all the different Applications.BLANKPath options I can find (ie; StartupPath, CommonAppDataPath, etc.) and they all return essentially the same error only with a different location.
This is the folder layout of my TXT File - I know it's a terrible, incredibly insecure and generally awful way of storing login information but this is just for a NEA so will never ever actually be used
This is the actual path of the TXT File if it helps
C:\Users\wubsy\source\repos\NEA Stock Page System\NEA Stock Page System\Username_And_Password_Raw.txt
The startup path is where your exe is located. That and all supporting files get copied to a binary directory when you compile in visual studio, in your case
C:\Users\wubsy\source\repos\NEA Stock Page System\NEA Stock Page System\bin\Debug\net6.0-windows
But what you're trying to do, reference the file where it sits in your solution, is probably not the best way to do it, and your code above will work (with a change, will mention later) if you change the properties of the file in the solution.
Right click on the file in the Solution Explorer Username_And_Password_Raw.txt, select Properties. Modify Copy to Output Directory to either Copy always / Copy if newer, depending on your requirement. Now that file will copy to the same directory your exe is in, and the code above should work.
Note, when creating a path, don't use string concatenation because you may have too many or too few \; use Path.Combine:
Dim filePath = Path.Combine(Application.StartupPath, "Username_And_Password_Raw.txt"
Dim fileContents = My.Computer.FileSystem.ReadAllText(filePath)

Word automation failing on server, but dev station works great

I am automating a oft-used paper form by querying the user on a web page, then modifying a base Word document and feeding that modified doc file to the user's browser for hand-off to Word.
The code is Visual Basic, and I am using the Microsoft.Office.Interop module to manipulate the document by manipulating Word. Works fine on the development system (Visual Studio 2015) but not on the production server (IIS 8.5).
Both the Documents.Open() call and the doc.SaveAs() call fail with Message="Command failed" Source="Microsoft Word" HResult=0x800A1066
Things I've tried:
Added debugging out the whazoo: Single-stepping is not an option on the production machine, so I pinpointed the problem lines with debug output.
Googled and found that this problem has been reported as early as 2007, but no viable solutions were reported.
A couple sites mentioned timing issues, so I added several pauses and retries -- none helped.
Some mentioned privileging, so I tried changing file permissions & application pool users -- neither helped.
Enhanced my exception handling reports to show more details and include all inner exceptions. That yielded the magic number 800A1066 which led to many more google hits, but no answers.
Added fall-back code: if you can't open the main document, create a simple one. That's when I found the SaveAs() call also failing.
Dropped back to the development system several times to confirm that yes, the code does still work properly in the right environment.
Greatly condensed sample code does not include fallback logic. My Word document has a number of fields whose names match the XML tokens passed as parameters into this function. saveFields() is an array of those names.
Dim oWord As Word.Application
Dim oDoc As Word.Document
oWord = CreateObject("Word.Application")
oWord.Visible = True
oDoc = oWord.Documents.Open(docName)
Dim ev As String
For i = 0 To saveFields.Length - 1
Try
ev = dataXD.Elements(saveFields(i))(0).Value
Catch
ev = Nothing
End Try
If ev IsNot Nothing Then
Try
Dim field = oDoc.FormFields(saveFields(i))
If field IsNot Nothing Then
If field.Type = Word.WdFieldType.wdFieldFormTextInput Then
field.Result = ev
End If
End If
Catch e As Exception
ErrorOut("Caught exception! " & e.Message)
End Try
End If
Next
...
oDoc.SaveAs2(localDir & filename)
oDoc.Close()
oWord.Quit(0, 0, 0)
The code should generate a modified form (fields filled in with data from the parameters); instead it fails to open, and the fallback code fails to save the new document.
On my dev system the document gets modified as it should, and if I break at the right place and change the right variable, the fallback code runs and generates the alternate document successfully -- but on the production server both paths fail with the same error.
Barring any better answers here, my next steps are to examine and use OpenXML and/or DocX, but making a few changes to the existing code is far preferable to picking a new tool and starting over from scratch.
Unfortunately, Lex Li was absolutely correct, and of course, the link to the reason why is posted on a site my company considers off limits, thus never showed up in my google searches prior to coding this out.
None of the tools I tried were able to handle the form I was trying to automate either -- I needed to fill in named fields and check/uncheck checkboxes, abilities which seemed beyond (or terribly convoluted in) the tools I evaluated ...
Eventually I dug into the document.xml format myself; I developed a function to modify the XML to check a named checkbox, and manipulated the raw document.xml to replace text fields with *-delimited token names. This reduced all of the necessary changes to simple string manipulation -- the rest was trivial.
The tool is 100% home-grown, not dependent upon any non-System libraries and works 100% for this particular form. It is not a generic solution by any stretch, and I suspect the document.xml file will need manual changes if and when the document is ever revised.
But for this particular problem -- it is a solution.
This was the closest I got to a complicated part. This function will check (but not uncheck) a named checkbox from a document.xml if the given condition is true.
Private Shared Function markCheckbox(xmlString As String, cbName As String, checkValue As Boolean) As String
markCheckbox = xmlString
If checkValue Then ' Checkbox needs to be checked, proceed
Dim pos As Integer = markCheckbox.IndexOf("<w:ffData><w:name w:val=""" & cbName & """/>")
If pos > -1 Then ' We have a checkbox
Dim endPos As Integer = markCheckbox.IndexOf("</w:ffData>", pos+1)
Dim cbEnd As Integer = markCheckbox.IndexOf("</w:checkBox>", pos+1)
If endPos > cbEnd AndAlso cbEnd > -1 Then ' Have found the appropriate w:ffData element (pos -> endPos) and the included insert point (cbEnd)
markCheckbox = markCheckbox.Substring(0, cbEnd) & "<w:checked/>" & markCheckbox.Substring(cbEnd)
End If
' Any other logic conditions, return the original XML string unmangled.
End If
End If
End Function

multiple programming try to access same text file

I had created and text file using (AFL SCRIPTING LANGUAGE) this script will update (write) to a text file every 5 seconds. I will try to read file using vb.net, when I run the vb.net code form visual studio, everything works fine but (AFL script not able to update the text file), here is my vb.net code:
Dim FILE_NAME As New FileStream("C:\myreport\myfile.TXT", FileMode.Open, FileAccess.Read, FileShare.Read)
REM Dim FILE_NAME As String = "C:\myreport\myfile.TXT"
REM Dim TextLine As String
REM If System.IO.File.Exists(FILE_NAME) = True Then
Dim objReader As New System.IO.StreamReader(FILE_NAME)
Do While objReader.Peek() <> -1
MYSTRING(I) = objReader.ReadLine()
I = I + 1
Loop
REM End If
When I run the code above, ( AFL script not able to update the text file),
Put simply:
When I run the vb.net code (for accessing the text file), AFL script not able to update.
I had share read/write the folder (where the text file exists), no effect, same problem I am facing.
Unchecked "Enable visual studio hosting process", still problem not solved.
In .NET, the FileSystemWatcher class can help you with this problem. You can read the file each time the file watcher says that the files has changed. Here is the reference documentation for it.
You cannot read and write to a file from two processes at the same time. Well, technically you can, but it can lead to a race condition which is bad.
You need to implement some kind of shared locking mechanism around the file to prevent your two programs from fighting over it. Or, if you can guarantee that the consumer VB.NET program will have the file open for less than 5 seconds, you can go with MrAxel's solution and simply have the VB.NET program read the file every time it is updated.

Opening a file using impersonation

I have been searching the web looking for a way to open a WORD file from a secure network folder by impersonating a user who has access. The closest I've come to finding the answer was this from 2 years ago:
Impersonating in .net (C#) & opening a file via Process.start
Here is the code that I am using. When I set the arguments = LocalFile_Test, everything works perfectly because the user is accessing the local c:\ that is has access to. But when I set arguments = RemoteFile_Test, Word opens up a blank document which is the same effect as if I put garbage in the arguments. So it appears that it cannot find the file even though when I login with the user/domain/password that I specify in the properties below, I can find that exact file name and it is not empty. Does anything jump out at you right away? I appreciate your time.
Dim LocalFile_Test As String = "C:\New.docx"
Dim RemoteFile_Test As String = "\\Server1\Apps\File\New.docx"
Dim MyStartInfo As New System.Diagnostics.ProcessStartInfo
MyStartInfo.FileName = "C:\Program Files\Microsoft Office\Office12\WINWORD.exe "
MyStartInfo.Arguments = LocalFile_Test
MyStartInfo.LoadUserProfile = True
MyStartInfo.UseShellExecute = False
MyStartInfo.UserName = "specialuser"
MyStartInfo.Domain = "mydomainname"
MyStartInfo.Password = New System.Security.SecureString()
MyStartInfo.Password.AppendChar("p"c)
MyStartInfo.Password.AppendChar("a"c)
MyStartInfo.Password.AppendChar("s"c)
MyStartInfo.Password.AppendChar("s"c)
Process.Start(MyStartInfo)
My understanding is that you are trying to get a password protected file from a server, and when you do process start, it just opens up a blank word doc. I think the error is how you are trying to get the file, I think you have to map the actual physical path of the file on the server, like
System.Web.HttpContext.Current.Server.MapPath("\\Server1\Apps\File\New.docx")
From there, I am fairly certain, you need to create network credentials for the user like
System.Net.NetworkCredential=New NetworkCredential(userName:=, password:=)
Finally, once that is done, you can either write the file, or transmit the file like so...
System.Web.HttpContext.Current.Response.TransmitFile(file name)
System.Web.HttpContext.Current.Response.WriteFile(file name)
Then,once you get the file, you can try to open it with process start.
Hope that helps, let me know if what I said doesn't work.

how to open a vb.application from another vb.application with parameters

i have 2 vb applications. this is the code for the first one which when a button is clicked it will check if the other application is already open. If not, it'll open that application -
Dim sComputer As String
sComputer = Environ("COMPUTERNAME")
Dim LocalByName As Process() = Process.GetProcessesByName("ticket.prices", sComputer)
If LocalByName.Length = 0 Then
System.Diagnostics.Process.Start("http://ticket.prices.application")
End If
this runs fine. but what i need is that the customerid on the application 1 that is calling application 2, should be transfered while opening app 2.
e.g -
Customer 10001 screen is open on app 1. When i click open app 2, the above code runs and opens app 2. how do i make app 2 open to customer 10001 screen. Is there any way to pass parameters while opening app 2 in System.Diagnostics.Process.Start ?
Use the version of 'Process.Start' that takes 2 strings, the second being the commandline parameters. See here for details.
You want the ProcessStartInfo class, or use the Start method taking to strings. ProcessStartInfo gives you a lot of options about how to start your program, which often comes in handy. Its good to get familiar with it.
Dim info as New ProcessStartInfo()
info.Arguments = "10001"
info.FileName = "exename"
Dim LocalByName as New Process()
LocalByName.StartInfo = info
LocalByName.Start()
Getting the arguments in the new program is accomplished via Environment.GetCommandLineArgs()
For Each arg As String In Environment.GetCommandLineArgs()
Console.WriteLine(arg)
Next arg
It looks like what you ultimately want to accomplish is getting the currently selected row from App 1 and passing that to the second program, though. Is this correct? That opens a whole new ball of wax involving interprocess communication.
EDIT: The simplest way to get the selected edit would be to write the id out to a text file. You have to be careful when doing this because if you just write System.IO.File.WriteAllText("selectedrow.txt", "123"), you'll write to the app's startup path directory. You'll want to get the exe's current path as below
Dim u as New Uri(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
dim exepath as String = System.IO.Path.GetDirectoryName(u.LocalPath)
dim fullPath as String = System.IO.Path.Combine(exepath, "selectedrow.txt")
System.IO.File.WriteAllText(fullpath, "123")
This will overwrite the text in the file every time you change rows. You want to wrap this in a try/catch block so as not to crash the program. Make sure you log the errors; don't just swallow them. To read the data, you just do
dim id as string = System.IO.File.ReadAllText(PathToFileYoureWritingToInTheOtherProgram)
in the other program.
This isn't necessarily the best way to go about things, but its the simplest way I know of off the top of my head.
You might could look at MessageQueues if you a better solution, but as long as you're not changing selected rows every 100ms, writing the file should work fine.