Custom DLL to avoid the IE web browser control for "unsafe controls" in a tightly controlled and regulated environment - vb.net

Scenario:
My company has a legacy (read that as 32 bit) windows form application that will be around for quite some time in the future. This application uses an embedded web browser control that is supplied pages that are contained within the database that it maintains. It was built like this so we could extend/modify as needed. I say this so that I can validate that security is not a concern. Only the application and developers with the correct tools have access to the pages or database. The application is only available inside the office.
There are some processes that I need to accomplish using ActiveX objects that are embedded within the pages/application. One of the biggest and most annoying thing that happens is the ActiveX security warning when I got to create instances of things like “scripting.filesystemobject”. Example:
Set oFSO = CreateObject("Scripting.FileSystemObject")
My solution is to create a DLL that is installed locally on each machine that needs access to the extended functions, have the all the functions (whole DLL ??) marked as safe so that the web browser control does not present the security warning. I have been searching using google and came across very few examples, and all of which are in C# which is not my strongest language.
I’ve had to convert from C to Vb.Net visual basic to get what I have now. When I go to register my DLL, I get the following error message:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319>regasm
Z:\VBNet2017\APIInternal\APIInternal\bin\Debug\APIinternal.dll /tlb
Microsoft .NET Framework Assembly Registration Utility version 4.8.4084.0
for Microsoft .NET Framework version 4.8.4084.0
Copyright (C) Microsoft Corporation. All rights reserved.
Types registered successfully
RegAsm : error RA0000 : Type 'APIInternal.API.Accupay' has an invalid default COM
interface: 'APIInternal.API.Accupay'
UPDATE: Thank you Hans; the error is gone. I've also made some changes in the source code; I changed the ProgID to something that closely resembles where and what this is for. I'm still having issues in creating the object in VB Script.
This is the output from the current version of the code. This is the code, stripped down for clarity:
Option Strict On
Imports System.Runtime.InteropServices
Imports System.IO
Namespace API
Public Interface IAccupay
<DispId(1)>
Function GetFiles(ByVal Folder As String) As List(Of String)
End Interface
<Guid("8B4B5CEF-8B3A-49A1-9053-E909F82D9E73"),
ProgId("AddIn.Accupay"), ClassInterface(ClassInterfaceType.None),
ComDefaultInterface(GetType(IAccupay)), ComVisible(True)>
Public Class Accupay
Implements IAccupay
Private Function GetFiles(Folder As String) As List(Of String) Implements IAccupay.GetFiles
Return Directory.GetFiles(Folder).ToList
End Function
End Class
I have tried just about every combination of ProgID, Name space, Interface name and class name to get this error to go away without any luck. I do know there are other elements that need to be addressed or added, such as error trapping and, if I’m not mistaken, how to actually implement the ObjectSafetyOption which I still don’t know how to do.
I have been using the Guide at the bottom of this article:
Is it possible to mark an ActiveX object as safe so that IE settings need not be changed?, the second answer, but I haven’t had any success.
Please, can someone point me in the right direction, maybe show me what’s wrong with the code that I have and how to physically implement the ObjectSafteyOption that is needed for the web control. Links, additional reading, code examples or comments on how to get this fixed and working would really be appreciated.
Thank you for reading and any help you send my way, Fred
PS: If you need more information, or have a better solution, please don’t hesitate to reply or comment.
UPDATE:
With the code that I have now, I am able to access the DLL in VB.Net visual basic:
Imports System
Imports APIInternal.API
Module Program
Sub Main(args As String())
Dim API As New Accupay
Dim FileList = API.GetFiles("C:\Windows\")
For Each Item As String In FileList
Console.WriteLine(Item)
Next
End Sub
End Module
However, I still can't seem to get the correct calling for a VB Script/html page:
Set Test = CreateObject("Test.Accupay")
Which returns the VB Script error "ActiveX Component can't create object: Test.Accupay or any other iteration of the parts of the name that I tried. I think part of this is that I don't understand how the creation of the project leads to the creation of the object in a com base environment like VB Script.
Fred

The answer to this problem is two fold: You must target the correct platform (X86) AND use the 32 bit version of regasm. Once I realized this was the issue, I was able to create the DLL and use it's functions in the Web Browser control without the active X warning. One example is I can now open the default browser (in this case, NOT IE/EDGE) from a link within the WB Control and another is to get the contents of a folder for further processing within the WB page.

Related

vb.net NAudio.dll - Type 'AudioFileReader' is not defined

(Visual Studio 2019)
It seems I have run into a snag.
My sample code is this.
Imports NAudio.Wave
Partial Class _Default
Inherits System.Web.UI.Page
Dim filename As String
filename = "G:\VS_Lessons\Media\Read\01. Got to Choose.mp3
Dim reader As New AudioFileReader(filename)
Dim duration As String = reader.TotalTime.ToString("mm\:ss")
reader.Dispose()
Label1.Text = duration
End Sub
End Class
This only happens when I am running the site LIVE and NOT from VS.
Running it through VS, it works as it supposed to.
Running it from a live URL it gives the following error.
Type 'AudioFileReader' is not defined
On this line
Dim reader As New AudioFileReader(filename)
Now, I tried to register the NAudio.dll using. (The NAudio.dll file is in the BIN folder of the website)
gacutil -i NAudio.dll
However, I get the following line
Failure adding assembly to the cache: Attempt to install an assembly without a strong name
I followed the steps in this article here
How to add Strong Name to an existing DLL and install to the GAC
But I get a FAILURE when trying to create the DLL file on STEP 5. (Maybe I am doing it wrong because I am not the owner of the file. Not really sure, this is the first time I have ever done anything like this and was trying everything I could find online)
Any assistance on this would be mighty grateful.
Wayne
The website has to be converted into an Application.
IIS | Web Site |
Right-click on the web site name or sub-folder name
And choose [Convert to Application]
Run the script, and it works.
Now, I have to do this on the live site, but first, I will do the local site, as it runs the same script, and I will get all the bugs out of it, then I can do the LIVE IIS site.
It Could Be Due To Partial Class Instead Of Public Class. Or You Haven't Downloaded Genuine DLL Version Of NAudio.
If Its Problem 1 ( Due To Use Of Partial Class ) Then Change To Public Class
If Its Problem 2 ( Use Of Non-Genuine NAudio DLL ) Then Download NAudio From Here
If Problem Still Persists, Then It Would Be For Windows Form Application.

VBA / .Net download files from password protected website via Windows Security

I have a SharePoint test website (Azure SharePoint farm) which contains several image files and some document templates. I want to download the images to my local drive. I anticipate looping through a list of URLs, e.g. http://mySharePointSite/Sites/Images/Image01.png and downloading each in turn. I've tried URLDownloadToFile which works great if I put the images on a regular website but I'm unable to get past Windows Security with this approach.
I had a go at creating an InternetExplorer.Application Object (late binding) and can view my images but am unable to download them. Was trying ieApp.ExecWB but this throws a Run Time Error that seems insurmountable.
I've also tried WinHTTP.WinHTTPrequest.5.1 (StackOverflow 22051960) but, while that looked promising it returned a short string "???????" instead of an image.
I'm really hoping for a VBA solution and am wondering if Impersonate User might provide options, or if there are other options (excluding using SendKeys). Sadly I'm pushing the limits of my VBA knowledge and could really use some guidance.
Is it possible to download from share point from VBA?
If so how, am I missing something simple?
I can paste code, but really I'm not sure I have anything worth sharing. If this is not possible or unreliable in VBA then would be possible with VB.Net (my next steepest learning curve)?
Hope this helps someone. I ended up using Visual Studio to create a dll in VB.Net that I can call from VBA. VB.Net dll requires references to microsoft.sharepoint.client
And the VBA code requires a reference to the resulting dll.
Imports Microsoft.SharePoint.Client
Module Module1
Sub Main()
Dim myContext As Microsoft.SharePoint.Client.ClientContext
myContext = New ClientContext("http://TestSP-a.cloudapp.net/sites/Images/")
Dim myCredentials As New System.Net.NetworkCredential
'' I'm accessing a website from the outside so there
'' are no credentials on my PC. If on the same NW I
'' assume I can use the line below instead of the
'' 3 lines that follow.
'myCredentials = System.Net.CredentialCache.DefaultNetworkCredentials
myCredentials.UserName = "UserNameForSharePoint"
myCredentials.Password = "PassWordForSharePoint"
myCredentials.Domain = "" ' <-- Leave Blank
Dim mySiteSP As New Uri("http://TestSP-a.cloudapp.net/sites/Images/Image1.png")
Dim myTemp As String = "C:\temp\test.png"
My.Computer.Network.DownloadFile(mySiteSP, myTemp, myCredentials, True, 600000I, False)
End Sub
End Module

How to set ScriptingContext Response cookie after upgrade to .Net

We have a number of classic ASP websites using a VB6 DLL (COM) object for their functionality in the standard way. The DLL is regsvr32'd and the pages use Server.CreateObject to create an instance of the necessary object in the DLL, which in turn triggers the OnStartPage function of the object being created, passing in the ScriptingContext which we then use to get Request (querystring, form) information, read/update session information and read/write cookie information (etc). For clarification, the way you update/store a cookie value using ScriptingContext is
objSC.Response.Cookies(Key) = Value
In preperation of doing a complete .Net overhaul on the code base (and as a first step), we ran the code through the .Net 2008 VB upgrade tool, which makes a few minor code changes, sets up references to interop libraries (for ADODB, ASPTypeLibrary, CDO, etc) and adds the necessary attributes to allow the .Net object to be exposed to COM, and after a few tweaks here and there guided by comments (todos) left by the upgrade tool, the code is compilable except for anything that tried to update/store a cookie using the above code as now, through the ASPTypeLibrary (Interop), the Response.Cookies collection is readonly (with no obvious way to write a cookie now).
If I comment out the offending line of code, the code compiles, and all I need to do is register this new .Net DLL (and it's interop DLLs) in the GAC, use regasm to register it through COM and the classic ASP sites continue working as if nothing happened (except for writing cookies), using Server.CreateObject to create what it thinks is a COM object, triggering the call to OnStartPage, passing in the ScriptingContext.
So although the code base is "upgraded" to .Net it is using a lot of interop libraries to continues working as before, including using the ASPTypeLibrary.ScriptingContext object, as this is what the classic ASP pipeline exposes.
Does anyone know how to write/store a cookie in this scenario?
Need to convert cookie item to IWriteCookie interface. Then it will be writable.
Imports ASPTypeLibrary
Public Class Test
Private oContext As ASPTypeLibrary.ScriptingContext
Private oResponse As ASPTypeLibrary.Response
Public Sub OnStartPage(e As ScriptingContext)
oContext = e
oResponse = oContext.Response
With CType(oResponse.Cookies("fromdotnet"), IWriteCookie)
.Item = String.Format("hello from .Net : {0}", Date.UtcNow())
'.Domain = ""
'.Path = "/"
'.Secure = False
End With
End Sub
End Class
You may want to check out other interfaces such as IReadCookie, IStringList, IRequestDictionary etc.
With note that:
Full trust for the immediate caller. This member cannot be used by partially trusted code.
there is another option : ContextUtil.GetNamedProperty Method
System.EnterpriseServices.ContextUtil.GetNamedProperty("Response").Cookies("fromdotnet") = "hello"

System.IO.Directory.Getfiles Silverlight 4 is not working

I'm using Silverlight 4 OOB & elevated trust.
I need to get all the filenames on specific directory & populate an object List(Of String)
The compiler throws an error "Method not found" on .Getfiles() method.
Dim files() As String = System.IO.Directory.Getfiles(Path) 'this line is failing..
Help!
The GetFiles is marked as "Security Critical" and therefore cannot be used from your code.
You will want to use the EnumerateFiles method instead. GetFiles is sooo .NET 1.0, EnumerateFiles is much slicker, even in the full framework you'd want avoid this older Array returning API if you can.
As far as I know you cannot directly access the whole hard drive using Silverlight OOB.
Quoting from Silverlight site:
When running in a trusted environment, you can access only files in
user folders, specifically the MyDocuments, MyMusic, MyPictures, and
MyVideos folders. Although this makes sense from a security point of
view, it’s limiting. You want to enable the user to drag their data
from any location. As it stands right now, if you try to drop a file
from a location other than stated above, Silverlight will throw a
security error.
Please refer to this link for details on how to work with the hard drive using Silverlight OOB:
http://www.silverlight.net/learn/overview/out-of-browser-applications/advanced-silverlight-out-of-browser-introduction#Exercise3

Is there any way to display a Windows form BEFORE the "Startup" form is loaded in VB.NET?

My company's main software package includes a hefty configuration library which loads on startup. This config library includes some mandatory settings which, if not supplied (via command line arguments), cause the entire application to exit.
This has never been an issue for our users, who launch the software via scripts which have the needed command line arguments supplied automatically. But sometimes when debugging our software we developers forget to specify the necessary arguments in Visual Studio's debug options; it's then very annoying to be greeted with the message Config specification invalid -- missing required parameters X, Y, and Z -- shutting down (I'm paraphrasing, of course).
It's not really a big deal, just an annoyance. Still, I felt it worthwhile to throw together a little form to make this process a little less painful; it notifies the user which parameters are missing and allows him/her to specify values for those parameters directly on the form, without having to restart the application.
My intentions were good (I think?), but it seems I can't get this solution to actually work. The problem is that after I've launched our software with missing settings, the form pops up and prompts me as expected; but after I've entered the required parameters and it's time for the application to "really" start, I get this InvalidOperationException:
SetCompatibleTextRenderingDefault must
be called before the first
IWin32Window object is created in the
application.
I think I understand what's going on here: the VB.NET project I'm working on is doing something like this "behind the scenes"*:
Sub Main()
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
Application.Run(New MainForm)
End Sub
That call to SetCompatibleTextRenderingDefault is, apparently, throwing an exception because a form was already created and displayed prior to its execution.
Is there any way around this? Is there perhaps a more "proper" solution to this problem that I'm not thinking of (i.e., should I not be trying to collect user input via a form at all)?
*This is a best guess based on what I've seen in C# WinForms projects. Strangely, unless I'm missing something, it seems that VB.NET WinForms projects completely hide this from the developer.
Do make sure that you have the application framework option turned off and Sub Main selected as the starting method. Make it look similar to this:
Sub Main(ByVal args() As String)
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
If args.Length = 0 Then
Using dlg As New OptionsDialog
If dlg.ShowDialog <> DialogResult.OK Then Return
'' Use dlg result...
End Using
End If
Application.Run(New MainForm)
End Sub
Perhaps you could use the static Debugger.IsAttached (or even a #DEBUG directive) in your program's "main" function that feeds in some input file (say an XML file) into your parsed args collection instead?