WSC in python clears method arguments

T Malcolm nt_colonel at hotmail.com
Mon Nov 12 17:04:50 CET 2001


> > Well, see, the COM Component isn't a pure Python module.
> > All of my Python is in a Windows Script Component(WSC)...an xml file
> > parsed by the ActiveX Scripting engine.  Classes are set off with
> > <component></component> tags, and the COM interface is also described
> > using XML tags.  Since this isn't a proper python class there's no
> > "self" first argument on the methods, thus causing half of my
> > problems.  Everything calls, and it works just great, but it eats the
> > values stored in my argument variables.
> 
> Blerch. So are you trying to execute Python client-side with this?
> 
> Let's see some more code! What's the environment?
> 
> regards
>  Steve

I have a pair of VBScripts as a COM Client to this Windows Script
Component containing Python (COM Server).  The VBScripts are task
scheduled on a Win2k machine.  The VBS gets COM instances using the
regular old

Set objWhatever = CreateObject("ProgID")

but when you call a method like this:

objWhatever.cwd(directory)

the variable "directory" which would have held a string (like
"/FTP/ouput") before calling holds "" after calling, which in VB terms
would be Empty (or vbNullString, if you prefer).  Its possible that
VBScript could be translating whatever is being return in the arglist
(or not, as the case may be) into a string equivalent because it kinda
likes to type cast variables after you first use them.

The beautiful part of these WSC's is that they're easy to
register/unregister and the only thing you have to do to make the
typelib is right-click and choose "Generate Type Library" (although it
generates a new GUID for the typelib every time you do that).  I read
somewhere MS invented these WSC's because of security problems with
ASP giving up source code(which could give away DB passwords) and ASP
developers loathed recompiling and re-registering VB COM components
just to debug their code.

Here's the whole WSC COM component (ezFTPcomponent.wsc).

The <component> tag replaces where you would normally define a python
class.  Sort of.

----
<?xml version="1.0"?>
<component>
<registration
	description="FTP component"
	progid="ezFTP.FTP"
	version="1.0"
	clsid="{5A29080F-B1C3-4199-90EA-119FB413A5DA}"
 />

<public>
	<property name="host">
		<get internalName="GetHostName" />
		<put internalName="PutHostName" />
	</property>

	<property name="port">
		<get internalName="GetPort" />
		<put internalName="PutPort" />
	</property>

	<property name="user">
		<get internalName="GetUser" />
		<put internalName="PutUser" />
	</property>

	<property name="password">
		<get internalName="GetPassword" />
		<put internalName="PutPassword" />
	</property>

	<method name="connect" />

	<method name="cwd">
		<parameter name="Directory" />
	</method>

	<method name="download">
		<parameter name="RemoteFile" />
		<parameter name="LocalFile" />
	</method>

	<method name="pwd" />

	<method name="ListDir" internalName="listdir">
		<parameter name="Directory" />
	</method>

	<method name="delete">
		<parameter name="File" />
	</method>

	<method name="upload">
		<parameter name="LocalFileName" />
		<parameter name="RemoteFileName" />
	</method>

	<method name="close" />
</public>


<script language="Python">
<![CDATA[
#All of this code MUST be within this CDATA block
#to keep the XML parser from trying to read through it
#and choking.

from ftplib import FTP
import os

#property defaults
FTP.host = ''
FTP.port = 21
FTP.user = ''
FTP.password = ''
FTP.DirList = ''
FTP.fd = ''

'''Do not pass an argument into these functions that 
   changes the FTP=objFTP arguments.  It won't work
   if the local object instance gets overridden.
'''


#I should be able to reference this instance of FTP from within
#the functions without passing it...doesn't work that way.
objFTP = FTP()
objFTP.set_pasv(1)

#All of these functions are property put and property get functions.
def PutHostName(strHostName, FTP=objFTP):
	FTP.host = strHostName

def GetHostName(FTP = objFTP):
	return FTP.host

def PutPort(intPort, FTP = objFTP):
	FTP.port = intPort

def GetPort(FTP = objFTP):
	return FTP.port

def PutUser(UserName, FTP = objFTP):
	FTP.user = UserName

def GetUser(FTP = objFTP):
	return FTP.user

def PutPassword(Password, FTP = objFTP):
	FTP.password = Password

def GetPassword(FTP = objFTP):
	return FTP.password
	

#Method functions are defined here
def connect(FTP = objFTP):
	FTP.connect(FTP.host, FTP.port)
	FTP.login(FTP.user, FTP.password)

def cwd(directory, FTP = objFTP):
	FTP.cwd(directory)

def listdir(directory = '', FTP = objFTP):
	DirString = ''
	delimiter = ''

	if directory != '':
		DirList = FTP.nlst(directory)
		for file in DirList:
			DirString += delimiter + '"' + file + '"'
			delimiter = ', '
	else:
		DirList = FTP.nlst()
		for file in DirList:
			DirString += delimiter + '"' + file + '"'
			delimiter = ', '

	return DirString

def upload(localFileName, remoteFileName, FTP = objFTP):
	localFile = open(localFileName, "rb")
	FTP.storbinary("STOR " + remoteFileName, localFile)
	localFile.close()


def download(remoteFile, localFile, FTP = objFTP):
	file = open(localFile, "wb")
	FTP.fd = file.fileno()

	FTP.retrbinary("RETR " + remoteFile, FileWriter)

	file.close()

def FileWriter(binarydata, FTP = objFTP):
	os.write(FTP.fd, binarydata)

def pwd(FTP = objFTP):
	return FTP.pwd()

def delete(file, FTP = objFTP):
	FTP.delete(file)

def close(FTP = objFTP):
	try:
		FTP.quit()
	except:
		FTP.close()
	
]]>
</script>

</component>

----

I appreciate you helping me with this thing.

-- 
Tom



More information about the Python-list mailing list