I have an excel Macro that uses a webservice to authenticate if the user of the Excel is a valid user or not.
I declare my required objects as follows:
Dim ObjHTTP As New XMLHTTP
Dim xml As New MSXML2.DOMDocument
When I send this file to my end users, some of them get an error saying XMLHTTP is undefined. Using XMLHTTP60 and MSXML2.DOMDocument60 works for them
Is there a way to auto detect the correct ones available on the end user machine ?
Thanks
tldr: Use late binding.
You are currently using Early Binding which means you have the appropriate library loaded in your references. If the other person does not have that library, then the code will fail as you have seen.
Late Binding loses all the autocomplete hints you get with the reference loaded, but it means the reference can be loaded dynamically on another machine.
Your code would become:
Dim ObjHTTP As Object
Dim xml As Object
Set ObjHTTP = CreateObject("XMLHTTP")
Set xml = CreateObject("MSXML2.DOMDocument")
The rest of the code would remain the same, and the overhead of dynamically loading the library is so small as to be unworthy of optimization
I'd recommend using the XMLHTTP60, DOMDocument60, etc. ProgIDs unless you have to support Windows XP. MSXML 6.0 is included with .NET 3.0 and later, and Windows 7 includes .NET 3.5, so all semi-recent Windows installations will have MSXML6 installed.
I believe when you use the ProgIDs without specifying a version you get MSXML 3.0, which is pretty old by now (circa 2000).
Edit: according to Wikipedia MSXML 6.0 ships with XP SP3, so there really isn't a good reason to still be using 3.
Related
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.
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"
I want to migrate an application from VB6.0 to VB.net.
I migrate it myself and get an error on this two lines. The error says "ExecWB is not a member of System.Windows.Forms.WebBrowser"!!The same error with the ExecWB Method. I dont find any solution or any equivalent code in .net for that. Do I need an imprt or reference or equivalent type?
Please help.
eQuery = webBrowser.QueryStatusWB(SHDocVw.OLECMDID.OLECMDID_COPY)
webBrowser.ExecWB(SHDocVw.OLECMDID.OLECMDID_PAGESETUP,
SHDocVw.OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, Nothing, Nothing)
webBrowser?
Thank you
There are two different WebBrowser things, the WebBrowser Object and the WebBrowser Control. The object is the ActiveX version that you were using in VB6 while the control was completely redesigned to follow .Net standards. While there may be some common methods, properties and events between the two they are not really related.
You can continue to use the ActiveX version in .Net just fine if you want. You'll need to add a reference to it either via the Add References menu or by adding the Microsoft Web Browser object to your toolbox. If you want to use the .Net version then you'll need to find the updated way to do your specific tasks.
A 30s Google search returned this article that suggests you can use late binding on the ActiveXInstance property to access the methods directly.
Note that this method is marked as "infrastructure use only" and may well be subject to change/removal, etc at a later date.
This is tangled.
I've been handed a web site written in classic ASP, with a lot of behind the scenes stuff done in VB6 COM+ objects called from the ASP pages via Server.ObjectCreate() instantiations. For this incarnation, the VB6 routines have been converted to VB.NET simply by running the Visual Studio 2003 converter tool on them, and then upgrading that solution file to VS 2008. So there's a thousand and one possible sources for error.
One of the VB6 Modules that is giving me trouble clears a bunch of Response cookies by lines of the following form:
ASPResponse.Cookies("SysUserCode") = ""
Where ASPResponse is defined as :
Private ASPResponse As ASPTypeLibrary.Response
And was set up on Object Activation by:
Set ASPResponse = objContext("Response")
In the VB.NET conversion of this module, those lines became
ASPResponse = ContextUtil.GetNamedProperty("Response")
and
ASPResponse.Cookies("SysUserCode")() = ""
(note the extra pair of parentheses. Not being much of a VB person, I'm not real sure what that syntax means.)
Okay, here's the question: When this code executes on MY machine, that line is giving a VB error 13, with the Error.Description being "Specified cast is not valid." Huh? What cast?
Incidentally, this module runs fine on a co-workers machine, and he cannot see any difference in the configuration of my machine and the relevant components from his.
I'm totally at a loss here. Googling it has given me a bunch of stuff on VB.NET cookies, or COM components with VB.NET, but nothing related to classic ASP cookies.
Is...
Private ASPResponse As ASPTypeLibrary.Response
Set ASPResponse = objContext("Response")
...Post VB.NET conversion? If so, you'll need to explicitly cast objContext("Response") into the ASPTypeLibrary.Response object. This especially applies if Option Strict is on. e.g.
ASPResponse = CType(objContext("Response"), ASPTypeLibary.Response)
Also, Set and Let statements aren't supported in VB.NET.
This MAY have to do with the way the COM component's host is activated. I read another post ([Klaus H. Probst])1 that indicated that, in order to access the Response element, the COM component had to be activated as a Library (as opposed to Server) so that it was running in the ASP process space. So I tried changing the Activation type of the Component's hosting application to library, resetting and rebuilding a few times, and now I'm able to access the Cookies element of the Response. However, my co-worker is still running the host application as a Server, and has no problem.
I am a .NET student and currently we are learning about Application Domains.
We were given the following example code (for .NET 3.5). As expected, it throws a SecurityException. Note: TestApp.exe is added as a reference in the project.
Dim file As String = "TestApp.exe"
Dim hostEvidence As Object() = {New Zone(SecurityZone.Internet)}
Dim appDomainEvidence As Evidence = New Evidence(hostEvidence, Nothing)
Dim d As AppDomain = AppDomain.CreateDomain("MyDomain", appDomainEvidence)
d.ExecuteAssembly(file)
When trying to run this in VS2010 under .NET 4.0 I run into a problem.
First it shows a warning
'Public Sub New(hostEvidence() As Object, assemblyEvidence() As Object)' is obsolete: 'This constructor is obsolete. Please use the constructor which takes arrays of EvidenceBase instead.'.
I change the type of hostEvidence to EvidenceBase() and the warning is gone.
However, when trying to run the application it gives an error.
This method implicitly uses CAS policy, which has been obsoleted by the .NET Framework. In order to enable CAS policy for compatibility reasons, please use the NetFx40_LegacySecurityPolicy configuration switch. Please see http://go.microsoft.com/fwlink/?LinkID=155570 for more information.
I have viewed the page, followed the link to How to: Run Partially Trusted Code in a Sandbox and read http://blogs.msdn.com/shawnfa/archive/2009/05/27/coding-with-security-policy-in-net-4-0-implicit-uses-of-cas-policy.aspx but I'm having trouble understanding all of this.
The code example on MSDN is quite big compared to what I currently have, so any help with changing my code so it works without adding other stuff, will be very appreciated.
As it says in the link you provided, .NET is no longer supporting the policy portion of the code access security framework, as of version 4.0.
In other words, your lesson is about .NET 3.5 and does not pertain to the 4.0 framework. The solution is to revert to your original code and configure your project to target the 3.5 framework (you can still use Visual Studio 2010).
.