XMLHTTP40 type not defined - vba

I'm trying to use HTTP in VB6 project
Dim httpCnct As XMLHTTP40
Set httpCnct = CreateObject("Msxml2.XMLHTTP.4.0")
but when i run the code, the compiler highlight the above line and show me an error: type not defined
Do I need to add some reference and, how to use it ?

C:\Users>reg query hkcr /f xmlhttp
HKEY_CLASSES_ROOT\Microsoft.XMLHTTP
HKEY_CLASSES_ROOT\Microsoft.XMLHTTP.1.0
HKEY_CLASSES_ROOT\Msxml2.ServerXMLHTTP
HKEY_CLASSES_ROOT\Msxml2.ServerXMLHTTP.3.0
HKEY_CLASSES_ROOT\Msxml2.ServerXMLHTTP.4.0
HKEY_CLASSES_ROOT\Msxml2.ServerXMLHTTP.5.0
HKEY_CLASSES_ROOT\Msxml2.ServerXMLHTTP.6.0
HKEY_CLASSES_ROOT\Msxml2.XMLHTTP
HKEY_CLASSES_ROOT\Msxml2.XMLHTTP.3.0
HKEY_CLASSES_ROOT\Msxml2.XMLHTTP.4.0
HKEY_CLASSES_ROOT\Msxml2.XMLHTTP.5.0
HKEY_CLASSES_ROOT\Msxml2.XMLHTTP.6.0
End of search: 12 match(es) found.
Also be aware there is a limit on how many times you can call any particular XMLHTTP object before a lockout occurs. If that happens, and it does when debugging code, just change to a different xmlhttp object
It is probably wiser to change
Set httpCnct = CreateObject("Msxml2.XMLHTTP.4.0")
to (if I remember my vb6 syntax)
Set httpCnct = New Msxml2.XMLHTTP.4.0
This would give you fast early binding rather than slow late binding. Changing the Dim to object will slow things down.

Related

Using a local image with EmbedBuilder

According to the Discord.NET documentation page for the EmbedBuilder class, the syntax (converted to VB) to add a local image to an EmbedBuilder object should look something like this:
Dim fileName = "image.png"
Dim embed = New EmbedBuilder() With {
.ImageUrl = $"attachment://{fileName}"
}.Build()
I'm trying to use something like this to add a dynamically created image to the EmbedBuilder, but I can't seem to get it to work properly. Here's basically what I've got:
Dim TweetBuilder As New Discord.EmbedBuilder
Dim DynamicImagePath As String = CreateDynamicImage()
Dim AttachURI As String = $"attachment:///" & DynamicImagePath.Replace("\", "/").Replace(" ", "%20")
With Builder
.Description = "SAMPLE DESCRIPTION"
.ImageUrl = AttachURI
End With
MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendMessageAsync("THIS IS A TEST", False, Builder.Build)
My CreateDynamicImage method returns the full path to the locally created image (e.g., C:\Folder\Another Folder\image.png). I've done a fair amount of "fighting"/testing with this to get past the Url must be a well-formed URI exception I was initially getting because of the [SPACE] in the path.
MyClient is a Discord.WebSocket.SocketClient object set elsewhere.
The SendMessageAsync method does send the Embed to Discord on the correct channel, but without the embedded image.
If I instead send the image using the SendFileAsync method (like so):
MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendFileAsync(DynamicImagePath, "THIS IS A TEST", False, Builder.Build)
the image is sent, but as a part of the message, rather than included as a part of the Embed (this is expected behavior - I only bring it up b/c it was a part of my testing to ensure that there wasn't a problem with actually sending the image to Discord).
I've tried using the file:/// scheme instead of the attachment:/// scheme, but that results in the entire post never making it to Discord at all.
Additionally, I've tried setting the ImageUrl property to a Web resource (e.g., https://www.somesite.com/someimage.png) and the Embed looks exactly as expected with the image and everything when it successfully posts to Discord.
So, I'm just wondering at this point if I'm just missing something, or if I'm just doing it completely wrong?
I cross-posted this to issue #1609 in the Discord.Net GitHub project to get a better idea of what options are available for this and received a good explanation of the issue:
The Embed (and EmbedImage) objects don't do anything with files. They simply pass the URI as configured straight into Discord. Discord then expects a URI in the form attachment://filename.ext if you want to refer to an attached image.
What you need to do is use SendFileAsync with the embed. You have two options here:
Use SendFileAsync with the Stream stream, string filename overload. I think this makes it clear what you need to do: you provide a file stream (via File.OpenRead or similar) and a filename. The provided filename does not have to match any file on disk. > So, for example:
var embed = new EmbedBuilder()
.WithImageUrl("attachment://myimage.png")
.Build();
await channel.SendFileAsync(stream, "myimage.png", embed: embed);
Alternatively, you can use SendFileAsync with the string filePath overload. Internally, this gets a stream of the file at the path, and sets filename (as sent to Discord) to the last part of the path. So it's equivalent to:
using var stream = File.OpenRead(filePath);
var filename = Path.GetFileName(filePath);
await channel.SendFileAsync(stream, filename);
From here, you can see that if you want to use the string filePath overload, you need to set embed image URI to something like $"attachment://{Path.GetFileName(filePath)}", because the attachment filename must match the one sent to Discord.
I almost had it with my code above, but I misunderstood the intention and usage of the method and property. I guess I thought the .ImageUrl property somehow "automatically" initiated a Stream in the background. Additionally, I missed one very important piece:
As it's an async method, you must await (or whatever the VB.NET equivalent is) on SendFileAsync.
So, after making my calling method into an async method, my code now looks like this:
Private Async Sub TestMessageToDiscord()
Dim Builder As New Discord.EmbedBuilder
Dim AttachmentPath As String = CreateDynamicImage() '<-- Returns the full, local path to the created file
With Builder
.Description = "SAMPLE DESCRIPTION"
.ImageUrl = $"attachment://{IO.Path.GetFileName(AttachmentPath)}"
End With
Using AttachmentStream As IO.Stream = IO.File.OpenRead(AttachmentPath)
Await MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendFileAsync(AttachmentStream, IO.Path.GetFileName(AttachmentPath), "THIS IS A TEST", False, Builder.Build)
End Using
End Sub
Now, everything works exactly as expected and I didn't have to resort to uploading the image to a hosting site and using the new URL (I actually had that working before I got the response on GitHub. I'm sure that code won't go to waste).
EDIT
Okay, so I still ended up going back to my separately hosted image option for one reason: I have a separate event method that modifies the original Embed object during which I want to remove the image and replace the text. However, when that event fired, while the text was replaced, the image was "moved" to the body of the Discord message. While I may have been able to figure out how to get rid of the image entirely, I decided to "drop back and punt" since I had already worked out the hosted image solution.
I've tried everyting I could, but I got stuck at the same point at where you are now.
My guesses are that Discord doesn't like the embedded images from https://cdn.discordapp.com/attachments, and only accepts the new files from https://media.discordapp.net. I might be wrong though, this is the way it worked for me.
I believe it's only a visual glitch, as I found if you send a link for an image from cdn.discordapp.com/attchments in your regular Discord client, it bugs out and shows an empty embed for some reason.
That would make sense since the default link used in an embedded image actually starts with https://cdn.discordapp.com/attachments/...
You could solve this issue by using https://media.discordapp.net, but it seems like Discord.net is configured to use the old domain.

Programmatically modify web.config for a self-hosted service (not via changes to applicationHost.config)

I'm stuck on something I should probably move on from but it's driving me nuts...
I can programmatically update SSL certificate info for a self-hosted WCF service using:
Dim config As Microsoft.Web.Administration.Configuration = _
serverManager.GetApplicationHostConfiguration
site.Bindings.Clear()
Dim binding = site.Bindings.Add(ipport, cert.GetCertHash, store.Name)
serverManager.CommitChanges()
and can also change sections of my local web.config using a known file path starting with:
Dim cfg As System.Configuration.Configuration = _
System.Web.Configuration.WebConfigurationManager.OpenMappedWebConfiguration(ConfigFileMap, target)
but if I try to drill down to system.webServer/security/access using:
Dim accessSection = cfg.GetSection("system.webServer/security")
I get Nothing/null and further digging helpfully produces this status for the section "System.Configuration.IgnoreSection", which apparently indicates that System.Configuration doesn't want to play nice with that specific piece - even though it's not denied access in applicationHost as near as I can tell.
On the other hand, if I try to use Microsoft.Web.Administration I can only figure out how to make the change to applicationHost.config, not to the local web.config.
The only thing that seems to want to put the client certificate requirement (sslFlags setting) in the local web.config is IIS Manager (which also doesn't show the setting correctly if it is located in the applicationHost.config)
Obviously there are all sorts of ways to do this but I can't believe there isn't a simple dot net way (other than editing the xml). Does anyone know what the heck I am doing wrong?
Doh!!! Apparently I need to learn to read the manual (although MS doesn't make it easy).
You can simply do:
Using serverManager As New ServerManager
Dim config As Microsoft.Web.Administration.Configuration = _
serverManager.GetWebConfiguration("site name", "/application")
Dim accessSection As Microsoft.Web.Administration.ConfigurationSection = _
config.GetSection("system.webServer/security/access")
accessSection("sslFlags") = "Ssl,SslRequireCert"
serverManager.CommitChanges()
End Using
Retroactively obvious link: Relevant StackOverflow Question

Detect if printer support duplex programmatically using obj-c

I have been stumped by this for the last few days. I need to detect if a printer support duplex printing.
I have had partial success using code like:
NSPrinter * printer = [NSPrinter printerWithName:pname];
[printInfo setPrinter:printer];
PMPrintSettings settings = printInfo.PMPrintSettings;
PMDuplexMode pmDuplexMode = 0;
OSStatus status = PMGetDuplex(settings, &pmDuplexMode);
supportsDuplex = (status >= 0);
But this only work if I captured a full printerConfig through an NSPrintPanel. What I need is a way to detect if a printer with a specific name support duplex without requiring the user to 1st open a panel. I would like to do if for any printer defined on the local Mac. Any help is appreciated!
In your code snippet, I doubt that it's correct to interpret positive status as indicating support. In general, any value other than zero (noErr) is a failure of some sort.
If you're confident that PMGetDuplex() returns an error for a print settings object when the printer doesn't support duplex, you can try this approach: create a session with PMCreateSession(), obtain a PMPrinter using PMPrinterCreateFromPrinterID() or by searching the array returned from PMSessionCreatePrinterList() for on which matches whatever criteria you want, set the session to use that printer using PMSessionSetCurrentPMPrinter(), create a print settings object with PMCreatePrintSettings(), call PMSessionDefaultPrintSettings() to initialize the print settings from the session, call PMSessionValidatePrintSettings() just for good measure, then call PMGetDuplex() and check the return value.
It might also be worth trying to set a duplex mode with PMSetDuplex() and check the return code and, possibly, calling PMSessionValidatePrintSettings() and checking if it changed that setting.

Using COM object from PowerBuilder - error 36: name not found accessing external object

I'm trying to access a third-party COM server from within Powerbuilder. I can instantiate the object but whenever I try to call a method or a property on the object I get error 36: "name not found accessing external object".
OLEObject PNSession
PNSession = CREATE OLEObject
ll_status = PNSession.ConnectToNewObject("PNSrv9.PNSession")
if ll_status = 0 then
// Set the session printer
try
PNSession.SetSessionPrinter('TIFF Image Printer 9.0', 1, g_pfapp.null_string, False)
catch (oleruntimeerror lole_error2)
messagebox('Set Error', lole_error2.description)
end try
// Turn job tracking on
PNSession.TrackingOn = True
end if
The ConnectToNewObject call succeeds and I see the COM server in my Task Manager, but subsequent calls fail. The above looks correct based on all the COM automation code samples for Word, Excel that I looked at.
The COM server is a C++ ATL COM Server, not a .NET COM object if that makes any difference.
Does anyone have an idea why this isn't working or what I am missing?
Thanks.
You probably don't have the parameter types correct. Looking at SetSessionPrinter, I would try passing 0 for PortsPreCreated. For PortBaseName try a string initialized to "" and also try 0.
Similarly, try PNSession.TrackingOn = 0.

Can't access the COM interface

I am working with the scantest of application documentation (shocker), and what there is seems to be misleading/contradicting. I will ask the software company as well, but their last reply took weeks. In the meantime....(thanks).....
I am trying to access the [alledged] COM interface of a GUI application we'll call: Xyz
My Question: Would the results below imply to you that there IS no COM interface available, that it needs to be registered, etc...
USER MANUAL STATES:
Here are the only two quotes related to the app's COM Interface ability:
"Since Xyz is a 32 bit application using COM (Component Object Model) components,
running Xyz from a network......".
"You can access the Xyz.Interface COM object to query for information and present it in a format you like".
CODE EXAMPLE 1:
Dim xyz_com
Set xyz_com= CreateObject("Xyz.Interface")
xyz_com.Visible=false
RESULT 1:
"Object doesn't support this property or method: 'Visible'"
CODE EXAMPLE 2:
Dim xyz_com
Set xyz_com= CreateObject("Xyz.Interface")
RESULT 2:
The initial application screen appears which - if I AM starting the application in 'server mode' as they say - I wouldn't think I would have the screen showing.
CODE EXAMPLE 3:
Dim xyz_com
Set xyz_com= CreateObject("Xyz.Interface")
xyz_com.QueryInterface()
RESULT 3:
"Object doesn't support this property or method: 'QueryInterface'"
Would the results below imply to you
that there IS no COM interface
available, that it needs to be
registered, etc..
The CreateObject call succeeds, so the COM interface exists and is registered.
Some comments:
You can't directly call QueryInterface like that from VB
You need to cast the object to the correct interface before setting the Visible property. Try Dim xyz_com as Xyz.Interface instead of just Dim xyz_com