View Full Version : Visual Lisp Help - Check if URL Exists
caddog71
2008-07-29, 03:52 PM
I am trying to write a program to check to see if a url exists or not. I did something similar in VBA using the GetRemoteFile method. Is there something in Visual Lisp that I can use?
patrick35
2008-07-29, 06:08 PM
Hi
(defun download(lien rep / cp ok tmp util)
(setq util (vla-get-Utility (vla-get-ActiveDocument (vlax-get-acad-object))))
(if (eq (vla-isurl util lien) :vlax-true)
(if (vl-catch-all-error-p (vl-catch-all-apply 'vla-GetRemoteFile (list util lien 'tmp :vlax-true)))
(princ "\nErreur lors du téléchargement.")
(progn
(setq cp (strcat rep (vl-filename-base lien) (vl-filename-extension lien)))
(if (findfile cp)
(vl-file-delete cp)
)
(if (vl-catch-all-error-p (vl-catch-all-apply 'vl-file-copy (list tmp cp)))
(progn
(princ "\nUnable to move the file \""
(strcat (vl-filename-base cp)(vl-filename-extension cp))
"\" since the directory \n\""
tmp
)
(vl-file-delete tmp)
)
(progn
(vl-file-delete tmp)
(if (zerop (vl-file-size cp))
(progn
(vl-file-delete cp)
(princ "\nUnable to download the file.")
)
(setq ok T)
)
)
)
)
)
(princ "\nThe url is not valid.")
)
ok
)
Example
(download "http://carnet-de-cablage.chez-alice.fr/Lisp/Gef.zip" "c:/test/")
If OK, return T
An another with activex
(defun download (url dir / byte fic file fso http tbl)
(setq http (vlax-create-object "MSXML2.XMLHTTP")
fso (vlax-create-object "Scripting.FileSystemObject"))
(vlax-invoke-method http 'open "get" url :vlax-false)
(vlax-invoke http 'send)
(while (not (eq (vlax-get http 'readyState) 4))
(repeat 100)
)
(setq file (strcat dir (vl-filename-base url) (vl-filename-extension url))
tbl (vlax-safearray->list (vlax-variant-value (vlax-get-property http 'responsebody)))
fic (vlax-invoke fso 'CreateTextFile file))
(foreach byte tbl
(vlax-invoke fic 'write (vl-list->string (list byte)))
)
(vlax-invoke fic 'close)
(vlax-release-object http)
(vlax-release-object fso)
(princ)
)
@+
caddog71
2008-08-04, 04:12 PM
Thank you Patrick for the response to my question. Now this posses another question that I have. I am using Acad 2002 and I am going through the help files looking for the "vla" functions and there are none listed, there are only "vl" ,"vlax", and "vlr" functions. Are "vla" functions something that was introducted to Acad after the 2002 verison?
irneb
2008-08-04, 04:51 PM
From the Developer Help: AutoLisp Developer's Guide --> Using the Visual LISP Environment --> Working with ActiveX --> Using Visual LISP functions with ActiveX methods
This explains the idea behind vla functions.
DarrenYoung
2008-08-04, 07:43 PM
Thank you Patrick for the response to my question. Now this posses another question that I have. I am using Acad 2002 and I am going through the help files looking for the "vla" functions and there are none listed, there are only "vl" ,"vlax", and "vlr" functions. Are "vla" functions something that was introducted to Acad after the 2002 verison?
If you have access to the Autodesk University content (either for Autodesk University for older content from AUGI), there's a class I held on ActiveX from Lisp which covers how you translate the VBA object model into Lisp code. Here's the link to the older AU content hosted by AUGI...
http://www.augi.com/education/auhandouts/2002/CP31-1.pdf
The Class i did the last copule years at AU covered the same information and is esentially the same although I added other non ActiveX topics like recursion and reactors in the newer classes.
The above link should give you what you are looking for.
caddog71
2008-08-07, 03:57 PM
Thank you very much Darren for the link to the document. I am trying to figure out how to pass a Lisp variable to a Vlisp string. I understand that when you are dealing with autocad entities with Lisp and you need to access them using Vlisp you need to convert them to an object before being able to work with them using any "vla-" functions using (vlax-ename->vla-object. I am creating a URL by concantinating a couple of different Lisp variables then I want to pass the completed URL string to the "vla-getremotefile" function to copy a dwf from the web. Can anyone point me in the right direction?
(setq baseurl "http://www-go.sce.com/fim/images/")
(setq dprefix(getvar "dwgprefix"))
(setq distnum(substr dprefix 8 2))
(setq dwgname(vl-filename-base(getvar "dwgname")))
(setq url (strcat baseurl distnum "/" dwgname ".dwf"))
(vla-GetRemoteFile url, true)
Thanks for the help.
Moderator Note:
Please use [ CODE ] tags... (http://forums.augi.com/misc.php?do=bbcode#code)
irneb
2008-08-07, 05:06 PM
You're correct, but it's reasonably simple. You convert the ename to a vla-object. The ename is what's returned in entsel or ssname (from a selection set). The same thing you use when getting the entity's data with entget.
So you basically have something like:
(setq ename (entsel "Select entity to add hyperlink to:"))
(setq objref (vlax-ename->vla-object (car ename)))
Then add the hyperlink to the hyperlinks collection through the vla-Add function:(setq hypcol (vla-get-Hyperlinks objref))
(vla-Add hypcol url hdescr hloc)Where:
url is URL (wierdly named Hyperlink Name in the ActiveX code)
hdescr is the text displayed in the tooltip while hovering the cursor over the entity
hloc is only used to open sav a particular view of a drawing. e.g. open the drawing in Model space then set this to ",Model". Otherwise leave as empty string ""
irneb
2008-08-07, 05:23 PM
One strange thing though: if you don't pass a NamedLocation to the vla-Add function, then the Description is ignored. E.g. I did the following:(setq hyp (vla-Add hypcol "http://www-go.sce.com/fim/images/" "test"
""))
;; Then display the object
(vlax-dump-object hyp)
This gave:; IAcadHyperlink: A URL and URL description
; Property values:
; Application (RO) = #<VLA-OBJECT IAcadApplication 00d74d3c>
; URL = "http://www-go.sce.com/fim/images/"
; URLDescription = ""
; URLNamedLocation = ""So then I tried the following:Command: (setq hyp (vla-Add hypcol "http://www-go.sce.com/fim/images/" "test"
"testing"))
#<VLA-OBJECT IAcadHyperlink 34181a5c>
Command: (vlax-dump-object hyp)
; IAcadHyperlink: A URL and URL description
; Property values:
; Application (RO) = #<VLA-OBJECT IAcadApplication 00d74d3c>
; URL = "http://www-go.sce.com/fim/images/"
; URLDescription = "testing"
; URLNamedLocation = "testing"As you can see the created hypelink passes the Location as the Description. So If you want to use a description, then obtain a ref of the created hyperlink as done in my examples (setq hyp (vla-Ad ...)). Then set that hyperlink's values, e.g. (vla-put-URLDescription hyp "Name to show")
caddog71
2008-08-11, 09:14 PM
Thank you for the responses to my thread but I still don't understand on how to make the "vla-getremotefile" function work. Help please.
(defun c:learn ()
(setq baseurl "http://www-go.sce.com/fim/images/")
(setq dwgname(vl-filename-base(getvar "dwgname")));Get drawing name without extension
(setq dprefix(getvar "dwgprefix"))
(setq distnum(substr dprefix 8 2))
(setq web (strcat baseurl distnum "/" dwgname ".dwf"))
(setq urlobj (vlax-make-safearray vlax-vbstring '(0 . 0)))
(vlax-safearray-put-element urlobj 0 web)
(vlax-safearray->list urlobj)
(vla-getremotefile (urlobj))
)
Hi caddog71,
You don't need to use safearrays and what-nots when passing basic string arguments. You also must study what it is the Method is expecting, and what object it must be called from.
In this case, the GetRemoteFile is a method of the Utility Object of the current drawing. It MUST be passed all 3 arguments, the URL to get, an empty variable that will hold the temporary file name, and a true/false of whether to download the file even if it was already downloaded in this session. That being said, this should work or be real close....I don't have anything to test this with right now.
(defun c:learn (/ BASEURL DISTNUM DOC DPREFIX DWGNAME UTIL WEB)
(setq baseurl "http://www-go.sce.com/fim/images/")
(setq dwgname(vl-filename-base(getvar "dwgname")));Get drawing name without extension
(setq dprefix(getvar "dwgprefix"))
(setq distnum(substr dprefix 8 2))
(setq web (strcat baseurl distnum "/" dwgname ".dwf"))
(setq doc (vla-get-activedocument (vlax-get-acad-object))
util (vla-get-utility doc)
)
(vla-getremotefile util web 'destination :vlax-true)
(princ)
)
Hope that helps a bit,
Jeff
DarrenYoung
2008-08-12, 06:33 PM
Thank you for the responses to my thread but I still don't understand on how to make the "vla-getremotefile" function work. Help please.
Try this...
(defun c:test (/ objDOC objUTL locfile)
(vl-load-com)
(setq objDOC (vla-get-activedocument (vlax-get-acad-object)))
(setq objUTL (vla-get-utility objDOC))
(vla-getremotefile
objUTL
"http://www.uspconnectors.com/cad/product/hc520.dwg"
'locfile
:vlax-true
)
;;; (vl-catch-all-apply
;;; (function vla-getremotefile)
;;; (list objUTL
;;; "http://www.uspconnectors.com/cad/product/hc520.dwg"
;;; 'locfile
;;; :vlax-true
;;; )
;;; )
(alert (strcat "File downloaded here -> " locfile))
(princ)
)
I've included a commented section that does the same thing only wraps the function in VL-CATCH-ALL-APPLY which is for error trapping purposes. Just save the return from VL-CATCH-ALL-APPLY to a variable and check it with VL-CATCH-ALL-ERROR-P to see if the return threw an error and if so, use VL-CATCH-ALL-ERROR-MESSAGE to check the error.
The document I referd you to earlier explains how to interpret the VBA documentation and translate that to Lisp. Essentially, most methods in VBA require an object. GETREMOTEFILE uses the UTILITY object and requires 3 arguments in VBA, in Lisp it requires 4, the first being the UTILITY object.
The other thing that's different with ActiveX in Lisp from traditional Lisp is that you are use to a function returning a value to a variable. This happens in ActiveX based Lisp as well but there's times where you also need to specify a quoted empty variable (LOCFILE in this case) and the function 'back fills' (for lack of a beter term) the value into that variable. That's why you won't see a (SETQ LOCFILE ...) anywhere in the code yet LOCFILE does indeed store the value.
The file is also downloaded using HTTP so it automatically get's stuffed into the temporary internet files folder where you can then move/copy it where ever you want.
PS: The file used in the sample is valid and on the web (one of my former clients). If it doesn't download or work on your system, it's likley a filewall or permission issue with your systems.
irneb
2008-08-13, 07:13 AM
Technically what Darren's referring to is that the vla functions are a way of making LISP (a Procedural Oriented Programming Language) use Methods and Properties from ActiveX (as used in Visual Basic for Applications), which is an Object Oriented Programming Language (or tries to be). The LISP function is a "wrapper" to this method. The basic difference between func & meth is that a function takes inputs and passes a result, while a method can be a "function" or a "procedure" (which takes inputs, but also outputs, but returns no result), or a method could be a combination of the 2 returning a result but also changing the values of variables passed to it. A method is always part of an Object, a function or a procedure will be separate from anything else (this is the basic difference between Procedural- and Object Oriented).
In VBA you'd have written:
UtilityObject.GetRemoteFile ("http://www.uspconnectors.com/cad/product/hc520.dwg", locfile, True)
Which basically says: "Call the UtilityObject's method named GetRemoteFile, passing it the 3 variables (a quoted string with url, a var for returning the file, and a True value to say ignore cached files & force download)."
What happens in VLISP with this function (vla-GetRemoteFile UtilityObject "http://www.uspconnectors.com/cad/product/hc520.dwg" 'locfile Vlax:True) is "Perform function named GetRemoteFile on UtilityObject, passing the variables." The reason that locfile is prefixed with a single quote is to rather pass the "reference" to the variable so that the method places the filename into the original variable. If you didn't do this then a "new" variable is created inside the vla-GetRemoteFile function, it's value gets changed but not passed back. In VBA this is automatic since you tell the Method which variables are By Value and which are By Reference. Lisp doesn't have such a destinction - so you have to trick it every time you call the function.
The easier type of vla function to understand is probably those wrapping the Object's Properties. These are the vla-get-... and vla-put-... functions. Although aff subject, I'm adding this for completeness. In VBA you'd have set an entity's Layer by:
EnRef.Layer = "Layer1" the equivalent VLISP code is (vla-put-Layer EnRef "Layer1")
And to get the entity's layer:
VBA: Value = EnRef.Layer VLISP: (setq Value (vla-get-Layer EnRef))
DarrenYoung
2008-08-14, 04:12 PM
Nice explination Irneb.
Another was to think of the 'locfile variable and understand why it's quoted, is to remember then everything in Lisp is evaluated to it's value. The function vla-getremotefile needs a variable to stuff a value into. Without quoting it, the variable is evaluated and locfile's value which would be NIL initially, would be passed to the vla-getremotefile function.
Quoting thte varible names passes the variable name to the function and doesn't evaluate it to the value it holds.
It was noted earlier in this thread that the VLA functions aren't documented. The reason for that is because they technically don't exist until a call to (vl-load-com) is made, then the functions are created for the AutoCAD object model. This isn't limited to just AutoCAD however. While this shortcut to creating Visp based commands for thr AutoCAD object model, you can do the same for any application that has an ActiveX object model like Excel or MS Word. Just use the (vlax-import-type-library) function to import the type library which will create a whole bunch of functions with the previx you define instead of vla-*, you could then have vlxls-* functions in Lisp that control Excel.
vBulletin® v3.6.7, Copyright ©2000-2009, Jelsoft Enterprises Ltd.